6.8.2 Alias-aware resolution everywhere the key is addressed — central project-by-key fallback, /issues/[key] 308 redirects, API old-key serving
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-7and/issues/PROD-7/edit308-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 +
resolveByKeysubstrate) 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