Skip to content

feat(streams): add bearer token auth and CI/CD deployment pipelines#1343

Merged
Kitenite merged 14 commits into
mainfrom
kitenite/productize-chat
Feb 9, 2026
Merged

feat(streams): add bearer token auth and CI/CD deployment pipelines#1343
Kitenite merged 14 commits into
mainfrom
kitenite/productize-chat

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Feb 9, 2026

Summary

  • Add bearer token auth middleware on /v1/* routes in streams server (DURABLE_STREAM_AUTH_TOKEN env var)
  • Add deploy-streams job to production workflow (Fly.io)
  • Add deploy-streams-preview job to preview workflow with status artifact
  • Add streams cleanup step to preview cleanup workflow
  • Add Streams row to preview comment template
  • Add SIGTERM handler for graceful Fly.io shutdown

Test plan

  • Verify auth works locally: DURABLE_STREAM_AUTH_TOKEN=test-token bun dev in apps/streams/
    • curl /health → 200 (no auth)
    • curl /v1/sessions/test → 401
    • curl -H "Authorization: Bearer test-token" /v1/sessions/test → 404 (auth passes)
    • curl / → 200 (no auth)
  • Verify auth disabled when no token: bun dev/v1/sessions/test returns 404 (no auth check)
  • Add DURABLE_STREAM_AUTH_TOKEN secret to production and preview GitHub environments
  • Push to PR branch and verify preview deployment includes Streams row

Summary by CodeRabbit

  • New Features

    • Added Streams deployment and preview support with PR preview links and status reporting.
    • Added optional Bearer-token authentication for Streams API endpoints.
  • Chores

    • Centralized and renamed Streams-related environment configuration for desktop and server.
    • Added CI cleanup step to remove Streams preview apps.
  • Documentation

    • New productionization plan and updated docs for Streams deployment, env vars, and integration.

Add authentication middleware on /v1/* routes and wire streams into
production, preview, and cleanup deployment workflows on Fly.io.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 9, 2026

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds 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

Cohort / File(s) Summary
CI/CD Workflows & Templates
​.github/templates/preview-comment.md, ​.github/workflows/cleanup-preview.yml, ​.github/workflows/deploy-preview.yml, ​.github/workflows/deploy-production.yml
Insert Streams row into preview comment template; add preview deploy job, artifact/status wiring, and cleanup step for Streams; add production Fly.io deploy job; wire STREAMS_STATUS/STREAMS_LINK into preview comment flow.
Streams Service Source & Config
apps/streams/src/env.ts, apps/streams/src/index.ts, apps/streams/src/server.ts, apps/streams/src/claude-session-store.ts, apps/streams/src/claude-agent.ts
Add centralized env validation/export (env); switch runtime to use STREAMS_* envs; add authToken option and conditional Bearer auth middleware for /v1/*; update data dir, ports, base URL, and remove some legacy binary/model/env fallbacks.
Streams Package
apps/streams/package.json
Add dependency @t3-oss/env-core.
Desktop Client Integration
apps/desktop/src/main/env.main.ts, apps/desktop/src/lib/trpc/routers/ai-chat/index.ts, apps/desktop/src/lib/trpc/routers/ai-chat/utils/session-manager/session-manager.ts
Expose STREAMS_URL and STREAMS_SECRET in desktop env schema; switch proxy URL to STREAMS_URL and consolidate Authorization header to use STREAMS_SECRET.
Docs / Plans
docs/ai-chat-plan.md, docs/productionize-chat.md
Document env-driven Streams configuration, auth requirements, productionization phases, deployment snippets, and operational checklist.

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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I fetched the keys and made them sing,
I nudged the Streams to take to wing,
Tokens wrapped, the proxy hums,
Claude replies and onward runs —
Hop, deploy, and share the spring ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The PR description covers the key changes but is missing several required template sections like Related Issues and Type of Change. It provides a summary and test plan but lacks complete alignment with the template structure. Fill in the missing template sections: specify Related Issues, select Type of Change checkboxes, add Testing section with detailed steps, and include any Additional Notes relevant to deployment.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main changes: adding bearer token auth and CI/CD deployment pipelines for the streams service.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch kitenite/productize-chat

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Create env.ts with zod schema that validates DURABLE_STREAM_AUTH_TOKEN
and ANTHROPIC_API_KEY as required, replacing raw process.env reads.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 9, 2026

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch
  • ✅ Electric Fly.io app
  • ✅ Streams Fly.io app

Thank you for your contribution! 🎉

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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),

Comment thread .github/workflows/deploy-production.yml Outdated
Comment on lines +409 to +420
- 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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 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 --stage updates 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, use fly secrets deploy (or trigger a release via fly deploy). (fly.io)

Citations:


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.

Comment thread apps/streams/src/env.ts Outdated
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)
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 ```env or ```text, Line 149 ```text, Line 406 ```text, etc.

Also applies to: 149-152, 175-186, 218-221, 271-276, 406-441

Comment thread docs/productionize-chat.md Outdated
Comment on lines +67 to +80
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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

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_TOKENSTREAMS_SECRET and DURABLE_STREAM_URLSTREAMS_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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant