// The Restate-facing process. Serves OnboardingWorkflow, one instance per // signup, keyed by handle. // // This used to poll getSession/refreshSession in a loop and perform the // actual blento-profile writes using an admin-held throwaway-password // session, ending with requestPasswordReset. That whole design was // untangled 2026-07-23: auto-provisioning is now a step the MEMBER // explicitly triggers, later, via a real ATProto OAuth flow (see // oauth.js) — no throwaway password, no admin-held session, no ordering // constraint to fight. // // A genuine technical constraint, not a preference, is why the actual // writes don't happen in here anymore: oauth.js's OAuthSession holds live // DPoP key material to authenticate each request. That can't be // JSON-serialized into a Restate workflow's input (Restate journals // whatever you hand it durably — you can't pass a workflow a live crypto // session object, and putting DPoP private key material in the journal // would be a bad idea even if you technically could serialize it). So // oauth.js's OAuth callback performs the write directly, then calls this // workflow afterward purely to record the outcome — `run` is now a // tracking/observability record, not the executor. Kept as a Restate // workflow (rather than dropped entirely) so provisioning events still // show up in `restate invocations list --service OnboardingWorkflow`, // matching this project's existing tooling (scripts/onboard-smoke-test.sh) // and habits. import * as restate from '@restatedev/restate-sdk'; import { SCRIPT_VERSION } from './shared.js'; async function run(ctx, input) { // input: { status: 'populated' | 'not-verified' | 'already-provisioned', did, handle } // The write (or the decision not to attempt one) already happened in // oauth.js's callback handler before this was ever invoked — see the // header comment for why. This just durably records the outcome. return { handle: ctx.key, ...input }; } const onboardingWorkflow = restate.workflow({ name: 'OnboardingWorkflow', handlers: { run } }); // Guarded so onboard.js/server.js can `import { onboardingWorkflow } from // './workflow.js'` (for the workflowClient(...) call) without also starting // a second Restate-serving process — same pattern onboard.js itself uses. if (import.meta.url === `file://${process.argv[1]}`) { console.log(`OnboardingWorkflow ${SCRIPT_VERSION} serving on port ${Number(process.env.RESTATE_SERVE_PORT) || 9080}`); restate.serve({ services: [onboardingWorkflow], port: Number(process.env.RESTATE_SERVE_PORT) || 9080 }); } export { onboardingWorkflow };