{"locator":"npm:@piotrkarwatka/marketing-consents","path":"@piotrkarwatka/marketing-consents","npm":"@piotrkarwatka/marketing-consents","github":"pkarw/marketing-consents","repoPath":null,"kind":"module","type":"community","enterprise":false,"title":"Marketing Consents","summary":"Register of marketing consent proofs: exact text with a SHA-256 digest, withdrawal with a reason, personal fields encrypted.","whenToUse":"Use when the app must keep evidence of each marketing consent and let staff withdraw it with a recorded reason.","whenNotToUse":"It sends nothing and grants no permission to send: your sending system must read the consent state.","category":"marketing-loyalty","tags":["consents","gdpr","marketing"],"providers":[],"moduleIds":["marketing_consents"],"requires":[],"replaces":[],"slotConflicts":[],"renamedFrom":[],"supersededBy":null,"alternatives":[],"status":"active","listed":true,"featured":false,"license":{"spdx":null,"kind":"proprietary","mismatch":false},"version":{"latest":"0.1.0","preview":null,"publishedAt":"2026-10-14","integrity":"sha512-ByUXs82VmoFMQa6c7kgE1yhKDBH9MNhZoMvTnkpU0ORD4KxHyv4/fQGUXOzmiUnfU6+Zsc4H1hncG7GbnaE2ig==","installableFrom":"2026-10-19","gitRef":null,"recommended":{"0.9":null,"0.8":null,"next":null}},"identity":{"builtFrom":"none","claimed":false,"source":"npm"},"compat":{"builtFor":{"range":"0.9.0","kind":"exact-pin","lines":["0.9"]},"lines":{"0.9":{"status":"broken","step":"typecheck","omVersion":"0.9.0","moduleVersion":"0.1.0","at":"2026-10-29T09:03:43Z","receipt":"r_20261029_540cc6cb533c","since":"2026-10-29","precheck":null,"patches":[],"finding":"Typecheck failed: TS2321 Excessive stack depth comparing types '{ title: string; titleHeadingLevel: 1; columns: LegacyColumnDef<ConsentRow>[]; data: ConsentRow[]; searchValue: string; searchPlacehold…"}},"verifiedOn":[]},"anatomy":{"version":"0.1.0","coverage":"full","counts":{"entities":2,"tables":2,"migrations":1,"routes":4,"publicRoutes":0,"aclFeatures":3,"eventsEmitted":0,"eventsConsumed":0,"backendPages":2,"frontendPages":0,"widgets":0,"workers":0,"cli":0,"aiTools":0,"aiAgents":0,"extends":0},"lists":{"aclFeatures":["marketing_consents.record","marketing_consents.view","marketing_consents.withdraw"],"eventsEmitted":[],"eventsConsumed":[],"env":[],"hosts":[],"tables":["marketing_consent_records","marketing_consent_withdrawal_evidence"],"publicRoutes":[],"credentials":[],"backendPages":["/backend/marketing_consents","/backend/marketing_consents/[id]"]},"callout":"ADDS 2 TABLES · 4 ROUTES (0 PUBLIC) · 3 PERMISSIONS","diff":null},"signals":{"receipt":{"0.9":"broken","0.8":"untested","next":"untested"},"fit":{"0.9":"ok","0.8":"no-fit","next":"drift"},"anatomy":"full","supplyChain":{"status":"ok","reasons":[]},"hygiene":{"status":"warn","failing":["peer-exact-pin","host-dependency-duplication"]},"maintenance":{"status":"current","lastRelease":"2026-10-14","catchUpDays":null},"declaredVsObserved":{"status":"mismatch","notes":["Built for 0.9; verified on no line."]}},"tier":"listed","quality":null,"agentPolicy":{"0.9":{"decision":"refuse","reasons":[{"code":"BROKEN","text":"Broken at typecheck on 0.9 since 29 Oct."},{"code":"THIRD_PARTY","text":"Third-party code runs with access to all tenants' data."},{"code":"LICENSE","text":"License: proprietary (UNLICENSED)."}]},"0.8":{"decision":"ask","reasons":[{"code":"THIRD_PARTY","text":"Third-party code runs with access to all tenants' data."},{"code":"NOT_VERIFIED","text":"Not yet tested in a new app on 0.8."},{"code":"LICENSE","text":"License: proprietary (UNLICENSED)."}],"consentText":"Install @piotrkarwatka/marketing-consents@0.1.0"},"next":{"decision":"ask","reasons":[{"code":"THIRD_PARTY","text":"Third-party code runs with access to all tenants' data."},{"code":"NOT_VERIFIED","text":"Not yet tested in a new app on next."},{"code":"LICENSE","text":"License: proprietary (UNLICENSED)."}],"consentText":"Install @piotrkarwatka/marketing-consents@0.1.0"}},"install":{"cli":"yarn mercato module add @piotrkarwatka/marketing-consents@0.1.0 --allow-third-party","cmm":"npx create-mercato-module install @piotrkarwatka/marketing-consents@0.1.0","needsAllowThirdParty":true,"moduleFlag":null},"stats":{"downloads30d":null,"stars":0},"sigil":{"glyph":"2220000","phase":125,"publicRoutes":false},"links":{"page":"https://modules.openmercato.com/m/@piotrkarwatka/marketing-consents","md":"https://modules.openmercato.com/m/@piotrkarwatka/marketing-consents.md","json":"https://modules.openmercato.com/m/@piotrkarwatka/marketing-consents.json","facts":"https://modules.openmercato.com/m/@piotrkarwatka/marketing-consents/v/0.1.0/facts.json","npm":"https://www.npmjs.com/package/@piotrkarwatka/marketing-consents","repo":"https://github.com/pkarw/marketing-consents","docs":null},"addedAt":"2026-10-23","updatedAt":"2026-10-29T09:22:28Z","_meta":{"com.openmercato.modules/installable":{"0.9":"0.1.0","0.8":"0.1.0","next":"0.1.0"}},"facts":{"factsVersion":1,"extractor":{"engine":"@open-mercato/cli@0.9.0 extractModuleFacts","factsContractVersion":2,"catalog":"om-modules rentgen 1","durationMs":70},"package":{"locator":"npm:@piotrkarwatka/marketing-consents","name":"@piotrkarwatka/marketing-consents","version":"0.1.0","integrity":"sha512-ByUXs82VmoFMQa6c7kgE1yhKDBH9MNhZoMvTnkpU0ORD4KxHyv4/fQGUXOzmiUnfU6+Zsc4H1hncG7GbnaE2ig==","source":"npm-tarball","gitRef":null},"gate":{"installable":true,"needsModuleFlag":false,"reason":null,"modules":[{"id":"marketing_consents","src":true,"dist":true}]},"kind":"module","license":{"value":"UNLICENSED","kind":"proprietary","mismatch":false,"sources":{"packageJson":"UNLICENSED","licenseFile":null,"moduleInfo":null,"integrationTs":null}},"omPeers":{"@open-mercato/core":"0.9.0","@open-mercato/shared":"0.9.0","@open-mercato/ui":"0.9.0"},"dependencies":{"@tanstack/react-query":"5.104.1","@tanstack/react-table":"9.2.6","zod":"4.4.3"},"agentsMd":false,"readmeExcerpt":"# @piotrkarwatka/marketing-consents\n\nInstall in an Open Mercato app:\n\n```sh\nyarn mercato module add @piotrkarwatka/marketing-consents --allow-third-party\n```\n\nDevelop in your existing app and publish another version with create-mercato-module. To make this repository the source of your module while keeping the same app for development:\n\n```sh\nnpx create-mercato-module link pkarw/marketing-consents\n```\n\nThe tool checks out this repo in the app's .mercato/module-repos/marketing_consents directory, backs up the original module, and links src/modules/marketing_consents to the checkout. Edits in the app are edits in this repository.\n\n## Trusted Publishing\n\nConfigure this package's trusted publisher on npmjs.com for the GitHub owner, repository, and workflow filename publish.yml. Then dispatch the included GitHub Actions workflow or push a v<version> tag matching package.json. For private dependencies, set a read-only NPM_READ_TOKEN repository secret.\n\nSee [create-mercato-module](https://github.com/open-mercato/create-mercato-module) for authentication, release tests, and development details.\n","modules":[{"id":"marketing_consents","title":"Marketing Consents","description":null,"requires":[],"ejectable":true,"data":{"entities":[{"id":"marketing_consents:consent_record","table":"marketing_consent_records","src":{"file":"src/modules/marketing_consents/data/entities.ts","line":21}},{"id":"marketing_consents:withdrawal_evidence","table":"marketing_consent_withdrawal_evidence","src":{"file":"src/modules/marketing_consents/data/entities.ts","line":79}}],"migrations":{"count":1,"first":"2026-10-12","last":"2026-10-12"},"customEntities":0},"http":{"routes":[{"method":"GET","path":"/api/marketing_consents/consents","requireAuth":true,"requireFeatures":["marketing_consents.view"],"hasOpenApi":true,"src":{"file":"src/modules/marketing_consents/api/consents/route.ts","line":151}},{"method":"POST","path":"/api/marketing_consents/consents","requireAuth":true,"requireFeatures":["marketing_consents.record"],"hasOpenApi":true,"src":{"file":"src/modules/marketing_consents/api/consents/route.ts","line":158}},{"method":"GET","path":"/api/marketing_consents/consents/[id]","requireAuth":true,"requireFeatures":["marketing_consents.view"],"hasOpenApi":true,"src":{"file":"src/modules/marketing_consents/api/consents/[id]/route.ts","line":45}},{"method":"POST","path":"/api/marketing_consents/consents/[id]/withdraw","requireAuth":true,"requireFeatures":["marketing_consents.view","marketing_consents.withdraw"],"hasOpenApi":true,"src":{"file":"src/modules/marketing_consents/api/consents/[id]/withdraw/route.ts","line":27}}],"legacyRouteFiles":0,"authResolved":1},"security":{"aclFeatures":["marketing_consents.record","marketing_consents.view","marketing_consents.withdraw"],"setupDefaultRoleFeatures":true},"events":{"emits":[],"subscribes":[]},"ui":{"backendPages":[{"path":"/backend/marketing_consents","requireFeatures":["marketing_consents.view"]},{"path":"/backend/marketing_consents/[id]","requireFeatures":["marketing_consents.view"]}],"frontendPages":[],"widgets":0,"extensionHosts":2},"background":{"workers":[],"cli":[]},"ai":{"tools":[],"agents":[]},"config":{"credentials":[],"env":[]},"network":{"hosts":[],"undeclared":[]},"extends":[],"omImports":{"@open-mercato/core":{"modules/directory/utils/organizationScope":["resolveOrganizationScopeForRequest"]},"@open-mercato/shared":{"lib/auth/server":["getAuthFromRequest"],"lib/commands":["CommandBus","CommandHandler","CommandRuntimeContext","registerCommand"],"lib/crud/errors":["CrudHttpError"],"lib/crud/factory":["CrudCtx","makeCrudRoute"],"lib/crud/optimistic-lock-command":["enforceCommandOptimisticLock"],"lib/crud/route-mutation-guard":["runRouteMutationGuards"],"lib/di/container":["createRequestContainer"],"lib/encryption/find":["findOneWithDecryption"],"lib/encryption/migration-backfill":["buildEncryptionMapBackfillSql"],"lib/encryption/tenantDataEncryptionService":["TenantDataEncryptionService"],"lib/frontend/useOrganizationScope":["useOrganizationScopeVersion"],"lib/i18n/context":["useT"],"lib/logger":["createLogger"],"lib/openapi":["OpenApiMethodDoc","OpenApiRouteDoc"],"modules/encryption":["ModuleEncryptionMap"],"modules/registry":["ModuleInfo","PageMetadata"],"modules/setup":["ModuleSetupConfig"]},"@open-mercato/ui":{"backend/CrudForm":["CrudField","CrudForm"],"backend/DataTable":["DataTable"],"backend/FilterBar":["FilterDef","FilterValues"],"backend/FlashMessages":["flash"],"backend/Page":["Page","PageBody"],"backend/RowActions":["RowActions"],"backend/detail":["AccessDeniedMessage","DetailFieldConfig","DetailFieldsSection","ErrorMessage","LoadingMessage","RecordNotFoundState"],"backend/forms/FormHeader":["FormHeader"],"backend/injection/useGuardedMutation":["useGuardedMutation"],"backend/utils/apiCall":["readApiResultOrThrow"],"backend/utils/crud":["fetchCrudList"],"hooks/useDialogKeyHandler":["useDialogKeyHandler"],"primitives/alert":["Alert"],"primitives/button":["Button"],"primitives/checkbox":["Checkbox"],"primitives/dialog":["Dialog","DialogContent","DialogDescription","DialogHeader","DialogTitle"],"primitives/label":["Label"],"primitives/status-badge":["StatusBadge"]}},"collisionKeys":{"moduleId":"marketing_consents","tables":["marketing_consent_records","marketing_consent_withdrawal_evidence"],"aclFeatures":["marketing_consents.record","marketing_consents.view","marketing_consents.withdraw"],"eventIds":[],"backendRoutes":["/backend/marketing_consents","/backend/marketing_consents/[id]"]},"publicRoutes":0,"glyph":"2220000","lint":[{"code":"peer-exact-pin","severity":"warn","message":"Peer dependencies pin Open Mercato exactly (@open-mercato/core 0.9.0 and 2 more). Use a range.","anchor":"i2 §1.4","src":null},{"code":"no-agents-md","severity":"info","message":"No AGENTS.md in the package.","anchor":"g3 §3","src":null}]}],"coverage":{"routesAuthResolved":1,"integrationTs":"absent"},"diagnostics":[]},"receipts":[{"schema":1,"id":"r_20261029_540cc6cb533c","cellKey":"540cc6cb533c372f3bac84d5a543bf333e0ddd5d435ecfaa3fd6bba0ea3312b0","module":{"locator":"npm:@piotrkarwatka/marketing-consents","version":"0.1.0","integrity":"sha512-ByUXs82VmoFMQa6c7kgE1yhKDBH9MNhZoMvTnkpU0ORD4KxHyv4/fQGUXOzmiUnfU6+Zsc4H1hncG7GbnaE2ig=="},"om":{"line":"0.9","version":"0.9.0","createApp":"create-mercato-app@0.9.0","preset":"classic"},"harness":{"version":"c349007c2b5b","node":"24.21.0","yarn":"4.17.1","runner":"ubuntu-latest","mode":"realistic","patches":[]},"baseline":{"status":"verified","receipt":"r_20261029_e5f612bd10e0"},"requiresInstalled":[],"steps":[{"name":"scaffold","status":"pass","sec":3,"signature":null,"excerpt":null,"file":null,"line":null},{"name":"install","status":"pass","sec":70,"signature":null,"excerpt":null,"file":null,"line":null},{"name":"add","status":"pass","sec":41,"signature":null,"excerpt":null,"file":null,"line":null},{"name":"generate","status":"pass","sec":27,"signature":null,"excerpt":null,"file":null,"line":null},{"name":"typecheck","status":"fail","sec":123,"signature":"4ddf9bcbda48fdc3d8f8776e6da9d580689c859e","excerpt":"node_modules/@piotrkarwatka/marketing-consents/types/modules/marketing_consents/components/ConsentsTable.tsx(154,13): error TS2321: Excessive stack depth comparing types '{ title: string; titleHeadingLevel: 1; columns: LegacyColumnDef<ConsentRow>[]; data: ConsentRow[]; searchValue: string; searchPlaceholder: string; ... 14 more ...; emptyState: Element; }' and 'IntrinsicAttributes & DataTableProps<ConsentRow>'.\nnode_modules/@piotrkarwatka/marketing-consents/types/modules/marketing_consents/components/ConsentsTable.tsx(154,89): error TS2322: Type 'LegacyColumnDef<ConsentRow>[]' is not assignable to type 'LegacyColumnDef<ConsentRow, any>[]'.\n  Type 'LegacyColumnDef<ConsentRow>' is not assignable to type 'LegacyColumnDef<ConsentRow, any>'.\n    Type 'ColumnDefBase_Core<LegacyFeatures, ConsentRow, unknown> & ColumnDef_CellSelection & ColumnDef_CellSpanning<LegacyFeatures, ConsentRow, unknown> & ... 9 more ... & StringHeaderIdentifier' is not assignable to type 'LegacyColumnDef<ConsentRow, any>'.\n      Type 'ColumnDefBase_Core<LegacyFeatures, ConsentRow, unknown> & ColumnDef_CellSelection & ColumnDef_CellSpanning<LegacyFeatures, ConsentRow, unknown> & ... 9 more ... & StringHeaderIdentif","file":"node_modules/@piotrkarwatka/marketing-consents/types/modules/marketing_consents/components/ConsentsTable.tsx","line":154},{"name":"initialize","status":"pass","sec":47,"signature":null,"excerpt":null,"file":null,"line":null},{"name":"build","status":"fail","sec":235,"signature":"e5cd126a3d06cbec37abad2be348dcff0b222442","excerpt":"node_modules/@piotrkarwatka/marketing-consents/types/modules/marketing_consents/components/ConsentsTable.tsx(154,13): error TS2321: Excessive stack depth comparing types '{ title: string; titleHeadingLevel: 1; columns: LegacyColumnDef<ConsentRow>[]; data: ConsentRow[]; searchValue: string; searchPlaceholder: string; ... 14 more ...; emptyState: Element; }' and 'IntrinsicAttributes & DataTableProps<ConsentRow>'.\nnode_modules/@piotrkarwatka/marketing-consents/types/modules/marketing_consents/components/ConsentsTable.tsx(154,89): error TS2322: Type 'LegacyColumnDef<ConsentRow>[]' is not assignable to type 'LegacyColumnDef<ConsentRow, any>[]'.\n  Type 'LegacyColumnDef<ConsentRow>' is not assignable to type 'LegacyColumnDef<ConsentRow, any>'.\n    Type 'ColumnDefBase_Core<LegacyFeatures, ConsentRow, unknown> & ColumnDef_CellSelection & ColumnDef_CellSpanning<LegacyFeatures, ConsentRow, unknown> & ... 9 more ... & StringHeaderIdentifier' is not assignable to type 'LegacyColumnDef<ConsentRow, any>'.\n      Type 'ColumnDefBase_Core<LegacyFeatures, ConsentRow, unknown> & ColumnDef_CellSelection & ColumnDef_CellSpanning<LegacyFeatures, ConsentRow, unknown> & ... 9 more ... & StringHeaderIdentif","file":"node_modules/@piotrkarwatka/marketing-consents/types/modules/marketing_consents/components/ConsentsTable.tsx","line":154},{"name":"start","status":"skipped","sec":null,"signature":null,"excerpt":null,"file":null,"line":null},{"name":"smoke","status":"skipped","sec":null,"signature":null,"excerpt":null,"file":null,"line":null}],"result":{"status":"broken","failedStep":"typecheck","alsoFailed":["build"],"classification":"module-fail","quarantineUntil":null},"transition":{"from":null,"to":"broken","confirmed":true},"run":{"id":40842502780,"attempt":2,"url":"https://github.com/open-mercato/modules/actions/runs/40846683223/job/123356065711","at":"2026-10-29T09:03:43Z","durationSec":613},"attestation":null}],"rules":[{"id":"LST-1","pass":true,"detail":"Descriptor is valid."},{"id":"LST-2","pass":true,"detail":"Stable version exists and is not deprecated."},{"id":"LST-3","pass":true,"detail":"src/modules and dist/modules pair found."},{"id":"LST-4","pass":true,"detail":"License: UNLICENSED."},{"id":"LST-5","pass":true,"detail":"No known malware or open critical advisory."},{"id":"LST-6","pass":true,"detail":"Name reviewed at merge."},{"id":"VER-1","pass":false,"detail":"Broken at typecheck on 0.9 since 29 Oct."},{"id":"VER-2","pass":true,"detail":"Fits statically on 0.9: ok."},{"id":"VER-3","pass":true,"detail":"Supply chain: ok."},{"id":"VER-4","pass":true,"detail":"No lint errors."},{"id":"VER-5","pass":true,"detail":"Tarball repository.url matches the descriptor."}],"hostDuplicates":[{"name":"@tanstack/react-query","moduleRange":"5.104.1","appVersion":"5.104.5","lines":["0.8","0.9","next"],"om":["0.8.0","0.9.0","0.10.1-develop.7701.1.87b1ad4224"],"message":"Bundles @tanstack/react-query 5.104.1 while a new app on 0.8, 0.9 and next ships 5.104.5. Two copies break types. Move it to peerDependencies."},{"name":"@tanstack/react-table","moduleRange":"9.2.6","appVersion":"9.3.1","lines":["0.8","0.9","next"],"om":["0.8.0","0.9.0","0.10.1-develop.7701.1.87b1ad4224"],"message":"Bundles @tanstack/react-table 9.2.6 while a new app on 0.8, 0.9 and next ships 9.3.1. Two copies break types. Move it to peerDependencies."}],"maintainers":["piotrkarwatka"]}
