Skip to content

fix(server): T3 Connect links even when the host clock is off - #19036

Open
shivamhwp wants to merge 1 commit into
pingdotgg:mainfrom
shivamhwp:t3android/issue-19034
Open

shivamhwp wants to merge 1 commit into
pingdotgg:mainfrom
shivamhwp:t3android/issue-19034

Conversation

@shivamhwp

@shivamhwp shivamhwp commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

T3 Connect link proofs were dated with the host clock, so a host ten minutes ahead issued a proof from the relay's future and a host ten minutes behind issued an expired one (#19034).

The shared HTTP/CLI signer (makeCloudLinkProof) now takes iat from the relay challenge and sets exp 300 seconds later. A missing, non-numeric, non-positive or unsafe challenge iat falls back to host time. The server only borrows the timestamp: the relay still verifies the embedded challenge's signature, age, issuer, audience, user and capabilities, and consumes both nonces, so a forged challenge gains nothing.

Verification at 72fc0738ac (one commit on 05b697f6a2):

  • Two regression tests in CloudLink.lifecycle.test.ts run the real CloudLink service with the clock 600 s ahead and 600 s behind, then verify the proof with the shared relay verifier at relay time. With the fix reverted they fail (iat in the future / proof expired); with it they pass. Both CloudLink suites: 38 passing.
  • Server typecheck, lint, format and knip pass locally; CI is green on this head.
  • An independent Codex (GPT-6.1 Sol) review of this head found no blocking issues.

Not verified: CLI reconciliation, relay HTTP/session auth and the full linking flow end to end, a deployed relay, real tunnel provisioning, and native or desktop clients. An isolated runtime run of the signer, relay token verifier and EnvironmentLinker passed at the earlier head 04d0d5296a (transcript); it was not rerun at this head. This is a server-only change with no visual surface.

Human gate: this changes how signed link proofs are dated, and Macroscope's approvability verdict asks for a maintainer to approve that timestamp policy.

Original author: @shivamhwp; rebuilt by @juliusmarminge; rebased onto main by Claude Opus 5.5 in T3 Code.

🤖 Generated with Claude Code

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Oct 13, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs Human Approval

Macroscope's review found this PR requires human approval — This focused bug fix changes production link-proof JWT timestamps by deriving them from relay-issued challenge claims, directly affecting authentication and relay acceptance. The clock-skew regressions are well targeted, but the authentication timestamp policy warrants human review.

You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Path: .coderabbit.config.ts
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: d6d49111-c405-4d38-ab57-c6f381095300
📥 Commits

Reviewing files that changed from the base of the PR and between 4ad5a93 and 72fc073.

📒 Files selected for processing: 2
  • apps/server/src/cloud/CloudLink.lifecycle.test.ts
  • apps/server/src/cloud/CloudLink.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 4 remain after this review.

📝 Walkthrough

Cloud link proof generation now uses a valid relay challenge iat, falls back to the current time when needed, and sets exp five minutes later. Lifecycle tests check proof verification when the host clock differs from relay time by 600 seconds.

Changes: Cloud link proof timestamps

Layer / File(s) Summary
Derive and verify proof timestamps
apps/server/src/cloud/CloudLink.ts, apps/server/src/cloud/CloudLink.lifecycle.test.ts
makeCloudLinkProof derives iat from a valid relay challenge claim and sets exp five minutes later. Lifecycle tests verify proof claims at relay time with the host clock 600 seconds ahead or behind.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: juliusmarminge

Merge Risk: ⚪ Minimal · up to 72fc0

No actionable issue remains from this review; the change is mergeable after normal approval and checks.

Architecture risk: 🔵 Low · up to 4ad5a

The change affects 1 system.

Changed systems: apps/server

Architecture concerns
No architecture-level concerns identified.

Review details

Systems and components

  • observed — apps/server (service) was modified; 3 changed files map to changed impact.

Before / after behavior

  • observed — Modified behavior in apps/server/src/cloud/linkChecks.test.ts: Added imports for relay JWT signing and verification, Effect and Result utilities, and JOSE key generation and export to support the new lifetime tests.
  • observed — Modified behavior in apps/server/src/cloud/linkChecks.test.ts: Added linkProofLifetime tests using generated EdDSA keys and signed relay challenges. A usable challenge iat determines the proof's iat and its exp is 300 seconds later; verification at the relay time succeeds, while verification using a fast host time fails. Invalid or missing challenge iat values fall back to the host time.
  • observed — Modified behavior in apps/server/src/cloud/linkChecks.ts: The file now imports decodeRelayJwt for decoding relay challenge tokens.
  • observed — Modified behavior in apps/server/src/cloud/linkChecks.ts: Adds linkProofLifetime, which takes the challenge’s positive safe-integer iat when available, otherwise falls back to nowSeconds, and sets exp to iat plus the five-minute maximum. challengeIssuedAt returns null if decoding throws or the claim is missing, nonnumeric, unsafe, or not positive.
Pre-merge checks: Passed 3 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Description check Warning The description clearly explains the problem, implementation, testing, limitations, and need for maintainer approval. However, it does not use the required Problem, Change, Scope and approval, and Ver… Rewrite the description using all template headings. Add the triaged issue or maintainer approval discussion with the approval comment. Keep the detailed verification results and unverified areas under Verification. End the description with…
Passed Passed checks: 3 passed
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main fix: allowing T3 Connect links to work when the host clock differs from the relay clock.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description clearly explains the problem, implementation, testing, limitations, and need for maintainer approval. However, it does not use the required Problem, Change, Scope and approval, and Verification headings. It also does not provide the required approval link or approval comment, and the agent attribution does not clearly identify both the model and harness.

Resolution

Rewrite the description using all template headings. Add the triaged issue or maintainer approval discussion with the approval comment. Keep the detailed verification results and unverified areas under Verification. End the description with the model and harness used for agent work.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@shivamhwp
shivamhwp force-pushed the t3android/issue-19034 branch from feb60e7 to 4ad5a93 Compare October 14, 2026 04:53
@juliusmarminge juliusmarminge self-assigned this Oct 19, 2026
@juliusmarminge

Copy link
Copy Markdown
Member

Taking over this one as maintainer for batch ssh-relay-remote-04. I will merge main into the original branch, rebuild the proof timestamp change with separate tests and implementation, and run independent adversarial reviews. Verification will cover clocks ahead and behind with the actual cloud-link service and relay verification where available. Authentication policy approval and unverified native/hosted flows will remain explicit. This will remain unmerged.

@github-actions github-actions Bot added size:S 10-29 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Oct 19, 2026
Link proofs were dated with the host clock, so a host running ahead issued
a proof from the relay's future and one running behind issued an expired
proof. The proof now takes its `iat` from the relay challenge and expires
300 seconds later, falling back to host time when the challenge timestamp
is unusable. The relay still verifies and consumes the challenge.

Rebased onto main as one commit; the regression tests now provide the
authenticated principal that linkProof requires since pingdotgg#19271.

Co-authored-by: shivamhwp <shivamhwp@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shivamhwp
shivamhwp force-pushed the t3android/issue-19034 branch from 04d0d52 to 72fc073 Compare October 22, 2026 04:13

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S 10-29 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants