Skip to content

fix(routes): canonicalize aliases and constrain compatibility - #980

Open
trac3r00 wants to merge 1 commit into
release/product-value-20260912-10from
release/product-value-20260912-11
Open

trac3r00 wants to merge 1 commit into
release/product-value-20260912-10from
release/product-value-20260912-11

Conversation

@trac3r00

@trac3r00 trac3r00 commented Sep 12, 2026

Copy link
Copy Markdown
Owner

Summary

fix(routes): canonicalize aliases and constrain compatibility. This is logical change 11/11 in the dependency-ordered product-audit release stack.

Closes #969

What changed

  • fix(routes): canonicalize aliases and constrain compatibility
  • Exact source commit: e5c99575be2bdad4286bce4c300fea6cf3f77b17; validated tree: e18ca0944a49196ae72e6dbf332594352c4cb93a.
  • Depends on the preceding release-stack PR. Retarget to main only after its dependency is merged and deployed.

Why

Keep canonical URLs and known compatibility links working while unknown paths correctly return 404.

Verification

  • bun run build passed on this exact candidate tree.
  • npm test -- --maxWorkers=2 passed on this exact candidate tree.
  • Affected behavior manually exercised as described below.
  • Latest GitHub Build, Unit Tests (Vitest), and E2E Tests (Playwright) must all pass before merge.
Tests  801 passed (801)
CANDIDATE_BUILD_UNIT_GREEN
Committed tree equals validated tree: e18ca0944a49196ae72e6dbf332594352c4cb93a

19 HTTP cases passed, including seven query-preserving HTML aliases, known/unknown compatibility paths, disabled API boundaries, health and favicon; real Korean alias navigation passed.

Final combined tree additionally passed 801 unit tests and all 293 Playwright tests with retries disabled, plus all 48 primary tool workflows at desktop and mobile. The exploratory Color Converter exact-HEX boundary remains a documented pre-existing defect; its runtime is unchanged by this stack.

Risk & rollback

  • Risk: Dependent commits require earlier stack changes; merge in order.
  • Rollback: revert this PR through a new PR; do not revert dependencies beneath already-merged dependents.
  • Release: require an approving review and latest-SHA CI. Respect the 15-minute soak between deploy-affecting merges and verify the production deployment before continuing.

Summary by cubic

Canonicalizes route aliases and constrains /tools/ compatibility redirects so .html aliases point to canonical URLs and unknown /tools paths return 404 instead of being rewritten. Closes #969.

  • /index.html, /about.html, /careers.html, /contact.html, /privacy.html, /security.html, and /terms.html now 301 to canonical paths, preserving query strings.
  • /tools/* redirects only for registered tools, known legacy redirects, or dev-only compat redirects; unknown suffixes return 404.
  • Dev-tool compatibility redirects are accepted only under development.
  • Password-generator API endpoints (/api/password, /api/username, /api/passphrase, /api/email, /api/cyberchef, /api/qr) now return 404 instead of the old disabled-API 403 response.

Rollout

  • Merge this after the preceding release-stack PR has been merged and deployed; retarget to main only after that dependency is in.

Written for commit e5c9957. Summary will update on new commits.

Review in cubic

Preserve query-bearing canonical redirects, reject unknown compatibility paths, and remove unreachable disabled API branches.

Ultraworked with [omo](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: sisyphus-dev-ai <sisyphus-dev-ai@users.noreply.github.com>

@cubic-dev-ai cubic-dev-ai 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.

1 issue found across 4 files

Confidence score: 4/5

  • In src/routes/password-generator.test.js, the test invokes the handler with /api/{prefix} URLs even though worker.js only routes /password-generator requests to it, so the test may validate behavior that production never reaches; align the test path with the worker’s routing gate.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/routes/password-generator.test.js">

<violation number="1" location="src/routes/password-generator.test.js:16">
P2: This test calls handlePasswordGeneratorRoutes directly with /api/{prefix} URLs, but in production the worker only routes to this handler for /password-generator (worker.js matchesToolPath gates on tool.path); /api/* is intercepted earlier by ASSETS 404, HTML_ALIAS_REDIRECTS, and legacy redirects. The handler 404s any non-/password-generator path, so each case passes trivially and the test provides no protection for the /api compatibility boundary it claims to verify. Exercise the real boundary through worker-level routing, or assert these 404s in the worker test rather than against the route handler in isolation.</violation>
</file>

Shadow auto-approve: would not auto-approve because issues were found.

Re-trigger cubic

]) {
it(`does not expose the disabled /api/${prefix} branch`, async () => {
const request = new Request(`https://simpletool.app/api/${prefix}`);
const response = await handlePasswordGeneratorRoutes(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: This test calls handlePasswordGeneratorRoutes directly with /api/{prefix} URLs, but in production the worker only routes to this handler for /password-generator (worker.js matchesToolPath gates on tool.path); /api/* is intercepted earlier by ASSETS 404, HTML_ALIAS_REDIRECTS, and legacy redirects. The handler 404s any non-/password-generator path, so each case passes trivially and the test provides no protection for the /api compatibility boundary it claims to verify. Exercise the real boundary through worker-level routing, or assert these 404s in the worker test rather than against the route handler in isolation.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/routes/password-generator.test.js, line 16:

<comment>This test calls handlePasswordGeneratorRoutes directly with /api/{prefix} URLs, but in production the worker only routes to this handler for /password-generator (worker.js matchesToolPath gates on tool.path); /api/* is intercepted earlier by ASSETS 404, HTML_ALIAS_REDIRECTS, and legacy redirects. The handler 404s any non-/password-generator path, so each case passes trivially and the test provides no protection for the /api compatibility boundary it claims to verify. Exercise the real boundary through worker-level routing, or assert these 404s in the worker test rather than against the route handler in isolation.</comment>

<file context>
@@ -0,0 +1,25 @@
+  ]) {
+    it(`does not expose the disabled /api/${prefix} branch`, async () => {
+      const request = new Request(`https://simpletool.app/api/${prefix}`);
+      const response = await handlePasswordGeneratorRoutes(
+        request,
+        new URL(request.url),
</file context>

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.

1 participant