Files
agentic-dev/packages/core-consent/src/in-memory-consent.ts
Danijel Martinek 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

52 lines
1.4 KiB
TypeScript

import type { IConsent } from "./consent.interface";
import type {
ConsentCategory,
ConsentGrantMeta,
UserConsentState,
} from "./consent-types";
/**
* Volatile in-memory IConsent. State is lost on process restart.
*
* Used in dev-seed and test-isolation contexts where Payload is unavailable.
* Not a recording double — use RecordingConsent from @repo/core-testing for
* call-assertion in unit tests.
*/
export class InMemoryConsent implements IConsent {
private state = new Map<ConsentCategory, UserConsentState>();
isGranted(category: ConsentCategory): boolean {
return this.state.get(category)?.state === "granted";
}
async grant(
category: ConsentCategory,
meta?: ConsentGrantMeta,
): Promise<void> {
const existing = this.state.get(category);
this.state.set(category, {
category,
state: "granted",
grantedAt: new Date(),
withdrawnAt: existing?.withdrawnAt,
bannerVersion: meta?.bannerVersion,
policyVersion: meta?.policyVersion,
method: meta?.method,
});
}
async withdraw(category: ConsentCategory): Promise<void> {
const existing = this.state.get(category);
this.state.set(category, {
...existing,
category,
state: "denied",
withdrawnAt: new Date(),
});
}
getCategories(): UserConsentState[] {
return Array.from(this.state.values());
}
}