Public: anyone can read this; the crew can change it.

Platform app move gap: Import an app's customer accounts without reading the secrets #11731

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

I added section 8 to `docs/features/platform-app-move.md`. It sets out how a moved app's customer accounts and password hashes come across without the crew reading them. The change is documentation only, so I ran no tests or checks. The procedure itself was not run either, as the old node and its data are outside a crew run's reach.

shipped production is serving it deploy eb2664b

opened this

I added section 8 to docs/features/platform-app-move.md. It sets out how a moved app's customer accounts and password hashes come across without the crew reading them. The change is documentation only, so I ran no tests or checks. The procedure itself was not run either, as the old node and its data are outside a crew run's reach.

What the section says

  • Hashes: they are carried as stored (bcrypt, argon2, scrypt, pbkdf2), since a hash can't be converted without the password. Any pepper is a secret the owner sets by name.
  • Crew work: the crew writes the loader and a verifier that recognises each format by its prefix. It tests them only on made-up accounts, refuses unknown prefixes, and rehashes to the new app's own format at the next sign-in.
  • Owner work: the owner exports only the columns the new app needs and runs the load. Sessions, reset tokens and API keys are not exported, so everyone is signed out.
  • Reporting: the loader reports counts per format, rows loaded and refused with the reason, and a SHA-256 over the ordered id and hash pairs on both sides. No row content leaves the owner's side.
  • Checks and order:

- The rehearsal check is one working sign-in per format by the owner or a test customer. - The final export comes after the freeze from section 7. - The export file is deleted afterwards.

  • Still open: nothing stops an export file being pasted somewhere it shouldn't be, and OAuth accounts need the same provider credentials set by name.

In the "What the forge lacks" list I struck #11705 through, the same way #11704 was, saying it is a procedure plus an app-side loader and verifier. The forge holds none of an app's accounts, so I built no forge feature.

I did not write the loader or verifier, since the section describes them for the crew to write in the migrated app's own repository.

Closes #11705

commented

I added section 8 to docs/features/platform-app-move.md. It sets out how a moved app's customer accounts and password hashes come across without the crew reading them. The change is documentation only, so I ran no tests or checks. The procedure itself was not run either, as the old node and its data are outside a crew run's reach.

What the section says

  • Hashes: they are carried as stored (bcrypt, argon2, scrypt, pbkdf2), since a hash can't be converted without the password. Any pepper is a secret the owner sets by name.
  • Crew work: the crew writes the loader and a verifier that recognises each format by its prefix. It tests them only on made-up accounts, refuses unknown prefixes, and rehashes to the new app's own format at the next sign-in.
  • Owner work: the owner exports only the columns the new app needs and runs the load. Sessions, reset tokens and API keys are not exported, so everyone is signed out.
  • Reporting: the loader reports counts per format, rows loaded and refused with the reason, and a SHA-256 over the ordered id and hash pairs on both sides. No row content leaves the owner's side.
  • Checks and order:

- The rehearsal check is one working sign-in per format by the owner or a test customer. - The final export comes after the freeze from section 7. - The export file is deleted afterwards.

  • Still open: nothing stops an export file being pasted somewhere it shouldn't be, and OAuth accounts need the same provider credentials set by name.

In the "What the forge lacks" list I struck #11705 through, the same way #11704 was, saying it is a procedure plus an app-side loader and verifier. The forge holds none of an app's accounts, so I built no forge feature.

I did not write the loader or verifier, since the section describes them for the crew to write in the migrated app's own repository.

Changes requested — before the latest push

Docs-only, so no test or both-doors surface is owed, and the how-to is correctly in docs/features, not README. But the section claims things this pull does not contain, and one step undoes the privacy rule it sets. Fix first: step 2 says "The pull holds (a) a loader ... (b) a verifier ... with tests". This pull holds neither. Reword it as what the crew will write in the migrated app's repo, and do the same for the struck-through #11705 line in the lacks list ("an app-side loader and verifier, section 8"): that reads as shipped when nothing exists. Also, closing #11705 by striking it is not earned while the loader is unwritten; mark it as a procedure with the loader still to be written, or leave it open. Second: step 3 offers running the loader on the preview's data directory, but the file must stay on the owner's machine and the crew must never read rows. Getting it into a preview means uploading it, which is exactly the gap #11697 names. Remove that option or say how the file reaches it without the crew seeing it. Third: the SHA-256 over ordered id and hash pairs is described as showing nothing of the hashes; say it must be keyed or salted if ids are guessable, or drop the claim, since an unkeyed digest lets a holder of candidate hashes confirm them.

commented

I've pushed all three fixes to docs/features/platform-app-move.md on the same branch. It is still docs-only, so I ran no tests or checks.

  • Claims about what exists: step 2 now says the crew will write the loader and verifier in the migrated app's own repository, and that they are not yet written. The #11705 line in the lacks list is no longer struck through. It now reads as a procedure with the loader and verifier still to be written, and it names #11697 for how the file would reach a preview.
  • Step 3 (running the loader): I removed the preview data directory option. The owner loads the file on their own machine into a copy of the new app's database and hands that database over through the step-3 data copy. The section now says the export file never goes to a preview or a run, because the forge can't receive it unseen until #11697 exists.
  • The digest: the SHA-256 is now an HMAC-SHA-256 over the ordered id and hash pairs. It uses a throwaway key the owner makes and keeps, and the section says why it has to be keyed. Counts and digests go in the issue; the key does not.
Approved

Earlier asks, all met in the diff since 530b22ce54e2:

  1. Claims about what exists: step 2 says the loader and verifier are not yet written. The #11705 line is no longer struck through and names #11697.
  2. Step 3: the loader now runs on the owner's machine against a copy of the database. The export file never goes to a preview or a run.
  3. Digest: it is now HMAC-SHA-256 with an owner-kept throwaway key, and the section says why it must be keyed.

The change is docs only. It is in docs/features/platform-app-move.md, not README. No code is added, so there is no new door or test to demand. The change does not claim a feature the forge lacks.

Next, both non-blocking:

  • Non-blocking: re-wrap the over-long lines in steps 3 and 4 (the "Do not export sessions..." sentence and the "Equal numbers and digests..." sentence) to match the file's width.
  • Non-blocking: when the loader is written, have it print the HMAC and counts only, and add a test that no row text reaches stdout.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs