How provisioning works
Provisioning turns a new Pro or Max sign-up into a working Workspace. Step through the 14 scenes with the arrow keys or a click on the board. Turn on Voice for the narration. Each scene has its own link: add #7 to the address to open scene 7.
Transcript
1. How provisioning works
Provisioning is the step that turns a new Pro or Max sign-up into a working Workspace: your own career-ops copy, set up from your CV, on a disk that is kept between runs. This explainer follows one new User from sign-up to Inicio, names every service it touches, and ends with what to watch in the E2E test.
Source: apps/api/src/runs/service.ts
2. The journey, end to end
Six moments. You sign up with Privy, accept the privacy notice, and send the intake: your CV and a short form. Then the api checks your Plan. Pro or Max starts a setup run that takes about a minute, and the app opens on Inicio. Free skips the setup entirely and gets one job search a day.
Source: apps/api/src/routes/v1.ts · apps/api/src/onboarding.ts
3. Gate 1: the CV is checked before anything is paid for
The api reads the CV itself before saving it: it must be a PDF, at most 5 MB, with at least 200 characters of real text. A scan or a photo fails here, on the spot, instead of failing a paid setup run later. A good CV goes to Cloudflare R2, and the form answers plus the CV's key go to Postgres.
Source: apps/api/src/intake.ts · apps/api/src/routes/v1.ts
4. Who gets a setup run, and what starts it
One function decides: provisionIfEligible. Six conditions must all hold. Four moments call it: sending the intake, giving consent, Stripe confirming a payment, and a sweep every 60 seconds that catches anything the others missed, such as a Plan changed by hand. A failed setup does not retry by itself: it waits for a new intake.
Source: apps/api/src/runs/service.ts · apps/api/src/routes/v1.ts · apps/api/src/index.ts · apps/api/src/billing/service.ts (feat/stripe-billing)
5. Free and Pro take different roads
Free Users never get a Workspace. Their job search runs in a throwaway session with no disk, on the image's own career-ops copy, with the title filter set from their target roles. It costs no model tokens. Pro and Max get a Volume of their own, where every later step runs.
Source: apps/api/src/runs/service.ts · apps/api/src/runs/career-ops.ts · live run 2026-10-17, budi-agent
6. The machinery
The api on Railway drives everything. Your files live on a Tenki Volume named budi-<userId>, 5 GiB, kept between runs. Each run starts a fresh Tenki session from the pinned image budi-session (career-ops at a fixed commit, Claude Code 2.1.300, Chromium) and mounts your Volume at /workspace/data. The session ends when the run ends.
Source: apps/api/src/workspace/tenki.ts · apps/api/src/workspace/runner.ts · apps/api/src/image/recipe.ts
7. Inside the session: preparing the Workspace
Before any model call, plain shell work. career-ops is copied from the image onto your Volume, the first time only. Folders for Claude Code's config and the browser profile are created. portals.yml starts from the template. Your CV is downloaded from R2 and placed where career-ops' intake mode looks for it. The form answers sit next to it, on the session's scratch disk, not on the Volume.
Source: apps/api/src/runs/service.ts · apps/api/src/workspace/runner.ts · apps/api/src/runs/prompts.ts
8. Claude Code does the setup
Claude Code runs headless in career-ops with one prompt and six tasks: run intake mode, write cv.md, fill the profile, write the archetypes and North Star, retarget the job-board filter to your roles, then run doctor and fix what it lists. It may not invent anything: everything comes from the CV or the form. It runs detached, with a $2 cap and a 20 minute ceiling, and the api checks for its exit file every 10 seconds.
Source: apps/api/src/runs/prompts.ts · apps/api/src/runs/service.ts · apps/api/src/workspace/tenki.ts
9. Gate 2: the api does not take the agent's word
Claude Code writes its verdict to result.json. If it says the CV was unreadable or the profile is incomplete, the run stops and asks for a human. If it says ready, the api checks for itself: it runs career-ops' doctor and confirms the profile is not still the example. Only then is the Workspace marked seeded, and every Pro step unlocks.
Source: apps/api/src/runs/service.ts · apps/api/src/runs/career-ops.ts
10. What the User sees
While the setup runs, the app shows "Preparando tu espacio de trabajo" and asks the api for /me every 5 seconds. When the Workspace is seeded, the same page turns into Inicio. If the setup stopped, the User is back on the intake form with the reason, for example "Budi no pudo leer tu CV", and uploading again starts a new setup.
Source: apps/web/src/App.tsx · apps/api/src/onboarding.ts
11. When something breaks
Failures before any real work (Tenki not ready, the Volume still busy) are retried, up to 3 attempts. A Volume released by the last session can stay busy a minute or two, so attaching retries every 10 seconds for up to 3 minutes. If the api restarts mid-run, on boot it closes the orphaned session and fails the run, so the User is not stuck. Once Claude Code has started, a failure is not retried: the run fails and says why.
Source: apps/api/src/runs/service.ts · apps/api/src/workspace/tenki.ts
12. The numbers to expect
From the live run on 2026-10-17: setup took 67 seconds and cost $0.23 in model tokens. The first job search on the new Workspace found 32 listings. A Free search, with no Workspace, took 2 minutes 46 seconds and found 8. The caps are much higher than the measured cost, on purpose: they stop a runaway, not a normal run.
Source: live run 2026-10-17, budi-agent · apps/api/src/runs/service.ts
13. What to watch in the E2E
Follow one run through four places: the app, the Railway logs, Tenki, and the database. Each checkpoint has a line you can look for. Time it from sending the intake to seeing Inicio. In the E2E: anything over 5 minutes on "Preparando", a needs_attention state, or a CLOSE FAILED log line is a finding. Write it down with the time.
Source: apps/api/src/runs/service.ts · apps/api/src/workspace/tenki.ts · apps/api/src/index.ts
14. The design decisions, in one board
Six choices shape all of this. Each one trades a little complexity for something a User or the budget feels. This is the page to come back to when one of them is questioned.
Source: apps/api/src/runs/service.ts · apps/api/src/workspace/tenki.ts · apps/api/src/image/recipe.ts