V1 Web PWA · Walk result

Journey result: Account deletion + DSAR

A dated evidence record for V1 Web PWA: observed behavior, current source reconciliation, automation evidence, and explicit proof limits.

verdict: partial· 2026-06-25
8sections5 minread1table

On this page
  • Walked: 2026-06-25 through the live local BFF, Redis deletion fan-out, migrated Isis store, and customer/admin browser surfaces.
  • Reconciled: 2026-07-17 against the current data-export, data-deletion, consent, Admin DSAR, profile, memory, and Playwright sources. This reconciliation does not widen the services exercised by the recorded walk.
  • Verdict: partial — the shipped customer export/deletion spine, two signed immediate-erasure consumers, cancellation, readback, and Admin DSAR review lifecycle have deep coverage. Identity verification, the literal six-domain erasure fan-out, production signing custody, and the final cross-service audit-platform attestation remain outside the proved result.

Result at a glance#

Lane Proven result Boundary
Scoped customer export Completed export bundle with selected categories, format, bytes, and SHA-256 integrity manifest Local BFF bundle; not an external delivery channel
Grace-period deletion Scheduled request, cancel deadline, materialized tombstones, persisted readback, cancellation No email identity-verification round trip
Immediate voice deletion Redis-backed voice_profile consumer returns and persists a signed receipt Test signer uses the development key path
Immediate generated-artifact deletion Real subject-owned Isis row is removed; signed generated_artifact receipt reports one erased row One local domain store, not all product domains
Admin DSAR review Export package → download record → completion, with terminal/type/scope refusals Separate Admin lifecycle; no customer notification proof
Offline read surface Warmed /profile/data replays the previously rendered rows Read-only cache replay, not offline mutation

Evidence map#

flowchart LR A[Customer data-rights UI] --> B{Request type} B -->|export| C[Scoped export] C --> D[Completed bundle + SHA-256 manifest] B -->|grace deletion| E[Scheduled + cancel deadline] E --> F[Cancel or await execution] B -->|immediate voice| G[Redis voice-profile consumer] B -->|immediate artifacts| H[Isis generated-output eraser] G --> I[Signed persisted receipt] H --> I J[Admin DSAR review] --> K[Generate package] K --> L[Record download] L --> M[Complete request] N[Other product-domain erasers] -. not proved .-> I

Proven observations#

Customer export and readback#

  • POST /v1/data-rights/exports accepts the canonical non-empty category list and format, returns 201 completed, and exposes a real SHA-256 integrityManifest through the snapshot and standalone read page.
  • Malformed bodies, empty categories, and anonymous requests are rejected before an export is created.
  • The profile UI renders the canonical category/format controls, rejects an empty selection, and adds the completed bundle to history.
  • /profile/data reads consent, export, and deletion snapshots in parallel, renders authenticated empty and populated states, and links back to /profile?path=data-rights for mutations.
  • The readback suite pins the current kept-history cap and mobile footer/download tap targets. It does not claim pagination that the product does not expose.

Grace-period deletion#

  • A full-clear request enters scheduled with cancelDeadlineAt and materialized tombstones that persist on get-by-id.
  • The profile and memory surfaces show the active grace banner. Cancellation clears the banner and restores the customer action.
  • Wrong confirmation tokens, a second concurrent active deletion, and anonymous creation are rejected with their specific 400, 409, and 401 contracts.

Immediate erasure receipts#

  • The voice case runs through the real Redis fan-out binding and persists a signed voice_profile receipt. The focused fixture has no seeded voice row, so the honest result is not_found with zero rows—not a fabricated erase.
  • The generated-artifact case migrates the local Isis database, seeds a subject-owned generated_outputs row, invokes the live eraser, receives status=erased and rowsRemoved=1, verifies the row is gone, and reads the same receipt back by deletion id.
  • The browser renders only tombstones with a valid attestation payload; an unattested tombstone does not become a receipt row.

Admin DSAR review#

  • The live Admin route drives the seeded export request through generate_export_package, record_export_download, and complete with explicit stage transitions.
  • Package generation is refused for terminal and delete-type requests, and a non-admin caller receives 403 admin_scope_missing.
  • A separate consent review is visible in the structured privacy audit-log feed; this is evidence of that Admin decision, not proof that every erasure consumer wrote an audit-platform attestation.

Boundaries and gaps#

  • Two consumers, not six domains. The live result proves voice_profile and the local Isis generated_artifact eraser. It does not prove Tara, Arete, Veritas, Nyx, Nisaba, and Metis service-specific deletion in one request.
  • No email-link verification. The local BFF flow accepts the confirmation contract directly; no real mailer or identity-verification return trip is in the harness.
  • Development signing evidence. The suites validate receipt structure, signature, key id, persistence, and UI projection with the dev-key route. They do not prove production HSM/KMS custody, rotation, or verifier availability.
  • No mid-fan-out recovery proof. Domain RPC failure, retry/idempotency after a partial fan-out, receipt reconciliation, and tombstone-propagation drift remain uncovered.
  • Offline is readback only. The service worker replays a warmed server document. It does not enqueue deletion/export requests or synchronize them after reconnect.
  • Notification closure is not shown. Admin completion does not by itself prove customer delivery, download expiry, or a final cross-service audit package.

Re-run evidence#

The current evidence is intentionally split so failures identify the browser, route, persistence, or Admin boundary:

bash
PW_BROWSER_CHANNEL=chrome pnpm exec playwright test \
  -c apps/oshun/web/playwright.config.ts \
  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 \
  apps/oshun/web/e2e/data-rights-dsar-bff.spec.ts \
  apps/oshun/web/e2e/account-deletion-dsar.spec.ts \
  --workers=1

The database/Redis cases create isolated local test state and must remain serial on a resource-constrained host.

Source trail#

Cross-references#

Open questions#

  • Which service owns the authoritative orchestration record when more than one erasure consumer succeeds and another fails?
  • What production key-custody and public-verification contract replaces the development signer used by the focused suites?
  • How are email verification, customer notification, export expiry, and Admin completion joined into one observable request timeline?
  • What retry, idempotency, and reconciliation evidence is required before the six-domain fan-out can be called complete?