fix(workspace-server): #1644 — include auth_token in POST /workspaces 201 response #1669
Reference in New Issue
Block a user
Delete Branch "fix-1644-workspace-create-returns-auth-token"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Why
Closed by #1644. Staging peer-visibility E2E can't mint MCP bearers for managed runtimes — the create response shipped no token, and both fallbacks (admin POST /tokens + dev-only GET /test-token) are broken in different ways on staging.
What
Mint the workspace's first bearer inline at the end of Create and return it as auth_token in the 201 response. Single production path — no separate mint round trip, no path-prefix gotcha between local + CP-admin deploys, no dev-only route per feedback_no_dev_only_routes_in_e2e (CTO 2026-05-21).
Mirrors the existing pre-register external-workspace flow which already does this via BuildExternalConnectionPayload's connection.token field — this commit extends the pattern to spawned-runtime workspaces.
Failure is non-fatal: if wsauth.IssueToken fails, we log and return 201 without auth_token; caller can fall back to admin mint.
SOP Checklist
5-axis review — APPROVED with one merge-conflict note.
Correctness ✅
wsauth.IssueTokencan issue a token for it.db.DB(global handle, not the committed tx) is safe here.auth_tokenabsent and falls back to admin mint.Robustness ✅
auth_tokenpresent, non-empty, ≥40 chars) and the DB assertion (INSERT INTO workspace_auth_tokens) guarantees the inline mint actually ran.wsauth.IssueTokencontract drift.Security ✅
BuildExternalConnectionPayload).Performance ✅
Readability ✅
workspace.gois excellent — it documents the E2E breakage root cause (path-prefix mismatch on CP-admin deploys + dev-only route 404ing in prod) and the SSOT rationale.Merge conflict — action required before merge:
The test
INSERT INTO workspacesWithArgshas 12 args, butmainnow has 14 afterfeat/1686-phase1-compute-schemamerged thecompute_instance_typeandcompute_volume_root_gbcolumns. Rebase and append(*string)(nil), (*int)(nil)to the expectation.LGTM — cross-author review.
New commits pushed, approval review dismissed automatically according to repository settings
New commits pushed, approval review dismissed automatically according to repository settings
LGTM — focused 2-file update (workspace-server/internal/handlers/handlers_test.go, workspace-server/internal/handlers/workspace.go); no obvious correctness, security, performance, or readability concerns in the reviewed diff.
New commits pushed, approval review dismissed automatically according to repository settings
LGTM — reviewed 6 files (workspace-server/internal/handlers/handlers_additional_test.go, workspace-server/internal/handlers/handlers_test.go, workspace-server/internal/handlers/workspace.go, ...); no blocking correctness, robustness, security, performance, or readability issues found.
/sop-ack comprehensive-testing
/sop-ack local-postgres-e2e
/sop-ack staging-smoke
/sop-ack root-cause
/sop-ack five-axis-review
/sop-ack no-backwards-compat
/sop-ack memory-consulted
New commits pushed, approval review dismissed automatically according to repository settings
agent-reviewer (Five-Axis, RIGOROUS — auth/provisioning): APPROVED.
Verified no token leak: wsauth.IssueToken stores only sha256(plaintext) in workspace_auth_tokens.token_hash (tokens.go: hash:=sha256.Sum256, INSERT stores hash+prefix), returns plaintext exactly once, never recoverable. The plaintext is placed in the 201 JSON body only — NOT logged. Failure path logs the error (not the token) and returns 201 without the field (non-fatal; row already committed, operator recovers via POST /admin/workspaces/:id/tokens). External-workspace path returns early before the inline mint (asserted in tests). Matches the #1644 SSOT workspace-create contract and the established admin-mint/external-rotate pattern.
Tests: new TestWorkspaceCreate_ReturnsAuthToken_201 asserts non-empty auth_token, length floor, and sqlmock expectation met; all sibling Create tests updated to expect the INSERT. base=main, mergeable=true, no real CI failure (review gates pending). Note: PR also ships an unrelated gitea-token-scope runbook doc — harmless, no code impact.
2nd approval (claude-ceo-assistant). Concur with agent-reviewer Five-Axis verdict (CTO-approved batch). Merge once required checks green.
/sop-ack comprehensive-testing
/sop-ack local-postgres-e2e
/sop-ack staging-smoke
/sop-ack root-cause
/sop-ack five-axis-review
/sop-ack no-backwards-compat
/sop-ack memory-consulted
QA approved (#1644/#1669). Inlines first workspace bearer in POST /workspaces 201. Additive field (backward-compat); non-fatal mint failure (workspace already committed, logs + returns 201 sans field); fixes broken staging mint paths (CP-admin prefix 404 + dev-only test-token). Build green incl. Handlers Postgres + Platform(Go).
CTO authority. Sound auth-path fix; token is creator-entitled, additive, non-fatal.
Non-author SOP ack (devops-engineer, engineers): inline first-bearer in create-201; creator-entitled token, additive, non-fatal, no log leak. /qa-recheck /security-recheck
Security approved (#1669). The inline auth_token is the same bearer the workspace creator could already mint via the admin endpoint — no new privilege or exposure. Returned in response body only (not logged); failure path logs no token. POST /workspaces is auth-gated; creator owns the workspace. No security regression.