Repository navigation
feat(tokens): sign canonical meta.machineId on History assertions - #113
Conversation
POST /v1/tokens/relayhistory-assertion now takes a machineId and signs it as meta.machineId, so ingest can bind a courier's token to the machine (the manifest key's m= component) on manifest POST and status. - Canonical form: 1-128 chars of [A-Za-z0-9._-], no leading '.', no relay_ alias prefix, exact bytes. Anything needing trimming, case folding or alias stripping is refused (400 invalid_machine_id), never rewritten. null, "" and non-strings are malformed, not missing. - Missing machineId: 400 machineId_required, unless the default-off compat flag RELAYAUTH_ALLOW_RELAYHISTORY_ASSERTION_WITHOUT_MACHINE_ID is exactly "true" (chart: relayhistory.allowMissingMachineId). Such tokens have no meta.machineId and their audit row is flagged machineIdMissing: "true". - The audit row records machineId. - Trust: RelayAuth validates form only and signs what the holder of the dedicated relayauth:assertion:create:relayhistory key (Cloud's broker) asserts after its own authorization, as for orgId/workspaceId/ sponsorId. The route still requires that key over x-api-key (bearer refused), so couriers and other callers cannot choose it. Documented in docs/self-hosting.md. - Not widened: org/workspace/sponsor handling is unchanged. The known cross-org property of this route (orgId/sponsorId from the body) is left as is; a separate hardening is proposed in the PR. Rollout: required by default, so the broker must send machineId before this deploys, or the compat flag must be on for the window. Review: adversarial pass (no new caller can mint, malformed/alias/ whitespace/unicode/oversize values refused under both flag states, flag enables only on exact "true", injected body meta/org fields ignored, claims org/wks/sponsor unchanged) and contextual pass (existing tests, selfhost smoke script, Helm chart, env wiring, docs updated). Validation (local; hosted CI runs on PRs to main): - relayhistory-assertion tests: 114/114 (27 new) - npm test (turbo 16/16): server 714/714, sdk 169/169, ai 70/70, core 19/19, migrate 18/18, relayauth 12/12, types 1/1, root 8/8 - server test:e2e: 40 pass, 0 fail, 93 skipped - turbo typecheck --force 11/11, turbo build --force 9/9 - helm template renders the env only with allowMissingMachineId=true; bash -n scripts/selfhost-smoke.sh OK Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Request contract and validation packages/server/src/routes/tokens.ts |
The assertion request accepts an optional machineId. Validation accepts 1–128 characters from A-Za-z0-9._-, except values starting with . or relay_. Invalid values return 400 invalid_machine_id. |
Assertion and audit metadata packages/server/src/routes/tokens.ts |
Accepted IDs appear in signed assertion metadata and audit records. When the field is omitted, the audit metadata records machineIdMissing: "true". |
Tests and self-hosting examples packages/server/src/__tests__/tokens-route.test.ts, packages/server/src/__tests__/selfhost-keys-issuer-bootstrap.test.ts, scripts/selfhost-smoke.sh, docs/self-hosting.md |
Route tests cover valid, invalid, and omitted IDs, along with authorization and required-claim behavior. The bootstrap test and smoke request supply an ID. The guide documents the format and caller restrictions. |
Estimated code review effort: 3 (Moderate) | ~20 minutes
Change: Feature
Sequence Diagram(s)
sequenceDiagram
participant Caller
participant AssertionRoute
participant issueRelayhistoryAssertion
participant createAssertionAuditEntry
Caller->>AssertionRoute: Assertion request with optional machineId
AssertionRoute->>issueRelayhistoryAssertion: Validated request
issueRelayhistoryAssertion->>createAssertionAuditEntry: machineId for audit metadata
Possibly related PRs
- AgentWorkforce/relayauth#107: Adds the self-hosted assertion flow and files that this change extends.
- AgentWorkforce/relayauth#119: Defines the broker-scope delegation rule referenced by the assertion authorization tests.
Suggested reviewers: khaliqgant, miyaontherelay
Merge Risk: 
Minimal · up to 92a8d
-
The change adds optional machine binding to History assertions. No merge-blocking issue was identified.
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passed-
Full details: Description check
-
Explanation
The pull request description directly explains the added machineId support, validation, audit behavior, authorization boundary, compatibility requirements, and test results. It is relevant to the changeset.
-
Full details: Docstring Coverage
-
Explanation
Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 6 functions across 4 files. (1 skipped: 1 unsupported.)
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
-
Finishing Touches
-
Generate docstrings
-
- Commit to this branch
- Create a new PR
Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
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.
A rabbit checks the token’s trail
A machine ID rides without fail
The signed claims hold what passed the gate
The audit marks an absent state
I nibble clover, pleased and bright
# Conflicts: # charts/relayauth/templates/deployment.yaml # docs/self-hosting.md
|
Takeover update for exact head
Hosted exact-head CI and independent SOC2 review are pending. This PR remains draft. No image publish, deploy, or merge was performed. |
|
Additional exact-head validation on |
|
Hosted validation is now green on exact head |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
[Medium impact] The PR appears safe to merge; no actionable issues were found.
|
Summary
machineIdonPOST /v1/tokens/relayhistory-assertionand sign it asmeta.machineIdwhen present.A-Za-z0-9._-, no leading., and norelay_alias prefix. Invalid values fail withinvalid_machine_id; values are never trimmed or case-folded.machineIdMissing: "true".Security model and compensating control
RelayAuth validates and signs a supplied machine ID but cannot independently know which courier machine a control-plane request represents. The dedicated assertion-key holder remains responsible for deriving the ID from an authenticated courier session. The assertion key must never be given to a courier.
The route already accepts
orgId,workspaceId, andsponsorIdfrom that dedicated broker. This existing cross-org trust boundary is not widened here and remains a residual risk for the control matrix.Machine binding for writes is a consumer control. The 96Bulls ingest path fails closed before mutation when
meta.machineIdis absent or when it differs from eithermanifest.session.machine_idormanifest.writer.delivery_instance_id:The limited claimless compatibility window is read-only, audited, and capped at 72 hours; migration assertions use a separate grant-bound path. RelayHistory Cloud does not currently enforce machine binding, so this PR does not claim that control for Cloud. Audit reviews of
machineIdMissingmust correlategrantedScopesand the consumer operation because legitimate non-machine mints also omit the claim.Exact-head validation (
92a8da72d1a28bed7fbb61ca328e86e42ccb5ff2)The final commit is comment-only; the executed validation was on its code-identical parent
2dd88a12cf8f15d0efb6880111527e20722bdd6c:npm test: 16/16 workspace tasks; server 740/740; root follow-up 8/8.npm run typecheck: 11/11.npx turbo build --force: 9/9, 0 cache hits.helm lint charts/relayauth: 1 chart, 0 failures.git diff --check: clean.No package was published, no service was deployed, no live system was changed, and no credentials were read or written. Hosted exact-head checks and independent review are required before merge.
Agent Relay sessions
claudesession719b5435· opened viagh pr create· last active 2026-10-30codexsession01a18a0b· contributor · pushed commits · last active 2026-10-31