Historical full-data cutover design (not the production release)#
The user subsequently required existing IAM Silicons and their data to remain in place. The current production authority is parallel-production.md. Do not execute the old identity adoption, service replacement, or decommissioning steps below. These notes are retained as the tested design for a possible separately authorized future adoption.
For the later Accounts canonical UUID change, follow account-uuids.md after identity linking and before reopening writes.
From service part 1 (identity), 2026-10-10#
Before deploying the new service:
- Silicon Accounts app
briefcase(with the app's own credentials, never from the Briefcase CLI): sign-in setup allowshttps://briefcase.teamofsilicons.com/auth/callback,device_flow: true,public_client: true, optional fieldemail. Set the webhook:PUT /v1/apps/briefcase/webhook {"url": "https://backend.briefcase.teamofsilicons.com/webhook/"}and keep the returnedwhsec_…secret (a PUT keeps an existing secret and returnsnull). - Secrets and settings on the base-tier host (
/etc/silicon-briefcase/*.env/ Secrets Managersilicon-briefcase/production): addBRIEFCASE_APP_SECRET,BRIEFCASE_ACCOUNTS_WEBHOOK_SECRET,BRIEFCASE_PROOF_ISSUERS(production value in decisions.md S4); setACCOUNTS_URL=https://accounts.teamofsilicons.comandBRIEFCASE_APP_ID=briefcase; remove everyBRIEFCASE_IAM_*,BRIEFCASE_HONEYCOMB_*,BRIEFCASE_TEST_ENVIRONMENT_ENCRYPTION_KEY,BRIEFCASE_TEST_DATABASE_URLandBRIEFCASE_TEST_WORKER_DATABASE_URL. The API refuses to start without the app secret or webhook secret. - Migrate with
briefcase-migrate(adds migration 0048; no existing data changes). - Drain delegated uploads made under IAM (
delegated_uploadsrows inreserved/receiving/staged): their identity keys will not match proof-authenticated calls after the switch. Same foridempotency_recordsstillin_progress.
Switch together (they break otherwise):
- Interface (outside this migration) must switch its Files feature to User verification proofs at the same
time: it uses the removed
/api/v1/auth/slt+/auth/refreshbroker andX-Org-IDbearer calls today. WithBRIEFCASE_PROOF_ISSUERSit may usebriefcase.entries.list,briefcase.files.read,briefcase.folders.create,briefcase.uploads.*,briefcase.invitations.create,briefcase.link_access.update(confined toapps/interface/until part 3 widens it). Otherwise disable Interface Files at the cutover. - Waveform, Extend, Silicon Browser call
/api/v1/obo/*with IAM OBO headers through the vendoredbriefcase-client3.x: they must sendAuthorization: Proof sap_…(User verification for receiving appbriefcasewith the scopes above) and, for the byte transfer,X-Org-ID: <the proof user's uuid>. - Stemcell checks
briefcase iam --jsonand installs through Honeycomb (CLI stage handles the alias).
After the switch: IAM webhook deliveries to /webhook/ answer 401 (expected); remove the IAM webhook
registration. The testing-plane database and the Honeycomb/testing tables are no longer used; back them up and
decommission with the Carbon's approval.
Open for parts 2 and 3: legacy org tenants (tos) are not reachable until the identity re-keying and drive
restructure run; do not cut over production before those parts land.
From service part 2 (drives and permissions), 2026-10-10#
- Migration 0049 (with 0048) changes no existing content. It adds the drive constraints and indexes, the
Silicon allow-list table and the cross-drive SECURITY DEFINER functions, and backfills
organization_storage_configs.external_idwith the exact derivation in use today (so customers' role trust policies keep working; check withSELECT org_id, external_id FROM briefcase.organization_storage_configs). It must run as the usual migrator role: the definer functions' cross-drive reads rely on policies created for the role that ran the migration. - No new settings. Quotas stay at 100 GiB/day and 1 PiB, now per drive; an organization's overrides are carried to its owner's drive by part 3's re-keying.
- Legacy organization data stays unreachable until part 3 moves it into drives (
{org}-public/, tag folders,apps/{app}/{org}-public/,unclaimed/…) with snapshot shares. Do not cut over before part 3. - Silicon allow-lists start empty. After the switch a share to a Silicon from outside its custodian's Silicons needs the Silicon or its custodian to allow the sharer first. Part 3's snapshot shares record access members already had, so the re-keying command must write them directly rather than through the API's allow-list check. Tell Carbons that new shares to someone else's Silicon need an allowance.
- Clients switch to drives together with the service (the web and CLI stages, and Interface): there is no
root_typepublic/tag any more, paths no longer start withprivate/{id}/, the top of a drive is a real folder (GET /drivesgives its id),drivenames another account's drive, andGET /sharedreplaces browsing other members' private folders. Apps acting through proofs reach only the user's own drive. - Account deletion is destructive by design:
account.deletederases the account's own drive (purged at once by the worker, bring-your-own objects included). Before the switch, confirm the worker's cleanup can assume each bring-your-own role with the stored External ID.
From service part 3 (addresses, other apps, moving the data), 2026-10-10#
This completes the service side: production data can now be moved. Order of the switch:
- Stop the API and the worker; drain in-flight work (the command refuses otherwise: idempotency records in progress, delegated uploads reserved/receiving/staged/cleanup pending, multipart sessions open, outbox pending).
- Back up the database (
pg_dump --format=custom; the 2.1.0 dump was 4.4 MB) and keep it until the cutover is accepted. It is the way back once the new service has been used. - Migrate:
briefcase-migrateapplies 0048–0050 (no data changes). - Write the mapping (
docs/migration/decisions.mdS44 has the format). For each identity stored in the organization (SELECT DISTINCT actor_type, actor_id FROM briefcase.organization_membersas the migrator, plusiam_identity_bindingsfor principal UUIDs), find the Silicon Accounts account — normally the same handle:lookup_by_idwith Briefcase's app credentials, cross-checked with the IAM export — and writeiam_principal_id,accounts_uuid,kind,accounts_id, e.g.c:saket,zQo,carbon,c:saket. Leave out members who have no account (their files go tounclaimed/in the owner's drive). Iftoshas no single active owner in the projection, addorg:tos,<uuid>. - Dry run:
briefcase-migrate link-identities --file mapping.csv --dry-run(same environment as the migrator). Read the report: lines that matched nothing, members without an account, where each space went and with how many accounts it is shared, renames. Fix the mapping and repeat until it is right. - Apply: the same without
--dry-run(--jsonfor the full report; it is also stored inbriefcase.identity_link_runs.report). Expect, for production as surveyed: ~190 entries moved, the 79 link-shared entries still link-shared, 30-ish identities linked. A corrected mapping can be applied by running again — it undoes the previous run first — until the service is opened; afterwards restore the backup instead. - Settings: add
BRIEFCASE_PROOF_FIRST_PARTY_ISSUERS=interfacenext toBRIEFCASE_PROOF_ISSUERS(S4's value). Start the API and worker. - Check: as the owner,
GET /api/v1/drives(own drive plus each Silicon looked after),GET /api/v1/entries(moved files at the top,tos-public, tag spaces,unclaimed/), an old link anonymously (/org/tos/public/<a link-shared file>→ 200), a member'sGET /api/v1/shared.
Switch together with Briefcase (in addition to part 1's list):
- Interface: Files works through proofs on
/api/v1/obo/*withinterfacefirst-party (lists and reads in any drive the account reaches;drivenames one). Proofs are accepted only on those routes — resolving an address at/api/v1/paths/…takes a bearer token — so Interface lists and reads through the obo routes. Its permanent-URL validator must accepthttps://briefcase.teamofsilicons.com/{c:|si:id}/…and keep accepting/org/…. - DM, Commit: stored
/org/{org}/…links keep working (aliases); their validators must also accept the new/{owner id}/{path}form for new attachments. - Waveform, Extend, Browser: upload with reserve/transfer/commit (no
X-Org-IDneeded any more); they stay inapps/{app}/of the account's drive. Extend's invite step stays possible (briefcase.invitations.create) but the custodian already sees its Silicons' files. - The web (later stage) serves
/{owner}/{path}(ids contain:, so they never collide with its own routes; a uuid owner segment can appear while an owner's id is unknown) by callingGET /api/v1/paths/…through the BFF, follows a308by redirecting the browser to the body'spermanent_url, and serves/org/{org}/{path}by calling the API's/org/…and redirecting to the entry'spermanent_url.
Notes:
- After the switch, Silicons' custodians are learned lazily (S47); a Carbon may need to open its drive list once more for a Silicon that has not signed in since the cutover.
legacy_path_aliaseslives on; nothing expires it. Old ids redirect for as long asaccount_id_historykeeps them (an id taken by someone else belongs to its new holder).- The legacy organization rows (now empty structural folders, members, tags, contacts, idempotency records) stay; propose a cleanup migration only after the cutover is accepted.