User flows
How an actor moves through the product: step, screen, endpoint.
7 journeys · 3 complete. A flow is only done when every step is — press play to walk one.
UF-001Sign up → organization created → dashboard
doneThe bootstrap path. Creates the organization and its owner in one transaction, so there is never an org without an owner or a user without a tenant.
Submit the signup form
/signupPOST /api/v1/auth/signup
API creates Organization + owner User in one transaction
First audit row written
Tokens stored, session established
Land on the command centre
/dashboardGET /api/v1/auth/me
Claude: The signup UI is not built yet — the API path is, and is covered by tests.
UF-002Read the build board
doneWhat is built, what is next, how it is architected, what is tested, and the docs — without leaving the app or opening the repo.
Open the landing page
/
Follow through to the command centre
/dashboard
Overview shows progress and what's coming up, computed across sections
/dashboard
Open the Features tab, expand an item for its remarks and updates
/dashboard
Open the Docs tab and read any doc in place
/dashboard
Claude: Server-rendered from data/dashboard/*.json and docs/*.md — no client fetch, no waterfall.
UF-003Plan a quarter for a project
plannedThe core planning loop: brief in, plan out, calendar populated.
Create a project
/projects/newPOST /api/v1/projects
Write the campaign brief — audience, offer, budget, success metric
/projects/{id}/briefPOST /api/v1/projects/{id}/brief
Generate a plan (channel mix, budget split, cadence)
/projects/{id}/planPOST /api/v1/projects/{id}/plan/generate
Edit the plan — the AI output is a draft, not a decision
/projects/{id}/planPATCH /api/v1/projects/{id}/plan
Accept — plan expands into calendar slots across the three tracks
/projects/{id}/schedulerPOST /api/v1/projects/{id}/plan/accept
Claude: Step 4 is deliberate: a generated plan that lands straight on the calendar removes the judgement the plan needs.
UF-004Agency drafts → lead approves → publishes
plannedThe approval gate in its normal shape. An outside contributor produces work; an internal owner takes responsibility for it before it ships.
Agency member logs in, sees only assigned projects
/projectsGET /api/v1/projects
Drafts a multi-channel post with per-channel overrides
/composerPOST /api/v1/posts
Submits for approval
/composerPOST /api/v1/posts/{id}/submit
Lead is notified
Lead reviews and approves (or rejects with a comment)
/approvalsPOST /api/v1/posts/{id}/approve
Post is scheduled into a calendar slot
/calendarPOST /api/v1/posts/{id}/schedule
Worker publishes at the slot time; failures retry with backoff
Claude: Step 1 is the security-critical one: org scope is not enough for an agency user, the project assignment is checked too.
UF-005Agent proposes → human approves → it is applied
doneThe agentic loop, and the gate that makes it safe. An agent writes its whole proposal while the run is `awaiting_approval` — nothing has touched content, a budget or a platform at that point, so a rejected run costs model tokens and nothing else. There is deliberately no `running → applied` edge in the state machine.
Press Run now on an agent
/projects/:id/agentsPOST /api/v1/agents/runs
Plan + project visibility checked; run written as `queued` and published to RabbitMQ
Worker picks it up (`running`), the agent reads the project, and writes its proposal (`awaiting_approval`)
Proposal appears beside the team it came from
/projects/:id/agents/proposalsGET /api/v1/agents/runs
Someone with `agents:approve` reads what it found and decides
/projects/:id/agents/proposalsPOST /api/v1/agents/runs/:id/approve
`apply.ts` runs — the Drafter creates posts, the others record or unlock the next step
/projects/:id/content
Claude: No auto-apply mode. adwords-adsense planned autopilot as the default; that is where the money risk lives.
Claude: Marked done. The flow shipped; this row still described the planned shape, including a /approvals screen that now means something else — post sign-off, not agent proposals. Full walkthrough with diagrams in docs/AGENT_FLOW.md.
UF-006Answer 'what is running and what is it returning?'
plannedThe success metric from the brief: under 60 seconds, no spreadsheet.
Open the KPI surface
/kpisGET /api/v1/analytics/kpis
Every channel, organic and paid, with spend, return and freshness
/kpis
Compare against vertical benchmarks
/kpisGET /api/v1/ads/benchmarks
Drill into a project or a channel
/kpis/{scope}
Claude: Step 2 carries an as-of timestamp per source. A stale number that looks live is worse than no number.
UF-007Connect a channel
plannedOAuth into a platform and keep the connection alive without anyone watching it.
Pick a platform
/settings/channels
Redirect to the platform's consent screen
GET /api/v1/channels/{platform}/oauth/start
Callback exchanges the code; tokens encrypted at rest
GET /api/v1/channels/{platform}/oauth/callback
Profile fetched, account listed as connected
/settings/channels
Hourly job refreshes tokens expiring within 24h; a 6-hourly health check flags a break before a publish fails
Claude: Step 5 matters more than it looks — a silently expired token surfaces as a mysterious publish failure days later.