feat: relayauth integration — JWKS verification + path-scoped access#5
feat: relayauth integration — JWKS verification + path-scoped access#5khaliqgant wants to merge 10 commits intomainfrom
Conversation
…E2E infrastructure Extends the Go server with bulk seed/export endpoints, WebSocket file-change notifications, and binary file support. Hardens mount sync with conflict resolution and bidirectional sync. Adds E2E test script, workflow definitions, design docs, and updated TypeScript SDK. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds relayfile-cli with login/mount/seed/export commands, Homebrew tap formula, GitHub Actions release workflow, install script, and user-facing docs (API reference, CLI design, guides). Updates .gitignore to exclude compiled binaries and agent tool configs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds OIDC-based npm publish with provenance for the TypeScript SDK. Includes npm update step per prpm trusted publishing guidance to avoid outdated npm versions on runners. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds dedicated GitHub Actions workflows for CI (tests + typecheck), npm publishing, and Go binary releases. Updates SDK package.json, tsconfig, and README. Adds CI/CD design doc. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds sdk/relayfile package that downloads the correct platform binary on install, so users can `npx relayfile` or `npm install -g relayfile`. Updates publish-npm workflow to use OIDC (no NPM_TOKEN), adds npm update step, and publishes both @relayfile/sdk and relayfile packages with version sync. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Configures root package.json with workspaces pointing to sdk/relayfile-sdk and sdk/relayfile. Makes CLI postinstall non-fatal so installs work before a release binary exists. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Renames sdk/relayfile-sdk and sdk/relayfile to packages/. Updates all workflow files, GitHub Actions, and package.json references to use the new paths. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Provenance only works in CI with OIDC — removing from package.json so local publishes work. CI workflows already pass --provenance explicitly. Also normalizes repository URLs to avoid npm publish warnings. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Workflow to add relayauth JWT verification to the Go server and mount daemon. Path-scoped access (relayfile:fs:write:/src/api/*), JWKS caching, backwards compat with existing relayfile JWTs. Depends on: @relayauth/sdk (for types reference), Go JWKS verification Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| case "tar": | ||
| if err := s.writeTarExport(w, visible); err != nil { | ||
| writeError(w, http.StatusInternalServerError, "internal_error", err.Error(), correlationID) | ||
| } |
There was a problem hiding this comment.
🔴 Tar export sends HTTP 200 before writing, making error responses impossible
writeTarExport calls w.WriteHeader(http.StatusOK) at internal/httpapi/server.go:2033 before writing tar entries. If tw.WriteHeader or tw.Write fails afterward (lines 2047-2051), the error is returned to handleExport at internal/httpapi/server.go:1429-1430, which calls writeError with status 500. However, since WriteHeader(200) was already called, Go's HTTP server silently ignores the second WriteHeader(500) call. The client receives a truncated/corrupt tar file with a 200 OK status, making the failure invisible to the caller.
Prompt for agents
In internal/httpapi/server.go, the handleExport function at line 1428-1431 calls writeTarExport which sends a 200 OK header before writing tar content. If tar writing fails after that, the writeError call at line 1430 has no effect because the status code was already sent. Fix this by having writeTarExport decode all content BEFORE calling WriteHeader, so that decoding errors can still produce proper error responses. For write errors that occur during streaming (after WriteHeader), either log the error and let the truncated response signal failure to the client, or buffer the entire tar in memory before writing (trading memory for correctness). Remove the writeError call at line 1430 since it cannot meaningfully change the response after WriteHeader was already called inside writeTarExport.
Was this helpful? React with 👍 or 👎 to provide feedback.
| case "", "utf-8", "utf8": | ||
| return "utf-8", nil |
There was a problem hiding this comment.
🟡 normalizeEncoding returns "utf-8" for empty input, making omitempty on File.Encoding ineffective
normalizeEncoding("") returns "utf-8" at internal/relayfile/store.go:3690-3691. This value is stored in File.Encoding (which has json:"encoding,omitempty" at line 76). Because the returned value is non-empty, omitempty never triggers, so every file written via WriteFile or BulkWrite — including plain text files where the caller did not specify encoding — will have "encoding": "utf-8" in JSON responses. Meanwhile, provider-synced files explicitly set Encoding: "" at internal/relayfile/store.go:3259, so they omit the field. This creates an inconsistency: the same text file has different JSON shapes depending on whether it was written by an agent or synced from a provider. The fix is to return "" (empty string) instead of "utf-8" for the default case, letting omitempty omit the field for text files.
| case "", "utf-8", "utf8": | |
| return "utf-8", nil | |
| case "", "utf-8", "utf8": | |
| return "", nil |
Was this helpful? React with 👍 or 👎 to provide feedback.
khaliqgant
left a comment
There was a problem hiding this comment.
Review: relayauth integration (relayfile)
Verdict: Needs changes before merge
This PR bundles ~6 distinct features. Key issues:
Critical/High
- Misleading title — no actual JWKS code; relayauth is only a workflow definition. Should split into focused PRs.
- Hardcoded local paths in workflow files.
- Duplicate release workflows — both trigger on
v*tags creating races. - Potential deadlock in syncer mutex discipline.
- Silent event dropping with no logging.
Medium
- No bulk write size limits enforced (despite design doc claims).
- WebSocket token in query params (security consideration).
- Homebrew formula has placeholder SHA256s.
- README references old SDK path.
Missing Tests
- CLI tool: 940 lines, zero test coverage.
- No tests for bulk write limits, WebSocket reconnection.
| for i := range files { | ||
| fmt.Fprintf(stdout, "Seeding %d/%d files...\n", i+1, len(files)) | ||
| } |
There was a problem hiding this comment.
🟡 CLI seed prints all progress messages instantly before the bulk upload even starts
The runSeed function at lines 434-436 uses a for i := range files loop that simply iterates over the already-collected files slice and prints "Seeding X/Y files..." for each one. This loop completes instantly before the single bulk API call at line 439. The user sees all progress lines (e.g. "Seeding 1/100", "Seeding 2/100", ..., "Seeding 100/100") dumped at once, then a pause while the actual upload happens. The loop should either be removed (since all files are sent in one request) or the progress should be tied to actual batched uploads.
| for i := range files { | |
| fmt.Fprintf(stdout, "Seeding %d/%d files...\n", i+1, len(files)) | |
| } | |
| fmt.Fprintf(stdout, "Seeding %d files...\n", len(files)) | |
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
Adds workflow (
workflows/integrate-relayauth.ts) to integrate relayauth into relayfile:relayfile:fs:write:/src/api/*restricts file writes to matching paths--tokenflagfromRelayAuth()factory for relayauth-authenticated clientsDepends on
@relayauth/sdktypes (for token format reference)Run
🤖 Generated with Claude Code