legal-privacy.mdprofile-data.mdprofile-memory.mdprofile-safety.mdprofile.mdoperator-admin.mdJourney flow#
Generated from the authored steps below — click a node to jump to that section.
This journey joins two shipped customer surfaces and the operator review path.
/profile/memory manages Iris memory, produces a downloadable local bundle, and
records a BFF export receipt when Iris is available. The data-rights surface at
/profile?path=data-rights and its read-only /profile/data summary create and
display BFF-backed export and deletion requests. The wider six-domain tombstone
fan-out remains only partially implemented. The walk therefore distinguishes a
local memory clear, a scoped data-rights deletion, and the still-open
cross-service erasure promise instead of treating them as one event.
Personas#
- Signed-in memory customer exporting, pausing, or clearing Iris memory at
/profile/memory - Signed-in data-rights customer creating a scoped export or deletion from
/profile?path=data-rightsand reviewing it at/profile/data - DSAR operator in
/operator/admintriaging the case and attaching per-tombstone attestation - Legal operator taking the
dsar-fulfillmentadmin-inspection role for sensitive-category reads required during fulfillment - Out-of-band data subject — a target persona for email-link or operator-signoff verification; no anonymous browser flow ships today
Pre-conditions#
- Customer is signed in for the shipped browser flows; admin review requires an admin-scoped bearer
- Iris adapter routes (
/v1/iris/adapter/review,/pause,/export) and the data-rights routes (/v1/data-rights/exports,/deletions) are reachable - The canonical
IrisDataRightsRequeststate machine exists inlibs/oshun/memory-iris/src/data-rights.ts, but the current BFF export and deletion stores do not yet persist that contract end to end
Steps#
1. Customer arrives at the privacy controls#
- Customer signs in, opens
/profile, follows the Memory row to/profile/memory - Verify:
customer/09-account/profile.mdsurface resolver + sub-route nav - Verify:
customer/09-account/profile-memory.mdpopulated state, scope/category chips, export + forget affordances
2. Submit a DSAR export request#
- Customer clicks "Export JSON" (
data-profile-memory-export=""); optional DSAR case id viadata-profile-memory-dsar-input=""flips the button to "Sign DSAR bundle" -
exportIrisUserMemoryBundlereturns{ json, fileName }; notice reads "DSAR exportsigned and ready to download." (or generic export) - When the Iris adapter is hydrated, the same action POSTs
/v1/iris/adapter/export?role=settingsand renders a synced server receipt; if that call fails, the downloadable local bundle remains available with an honestunavailablereceipt state - On
/profile?path=data-rights, a scoped export POSTs/v1/data-rights/exports;/profile/datareads the completed request and its SHA-256 integrity manifest back from the BFF
3. Submit a deletion request#
- On
/profile/memory, the customer opens "Forget everything", types the confirmation phrase, and passesensureStepUp('forget-all') -
requestIrisUserMemoryFullClearreturns{ ok: true, grace }; thedata-profile-memory-grace-banner=""shows the seven-day grace window - This memory-panel grace request is local profile state; cancelling it clears the banner. It is not evidence that the account-wide BFF deletion fan-out ran
- On
/profile?path=data-rights, the customer can separately POST a scoped deletion to/v1/data-rights/deletions, choosing grace-period or immediate mode;/profile/datareads the scheduled/completed request and any supported erasure attestations back
4. Authentication and verification boundary#
- Shipped customer data-rights routes require the signed-in bearer; missing authentication returns 401
- Per-fact / per-category forgets on
/profile/memoryuse theSTEP_UP_CHALLENGEphrase viaissueIrisUserMemoryStepUpToken— no email round-trip - The canonical
session-token,email-link, andoperator-signofftransitions exist indata-rights.ts, but an email-link browser round-trip is not wired into the current data-rights route
5. Cross-service fan-out — partially shipped#
Per V1/ARCHITECTURE.md § Privacy, Consent, Residency, DSAR.
- The BFF fan-out and signed-receipt path is implemented for the
voice_profileconsumer and for subject-owned Isisgenerated_artifactrows - Tara, Arete, Veritas, Nyx, Nisaba, and Metis do not yet expose a proven six-service erasure fan-out from this browser journey
- The canonical
verified → in-progress → completedtransition sequence is modeled indata-rights.tsbut is not the persisted record used by every current data-rights endpoint
6. Attestation per supported erasure consumer#
- Immediate voice-profile and generated-artifact deletions return signed per-consumer receipts with status, row count, audit key id, and signature
- The broader
@oshun/audit-platformattestation fan-out and a single scope-complete gate across every domain remain open
7. DSAR receipt back to user#
- Export requests expose a real SHA-256 integrity manifest; supported immediate deletions expose signed erasure receipts
- Verify:
operator/operator-admin.mdinbox detail card reflects the closed DSAR case with attestation bundle -
/profile/dataand the profile data-rights surface render the BFF request state and supported receipts in-app - Email delivery of the DSAR receipt is not wired in the current harness
8. Read back the affected scope#
- Customer returns to
/profile/dataand sees the completed export or scheduled/completed deletion row from the BFF - A supported immediate generated-artifact deletion proves the seeded Isis row is gone before the signed receipt is persisted
- A local "Forget everything" action can empty
/profile/memory, but that local state is not presented as proof of account-wide erasure - Verify:
customer/09-account/profile-memory.mdlocal empty and grace-window states - Verify:
customer/09-account/profile-safety.mdempty-state copy avoids alarming framing post-deletion - Verify:
customer/00-public/legal-privacy.mddata-retentionsection consistent with what the receipt retained vs purged
Post-conditions#
/profile/memoryalways produces a downloadable bundle; when Iris is reachable it also shows the synced export receipt- BFF export/deletion requests remain readable at
/profile/data; grace-period deletions can be cancelled beforecancelDeadlineAt - Supported immediate erasures persist signed per-consumer receipts, and the generated-artifact path proves the subject-owned row was removed
- No claim is made that the unimplemented six-domain fan-out completed; that remains a release-gate requirement
Failure modes#
- Iris export adapter unavailable —
/profile/memorylabels the receipt unavailable and still offers the local download; it never fabricates a synced receipt - Wrong deletion confirmation token — BFF returns 400; no erasure begins
- Second active deletion — BFF returns 409 rather than creating competing requests
- Unsupported erasure category — the request must not imply that a signed per-consumer receipt exists; the six-domain fan-out remains incomplete
- Verification window elapses — the canonical state machine supports an
expiredterminal state, but this email/operator verification path is not yet wired into the shipped browser flow - Silent re-creation from old conversations — treat any reappearance after a supported hard-delete receipt as P0; the broader cross-service guarantee is not yet proven
- Full memory clear cancelled within grace —
cancelIrisUserMemoryFullClearremoves the local grace request; BFF data-rights cancellation is a separate endpoint and state transition
E2E coverage#
- Backed by
apps/oshun/web/e2e/profile-customer-data-deletion.spec.ts,apps/oshun/web/e2e/profile-data-rights.spec.ts,apps/oshun/web/e2e/profile-customer-data-export.spec.ts,apps/oshun/web/e2e/profile-data-readback.spec.ts— the deletion spec asserts the UI controls (scope/mode/token selectors), schedules an account deletion through the confirmation modal, cancels it via the active banner, and (2026-06-23) drives the real signed-receipt UI path: Playwright boots the BFF with Redis-backed deletion fan-out, the browser submits an immediatevoicecategory deletion, the BFF runs thevoice_profileconsumer and attaches a dev-key Ed25519 receipt, and the profile UI renders the resultingdata-profile-deletion-attestation="voice_profile"row from the live BFF response (status=not_found, zero rows, audit key id, truncated signature). (2026-06-26) The same browser surface now seeds a subject-owned Isisgenerated_outputsrow, submits an immediategenerated_artifactsdeletion, renders the live signedgenerated_artifactreceipt (status=erased,rowsRemoved=1, audit key id, truncated signature), and verifies the Isis row is hard-deleted. The older page-boundary snapshot case remains only as a negative render guard: an attested tombstone renders a row and an unattested tombstone renders none. The data-rights spec exercises scoped export, deletion scheduling, cancellation within the grace window (the button reverts and a "Deletion request cancelled" toast fires), and the immediate-mode path (switch to immediate erasure → confirm → "Account deletion completed"); the export spec validates the full category/format list, a submitted export appearing in history as completed, and rejection when no category is selected. The readback spec (2026-06-24) verifies the standalone/profile/datapage against the same real BFF contracts: authenticated empty export/deletion states,/profile?path=data-rightshandoff, and server-rendered completed export + scheduled deletion rows seeded by live POSTs. (2026-06-27) It also warms/profile/dataunder the real Chromium service worker, verifies the route document is cached after online live-BFF render, switches the browser offline, reloads/profile/datafrom the SW cache, and asserts the completed export + scheduled deletion rows remain visible whilenavigator.onLineis false and without falling back to the generic offline shell card. - Backed by
apps/oshun/web/e2e/data-rights-dsar-bff.spec.ts— real HTTP integration against the live BFF store-backed privacy core (steps 2, 3, 7): customer export (POST/GET /v1/data-rights/exports→ 201completedwith a real sha256integrityManifestsurfaced back in the snapshot; malformed/empty-category bodies → 400; anonymous → 401); customer deletion (POST/GET /v1/data-rights/deletions→ grace-period requestscheduledwith acancelDeadlineAtand materialised tombstones that persist onGET-by-id; immediatevoicecategory deletion over Redis fan-out →completedwith a signedvoice_profiletombstone attestation persisted onGET-by-id; (2026-06-25) immediategenerated_artifactscategory deletion seeds a real Isisgenerated_outputsrow for the subject, runs the live Redis-backedgenerated_artifacteraser, returns a signederasedattestation withrowsRemoved=1, persists that receipt onGET-by-id, and verifies the Isis row is hard-deleted; wrongconfirmationToken→ 400; a second active deletion → 409; anonymous → 401); the admin DSAR review lifecycle (POST /v1/admin/privacy/requests/:id/review-actiondriving generate_export_package → record_export_download → complete with specific state transitions, generate refused on a terminal request → 409 and on a delete-type request → 409); and a consent-review → privacy audit-log round-trip (/admin/privacy/consent-records/:id/reviewthen/admin/privacy/audit-log). Admin 403 (admin_scope_missing) is asserted for a non-admin caller. apps/oshun/web/e2e/account-deletion-dsar.spec.ts— the memory-surface counterpart to the profile-dashboard specs above: drives the grace-window banner on/profile/memory(a grace-period deletion request renders the banner; cancel clears it — round-trip) and the DSAR-mode case-id input on the memory export panel (step 2).- Coverage depth: deep — see
coverage.md. The export/deletion/DSAR lifecycle is driven over the real store-backed BFF: scoped export → 201completedwith a real sha256integrityManifest; grace-period deletion →scheduled+cancelDeadlineAt+ materialised tombstones that persist onGET-by-id; immediate voice-profile deletion runs through the real Redis fan-out and persists a signed receipt; immediate generated-artifact deletion uses the real Isisgenerated_outputstable in both the BFF API leg and the browser/profile?path=data-rightsleg, proving the subject-owned row is removed before persisting/rendering the signed receipt; the admin DSAR review state machine (generate_export_package → record_export_download → complete, with409refusals on terminal/delete-type requests); and the signed per-service erasure-receipt rows render from live BFF data. State transitions + post-conditions + multiple failure modes (wrongconfirmationToken→ 400, second active deletion → 409, anonymous → 401, admin scope-missing → 403, grace-window cancel round-trip) are all asserted, so the journey clears the deep bar. The remaining gaps are cross-service or identity-verification product gaps, not missing assertions over shipped browser/BFF behavior. - Uncovered:
- Steps 5–6, the literal per-domain six-service tombstone fan-out is only
partially driven. The BFF-owned Redis fan-out and signed receipt are now
covered for
voice_profileand the local Isisgenerated_artifactstore, but Tara/Arete/Veritas/Nyx/Nisaba/Metis service-specific erasure plus@oshun/audit-platformattestation remains open. - Step 4 identity verification via the
email-linkround-trip is not driven (no real mailer in the harness; the BFF data-rights flow auto-completes without an email hop). - The customer-facing
/profile/memoryexport + forget UI is not driven by this spec (it is a pure-BFF integration test); that web surface is covered bymemory-edit-pause-forget.md. - Failure modes around domain RPC failure mid fan-out and tombstone propagation drift remain uncovered (same fan-out gap as above).
- Steps 5–6, the literal per-domain six-service tombstone fan-out is only
partially driven. The BFF-owned Redis fan-out and signed receipt are now
covered for
Per-view files touched#
customer/09-account/profile.mdcustomer/09-account/profile-data.mdcustomer/09-account/profile-memory.mdcustomer/09-account/profile-safety.mdcustomer/00-public/legal-privacy.mdoperator/operator-admin.md
Cross-references#
V1/features.md§ User-Facing Memory Controls; § Customer memory UX flows; § Admin inspection state machine; § Customer-Facing Privacy Surface; § Admin DSAR and Operator-Access WorkflowV1/ARCHITECTURE.md§ Privacy, Consent, Residency, DSAR (the DSAR / deletion sequence mermaid is canonical)libs/oshun/memory-iris/src/data-rights.ts—IrisDataRightsRequest,ALLOWED_TRANSITIONS, default verify/deadline windowslibs/oshun/memory-iris/src/admin-inspection/state-machine.ts— onlydsar-fulfillmentmay transition fromrequestedfor the legal role- Sibling journeys:
memory-edit-pause-forget.md,incident-triage.md
Open questions / known gaps#
- Unify the BFF export/deletion records with the canonical
IrisDataRightsRequeststate machine, or document why they remain separate contracts - Wire and test the
email-link/operator-signoffverification paths for an out-of-band requester - Decide the email template id for the DSAR receipt and link it from
customer/13-system/system-emails.md - Confirm
/profile/safetytombstones along with the rest or runs a tighter retention thanMemoryEntry - Define telemetry event names:
dsar_export_built,dsar_export_signed,dsar_delete_requested,dsar_grace_cancelled(none exist today inapps/oshun/web/src/analytics/) - Specify the per-tombstone attestation export format (CSV vs signed JSON bundle); needs an operator-runbook entry