@@ -21,7 +21,12 @@ import { VersionConflictError } from "@secondlayer/shared/errors";
2121import { DeployWorkflowRequestSchema } from "@secondlayer/shared/schemas/workflows" ;
2222import { Hono } from "hono" ;
2323import { streamSSE } from "hono/streaming" ;
24- import { getApiKeyId , resolveKeyIds } from "../lib/ownership.ts" ;
24+ import {
25+ getAccountId ,
26+ getApiKeyId ,
27+ resolveApiKeyIdForWrite ,
28+ resolveKeyIds ,
29+ } from "../lib/ownership.ts" ;
2530import { InvalidJSONError } from "../middleware/error.ts" ;
2631
2732const MAX_TAIL_DURATION_MS = 30 * 60 * 1000 ; // 30 minutes (matches logs.ts)
@@ -133,8 +138,24 @@ app.post("/", async (c) => {
133138 }
134139
135140 const parsed = DeployWorkflowRequestSchema . parse ( body ) ;
136- const apiKeyId = getApiKeyId ( c ) ;
137- if ( ! apiKeyId ) return c . json ( { error : "API key required" } , 401 ) ;
141+
142+ // Accept either direct API key auth (sk-sl_…) OR session cookie auth
143+ // (ss-sl_…, used by the web chat authoring loop). Session users get
144+ // attributed to their account's oldest active API key.
145+ const apiKeyId = await resolveApiKeyIdForWrite ( c ) ;
146+ if ( ! apiKeyId ) {
147+ if ( getAccountId ( c ) ) {
148+ return c . json (
149+ {
150+ error :
151+ "This account has no active API keys. Create one in Settings before deploying workflows from chat." ,
152+ code : "NO_API_KEY" ,
153+ } ,
154+ 403 ,
155+ ) ;
156+ }
157+ return c . json ( { error : "API key required" } , 401 ) ;
158+ }
138159
139160 // Idempotency: replay cached result for dry-run-less deploys when the client
140161 // sends a clientRequestId and we've seen this exact tuple in the last 30s.
@@ -339,8 +360,15 @@ app.post("/", async (c) => {
339360// doesn't treat "bundle" as a workflow name.
340361
341362app . post ( "/bundle" , async ( c ) => {
363+ // Bundling is a pure, stateless operation — it doesn't attribute the
364+ // result to any specific key, it just needs to know the caller is
365+ // authenticated. Accept either an explicit API key OR a session cookie
366+ // (via accountId set by requireAuth).
342367 const apiKeyId = getApiKeyId ( c ) ;
343- if ( ! apiKeyId ) return c . json ( { error : "API key required" } , 401 ) ;
368+ const accountId = getAccountId ( c ) ;
369+ if ( ! apiKeyId && ! accountId ) {
370+ return c . json ( { error : "Unauthorized" } , 401 ) ;
371+ }
344372 const origin = readOrigin ( c ) ;
345373
346374 let body : { code ?: unknown } ;
0 commit comments