Skip to content

feat: relayauth integration — JWT verification + scope enforcement#102

Open
khaliqgant wants to merge 2 commits intomainfrom
feat/relayauth-integration
Open

feat: relayauth integration — JWT verification + scope enforcement#102
khaliqgant wants to merge 2 commits intomainfrom
feat/relayauth-integration

Conversation

@khaliqgant
Copy link
Copy Markdown
Member

@khaliqgant khaliqgant commented Mar 24, 2026

Summary

Adds workflow (workflows/integrate-relayauth.ts) to integrate relayauth into relaycast:

  • Replace opaque rk_live_ token auth with relayauth JWT verification via JWKS
  • Scope enforcement: relaycast:channel:read, relaycast:dm:send, etc.
  • Backwards compatible — existing tokens still work as fallback
  • SponsorChain propagated to request context

Depends on

  • @relayauth/sdk (TokenVerifier, ScopeChecker) — not yet published

Run

agent-relay run workflows/integrate-relayauth.ts

🤖 Generated with Claude Code


Open with Devin

Workflow to replace relaycast's opaque token auth with relayauth JWT
verification. Adds scope enforcement (relaycast:channel:read, etc.),
backwards compat with existing rk_live_ tokens, and sponsorChain
propagation.

Depends on: @relayauth/sdk

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 3 potential issues.

View 4 additional findings in Devin Review.

Open in Devin Review

Comment on lines +71 to +75
.step('read-worker', {
type: 'deterministic',
command: `cat ${RELAYCAST}/packages/server/src/worker.ts`,
captureOutput: true,
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 read-worker and read-relayauth-errors steps are orphaned — outputs never consumed

The read-worker step (line 71) and read-relayauth-errors step (line 89) capture file output but are never referenced in any dependsOn array or {{steps.*.output}} template. This means their output is wasted. Notably, read-relayauth-errors reads errors.ts which contains InsufficientScopeError — the exact type the implement-scopes step (line 175) instructs the agent to use for 403 responses. Without this context, the scope-dev agent won't know the error type's API. Similarly, read-worker reads how middleware is wired, which would be useful for the implement-auth step.

Prompt for agents
In workflows/integrate-relayauth.ts, two steps are defined but never consumed:

1. read-worker (line 71-75): Add 'read-worker' to the dependsOn array of the implement-auth step (line 139) and reference its output via {{steps.read-worker.output}} in the implement-auth task template (around line 140-172).

2. read-relayauth-errors (line 89-93): Add 'read-relayauth-errors' to the dependsOn array of the implement-scopes step (line 177) and reference its output via {{steps.read-relayauth-errors.output}} in the implement-scopes task template (around line 178-207), so the scope-dev agent knows about InsufficientScopeError.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +251 to +261
.step('fix', {
agent: 'architect',
dependsOn: ['review'],
task: `Fix any issues from the review and typecheck.

Typecheck: {{steps.run-tests.output}}
Review: {{steps.review.output}}

Fix all issues. Run typecheck again to verify.`,
verification: { type: 'exit_code' },
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 AGENTS.md violation: no steps to update README.md and openapi.yaml for API behavior changes

AGENTS.md requires: "Update README.md and openapi.yaml together when API behavior changes." This workflow introduces JWT authentication and scope-based authorization (new 403 responses on scope failures), which are significant API behavior changes. However, the workflow contains no steps to update README.md or openapi.yaml. The current openapi.yaml (line 7) only documents rk_live_* and at_live_* auth, and README.md has no mention of JWT auth. After this workflow runs, the docs will be stale and out of sync with the new auth behavior.

Prompt for agents
In workflows/integrate-relayauth.ts, add a new step (e.g., 'update-docs') after the 'fix' step that instructs an agent to update README.md and openapi.yaml to document the new JWT authentication method and scope-based authorization. Specifically:

1. Update openapi.yaml to add a new securityScheme for relayauth JWT tokens alongside the existing workspaceKey and agentToken schemes (around openapi.yaml line 27-35), and document the new 403 scope error responses.
2. Update README.md to mention JWT authentication via relayauth as an alternative auth method.

This is required by the AGENTS.md docs hygiene rule: 'Update README.md and openapi.yaml together when API behavior changes.'
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@github-actions
Copy link
Copy Markdown

Preview deployed!

Environment URL
API https://pr102-api.relaycast.dev
Health https://pr102-api.relaycast.dev/health
Observer https://pr102-observer.relaycast.dev/observer

This preview shares the staging database and will be cleaned up when the PR is merged or closed.

Run E2E tests

npm run e2e -- https://pr102-api.relaycast.dev --ci

Open observer dashboard

https://pr102-observer.relaycast.dev/observer

Copy link
Copy Markdown
Member Author

@khaliqgant khaliqgant left a comment

Choose a reason for hiding this comment

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

Review: relayauth integration workflow

Verdict: Needs changes before merge

Issues Found

1. Bug (High): Exit code capture is broken (line 223)
npx turbo typecheck 2>&1 | tail -15; echo "EXIT: $?"$? captures tail's exit code (always 0), not turbo typecheck's. Fix: use set -o pipefail or ${PIPESTATUS[0]}.

2. Orphaned steps (Medium): read-worker and read-relayauth-errors are never consumed
Neither appears in any dependsOn or {{steps.*.output}} template.

3. Missing docs update step (Medium) — JWT auth and 403 responses need README/openapi updates.

4. Hardcoded absolute paths (Low-Medium) — non-portable.

5. Untyped callback (e: any) (Low)

Positives

TDD approach, backwards compat preserved, well-structured DAG, security review step.

Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 2 new potential issues.

View 6 additional findings in Devin Review.

Open in Devin Review

Comment on lines +21 to +22
const RELAYCAST = '/Users/khaliqgant/Projects/AgentWorkforce/relaycast';
const RELAYAUTH = '/Users/khaliqgant/Projects/AgentWorkforce/relayauth';
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Hardcoded local machine paths make workflow unusable for other developers

Lines 21–22 hardcode absolute paths to a specific developer's home directory (/Users/khaliqgant/Projects/AgentWorkforce/...). Since this file is committed to the shared repository, no other developer or CI environment can execute this workflow without manually editing these paths. These should be derived from environment variables, __dirname, or a config file.

Prompt for agents
In workflows/integrate-relayauth.ts lines 21-22, replace the hardcoded absolute paths with values derived from the environment or relative to the repository root. For example, use process.env.RELAYCAST_DIR and process.env.RELAYAUTH_DIR with sensible defaults based on path.resolve(__dirname, '..') or similar. This ensures the workflow is portable across developer machines and CI environments.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +71 to +75
.step('read-worker', {
type: 'deterministic',
command: `cat ${RELAYCAST}/packages/server/src/worker.ts`,
captureOutput: true,
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 read-worker step output is never consumed by any downstream step

The read-worker step (lines 71–75) reads worker.ts but its output is never referenced via {{steps.read-worker.output}} in any downstream task, and no step lists it in dependsOn. The worker file shows how middleware is mounted and routes are organized—information that would be important for the implement-auth and implement-scopes agents to understand the middleware stack. Without it, the generated code may not integrate correctly with the existing middleware chain.

Prompt for agents
In workflows/integrate-relayauth.ts, the step 'read-worker' at lines 71-75 reads worker.ts but no downstream step consumes its output. Either remove this step if truly unnecessary, or add 'read-worker' to the dependsOn array of 'implement-auth' (line 139) and inject {{steps.read-worker.output}} into its task template so the auth-dev agent understands how middleware is composed in the Hono app.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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