feat(streams): add bearer token auth and CI/CD deployment pipelines#1343
Conversation
Add authentication middleware on /v1/* routes and wire streams into production, preview, and cleanup deployment workflows on Fly.io.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a new Streams service with environment validation and token-auth, updates desktop client to use STREAMS_URL/STREAMS_SECRET, and extends CI/CD (preview and production) to deploy and clean up Streams on Fly.io with status reporting in preview comments. Changes
Sequence Diagram(s)sequenceDiagram
participant Desktop as Desktop Client
participant Preview as Preview Workflow
participant Streams as Streams Proxy (app)
participant Claude as Claude Agent
participant Fly as Fly.io
Desktop->>Streams: POST /v1/... (Authorization: Bearer STREAMS_SECRET)
Streams-->>Streams: Validate Authorization header vs authToken
Streams->>Claude: Forward request to internal agent (STREAMS_INTERNAL_URL)
Claude-->>Streams: Respond with model output
Streams-->>Desktop: Return proxied response
Preview->>Fly: Deploy / Destroy Streams app (deploy-preview / cleanup-preview)
Fly-->>Preview: Return STREAMS_STATUS / STREAMS_LINK
Preview->>Desktop: Publish preview comment including STREAMS status/link
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Create env.ts with zod schema that validates DURABLE_STREAM_AUTH_TOKEN and ANTHROPIC_API_KEY as required, replacing raw process.env reads.
🧹 Preview Cleanup CompleteThe following preview resources have been cleaned up:
Thank you for your contribution! 🎉 |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @.github/workflows/deploy-production.yml:
- Around line 409-420: Move the "Set secrets" step to run before the "Deploy to
Fly.io" step and use staging to avoid a redundant redeploy: invoke "flyctl
secrets set" with the "--stage" flag to stage ANTHROPIC_API_KEY and
DURABLE_STREAM_AUTH_TOKEN (instead of setting them after deploy), then run
"flyctl deploy" afterwards; keep the workflow step names "Set secrets" and
"Deploy to Fly.io" but ensure the secrets step runs first and uses "--stage" so
the initial deployment has the required env vars without triggering a second
automatic deploy.
In `@apps/streams/src/env.ts`:
- Line 9: The env schema requires DURABLE_STREAM_AUTH_TOKEN but tests expect
auth-disabled mode; make DURABLE_STREAM_AUTH_TOKEN optional (or provide a
default empty string) in the zod schema so the app won't crash when it's unset,
ensuring it can be undefined to match AIDBProxyServerOptions.authToken and the
existing auth check in server.ts that uses if (options.authToken). Update the
symbol DURABLE_STREAM_AUTH_TOKEN in the env.ts zod definition accordingly so
runtime and tests can run without the token.
🧹 Nitpick comments (1)
apps/streams/src/env.ts (1)
1-13: Consider adding.min(1)to required string fields to reject empty strings.Empty strings would pass
z.string()validation but would result in broken API keys or ineffective auth tokens at runtime.Suggested hardening
- DURABLE_STREAM_AUTH_TOKEN: z.string(), - ANTHROPIC_API_KEY: z.string(), + DURABLE_STREAM_AUTH_TOKEN: z.string().min(1), + ANTHROPIC_API_KEY: z.string().min(1),
| - name: Deploy to Fly.io | ||
| env: | ||
| FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }} | ||
| run: flyctl deploy --config apps/streams/fly.toml --remote-only | ||
| - name: Set secrets | ||
| env: | ||
| FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }} | ||
| run: | | ||
| flyctl secrets set \ | ||
| ANTHROPIC_API_KEY="${{ secrets.ANTHROPIC_API_KEY }}" \ | ||
| DURABLE_STREAM_AUTH_TOKEN="${{ secrets.DURABLE_STREAM_AUTH_TOKEN }}" \ | ||
| --app superset-stream |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n .github/workflows/deploy-production.yml | sed -n '400,425p'Repository: superset-sh/superset
Length of output: 1054
🌐 Web query:
flyctl secrets set --stage flag documentation
💡 Result:
flyctl secrets set supports a --stage flag.
- CLI reference (fly secrets set):
--stage— “Set secrets but skip deployment for machine apps”. (fly.io) - Concept/docs (Secrets and Fly Apps): Using
--stageupdates the app’s secret vault but defers updating/restarting Machines; the staged secret becomes available only on Machines started/updated after staging. To apply staged secrets without rebuilding, usefly secrets deploy(or trigger a release viafly deploy). (fly.io)
Citations:
- 1: https://fly.io/docs/flyctl/secrets-set/?utm_source=openai
- 2: https://fly.io/docs/apps/secrets/?utm_source=openai
Secrets are set after deploy — first deployment will start without required env vars.
flyctl secrets set runs after flyctl deploy, so on the initial deployment the app boots without ANTHROPIC_API_KEY and DURABLE_STREAM_AUTH_TOKEN. Since env.ts requires both via z.string() (no .optional()), the process will crash on startup.
Additionally, flyctl secrets set triggers a re-deploy by default, causing a redundant second deployment. Use --stage to set secrets without triggering deployment, then apply them during deploy:
Suggested fix: stage secrets before deploy
steps:
- uses: actions/checkout@v4
- uses: superfly/flyctl-actions/setup-flyctl@master
+ - name: Stage secrets
+ env:
+ FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
+ run: |
+ flyctl secrets set \
+ ANTHROPIC_API_KEY="${{ secrets.ANTHROPIC_API_KEY }}" \
+ DURABLE_STREAM_AUTH_TOKEN="${{ secrets.DURABLE_STREAM_AUTH_TOKEN }}" \
+ --app superset-stream \
+ --stage
- name: Deploy to Fly.io
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
run: flyctl deploy --config apps/streams/fly.toml --remote-only
- - name: Set secrets
- env:
- FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
- run: |
- flyctl secrets set \
- ANTHROPIC_API_KEY="${{ secrets.ANTHROPIC_API_KEY }}" \
- DURABLE_STREAM_AUTH_TOKEN="${{ secrets.DURABLE_STREAM_AUTH_TOKEN }}" \
- --app superset-stream🤖 Prompt for AI Agents
In @.github/workflows/deploy-production.yml around lines 409 - 420, Move the
"Set secrets" step to run before the "Deploy to Fly.io" step and use staging to
avoid a redundant redeploy: invoke "flyctl secrets set" with the "--stage" flag
to stage ANTHROPIC_API_KEY and DURABLE_STREAM_AUTH_TOKEN (instead of setting
them after deploy), then run "flyctl deploy" afterwards; keep the workflow step
names "Set secrets" and "Deploy to Fly.io" but ensure the secrets step runs
first and uses "--stage" so the initial deployment has the required env vars
without triggering a second automatic deploy.
Rename DURABLE_STREAM_AUTH_TOKEN → STREAMS_SECRET and DURABLE_STREAM_URL → STREAMS_URL to match existing naming conventions (ELECTRIC_SECRET, ELECTRIC_URL). Use createEnv() from @t3-oss/env-core for required env validation.
Move all process.env reads into the validated env.ts module so every env access goes through createEnv() with type safety.
- INTERNAL_PORT → STREAMS_INTERNAL_PORT - CLAUDE_AGENT_PORT → STREAMS_AGENT_PORT - DURABLE_STREAMS_URL → STREAMS_INTERNAL_URL - DURABLE_STREAMS_DATA_DIR → STREAMS_DATA_DIR - Remove CLAUDE_MODEL and CLAUDE_BINARY_PATH from env.ts (dev-only overrides that don't need validation)
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@docs/productionize-chat.md`:
- Around line 67-80: The doc uses stale env names DURABLE_STREAM_AUTH_TOKEN and
DURABLE_STREAM_URL while the code expects STREAMS_SECRET and STREAMS_URL; update
every occurrence of DURABLE_STREAM_AUTH_TOKEN → STREAMS_SECRET and
DURABLE_STREAM_URL → STREAMS_URL in the document (including the flyctl secrets
set snippet, the "Secrets to add to GitHub" list, and the ".env.example"
section) and ensure the example values and descriptions reflect STREAMS_SECRET
as a bearer/secret token and STREAMS_URL as the production URL so names match
the runtime code (search for both old names and replace with the new names used
by env.main.ts / ai-chat/index.ts / apps/streams/src/env.ts).
🧹 Nitpick comments (1)
docs/productionize-chat.md (1)
109-111: Add language specifiers to fenced code blocks.Several fenced code blocks are missing language identifiers, flagged by markdownlint. For example, Line 109 could use
```envor```text, Line 149```text, Line 406```text, etc.Also applies to: 149-152, 175-186, 218-221, 271-276, 406-441
| flyctl secrets set \ | ||
| ANTHROPIC_API_KEY="${{ secrets.ANTHROPIC_API_KEY }}" \ | ||
| DURABLE_STREAM_AUTH_TOKEN="${{ secrets.DURABLE_STREAM_AUTH_TOKEN }}" \ | ||
| --app superset-stream | ||
| env: | ||
| FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }} | ||
| ``` | ||
|
|
||
| **Secrets to add to GitHub:** | ||
| - `DURABLE_STREAM_AUTH_TOKEN` — bearer token for auth (generate a random 64-char string) | ||
|
|
||
| **Env vars to add to `.env.example`:** | ||
| - `DURABLE_STREAM_URL` — production URL (e.g., `https://superset-stream.fly.dev`) | ||
| - `DURABLE_STREAM_AUTH_TOKEN` — bearer token for authenticated requests |
There was a problem hiding this comment.
Stale environment variable names — doc references DURABLE_STREAM_* but code uses STREAMS_*.
The workflow snippet and secrets list reference DURABLE_STREAM_AUTH_TOKEN and DURABLE_STREAM_URL, but the actual code (in env.main.ts, ai-chat/index.ts, and apps/streams/src/env.ts) has been refactored to STREAMS_SECRET and STREAMS_URL. This mismatch will confuse anyone following this plan.
Update all occurrences of DURABLE_STREAM_AUTH_TOKEN → STREAMS_SECRET and DURABLE_STREAM_URL → STREAMS_URL throughout this document (also Lines 103, 147, 195, 219-220, 395, 453, 456).
🤖 Prompt for AI Agents
In `@docs/productionize-chat.md` around lines 67 - 80, The doc uses stale env
names DURABLE_STREAM_AUTH_TOKEN and DURABLE_STREAM_URL while the code expects
STREAMS_SECRET and STREAMS_URL; update every occurrence of
DURABLE_STREAM_AUTH_TOKEN → STREAMS_SECRET and DURABLE_STREAM_URL → STREAMS_URL
in the document (including the flyctl secrets set snippet, the "Secrets to add
to GitHub" list, and the ".env.example" section) and ensure the example values
and descriptions reflect STREAMS_SECRET as a bearer/secret token and STREAMS_URL
as the production URL so names match the runtime code (search for both old names
and replace with the new names used by env.main.ts / ai-chat/index.ts /
apps/streams/src/env.ts).
Add step_setup_streams to generate a unique auth token via openssl rand for each workspace, matching the pattern used for other secrets.
- Move flyctl secrets set before deploy with --stage flag so the first boot has required env vars without triggering a redundant redeploy - Replace DURABLE_STREAM_* with STREAMS_* in productionize-chat.md
Summary
/v1/*routes in streams server (DURABLE_STREAM_AUTH_TOKENenv var)deploy-streamsjob to production workflow (Fly.io)deploy-streams-previewjob to preview workflow with status artifactTest plan
DURABLE_STREAM_AUTH_TOKEN=test-token bun devinapps/streams/curl /health→ 200 (no auth)curl /v1/sessions/test→ 401curl -H "Authorization: Bearer test-token" /v1/sessions/test→ 404 (auth passes)curl /→ 200 (no auth)bun dev→/v1/sessions/testreturns 404 (no auth check)DURABLE_STREAM_AUTH_TOKENsecret to production and preview GitHub environmentsSummary by CodeRabbit
New Features
Chores
Documentation