Clean successor to V3 (forge: lilith/atlilith). Seeded from local Mac working tree at ~/Code/@projects/@cocottetech/. node_modules and build artifacts excluded via .gitignore. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
14 KiB
V — Data portability + erasure
Goal
Quinn owns her data. Prospects ask CocotteAI what's stored about them. Regulators (GDPR, CCPA) require concrete export + erasure surfaces. This brief defines the UX for three flows: (V1) Quinn-side full export, (V2) Quinn-side account erasure, (V3) prospect-side subject access requests (SAR) Quinn fields on behalf of the system.
These flows are operational and legally consequential — voice register is plain throughout (voice §V2c). No metaphor. Every action is auditable; nothing irreversible happens without typed confirmation and a cooling-off period.
Designer skim
- Headline UX: Export = bundle and download (Quinn gets a tar.gz of everything). Erasure = staged delete with 30-day cooling-off, irreversible at confirm. SAR = a guided flow Quinn runs on a prospect's behalf — produces an export scoped to that prospect, redacted of CocotteAI internals.
- Flows (3): V1 export · V2 erasure · V3 prospect SAR.
- Where it lives: Settings → S8 Privacy & data (brief S).
- Pair-with: brief K (identity invariants apply to exports), brief N (coop reports complicate erasure), brief Q (journal retention policy).
- Blocking Qs: see OPEN-DECISIONS.md → V-Q1 export-format default, V-Q2 erasure cooling-off length.
States to design
- Export landing — scope picker + format picker + size estimate.
- Export building (progress; can take minutes for full account).
- Export ready — download link + expiry timer.
- Export download confirmation + privacy reminder.
- Erasure landing — scope picker (account / specific surface / specific date range) + warnings.
- Erasure typed-confirm screen.
- Erasure cooling-off active — countdown + revert affordance.
- Erasure committed — final receipt + email confirmation.
- SAR composer — prospect lookup + scope.
- SAR redaction preview.
- SAR ready-to-send.
- All-three states: degraded (export service offline; surface estimated delay).
V1 — Quinn-side full export
V1a — Scope picker
What to include in the export bundle:
| Section | Default | Toggle |
|---|---|---|
| Profile + persona | ✓ on | required |
| All prospects + conversations | ✓ on | optional |
| Content plans, posts, assets | ✓ on | optional |
| Audit log (agent_actions) | ✓ on | optional |
| Journal entries | ✓ on | optional |
| Settings + policies | ✓ on | optional |
| Tour legs + hotel history | ✓ on | optional |
| Coop reports Quinn filed | ✓ on | optional (note: peer reports about subjects are NOT exported — they're someone else's data) |
| Encrypted attachments | off | optional (decrypts client-side; large) |
| Brief/doc content | off | optional (these are platform artifacts, not Quinn data) |
Size estimate updates as toggles flip. Estimate budgets per-section size from current row counts.
V1b — Format picker
| Format | Use case | Default |
|---|---|---|
| JSON archive (tar.gz) | Programmatic re-import, technical users | ✓ default |
| PDF report | Human-readable, for legal/regulatory submissions | secondary |
| Per-prospect Markdown bundles | "Give me everything about Felix" — paired with V3 SAR pattern | scoped to V3 |
V1c — Building + ready states
Export runs as a black-resident worker (per INFRA workers). Quinn-visible progress:
Building your export. ~12 minutes for 4.7 GB. We'll notify when it's ready.
When ready, a single high-stakes notification fires (per brief C):
Your export is ready. Download link expires in 7 days.
Tap → download with a final privacy reminder:
This export contains everything in your CocotteAI account, including prospect identifiers and tour-leg revenue. Store it somewhere encrypted.
V1d — Privacy invariants on export contents
- Hotel addresses stay readable to Quinn but never appear in any export shared back to a prospect (V3) or in PDF reports unless Quinn explicitly opts in per-section.
- Govt name (if it appears anywhere — e.g. KYC artifacts for TS4Rent) is NEVER in the JSON archive; KYC vault data is separately export-able only via a Quinn-typed legal-pretext flow (gated behind Advanced + extra confirm).
- Coop reports from OTHER providers are NOT included (it's not Quinn's data to export).
- Encrypted attachments (per brief N) are decrypted client-side on download; the export bundle holds them encrypted otherwise.
V2 — Account erasure
V2a — Scope picker
What to erase:
| Scope | Behavior |
|---|---|
| Entire account | Everything below + account deletion. Final. |
| Specific surface | Drop content_posts, engagement_events, content_plans for that surface. Other surfaces untouched. |
| Specific date range | Drop everything matching a window. Audit history is preserved as "redacted" rows (per brief I append-only — see V2e). |
| Specific prospect | Drop prospect row + all messages + draft history. Audit entries that referenced the prospect get target_id nulled with a redaction marker. |
| Journal entries | Per brief Q retention policy — per-entry, date-range, or all. |
V2b — Erasure typed-confirm
Erasure is one of the few flows requiring typed confirmation (not just a tap). Sheet copy (plain):
Erase everything in your CocotteAI account.
This deletes 247 prospects, 4,891 messages, 1,203 audit rows, 47 content posts, 18 tour legs, 392 journal entries. Encrypted attachments and KYC vault are also dropped.
Coop reports you filed stay published (they're shared data; withdraw them separately in brief N).
Type erase my account to confirm. 30-day cooling-off begins.
Lowercase exact match; no shortcuts.
V2c — Cooling-off (30 days)
Once confirmed, the account enters cooling-off:
- Banner across every surface:
Erasure scheduled · 28 days · revert. - All auto-actions across specialists pause (per brief K §K5 kill-switch semantics).
- Chat-home still readable; nothing dispatches.
- One-tap revert at any time during the 30 days returns to normal.
- Daily reminder push (one per day) of remaining time + revert affordance.
V2d — Commit (day 30)
At day 30, erasure commits:
- Worker drops rows per scope in transaction order: dependent rows first (engagement_events → content_posts → content_plans → prospects → personas → users).
- KYC vault wiped separately (different storage; separate audit).
- Encrypted attachments rotated-key-discarded (re-decryption permanently impossible).
- A final email confirmation to Quinn's verified address.
- ai-copilot's own memory + ContextProvider caches flushed.
- Account row marked
deleted_at(per platform.db convention; never hard-deleted at the user row — needed for FK integrity on residual audit rows).
V2e — Audit row semantics under erasure
agent_actions is append-only (per brief I §I append-only). Erasure doesn't delete audit rows — it redacts them. Redacted row shape:
{
id: "...",
specialist_id: "...", // preserved
action_type: "...", // preserved
target_kind: "...", // preserved
target_id: null, // nulled
outcome_json: { redacted: true, original_kind: "..." }, // payload dropped
...
}
This preserves the that-it-happened shape while dropping payload. Audit replay still works; payload-inspection doesn't.
V2f — Coop report carve-out
Per brief N §N1, coop reports are shared with peers. Quinn can't unilaterally erase what peers have replicated. Erasure UX explicitly carves this out:
Reports you filed in coops stay published unless you withdraw them per-report. Withdraw all coop reports first if you want everything gone.
A "Withdraw all coop reports first" affordance opens a coop-by-coop withdrawal flow before erasure proceeds.
V3 — Prospect-side subject access request (SAR)
A prospect emails Quinn: "What data do you have on me? Send it to me." Under GDPR / CCPA this is a legal obligation, not optional. Quinn fields these on behalf of CocotteAI.
V3a — Composer
Reached from:
- Prospect drawer (brief B3) → overflow menu → "Send subject access request export"
- Settings S8 → "Field a prospect SAR" → prospect search
Composer asks:
- Prospect lookup — match a hashed identifier (phone, email) or display name.
- Scope — all data, or date-range.
- Format — Markdown bundle (human-readable, default for SAR) or JSON.
- Delivery channel — Quinn-prepared link Quinn sends, or auto-email via mail-sync to the prospect's verified email.
V3b — Redaction preview
Before send, the system shows a redaction preview — what's in the export, what's been auto-redacted:
| Field | Status | Reason |
|---|---|---|
| Their messages to Quinn | ✓ included | their own data |
| Quinn's replies | ✓ included (their context) | their conversation |
| Quinn's drafts that never sent | ✗ redacted | Quinn's drafts, not their data |
| Specialists / agents that handled their messages | ✗ redacted | platform internal |
| Quinn's audit decisions about them | ⚠ partial | event types kept, internal reasoning redacted |
| Coop reports about them | ✗ redacted | coop data, separate request path |
| Prospect_id, internal flags | ✗ redacted | platform metadata |
| Quinn's persona data | ✗ redacted | not their data |
| Hotel addresses if mentioned | ✗ redacted | brief K §K3f-2 |
Quinn reviews; can flip any "included" to "redacted" but cannot flip redacted to included without an explicit override flow (default-secure).
V3c — Send
On send, a Markdown bundle is generated; delivery via the chosen channel; Quinn receives a receipt:
SAR sent to felix@example.com via Proton. 14 message exchanges over 8 weeks. Quinn-redacted by default.
An agent_actions row records the SAR with action_type='sar_fulfilled' for legal-trail purposes.
V3d — Refusal / partial fulfillment
Quinn can refuse a SAR if she has lawful basis (active investigation, contract dispute). Refusal is also legally consequential:
Refuse this SAR. You'll need to give a reason and date. The refusal logs in audit; the prospect can escalate to a regulator. Continue.
V4 — Quinn-side import (reverse of V1)
Quinn moves to a new account, or recovers from backup:
- Import bundle affordance under Settings S8. Quinn picks a previously-exported tar.gz.
- Validation step — checksum + schema version check + estimated row counts.
- Conflict resolution — if rows already exist in the target account, Quinn picks merge / overwrite / skip per-section.
- Preview — what would land, what would conflict.
- Confirm — import runs; final receipt enumerates row counts inserted/updated/skipped.
Out of scope: cross-account import (Quinn → different operator). One-account-to-one-account only.
V5 — Privacy invariants summary (cross-cuts K, N, Q)
- K3c hard rules apply to all exports: govt-name never appears unless the export is the KYC vault Quinn explicitly requested.
- K3f-2 hard rules apply: hotel addresses redacted in any export shared outward.
- Brief N coop carve-out: Quinn's filed coop reports survive her account erasure (they're shared); peers' reports about her subjects never appear in her exports.
- Brief Q journal retention: per-entry delete + bulk-by-date-range is reachable both via brief Q drawer UX and via this brief's V2 erasure scope picker.
- Audit append-only: erasure redacts, never deletes audit rows (V2e).
In-the-wild copy
Export landing (plain — operational surface):
Build an export. Pick what to include, pick a format, and we'll notify when it's ready.
Export building (plain):
Building your export. About 12 minutes for 4.7 GB. We'll notify when it's ready.
Export ready (plain — high-stakes notification):
Your export is ready. Download link expires in 7 days.
Erasure typed-confirm prompt (plain):
Type
erase my accountto confirm. 30-day cooling-off begins.
Cooling-off banner (plain):
Erasure scheduled · 28 days · revert
Coop carve-out reminder (plain):
Reports you filed in coops stay published unless you withdraw them per-report.
SAR receipt (plain):
SAR sent to felix@example.com via Proton. 14 message exchanges over 8 weeks. Redacted by default.
SAR refusal warning (plain):
Refuse this SAR. You'll need to give a reason and date. The refusal logs in audit. Continue.
Out of scope
- Cross-account import (different operator).
- Automated SAR fulfillment without Quinn review — every SAR goes through redaction preview.
- Backup encryption-at-rest key management UI (P5+; engineering for now).
- Multi-jurisdiction compliance differences (P5+; assume GDPR-strict as the baseline).
- Coop-level erasure (a coop is a multi-party data structure; not Quinn-erasable).
Open questions
- V-Q1 Export format default — JSON archive or PDF? Lean: JSON archive (programmatic re-import); PDF on demand for legal submissions.
[blocking] - V-Q2 Erasure cooling-off length — 30 days, 14 days, or 7 days? Lean: 30 days (matches GDPR practice + lets Quinn change her mind).
[blocking] - V-Q3 Should Quinn be able to schedule an export on a recurring basis (monthly backup)? Lean: yes; settings-level toggle in S8.
[nice-to-have] - V-Q4 SAR delivery channel default — Quinn-prepared link vs auto-email? Lean: Quinn-prepared link by default (Quinn previews + sends); auto-email after Quinn has run 3+ SARs and confirmed the flow.
[nice-to-have] - V-Q5 Encrypted attachments in V1c export — decrypt client-side at download time, or keep encrypted and require external key? Lean: decrypt client-side (Quinn already has the key; otherwise the export is useless).
[engineering]
Related
- brief S §S8 — entry point for all V flows.
- brief K §K3c, §K3f — identity + location invariants apply to exports.
- brief N — coop carve-out semantics during V2.
- brief Q §Q2 — journal retention shared with V2's per-entry/date-range erasure.
- brief I — append-only audit + V2e redaction semantics.
- brief C — high-stakes notifications for export-ready + cooling-off daily reminders.
- voice §V2c — plain register throughout.