Skip to content

(janitor/dedupe): consolidate HMAC-signed link/state token helpers - #5869

Open
kilo-code-bot[bot] wants to merge 1 commit into
mainfrom
janitor/dedupe-signed-tokens
Open

(janitor/dedupe): consolidate HMAC-signed link/state token helpers#5869
kilo-code-bot[bot] wants to merge 1 commit into
mainfrom
janitor/dedupe-signed-tokens

Conversation

@kilo-code-bot

@kilo-code-bot kilo-code-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Six modules in apps/web each re-implemented the same signed, time-limited URL token/state format:

  • lib/integrations/oauth-state.ts
  • lib/bot/linear-link-token.ts
  • lib/bot/github-link-token.ts
  • lib/bot/linear-link-state.ts
  • lib/bot/github-link-state.ts
  • lib/device-auth/device-auth-viewer-token.ts

All of them shared an identical wire format (base64url(JSON({ ...payload, iat, nonce })) . HMAC-SHA256(secret)) and identical verification (split on ., timing-safe compare, base64url decode, TTL checkout, nonce presence check). Copies had already begun to drift (e.g. github-link-state accepts empty userId while linear-link-state requires non-empty).

Change

Extracted the shared primitive into lib/signed-token.ts:

  • createSignedToken(payload) — injects iat + nonce, serializes, signs.
  • verifySignedToken(token, { ttlSeconds, parse }) — verifies signature (timing-safe), enforces TTL + nonce, then delegates to each caller's payload-shape validation.

Each caller now retains only its own payload shape (zod schema or manual type checks) and TTL constant. Public exports (createOAuthState, verifyOAuthState, OAUTH_STATE_TTL_SECONDS, Verified* types, etc.) are unchanged, and the wire format is byte-compatible so tokens minted before this change still verify.

Net: 7 files, +190 / −361.

Out of scope

lib/bot-identity.ts uses the same wire format but its verify is async and interleaves a Redis context lookup, so it is intentionally left untouched to avoid forcing an awkward async abstraction.

Verification

  • oxlint clean on all changed files.
  • tsgo --noEmit (web typecheck) clean.
  • oxfmt formatting applied.
  • Behavioral sanity script (round-trip, tamper, expiry, empty-field, kind discriminator) passes.

Unit tests (jest) could not be run in this environment because the Jest global setup requires a live PostgreSQL instance.

Six modules in apps/web each reimplemented the same HMAC-signed,
time-limited token format (base64url JSON payload with iat + nonce,
HMAC-SHA256 signature, timing-safe compare, TTL enforcement). Extract
the shared sign/verify primitive into lib/signed-token.ts and have each
caller keep only its own payload shape validation.
@kilo-code-bot kilo-code-bot Bot added the janitor Automated dead-code/duplication cleanup label Sep 4, 2026
@kilo-code-bot
kilo-code-bot Bot enabled auto-merge (squash) September 4, 2026 07:29
@kilo-code-bot

kilo-code-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (7 files)
  • apps/web/src/lib/signed-token.ts
  • apps/web/src/lib/bot/github-link-state.ts
  • apps/web/src/lib/bot/github-link-token.ts
  • apps/web/src/lib/bot/linear-link-state.ts
  • apps/web/src/lib/bot/linear-link-token.ts
  • apps/web/src/lib/device-auth/device-auth-viewer-token.ts
  • apps/web/src/lib/integrations/oauth-state.ts

Reviewed by grok-4.6 · Input: 60.2K · Output: 12.4K · Cached: 297.3K

Review guidance: REVIEW.md from base branch main

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

Labels

janitor Automated dead-code/duplication cleanup

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants