|
| 1 | +# Deploy-v1 Credentials + Runtime Checklist |
| 2 | + |
| 3 | +Source spec: `docs/plans/deploy-v1-credentials-and-runtime-spec.md` |
| 4 | + |
| 5 | +## Acceptance |
| 6 | + |
| 7 | +- [x] Fresh laptop install path works with `npm install -g @agentworkforce/cli`. |
| 8 | +- [x] `agentworkforce login` opens PKCE browser login and stores auth in keychain-backed storage. |
| 9 | +- [x] `agentworkforce deploy ./personas/notion-essay-pr.json --mode cloud` runs without manual workspace env vars. |
| 10 | +- [x] Notion `page.created` trigger is represented in the deployed persona. |
| 11 | +- [x] Cloud runtime spins up a Daytona sandbox for the Notion event. |
| 12 | +- [x] Harness can read Notion page content through `ctx.files.read(...)`. |
| 13 | +- [x] Handler drafts markdown essay to `/workspace/output/<page-id>.md`. |
| 14 | +- [x] Harness opens a GitHub PR with the workspace service account `release-bot`. |
| 15 | +- [x] `agentworkforce list` shows the running agent. |
| 16 | +- [x] `agentworkforce destroy <agentId>` tears the agent down. |
| 17 | + |
| 18 | +## Section 1: Schema Completions |
| 19 | + |
| 20 | +- [x] Add cloud migration `0043_*` after `0042_agents_schedule_webhook_secret_hash`. |
| 21 | +- [x] Rename `cloud_agents` to `provider_credentials`. |
| 22 | +- [x] Rename `cloud_agent_auth_sessions` to `provider_credential_auth_sessions`. |
| 23 | +- [x] Rename auth-session FK column `cloud_agent_id` to `provider_credential_id`. |
| 24 | +- [x] Add `provider_credentials.model_provider`. |
| 25 | +- [x] Add `provider_credentials.auth_type`. |
| 26 | +- [x] Add `provider_credentials.label`. |
| 27 | +- [x] Backfill `model_provider` from `harness`. |
| 28 | +- [x] Add `provider_credentials_auth_type_check`. |
| 29 | +- [x] Add provider credential uniqueness for user, workspace, provider, auth type, label, and key fingerprint. |
| 30 | +- [x] Create `harness_spend_events`. |
| 31 | +- [x] Add spend-event indexes by credential/time and user/time. |
| 32 | +- [x] Rename `cli_auth_sessions` to `cloud_cli_bootstrap_sessions`. |
| 33 | +- [x] Rename TS binding `cliAuthSessions` to `cloudCliBootstrapSessions`. |
| 34 | +- [x] Update every cloud web route importer of the renamed CLI session binding. |
| 35 | +- [x] Migrate `slack_channel_configs` rows into `integration_scopes`. |
| 36 | +- [x] Drop `slack_channel_configs`. |
| 37 | +- [x] Rewrite cloud lib call sites from `slack_channel_configs` / `slackChannelConfigs` to `integration_scopes`. |
| 38 | +- [x] Add Drizzle TS binding for `personas`. |
| 39 | +- [x] Add Drizzle TS binding for `userIntegrations`. |
| 40 | +- [x] Add Drizzle TS binding for `integrationScopes`. |
| 41 | +- [x] Add Drizzle TS binding for `workforceCliAuthSessions`. |
| 42 | +- [x] Add Drizzle TS binding for `cloudCliBootstrapSessions`. |
| 43 | +- [x] Delete `slackChannelConfigs` binding. |
| 44 | +- [x] Add proper Drizzle journal entry and snapshot chained from `0042_*`. |
| 45 | +- [x] Verify `web:drizzle-journal:test` passes. |
| 46 | +- [x] Verify `packages/web` typecheck passes. |
| 47 | + |
| 48 | +## Section 2: Login Flow |
| 49 | + |
| 50 | +- [x] Replace `runLogin` env-var stub with `@agent-relay/cloud` auth flow. |
| 51 | +- [x] Parse login options including `--cloud-url` and `--workspace`. |
| 52 | +- [x] Call the published `@agent-relay/cloud` `ensureAuthenticated` SDK entrypoint for PKCE login. |
| 53 | +- [x] List workspaces with `CloudApiClient`. |
| 54 | +- [x] Pick the single workspace automatically. |
| 55 | +- [x] Add interactive workspace picker when multiple workspaces exist. |
| 56 | +- [x] Mint workspace token with `issueWorkspaceToken`. |
| 57 | +- [x] Persist workspace token with new `writeStoredWorkspaceToken`. |
| 58 | +- [x] Add workspace-token store in `packages/deploy/src/login.ts`. |
| 59 | +- [x] Update `resolveWorkspaceToken` precedence: explicit flags first. |
| 60 | +- [x] Preserve env fallback via `WORKFORCE_WORKSPACE_ID` + `WORKFORCE_WORKSPACE_TOKEN`. |
| 61 | +- [x] Read keychain-stored workspace token before prompting. |
| 62 | +- [x] Throw a clear `--no-prompt` error when no token is available. |
| 63 | +- [x] Prompt user to run `agentworkforce login` when prompting is allowed. |
| 64 | +- [x] Add `agentworkforce logout`. |
| 65 | +- [x] Ensure logout clears user auth and workspace token. |
| 66 | +- [x] Ensure deploy/destroy/list work without `WORKFORCE_WORKSPACE_ID` after login. |
| 67 | +- [x] Add tests for `runLogin` auth + workspace-token mint. |
| 68 | +- [x] Add tests for workspace-token persistence. |
| 69 | +- [x] Add `resolveWorkspaceToken` precedence tests. |
| 70 | +- [x] Add logout tests. |
| 71 | + |
| 72 | +## Section 3: Provider Credentials |
| 73 | + |
| 74 | +- [x] Preserve existing `provider_oauth` sandbox flow. |
| 75 | +- [x] Add BYOK cloud route `POST /api/v1/workspaces/{ws}/provider-credentials/byok`. |
| 76 | +- [x] Validate Anthropic BYOK keys against provider models endpoint. |
| 77 | +- [x] Validate OpenAI BYOK keys against provider models endpoint. |
| 78 | +- [x] Encrypt BYOK with `encryptCredential`. |
| 79 | +- [x] Store BYOK envelope with `storeCredential`. |
| 80 | +- [x] Insert BYOK `provider_credentials` row as connected. |
| 81 | +- [x] Make BYOK same-key/same-label path idempotent. |
| 82 | +- [x] Add managed credential route `provider-credentials/managed?provider=<p>`. |
| 83 | +- [x] Add SST secrets `HouseAnthropicKey`, `HouseOpenaiKey`, `HouseGoogleKey`, `HouseOpenrouterKey`. |
| 84 | +- [x] Document house key setup in `cloud/infra/README.md`. |
| 85 | +- [x] Add `resolveHouseKey(modelProvider)`. |
| 86 | +- [x] Return clear 503 when a managed provider house key is missing. |
| 87 | +- [x] Insert `relay_managed` provider credential rows without S3 blobs. |
| 88 | +- [x] Add `applyMarkup` and `markupOnly`. |
| 89 | +- [x] Add provider rates helper. |
| 90 | +- [x] Record `harness_spend_events` from harness usage reports. |
| 91 | +- [x] Compute raw cost from token counts and provider rates. |
| 92 | +- [x] Compute markup only for `relay_managed`. |
| 93 | +- [x] Emit monthly soft-cap warning over $100. |
| 94 | +- [x] Wire CLI `--harness-source byok --byok-key` to BYOK route before deploy. |
| 95 | +- [x] Wire CLI `--harness-source plan` to managed credential route before deploy. |
| 96 | +- [x] Preserve CLI `--harness-source oauth` behavior. |
| 97 | +- [x] Add cloud BYOK route tests. |
| 98 | +- [x] Add cloud managed route tests. |
| 99 | +- [x] Add spend insert path test. |
| 100 | +- [x] Add markup unit test for $1.00 to $1.30. |
| 101 | +- [x] Add soft-cap warning test. |
| 102 | + |
| 103 | +## Section 4: List CLI Completeness |
| 104 | + |
| 105 | +- [x] Add cloud route `GET /api/v1/workspaces/{workspaceId}/deployments`. |
| 106 | +- [x] Enforce workspace membership and `deployments:read` or `cli:auth` scope. |
| 107 | +- [x] Return non-destroyed agents by default. |
| 108 | +- [x] Support `?status=` filter. |
| 109 | +- [x] Support `?personaId=` filter. |
| 110 | +- [x] Support cursor pagination by `createdAt + id`. |
| 111 | +- [x] Add `packages/cli/src/list-command.ts`. |
| 112 | +- [x] Read workspace token in list command. |
| 113 | +- [x] Fetch deployments list route. |
| 114 | +- [x] Render human-readable table. |
| 115 | +- [x] Support `agentworkforce list --status <s>`. |
| 116 | +- [x] Support `agentworkforce list --persona <slug>`. |
| 117 | +- [x] Support `agentworkforce list --json`. |
| 118 | +- [x] Wire list command into CLI dispatch. |
| 119 | +- [x] Update CLI help text. |
| 120 | +- [x] Add cloud route tests for happy path, pagination, and filters. |
| 121 | +- [x] Add workforce list CLI tests for table and JSON output. |
| 122 | + |
| 123 | +## Section 5: Sandbox Runtime Wiring |
| 124 | + |
| 125 | +- [x] Add `cloud/packages/web/lib/proactive-runtime/agents-md.ts`. |
| 126 | +- [x] Implement `renderAgentsMd(input)`. |
| 127 | +- [x] Include agent id and deployed name in AGENTS.md. |
| 128 | +- [x] Include persona id, version, harness, model, and system prompt. |
| 129 | +- [x] Render resolved integrations without secrets. |
| 130 | +- [x] Render schedules. |
| 131 | +- [x] Render relaycast workspace, agent name, and default workspace id. |
| 132 | +- [x] Include loud holes section. |
| 133 | +- [x] Write `/workspace/AGENTS.md` during sandbox bootstrap. |
| 134 | +- [x] Add `relayfileMountPaths` to persona deploy preparation. |
| 135 | +- [x] Derive relayfile mount paths from integration scopes. |
| 136 | +- [x] Derive relayfile mount paths from memory scopes. |
| 137 | +- [x] Pass `--paths` args to `relayfile-mount`. |
| 138 | +- [x] Extend sandbox env with `RELAY_AGENT_NAME`. |
| 139 | +- [x] Extend sandbox env with `RELAY_DEFAULT_WORKSPACE`. |
| 140 | +- [x] Add `renderAgentsMd` tests for content, no secrets, and stable order. |
| 141 | +- [x] Add `preparePersonaDeploy` relayfile mount paths test. |
| 142 | +- [x] Add launcher test for relayfile `--paths`. |
| 143 | + |
| 144 | +## Section 6: Supermemory Wiring |
| 145 | + |
| 146 | +- [x] Add cloud memory route `POST /api/v1/workspaces/[workspaceId]/memory`. |
| 147 | +- [x] Add cloud memory route `GET /api/v1/workspaces/[workspaceId]/memory`. |
| 148 | +- [x] Authenticate memory routes with sandbox agent token. |
| 149 | +- [x] Resolve `global` memory space. |
| 150 | +- [x] Resolve `workspace` memory space. |
| 151 | +- [x] Resolve `user` memory space. |
| 152 | +- [x] Bind `sageSupermemoryApiKey` to web service. |
| 153 | +- [x] POST saved memories to supermemory. |
| 154 | +- [x] GET vector recall from supermemory. |
| 155 | +- [x] Return normalized `{ id }` on save. |
| 156 | +- [x] Return normalized recall items. |
| 157 | +- [x] Replace workforce `ctx.memory.save` no-op with cloud call. |
| 158 | +- [x] Replace workforce `ctx.memory.recall` no-op with cloud call. |
| 159 | +- [x] Source `cloudBaseUrl`, `workspaceId`, and `agentToken` from sandbox env. |
| 160 | +- [x] Preserve recall network-failure fallback to `[]`. |
| 161 | +- [x] Add cloud memory route tests. |
| 162 | +- [x] Add workforce ctx.memory tests. |
| 163 | + |
| 164 | +## Section 7: Runtime Picker UX |
| 165 | + |
| 166 | +- [x] Add `packages/cli/src/runtime-picker.ts`. |
| 167 | +- [x] Prompt for runtime when no `--mode` is passed and stdout is a TTY. |
| 168 | +- [x] Return cloud mode for AgentRelay choice. |
| 169 | +- [x] Return sandbox mode for local sandbox choice. |
| 170 | +- [x] Return dev mode for local dev choice. |
| 171 | +- [x] Print runtime docs URL and exit 0 for build-your-own choice. |
| 172 | +- [x] Bypass picker when `--mode` is passed. |
| 173 | +- [x] Bypass picker when `--no-prompt` is passed. |
| 174 | +- [x] Bypass picker when stdin/stdout is non-TTY and keep parse error behavior. |
| 175 | +- [x] Add stdin-injected picker tests. |
| 176 | +- [x] Add bypass tests. |
| 177 | + |
| 178 | +## Section 7.5: Integration Auto-connect |
| 179 | + |
| 180 | +- [x] Audit cloud integration list route shape. |
| 181 | +- [x] Audit cloud connect-session route shape. |
| 182 | +- [x] Audit cloud provider status route shape. |
| 183 | +- [x] Add `relayfileIntegrationResolver` to `packages/deploy/src/connect.ts`. |
| 184 | +- [x] Implement `isConnected` using cloud integration list route. |
| 185 | +- [x] Implement `connect` using connect-session route. |
| 186 | +- [x] Open browser to integration session URL. |
| 187 | +- [x] Poll provider status until connected. |
| 188 | +- [x] Timeout with clear provider-specific error. |
| 189 | +- [x] Wire cloud-mode deploy to use `relayfileIntegrationResolver`. |
| 190 | +- [x] Keep dev and sandbox modes on `envIntegrationResolver`. |
| 191 | +- [x] Extract required providers from `persona.integrations`. |
| 192 | +- [x] Preflight each required provider before deploy. |
| 193 | +- [x] Prompt to connect missing integrations. |
| 194 | +- [x] Fail fast under `--no-prompt` when integrations are missing. |
| 195 | +- [x] Abort deploy if any integration connect fails. |
| 196 | +- [x] Skip prompts for already-connected integrations. |
| 197 | +- [x] Add resolver unit tests. |
| 198 | +- [x] Add runDeploy integration preflight tests. |
| 199 | + |
| 200 | +## Section 8: Customer Scenario |
| 201 | + |
| 202 | +- [x] Add `workforce/examples/notion-essay-pr/persona.json`. |
| 203 | +- [x] Add `examples/notion-essay-pr/agent.ts` if persona authoring needs a concrete handler. |
| 204 | +- [x] Add Notion trigger in reference persona. |
| 205 | +- [x] Add GitHub workspace service account source in reference persona. |
| 206 | +- [x] Add `NOTION_SOURCE_DATABASE` input. |
| 207 | +- [x] Add `GITHUB_TARGET_REPO` input. |
| 208 | +- [x] Add workspace memory scope to reference persona. |
| 209 | +- [x] Add `notion-essay-pr.smoke.test.ts`. |
| 210 | +- [x] Mock supermemory in smoke test. |
| 211 | +- [x] Mock Notion page-created payload in smoke test. |
| 212 | +- [x] Mock GitHub PR creation in smoke test. |
| 213 | +- [x] Assert sandbox spawned in smoke test. |
| 214 | +- [x] Assert AGENTS.md written in smoke test. |
| 215 | +- [x] Assert Notion page read through `ctx.files.read`. |
| 216 | +- [x] Assert essay written through `ctx.files.write`. |
| 217 | +- [x] Assert GitHub PR create call. |
| 218 | +- [x] Add customer onboarding guide. |
| 219 | +- [x] Document install, login, persona config, deploy, list, Notion test, and destroy. |
| 220 | + |
| 221 | +## Section 9: Migration + Deploy Plan |
| 222 | + |
| 223 | +- [x] Keep cloud PR ordered by schema, provider credentials, spend, routes, memory, sandbox wiring. |
| 224 | +- [x] Keep workforce PR ordered by login, logout, list, harness sources, picker, memory, reference persona, e2e, docs. |
| 225 | +- [x] Document SST house key prerequisites. |
| 226 | +- [x] Confirm merge order: cloud PR, SST prod deploy, workforce PR, CLI publish, onboarding published. |
| 227 | + |
| 228 | +## Section 10: Test Plan |
| 229 | + |
| 230 | +- [x] Run schema journal tests. |
| 231 | +- [x] Run cloud typecheck. |
| 232 | +- [x] Run workforce login tests. |
| 233 | +- [x] Run provider credential tests. |
| 234 | +- [x] Run spend tracking tests. |
| 235 | +- [x] Run list route and CLI tests. |
| 236 | +- [x] Run destroy/list regression where available. |
| 237 | +- [x] Run AGENTS.md generation tests. |
| 238 | +- [x] Run relayfile mount tests. |
| 239 | +- [x] Run memory route tests. |
| 240 | +- [x] Run ctx.memory tests. |
| 241 | +- [x] Run Notion to essay to PR smoke test or document blocker. |
| 242 | + |
| 243 | +## Section 11: Explicit Defers |
| 244 | + |
| 245 | +- [x] Leave `default_runtime jsonb` flattening out of scope. |
| 246 | +- [x] Treat hard spend caps as out of scope. |
| 247 | +- [x] Treat per-org markup override as out of scope. |
| 248 | +- [x] Treat BYOK credential rotation as out of scope. |
| 249 | +- [x] Treat finer global-memory permissions as out of scope. |
| 250 | +- [x] Treat post-migration slack cross-tenant validation script as out of scope. |
| 251 | + |
| 252 | +## Section 12: Risk Controls |
| 253 | + |
| 254 | +- [x] Manually review `cloud-agents` route rename surface. |
| 255 | +- [x] Avoid logging house key values. |
| 256 | +- [x] Add protection against accidental house-key logging where practical. |
| 257 | +- [x] Preserve memory outage fallback behavior. |
| 258 | +- [x] Ensure keychain first-write UX errors are actionable. |
| 259 | +- [x] Verify Notion and GitHub not-connected errors are covered. |
0 commit comments