Repository navigation
Add the authenticated Iroh trust broker and relay minter - #7840
azooz2003-bit wants to merge 44 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
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 complete Iroh trust broker with cryptographic pairing and attestation flows, PostgreSQL persistence and retention, authenticated Next.js routes, isolated Rust relay-token minting, deployment configuration, protocol documentation, and extensive tests. ChangesIroh trust broker
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Sequence Diagram(s)sequenceDiagram
participant Client
participant IrohRoute
participant IrohTrustBroker
participant IrohRepository
participant IrohRelayMinter
Client->>IrohRoute: Authenticated Iroh request
IrohRoute->>IrohTrustBroker: Dispatch operation
IrohTrustBroker->>IrohRepository: Validate or update binding state
IrohRepository-->>IrohTrustBroker: Binding, challenge, or issuance result
IrohTrustBroker->>IrohRelayMinter: Mint relay token when required
IrohRelayMinter-->>IrohTrustBroker: Token and expiry
IrohTrustBroker-->>IrohRoute: Broker response
IrohRoute-->>Client: JSON response
Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 error, 1 warning)
✅ Passed checks (23 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 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 |
Greptile SummaryThis PR adds an authenticated Iroh trust broker and relay-token minter. The main changes are:
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (17): Last reviewed commit: "fix(iroh): use public host for firewall ..." | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/iroh-offline-pairing-v1.md`:
- Around line 86-95: Add the pending privacy review for pseudonymous attestation
correlation to the “Release gate” checklist, alongside the existing Swift-client
requirements, explicitly requiring resolution before release.
In `@web/services/iroh/crypto.ts`:
- Around line 134-150: Update verifyEndpointRegistrationSignature to decode
input.signature with decodeCanonicalBase64url, matching verifyPairGrant,
verifyEndpointAttestation, and offline-pair proof verification; enforce the
canonical base64url format and exact 64-byte length before passing the result to
node:crypto verify.
In `@web/services/iroh/errors.ts`:
- Around line 53-63: Replace the description-based symbol lookup in
irohExpectedError with the exported FiberFailureCauseId from effect/Runtime,
confirming it is available in effect@3.21.2. Import and access
error[FiberFailureCauseId] directly, then pass the cause to errorFromCause when
present, removing the Object.getOwnPropertySymbols search.
In `@web/services/iroh/relayMinter.ts`:
- Around line 44-101: The catch handler in the relay minting Effect incorrectly
converts IrohInvalidInputError from endpointId into minter_unavailable. Update
the catch logic in the Effect.tryPromise block to explicitly preserve and return
IrohInvalidInputError, or move endpointId validation before tryPromise, ensuring
invalid endpoint IDs surface as invalid_endpoint_id.
In `@web/services/iroh/trustBroker.ts`:
- Around line 276-281: Extract the existing grantSigningKid presence and
/^[A-Za-z0-9._-]{1,64}$/ format check from issuePairGrant into a shared
validation helper, preserving the IrohConfigurationError behavior. Use this
helper in both issuePairGrant and issueEndpointAttestation before passing the
value to signing or verification-key logic, including the
signEndpointAttestation path.
In `@web/tests/iroh-db-behavior.test.ts`:
- Around line 483-496: Remove the FinalizeEndpointAttestation type declaration,
defensive cast, runtime type assertion, and early return in the “fails
attestation finalization when revocation commits during signing” test; use the
already-typed repository.finalizeEndpointAttestation method directly, matching
the earlier test in this file.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 5046591a-d285-4950-9f74-d67c1e8944a4
⛔ Files ignored due to path filters (1)
services/iroh-relay-minter/Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (41)
.github/workflows/iroh-relay-minter.ymldocs/iroh-offline-pairing-v1.mdservices/iroh-relay-minter/.env.exampleservices/iroh-relay-minter/.gitignoreservices/iroh-relay-minter/Cargo.tomlservices/iroh-relay-minter/README.mdservices/iroh-relay-minter/api/relay-token.rsservices/iroh-relay-minter/rust-toolchain.tomlservices/iroh-relay-minter/src/lib.rsservices/iroh-relay-minter/vercel.jsontests/fixtures/iroh/path-hint-v1.jsontests/fixtures/iroh/relay-minter-request-v1.jsonweb/.env.exampleweb/app/api/account/route.tsweb/app/api/devices/iroh/challenge/route.tsweb/app/api/devices/iroh/endpoint-attestations/route.tsweb/app/api/devices/iroh/pair-grants/route.tsweb/app/api/devices/iroh/register/route.tsweb/app/api/devices/iroh/relay-token/route.tsweb/app/api/devices/iroh/route.tsweb/app/api/internal/iroh/retention/route.tsweb/app/env.tsweb/db/migrations/20260709000000_iroh_trust_broker/migration.sqlweb/db/migrations/20260710000000_iroh_trust_broker_hardening/migration.sqlweb/db/migrations/20260710010000_iroh_trust_broker_review_hardening/migration.sqlweb/db/schema.tsweb/services/iroh/README.mdweb/services/iroh/config.tsweb/services/iroh/crypto.tsweb/services/iroh/errors.tsweb/services/iroh/model.tsweb/services/iroh/relayMinter.tsweb/services/iroh/repository.tsweb/services/iroh/routeHandler.tsweb/services/iroh/trustBroker.tsweb/tests/client-config-env.test.tsweb/tests/iroh-db-behavior.test.tsweb/tests/iroh-model-crypto.test.tsweb/tests/iroh-route-handler.test.tsweb/tests/iroh-trust-broker.test.tsweb/vercel.json
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@web/.env.example`:
- Around line 47-63: Reorder the CMUX_IROH entries in the environment template
alphabetically by variable name to satisfy dotenv-linter, including placing
ACCOUNT_SUBJECT_SECRET_B64 after LAN_DISCOVERY_SECRET_B64 and MINT_URL before
MINT_HMAC_SECRET_B64; preserve all comments and values.
In
`@web/db/migrations/20260710113000_iroh_relay_reservation_expiry/migration.sql`:
- Around line 4-6: Update the constraint definition in the migration to add the
CHECK constraint with NOT VALID, then add a subsequent VALIDATE CONSTRAINT
statement for iroh_relay_token_issuances_status_check so existing rows are
checked separately from constraint creation.
In `@web/services/iroh/config.ts`:
- Line 38: Update the configuration construction in the relevant config module
so deploymentEnvironment is sourced from the validated env object, matching the
other fields, rather than reading process.env directly. Add VERCEL_ENV and
NODE_ENV to the validated exports in the env module if needed, then use those
values with the existing fallback semantics while preserving the
deviceLimitOverrideAllowed behavior.
In `@web/services/iroh/model.ts`:
- Around line 271-276: Remove the redundant `kind === "relay_url" && source !==
"native"` check and its `IrohInvalidInputError` throw after `managedRelayUrl`;
rely on `managedRelayUrl` to reject non-native relay hints while preserving the
existing `hintValue` behavior.
In `@web/services/iroh/routeHandler.ts`:
- Around line 70-89: Wrap the broker Effect executed in the try block of the
route handler with an application-level Effect.timeout using the service’s
appropriate request deadline, covering both the injected broker and
runtime-provided broker paths. Handle timeout failures through the existing
irohExpectedError/JSON error flow so requests return a clean response instead of
waiting for the platform timeout.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 59ddf908-811e-44a6-8d88-9379dbe827a4
⛔ Files ignored due to path filters (1)
services/iroh-relay-minter/Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (42)
.github/workflows/iroh-relay-minter.ymldocs/iroh-offline-pairing-v1.mdservices/iroh-relay-minter/.env.exampleservices/iroh-relay-minter/.gitignoreservices/iroh-relay-minter/Cargo.tomlservices/iroh-relay-minter/README.mdservices/iroh-relay-minter/api/relay-token.rsservices/iroh-relay-minter/rust-toolchain.tomlservices/iroh-relay-minter/src/lib.rsservices/iroh-relay-minter/vercel.jsontests/fixtures/iroh/path-hint-v1.jsontests/fixtures/iroh/relay-minter-request-v1.jsonweb/.env.exampleweb/app/api/account/route.tsweb/app/api/devices/iroh/challenge/route.tsweb/app/api/devices/iroh/endpoint-attestations/route.tsweb/app/api/devices/iroh/pair-grants/route.tsweb/app/api/devices/iroh/register/route.tsweb/app/api/devices/iroh/relay-token/route.tsweb/app/api/devices/iroh/route.tsweb/app/api/internal/iroh/retention/route.tsweb/app/env.tsweb/db/migrations/20260709000000_iroh_trust_broker/migration.sqlweb/db/migrations/20260710000000_iroh_trust_broker_hardening/migration.sqlweb/db/migrations/20260710010000_iroh_trust_broker_review_hardening/migration.sqlweb/db/migrations/20260710113000_iroh_relay_reservation_expiry/migration.sqlweb/db/schema.tsweb/services/iroh/README.mdweb/services/iroh/config.tsweb/services/iroh/crypto.tsweb/services/iroh/errors.tsweb/services/iroh/model.tsweb/services/iroh/relayMinter.tsweb/services/iroh/repository.tsweb/services/iroh/routeHandler.tsweb/services/iroh/trustBroker.tsweb/tests/client-config-env.test.tsweb/tests/iroh-db-behavior.test.tsweb/tests/iroh-model-crypto.test.tsweb/tests/iroh-route-handler.test.tsweb/tests/iroh-trust-broker.test.tsweb/vercel.json
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
web/db/migrations/20260710113000_iroh_relay_reservation_expiry/migration.sql (1)
1-9: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick winSplit the constraint add and validation into separate migrations
ALTER TABLE ... ADD CONSTRAINT ... NOT VALIDstill takes anACCESS EXCLUSIVElock, and Drizzle runs each Postgres migration file in a transaction, soVALIDATE CONSTRAINThere still keeps readers blocked until commit. Split the add and validate steps into separate migration files if this is meant to be a zero-downtime pattern for populated tables.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/db/migrations/20260710113000_iroh_relay_reservation_expiry/migration.sql` around lines 1 - 9, Split the constraint change currently represented by the iroh relay reservation expiry migration into two sequential migration files: one that drops and re-adds the status check constraint as NOT VALID, and a later one that runs VALIDATE CONSTRAINT. Ensure the migration ordering guarantees validation occurs only after the add migration has committed.Source: Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In
`@web/db/migrations/20260710113000_iroh_relay_reservation_expiry/migration.sql`:
- Around line 1-9: Split the constraint change currently represented by the iroh
relay reservation expiry migration into two sequential migration files: one that
drops and re-adds the status check constraint as NOT VALID, and a later one that
runs VALIDATE CONSTRAINT. Ensure the migration ordering guarantees validation
occurs only after the add migration has committed.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: ceba8ceb-7797-49d9-b2ef-79cf1e2ec6a9
📒 Files selected for processing (9)
docs/iroh-offline-pairing-v1.mdweb/db/migrations/20260710113000_iroh_relay_reservation_expiry/migration.sqlweb/services/iroh/crypto.tsweb/services/iroh/errors.tsweb/services/iroh/model.tsweb/services/iroh/relayMinter.tsweb/services/iroh/trustBroker.tsweb/tests/iroh-db-behavior.test.tsweb/tests/iroh-model-crypto.test.ts
💤 Files with no reviewable changes (1)
- web/services/iroh/model.ts
…v URLs Replaces the 4 hosted iroh.link relays with our self-hosted fleet in both allowlists (web MANAGED_RELAY_URLS + presence worker APPROVED_IROH_RELAY_URLS, kept in lockstep) and the tests that referenced hosted URLs. The self-hosted relays run iroh-relay 1.0.2 behind per-region MIG+L4-LB (zero-downtime upgrades), gated by the cmux EdDSA JWT that /api/relay/token (merged, #7879) mints.
iroh broker: use the 7 self-hosted relay.cmux.dev relays
e6f1aee to
695de0c
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit ac4decb. Configure here.
| return hostname === "localhost" || | ||
| hostname === "127.0.0.1" || | ||
| hostname === "[::1]"; | ||
| } |
There was a problem hiding this comment.
IPv6 loopback host check broken
Low Severity
isCanonicalLoopbackHost compares against `[::1]`, but WHATWG URL.hostname returns IPv6 addresses without brackets (::1). An opted-in local HTTP minter URL using IPv6 loopback is therefore rejected even though tests and the policy treat that form as allowed; localhost and 127.0.0.1 still work.
Reviewed by Cursor Bugbot for commit ac4decb. Configure here.


Summary
Security properties
Verification
bun test tests/iroh-model-crypto.test.ts tests/iroh-trust-broker.test.ts tests/iroh-route-handler.test.ts tests/client-config-env.test.ts: 72 passedbun run db:test: migrations applied twice and 141 database behavior tests passedbun run typecheck: passedcargo fmt --check: passedcargo clippy --all-targets --locked -- -D warnings: passedcargo test --locked: 10 passed./scripts/reload.sh --tag irhbk1: tagged macOS build passedDeployment is intentionally separate. The planning credential must be rotated before production, then migrations, minter secrets, and web secrets can be applied in order.
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.Note
High Risk
New auth, pairing, grant signing, and relay minting paths with many secrets and DB invariants; misconfiguration or broker/minter bugs could affect device trust and relay access.
Overview
Introduces personal-account Iroh end-to-end: a TypeScript trust broker on the web app, an isolated Rust relay-token minter, schema/migrations, and a v1 offline same-account pairing spec.
The broker adds authenticated routes under
/api/devices/iroh(discovery, challenge/register, pair grants, endpoint attestations, relay-token brokerage, revocation) plus cron-gated/api/internal/iroh/retention. It persists bindings, challenges, grant/relay issuance audit rows, and account security state; account deletion now cascades those tables. Route publication for devices is tightened so server-stored Iroh presence keeps only approved relay hints (legacy non-Iroh routes unchanged). Env gains required broker secrets (LAN discovery, account subject, Ed25519 grant signing/verification, rate-limit id) and optional minter URL/HMAC; the Iroh Services API key is explicitly not on the web project.services/iroh-relay-minteris a new Vercel Rust function:POST /api/relay-tokenwith HMAC-SHA256 over method/path/timestamp/body hash, 30s clock skew, optional previous HMAC during rotation, and mints 24hrelay:useRCANs viairoh-services. CI (.github/workflows/iroh-relay-minter.yml) runs fmt/clippy/test/release build. Migrations add indexes, path-hint expiry, relay reservationexpiredstatus, and a one-time wipe of legacy server-held Iroh path hints / device Iroh routes before relay-only publication.Reviewed by Cursor Bugbot for commit ac4decb. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by cubic
Adds an authenticated Iroh trust broker and an optional Rust relay‑token minter for same‑account offline pairing and managed relay access using our 7 self‑hosted
relay.cmux.devrelays. Enforces server and presence route privacy by storing/publishing only EndpointID + an approved relay URL; the legacy hosted minter is no longer required.New Features
challenge,register,discover,revoke,endpoint_attestation,pair_grant,relay_token.ALPN, scope, expiry; replay protection; linearized auth/revocation/deletion; serialized LAN discovery; globally unique active EndpointIDs.relay:useRCAN via an isolated Rust minter (services/iroh-relay-minter) with bounded HMAC rotation, dev‑only insecure loopback opt‑in, and CI at.github/workflows/iroh-relay-minter.yml; broker/worker enforce the 7 self‑hostedrelay.cmux.devURLs./api/internal/iroh/retention(abandoned reservations auto‑expire asexpired); canonical errors;@vercel/firewallrate‑limit integration with in‑flight caps, timeout recovery, and public‑host fallback; accepts JSON media type parameters; stricter env parsing and DB indexes; deferred reservation constraint validation.Migration
IROH_SERVICES_API_SECRET,CMUX_IROH_MINT_HMAC_SECRET_B64(and optionalCMUX_IROH_MINT_HMAC_PREVIOUS_SECRET_B64during rotation).CMUX_IROH_LAN_DISCOVERY_SECRET_B64,CMUX_IROH_ACCOUNT_SUBJECT_SECRET_B64,CMUX_IROH_GRANT_SIGNING_KEY_P8,CMUX_IROH_GRANT_SIGNING_KID,CMUX_IROH_GRANT_VERIFICATION_KEYS_JSON, and (only if minting via the hosted service)CMUX_IROH_MINT_URL,CMUX_IROH_MINT_HMAC_SECRET_B64, plusCMUX_IROH_RATE_LIMIT_ID.CMUX_IROH_DEV_ALLOW_INSECURE_LOOPBACK_MINTER=1and run the loopback minter (examples/loopback.rs, portCMUX_IROH_MINT_DEV_PORT); keep HTTPS in all deployments.Written for commit ac4decb. Summary will update on new commits.
Summary by CodeRabbit