Files
iios/packages/iios-service/src/calendar/calendar-consent.ts
T
maaz519 55acc3c187 feat(p8): consent gate → transcript → summary → action items (KG-14/Scenario 6)
Task 8.3: checkMeetingConsent requires unanimous attendee GRANTED consent + CMP
non-DENY before any recording artifact. generateTranscript → BLOCKED (no segments)
unless the gate passes, else READY + speaker segments. summarize re-checks consent
live (revoke blocks re-summary), reuses P7 AiJobService over a synthetic transcript
interaction → IiosMeetingSummary(aiArtifactId) + action items + per-attendee
MEETING_FOLLOWUP inbox items, excluding visibility=NONE. 6 tests cover the spine.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 17:57:36 +05:30

31 lines
1.2 KiB
TypeScript

import type { IiosPlatformPorts } from '@insignia/iios-contracts';
import type { IiosMeetingParticipant } from '@prisma/client';
export interface ConsentVerdict {
allowed: boolean;
reason?: string;
receiptRef?: string;
}
/**
* The P8 safety spine (Critics KG-14 / Scenario 6). A recording artifact
* (transcript / summary / action items) may exist ONLY when **every** participant
* has GRANTED recording consent AND the CMP purpose check does not DENY. Anything
* else fails closed. This is deliberately unanimous: one non-consenting attendee
* blocks the whole recording.
*/
export async function checkMeetingConsent(
ports: IiosPlatformPorts,
meetingId: string,
participants: Pick<IiosMeetingParticipant, 'recordingConsent'>[],
): Promise<ConsentVerdict> {
const cmp = await ports.cmp.checkPurpose({ purpose: 'meeting_recording', meetingId });
if (cmp.status === 'DENY') return { allowed: false, reason: 'CMP_DENIED' };
const nonConsenting = participants.filter((p) => p.recordingConsent !== 'GRANTED');
if (nonConsenting.length > 0) {
return { allowed: false, reason: 'ATTENDEE_CONSENT_MISSING' };
}
return { allowed: true, receiptRef: cmp.receiptRef };
}