Repository navigation
Conversation
Mount the incoming migration flow that earlier changes shipped dormant. Browser surfaces under /incoming let the saved user prepare, renew, cancel, recover, resume and activate an arrival and see its state. Each POST needs the verified session, same-origin and CSRF checks and, where the action is sensitive, a fresh email code. A repeat prepare by the same saved user returns the existing operation ID. Tool surfaces reuse standard XRPC. submitPlcOperation and createAccount are treated as incoming only when the Entryway-Arrival-Code header is present and are then never handled as hosted or managed movement. The arrival code selects the arrival and its saved user, and the method-bound source JWT is verified before the ownership lease is taken. createAccount returns tracked credentials only after the account is bound. refreshSession and activateAccount serve a tracked arrival credential and otherwise fall through to the ordinary routes. Pending arrivals are refused by registration, the account console, OAuth consent and signup, in addition to the existing status and migration checks. Activation by any consumer goes through the single guarded operation. Account storage gains bindPlacedAccount, which fails closed on a binding to another user. No schema change and no configuration key. The live public journey, the contracts group and the stock PDS callback have not been run for this change. This work was assisted by a machine
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
…outes The incoming activateAccount and refreshSession handlers run before the ordinary routes and must answer only for a tracked arrival credential. They ran the strict token check first, so an ordinary account whose access token had expired or whose session family was revoked got the incoming 400 ExpiredToken where the ordinary route answers 401. An expired ordinary refresh token had the same flaw. A live run against a stock PDS found it: delegated activation of a deactivated hosted account returned 400. The handlers now verify the token's signature, type, issuer and audience while tolerating expiry, look up whether the session family is tracked to an arrival, and fall through for anything untracked without writing anything. The strict checks still run before any incoming answer. A finished arrival's family is an ordinary session, so once the session store finds it expired or revoked it also falls through. A tracked family of an unfinished arrival keeps the incoming refusal. Also update the stale password step in the public-mechanisms test: the form moved to the password page. This work was assisted by a machine
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.




Part of TECH-681. Stacked on #28. Implements plan 012: the public arrival API and pending-guard integration.
Draft. This PR mounts the incoming-migration routes on every deployment, with no configuration key or opt-out. The live public journey and the stock PDS callback now pass in Atmosphere in a Box on SQLite (see Validation). It stays a draft until the open decisions below are settled and both developers have reviewed it.
What changes
Browser surfaces (verified session, same-origin and CSRF on every POST,
no-store, strict bodies)GET /incomingPOST /incoming/codePOST /incoming/preparePOST /incoming/renew,/cancel,/recover,/activatePOST /incoming/resumeAnother user's operation and an unknown one return the same 404. A repeat prepare by the same saved user for the same DID returns the existing operation ID, so a lost preparation page is recoverable.
Tool surfaces (standard XRPC, no cookie)
submitPlcOperationandcreateAccountare incoming only when theEntryway-Arrival-Codeheader is present. With the header they are never handled as hosted or managed movement; without it the ordinary routes are unchanged.createAccountreturns tracked credentials only after binding and committed family association.refreshSessionandactivateAccountserve a tracked arrival credential and otherwise fall through to the ordinary routes. After a completed migration, a later ordinary deactivation and reactivation use the ordinary route.Pending guard
assertNoMigration; login, security changes, admin and OAuth paths rely on theprovisioningstatus. A single enforced guard is follow-up work.setStatuscannot activate a pending arrival.Changes to shared and other plans' code
These need review from both developers.
bindPlacedAccount(did, userId). It runs in the arrival's binding transaction and fails closed withIdentityConflictif the DID is already bound to another user. No schema change.compose-incoming-arrival.mjs): now builds the production arrival storage and authority, and adds the tool-facing admission.activate-arrival.ts): the committed-retry result is returned only while the account is active.request-event.ts: four error codes added to the safe list so they are not reported asRequestFailed.refreshSessionandactivateAccountnow do one arrival lookup before the ordinary handler.Decisions
Made
Still open (marked as pending in
docs/incoming-migration.mdand the Changeset)tool-admission.ts) so it can change.createAccountaccepts onlyhandleplus optionaldid,emailandinviteCode. It rejectspassword, so an unmodified stock tool that sends it does not work.createAccountretry after the destination move gets 403AccountMismatch, because the source key no longer verifies; recovery or resume is the path./incoming/activate,/resume,/codeand the status page.incoming-browser-ipandincoming-tool-ip, at the existing 30 per 10 minutes. Submit and create share one tool bucket, and retries spend it.Validation
Run at
c7f65b7.Native, Node 24
npm run build,check,lint,format:check,schema:check,changeset:check: exit 0.npm run test:unit: 817 tests, 798 pass, 0 fail, 19 skipped.npm run test:incoming-reconciliation: 23 pass, 0 fail.no-store, the pre-lease JWT verification, the active-account check and the tracked-family fall-through each make tests fail.Live, owned Atmosphere in a Box project, rootless Docker, SQLite single node
incoming-public-journeyincoming-public-mechanismsbrowsercontractsThe journey uses only public pages and XRPC: a stock standalone source with one record and one blob, browser email proof and preparation, source-signed handoff,
createAccountreturning tracked credentials for a paused destination, direct repository and blob transfer, refresh, and activation by callingactivateAccounton the stock destination PDS, which forwards to Entryway. That last step is the stock-callback proof.What the live run found
The first live
incoming-public-mechanismsrun failed. An ordinary deactivated hosted account callingactivateAccountwith its old access token got 400 from the new incoming handler; the ordinary route answers 401. The handler ran its strict token check before checking whether the session family belonged to an arrival. The same applied to expired ordinary refresh tokens and to expired or revoked sessions of an account whose migration had completed.c7f65b7fixes this: anything not tracked to an unfinished arrival falls through to the ordinary route with no writes. Native regression tests cover each case.The same commit updates one stale step in that test: the password form moved to the password page in
9184773.Limits
databasesandprofilesCI jobs, not by a live journey.c7f65b7(finished-arrival sessions falling through) was not independently reviewed../scripts/changesets.shauthoring flow was not run; the Changeset was written by hand andchangeset:checkpasses.🤖 Generated with Claude Code