feat(iios): retention_policy_snapshot + sweep (archive→redact, hold-aware) (P9)
Adds IiosRetentionPolicySnapshot (per-interaction frozen lifecycle timestamps) + IiosInteraction.dataClass, and a RetentionService whose sweep captures snapshots then archives (status change) and, past delete_after, redacts content in place (reusing the Slice-8 tombstone) — never a hard delete. An active compliance hold blocks both; every action is audited and tenant-scopeable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "IiosInteraction" ADD COLUMN "dataClass" TEXT NOT NULL DEFAULT 'internal';
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "IiosRetentionPolicySnapshot" (
|
||||
"id" TEXT NOT NULL,
|
||||
"policyKey" TEXT NOT NULL,
|
||||
"scopeSnapshotId" TEXT NOT NULL,
|
||||
"targetType" TEXT NOT NULL,
|
||||
"targetId" TEXT NOT NULL,
|
||||
"dataClass" TEXT NOT NULL,
|
||||
"retainUntil" TIMESTAMP(3),
|
||||
"archiveAfter" TIMESTAMP(3) NOT NULL,
|
||||
"deleteAfter" TIMESTAMP(3) NOT NULL,
|
||||
"sourceVersion" TEXT NOT NULL DEFAULT 'v1',
|
||||
"status" TEXT NOT NULL DEFAULT 'ACTIVE',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "IiosRetentionPolicySnapshot_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "IiosRetentionPolicySnapshot_status_deleteAfter_idx" ON "IiosRetentionPolicySnapshot"("status", "deleteAfter");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "IiosRetentionPolicySnapshot_scopeSnapshotId_status_idx" ON "IiosRetentionPolicySnapshot"("scopeSnapshotId", "status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "IiosRetentionPolicySnapshot_targetType_targetId_key" ON "IiosRetentionPolicySnapshot"("targetType", "targetId");
|
||||
@@ -435,6 +435,7 @@ model IiosInteraction {
|
||||
occurredAt DateTime @default(now())
|
||||
receivedAt DateTime @default(now())
|
||||
status IiosDeliveryState @default(RECEIVED)
|
||||
dataClass String @default("internal") // envelope data class; drives retention window (P9)
|
||||
policyDecisionRef String?
|
||||
consentReceiptRef String?
|
||||
crreBundleRef String?
|
||||
@@ -493,6 +494,27 @@ model IiosProcessedEvent {
|
||||
@@id([consumerName, eventId])
|
||||
}
|
||||
|
||||
/// Per-resource retention snapshot (P9). Absolute lifecycle timestamps frozen from the
|
||||
/// resource's age + policy window; read by the retention sweep. delete = redact-in-place.
|
||||
model IiosRetentionPolicySnapshot {
|
||||
id String @id @default(cuid())
|
||||
policyKey String
|
||||
scopeSnapshotId String
|
||||
targetType String // 'interaction'
|
||||
targetId String
|
||||
dataClass String
|
||||
retainUntil DateTime?
|
||||
archiveAfter DateTime
|
||||
deleteAfter DateTime
|
||||
sourceVersion String @default("v1")
|
||||
status String @default("ACTIVE") // ACTIVE | ARCHIVED | REDACTED
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@unique([targetType, targetId])
|
||||
@@index([status, deleteAfter])
|
||||
@@index([scopeSnapshotId, status])
|
||||
}
|
||||
|
||||
/// Legal/compliance hold (P9 DSR). An ACTIVE, unexpired hold over a target BLOCKS
|
||||
/// erasure/retention deletion until an authorised release. Never auto-released.
|
||||
model IiosComplianceHold {
|
||||
|
||||
Reference in New Issue
Block a user