coulomb-social/docs/release/client-data-export-review-2026-10-30.md
tegwick f34d46d9f6
Some checks failed
Use-case regression gate / usecase-regressions (push) Failing after 2m27s
Define concrete client offboarding scope and retained data boundaries
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a18e2d-f513-7742-b8e7-12af0b744ff3
2026-10-31 15:56:54 +01:00

6.6 KiB

Client data export and schema inventory

The operator export covers a selected tenant's application records and locally retained content. It addresses the data-export part of the business-app service contract; instance teardown, backup expiry and productive offboarding acceptance remain separate. This source has not been deployed and does not change the sealed storage release proposal.

export_client_dataset produces a private ZIP with a JSON manifest and original content files. It includes members, their local session principals, spaces, membership grants, assigned group/permission definitions and attributable admin history. It includes archived spaces, assets, page aliases and immutable revisions, including revisions of deleted pages. It never follows a body link, fetches remote resources or exports another tenant's files or record values.

Passwords, credential-bearing sessions and transient OIDC state are excluded. The schema inventory lists their storage separately. App-local principals must have unusable passwords; an unexpected usable credential refuses export rather than copying or silently discarding it. Independent backups and process logs stay under operator retention. Exporting data does not delete any of these stores or revoke sessions.

The operational inventory also names the prepared supervisor's private date-operations journals outside CONTENT_ROOT. They can retain original private index bytes, plan and backup metadata. The app cannot read that root store; operator offboarding must account for any retained client bytes and their explicit expiry separately. The supervisor rehearsal creates no production journal.

The inventory derives field names, database columns, types, nullability and relations from the loaded Django models. Every application field has an explicit classification. A new model or unclassified field refuses export until reviewed. The inventory also describes session/admin/configuration tables and the generated authorization join tables. Page bodies, metadata, filenames, attachments, revisions and admin text can contain arbitrary personal data; structured field categories are not a claim that free text has been inspected or anonymized.

Operator use

Run against an independently verified, externally quiesced database/content pair. Prefer the isolated retained restore for inspection. The source assertion below does not establish live admission, a writer fence or snapshot coherence. The SQL read uses a repeatable-read, read-only PostgreSQL transaction; file inventories and hashes before/after archiving detect ordinary content drift. Neither replaces external quiescence.

uv run manage.py export_client_dataset --inventory
uv run manage.py export_client_dataset \
  --tenant '<exact client tenant id>' \
  --quiesced-source \
  --output /private/operator/export/client.zip

The output directory must already exist with private permissions. The command requires an output outside the checkout and content root, refuses symlinks and overwrites, and publishes only after validating the archive's actual member hashes. The archive and staging file use mode 0600. Terminal output contains only counts, archive digest and incomplete-offboarding status; original record values and file paths remain inside the private archive. Hashing streams large files.

Cross-tenant relationships, duplicate storage slugs, unresolved content journals, unattributed content, links/special files and unattributable deleted-object admin history refuse. Resolve their ownership before repeating the export; the command does not repair or delete source data. An external-only content binding refuses. External references on spaces that also have local content remain listed in the manifest for owner reconciliation; their presence does not prove remote content has been captured. Do not call that export complete until those bindings are resolved for the client.

Verification and remaining acceptance

Synthetic tests cover tenant isolation, assigned permissions, local principal and membership records, aliases/assets/deleted-page revisions, session/password exclusion, ambiguous ownership and source refusal, content drift, private outputs, no overwrite and schema drift. The full make check gate includes the required browser journeys.

scripts/rehearse-client-export.py runs the exact source as an explicit overlay on the retained candidate, using the internal isolated recovery network and a read-only content mount. It checks every archive member hash against the selected tenant's source files, verifies all source SQL tables/files remain unchanged and removes the temporary private archive. It reports no original record values. The public proof is client-data-export-rehearsal-2026-10-30.json.

Native result: one User, Member, Space and SpaceMembership, plus all 81 selected local content/revision files, exported with matching archive hashes. There were no external bindings or attributable admin events in this recovered client. All 13 source SQL tables and 82 source files (including the excluded operational writer lock) remained unchanged. The temporary private archive was removed. make check passed all 340 tests with zero skips, including required browsers.

Before §6.2 acceptance, release the reviewed implementation and verify a coherent operator export for the current target; resolve remote/unattributed data; arrange private delivery to the client; define the separately authorized instance teardown, session revocation, process-log disposition and primary/mirror/protected-kit backup expiry. The existing independent-kit no-expiry protection must not be silently overridden. No client offboarding or productive deletion is authorized by this implementation or its tests.

October31 deployed return and offboarding scope

Revision19 has since deployed the reviewed exporter. Its packaged current-point proof verifies85selected local files and four record sets, no selected external bindings and unchanged source data; the temporary ZIP was removed afterward. See identity-export-release-client-export-2026-10-31.json. The earlier source-only and81file statements above retain their original dated scope.

The subsequent native scope check finds a second space outside the accepted export tenant, with an external binding under the deployment default tenant. Zero external bindings in the selected tenant must not be promoted to complete instance attribution. The retained content PVC, five isolated database restores, sessions, root journals and protected backup holds also need explicit disposition. T12's concrete review is client-offboarding-scope-review-2026-10-31.md; it does not authorize teardown or deletion of this active service.