MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-377

6.8.2 Alias-aware resolution everywhere the key is addressed — central project-by-key fallback, /issues/[key] 308 redirects, API old-key serving

Done
Description

Estimate: 25m · Depends on: 6.8.1

The read half: every key-addressed surface resolves old keys, from ONE central path.

Central resolution: projectsService.resolveByKey — live identifier first, then the alias table; returns the project + a viaAlias flag (callers decide serve-vs-redirect). The /api/projects/[key] route family switches to it and serves on an alias hit (the verified REST behaviour — REST calls on the old key just work; the response DTO carries the canonical identifier).

Issue pages: /issues/[key] + /issues/[key]/edit — on a lookup miss, parse the identifier prefix (split on the first hyphen; keys are 3–5 alnum, never hyphenated), resolve via alias, recompose the canonical identifier, and redirect() with 308 to the canonical URL (the verified link behaviour: old links redirect, their text is never rewritten). Neither live nor alias → the existing 404. Active-project pinning is id-based and unaffected (note + assert).

Acceptance criteria

  • After PROD→NIF: /issues/PROD-7 and /issues/PROD-7/edit 308-redirect to their NIF-7 canonicals; an identifier that was NEVER live 404s; a RELEASED alias's URLs 404 (release breaks old links — the mirror rule).
  • Every /api/projects/PROD/... route serves identically to its NIF twin (spot-assert access, members, estimation-config), with the canonical key in the DTO.
  • Resolution is alias-aware in exactly ONE service path (no per-route alias queries — asserted by review + a unit test on resolveByKey); chained renames PROD→NIF→ZAP resolve BOTH old keys flat (no chain-walking: each alias row maps directly to the project).
  • Integration tests over the redirect/serve/404 matrix; coverage ≥90%.

Context refs

  • 6.8.1 (the alias table + resolveByKey substrate)
  • app/(authed)/issues/[key]/page.tsx + edit/page.tsx (the lookup-miss seam); lib/projects/index.ts (getActiveProject — id-pinned, unaffected)
  • The /api/projects/[key] route family (access / members / estimation-config)
  • The verified Jira redirect-vs-serve split in the Story 6.8 description