Skip to content

refactor: extract download token helpers#542

Open
zereight wants to merge 3 commits into
mainfrom
refactor/download-token-helpers
Open

refactor: extract download token helpers#542
zereight wants to merge 3 commits into
mainfrom
refactor/download-token-helpers

Conversation

@zereight

@zereight zereight commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Summary

Part of #516.

This keeps the first refactor slice small and behavior-preserving:

  • moves encrypted download token creation/decryption into utils/download-token.ts
  • adds direct unit coverage for token round-trip and invalid token handling
  • keeps buildDownloadUrl() and registerDownloadProxy() in index.ts

Verification

  • rtk npm run build
  • node --import tsx/esm --test test/utils/download-token.test.ts
  • node --import tsx/esm --test test/test-remote-downloads.ts

Note

Low Risk
Mechanical refactor of token crypto with small decrypt hardening; download proxy behavior stays the same aside from stricter invalid-payload rejection.

Overview
Moves AES-256-GCM download token creation and decryption out of index.ts into utils/download-token.ts, with index.ts importing the helpers for buildDownloadUrl() and the download proxy.

The new module keeps the same env-driven key (DOWNLOAD_TOKEN_SECRET) and TTL behavior, and tightens decrypt validation (rejects empty h/t fields; parses DOWNLOAD_TOKEN_TTL only when it is a positive finite number). Adds test/utils/download-token.test.ts for round-trip, invalid, and expired tokens, and registers that file in the test:mock script.

Reviewed by Cursor Bugbot for commit b3dbf5a. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 02a7501b-24f0-44db-87c0-522cc20c8cfd

📥 Commits

Reviewing files that changed from the base of the PR and between b20e6ee and b3dbf5a.

📒 Files selected for processing (2)
  • test/utils/download-token.test.ts
  • utils/download-token.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (3)
utils/download-token.ts (2)

32-37: LGTM!


62-64: LGTM!

Also applies to: 79-80

test/utils/download-token.test.ts (1)

32-45: LGTM!


📝 Walkthrough

Summary by CodeRabbit

  • Refactor

    • Centralized download-token encryption/decryption into a shared utility and updated download URL token generation to use the shared helpers.
  • Tests

    • Added unit tests covering successful token round-trip, invalid token handling, and token expiration behavior.
  • Chores

    • Updated mock test suite script configuration.

Walkthrough

Inline AES-256-GCM download token logic is extracted from index.ts into a new utils/download-token.ts module. The module exports two interfaces and two functions (createDownloadToken, decryptDownloadToken) with key derivation from an environment variable, configurable TTL, and base64url encoding. index.ts now imports these helpers and drops its inline crypto primitives.

Changes

Download Token Utility Extraction

Layer / File(s) Summary
Download token utility: types, key derivation, encrypt/decrypt
utils/download-token.ts
Introduces DownloadTokenResource and DecryptedDownloadToken interfaces. Derives a symmetric AES-256-GCM key from DOWNLOAD_TOKEN_SECRET (SHA-256) or a random per-process key. Implements createDownloadToken (assembles JSON payload with header, token, expiry, optional URL and resource fields; encrypts with AES-256-GCM using random IV; appends auth tag; returns base64url-encoded result) and decryptDownloadToken (base64url-decodes; validates buffer length; decrypts with AES-256-GCM including auth tag verification; parses JSON payload; enforces DOWNLOAD_TOKEN_TTL expiry check; returns typed DecryptedDownloadToken or null on any failure).
Download token utility tests
test/utils/download-token.test.ts, package.json
Adds comprehensive test suite covering round-trip encryption/decryption with a specific auth header, API URL, and resource binding (asserting deep equality), confirms decryptDownloadToken returns null for invalid token strings, and tests expiry enforcement by saving/restoring and mocking Date.now to simulate time advancement past the TTL window. Updates test:mock npm script command to run the new tests.
index.ts: remove inline crypto, wire utility import
index.ts
Removes ~72 lines of inline key derivation and token functions, adds imports of createDownloadToken and decryptDownloadToken from ./utils/download-token.js, and narrows the node:crypto import to randomUUID only.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title 'refactor: extract download token helpers' accurately summarizes the main change—moving encrypted download token creation and decryption logic into a dedicated utility module.
Description check ✅ Passed The pull request description is clearly related to the changeset, detailing the extraction of download token helpers into utils/download-token.ts, the addition of unit test coverage, and verification steps.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/download-token-helpers
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch refactor/download-token-helpers

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

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Missing test:mock registration
    • Added test/utils/download-token.test.ts to the test:mock script in package.json alongside other utils tests.

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 8397aae. Configure here.

Comment thread test/utils/download-token.test.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 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 `@test/utils/download-token.test.ts`:
- Around line 28-31: Add a new test case in the test suite to verify that the
decryptDownloadToken function correctly rejects expired tokens by returning
null. Create a token with a short or manipulated TTL, advance time past the
token's expiry using a time mocking library (such as sinon or jest fake timers),
then call decryptDownloadToken and assert it returns null. Consider that the TTL
constant is set at module load time, so you may need to either use time mocking
to simulate expiry without waiting, or refactor the download-token.ts module to
make the TTL configurable for testing purposes.

In `@utils/download-token.ts`:
- Line 32: The DOWNLOAD_TOKEN_TTL constant assignment needs validation to ensure
the parsed value is a positive number. After parsing the environment variable
with Number.parseInt, add a check to verify the result is not NaN and is greater
than 0. If the parsed value fails validation, provide a safe default value (such
as 300) to prevent the TTL from becoming NaN and causing tokens to never expire.
This validation should occur before assigning the final value to the
DOWNLOAD_TOKEN_TTL constant.
- Around line 54-77: The decryptDownloadToken function returns a
DecryptedDownloadToken object without validating that the required fields header
and token exist in the decrypted payload. Add validation after parsing the JSON
payload to check that both payload.h and payload.t are present and have valid
values, returning null immediately if either required field is missing or
undefined. This ensures the returned object always conforms to the
DecryptedDownloadToken interface contract and prevents type-safety issues
downstream.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f2bf1d47-0d99-4589-acf1-ff69c2a5be5d

📥 Commits

Reviewing files that changed from the base of the PR and between c662a3d and 8397aae.

📒 Files selected for processing (3)
  • index.ts
  • test/utils/download-token.test.ts
  • utils/download-token.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (4)
  • GitHub Check: Cursor Bugbot Autofix
  • GitHub Check: test
  • GitHub Check: coverage
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (6)
utils/download-token.ts (3)

1-14: LGTM!


23-29: LGTM!


34-52: LGTM!

test/utils/download-token.test.ts (1)

1-26: LGTM!

index.ts (2)

129-129: LGTM!


504-504: LGTM!

Comment thread test/utils/download-token.test.ts
Comment thread utils/download-token.ts Outdated
Comment thread utils/download-token.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants