8 Commits

Author SHA1 Message Date
9b6deac954 feat(core-consent): add ConsentProvider + useConsent() React subpath
Adds the ./react subpath to @repo/core-consent following the same
pattern as @repo/core-analytics/react:

- ConsentProvider wraps IConsent in React context
- useConsent() returns the injected IConsent or throws ConsentContextError
- RTL tests cover context propagation, grant/withdraw delegation,
  isGranted state reflection, getCategories, and missing-provider error
- package.json: ./react export + React optional peerDep + RTL devDeps
- tsconfig: extend react-library.json, include .tsx
- vitest.config: jsdom environment for .test.tsx + jsdom setup

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 19:19:47 +00:00
94303f7e89 fix(core-consent): remove unused ConsentRouter import from router test
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 13:23:20 +00:00
e53f35a0c5 feat(core-consent): add handlers and consentRouter tRPC router
Protocol-agnostic handlers (grant, withdraw, isGranted, getCategories)
in core-consent/handlers/ call IConsent methods and return typed results.

consentRouter uses a consent-specific tRPC context (userId + consentFactory)
so each procedure can resolve the per-user IConsent instance at call time.
Auth middleware guards all four procedures and maps UnauthenticatedError →
UNAUTHORIZED via defineErrorMiddleware from core-shared (no local duplicate).

76 tests passing; new handler and router code at 100% branch coverage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 13:22:33 +00:00
b24f0666eb feat(core-consent): add extractAnonymousConsent and migrateAnonymousConsent helpers
Migration helpers let the auth signUp flow transfer anonymous cookie consent
to an authenticated user's record. extractAnonymousConsent parses the raw
Cookie header; migrateAnonymousConsent calls IConsent.grant with
method: "signup-migration" for each granted category, making the migration
traceable in the audit log. No-op when the consent cookie is absent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 12:59:53 +00:00
500a163e90 test(core-consent): add missing test coverage and fix diff allowlist
Add symbols.test.ts to cover CONSENT_SYMBOLS constant.
Add recording-consent.test.ts to core-testing (follows the pattern
of all other recording doubles which each have a sibling test file).
Refactor payload-consent.test.ts to extract a makeConsent() helper,
reducing clone groups from 7 to 2.
Add new test to cover grantedAt=null branch in deserializeEntry (withdraw
before any grant → persisted as null → loaded as undefined).
Extend coverage/diff.mjs allowlist for packages/core-testing/ since that
tooling package does not install @vitest/coverage-v8 and therefore produces
no lcov data.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 12:48:50 +00:00
7dd46b68b2 feat(core-consent): add PayloadConsent, RecordingConsent and DI binders
Implements the Payload-backed IConsent that reads/writes users.consentState
and emits CONSENT_GRANT/CONSENT_WITHDRAW audit entries via injected auditLog.
Adds RecordingConsent test double in core-testing for unit-test injection.
Adds bindProductionConsent/bindDevSeedConsent DI binders and InMemoryConsent
for dev/seed contexts. Contract tests cover grant/withdraw/isGranted round-trip,
audit entry shape, metadata persistence (bannerVersion/policyVersion/method),
and getCategories reflection of state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 12:39:31 +00:00
b992fee088 feat(core-consent): extend generator with consent template + fix withCapture brand propagation
- Add consent to CORE_PACKAGE_GENERATORS in turbo/generators/config.ts so
  pnpm turbo gen core-package consent is a valid command (not hand-rollable)
- Create turbo/generators/templates/core-package/consent/ mirroring the
  analytics template shape (AGENTS.md, package.json, tsconfig, turbo, vitest,
  eslint, src/index.ts scaffolds)
- Regenerate packages/core-consent/ from the new template (replaces the
  previous hand-rolled attempt that violated the generator-first rule)
- Add __consentChecked to withCapture PROPAGATED_BRANDS so the brand bubbles
  through the full withSpan→withCapture wrapper chain to the outermost binding
  that assertFeatureConformance reads

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 11:01:17 +00:00
9cb2fa321c feat(core-consent): scaffold package with types, IConsent, withConsent brand wrapper
- Add packages/core-consent with ConsentCategory, ConsentState,
  UserConsentState types and IConsent interface
- Add withConsent wrapper attaching __consentChecked brand at bind time;
  unit tests assert brand attachment and factory passthrough
- Add ConsentChecked<F> type to core-shared/conformance/brands.ts and
  isConsentChecked helper to brand-runtime.ts
- Extend FeatureManifest with requiresConsent?: readonly string[] field
- Extend assertFeatureConformance to require __consentChecked brand when
  requiresConsent.length > 0; synthetic fixture tests cover pass/fail cases
- Propagate __consentChecked in withSpan PROPAGATED_BRANDS so the outermost
  binding carries the brand

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 10:40:40 +00:00