Files
git.stella-ops.org/docs-archived/ui-analysis/rework/04-migration-map.md

426 lines
30 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Below is a **migration map** from your **current route surface (~120+)** to a **canonical release-control-plane IA**, plus a **redirect/alias strategy** designed to **preserve existing deep links**, keep bookmarks working, and **avoid breaking external references** (docs, emails, Slack links, ticket comments, etc.).
Im assuming the **new canonical IA** is:
* **Product flows (what customers do):**
`/` (Control Plane), `/releases`, `/approvals`, `/environments`, `/deployments`, `/security/*`, `/evidence/*`, `/witness/*`
* **Operations (running the platform):**
`/operations/*`
* **Settings (configuration + access control):**
`/settings/*`
* **Policy authoring (still first-class):**
`/policy/*` (instead of `/policy-studio/*`)
If you want to keep `/ops/*` and `/console/*` as canonical, you can—but then your route taxonomy stays inconsistent. The plan below keeps canonical clean **without breaking anything**, by keeping `/ops/*` and `/console/*` as legacy aliases indefinitely.
---
## 0) Canonical new route taxonomy (what were migrating to)
### 0.1 Control plane and release lifecycle
* `/`**Control Plane** (pipeline, pending approvals, drift/risk deltas)
* `/releases` → Releases list
* `/releases/:releaseId` → Release detail (gates, diff, evidence, proof chain)
* `/approvals` → Approvals inbox
* `/approvals/:approvalId` → Approval detail (diff-first + decision + evidence)
* `/environments` → Environments
* `/environments/:envId` → Environment detail
* `/deployments` → Deployments list
* `/deployments/:deployId` → Deployment detail (workflow DAG + artifacts + evidence)
### 0.2 Security (scanner heritage becomes “gate inputs”)
* `/security/overview` → Security overview dashboard (old Home dashboard preserved here)
* `/security/findings` → Findings (impact-to-release, reachability chips)
* `/security/scans/:scanId` → Scan run detail
* `/security/vulnerabilities` → CVE explorer
* `/security/vulnerabilities/:cveId` → CVE detail
* `/security/sbom/graph` → SBOM graph explorer
* `/security/lineage` → Lineage/compare (global)
* `/security/reachability` → Reachability center
* `/security/vex` → VEX hub (no longer under `/admin`)
* `/security/unknowns` → Unknowns tracking
* `/security/patch-map` → Patch map
### 0.3 Evidence and verification
* `/evidence` → Evidence center (packets, bundles, export, replay, provenance)
* `/evidence/:evidenceId` → Evidence packet viewer
* `/evidence/packs` and `/evidence/packs/:packId` → Evidence packs
* `/evidence/proofs/:subjectDigest` → Proof chain viewer
* `/witness/:witnessId` → Witness viewer (reachability slice + replay/verify)
### 0.4 Policy (rename, but keep semantics)
* `/policy/packs` (list)
* `/policy/packs/:packId/editor`
* `/policy/packs/:packId/yaml`
* `/policy/packs/:packId/simulate`
* `/policy/packs/:packId/approvals`
* `/policy/packs/:packId/rules`
* `/policy/packs/:packId/explain/:runId`
* `/policy/packs/:packId/dashboard`
* `/policy/exceptions` (exception queue + approvals)
### 0.5 Operations
* `/operations/orchestrator` (+ jobs, quotas)
* `/operations/quotas/*`
* `/operations/dead-letter/*`
* `/operations/slo/*`
* `/operations/health/*`
* `/operations/feeds/*`
* `/operations/offline-kit/*`
* `/operations/aoc/*`
* `/operations/scheduler/*`
* `/operations/doctor`
### 0.6 Settings
* `/settings/profile`
* `/settings/integrations/*` (hub + detail + activity)
* `/settings/admin/*` (tenants/users/roles/clients/tokens/branding)
* `/settings/trust/*` (keys/issuers/certs/score-config/audit)
* `/settings/registries` (registry token service)
* `/settings/notifications/*`
* `/settings/policy/governance`
* `/settings/sbom-sources`
* `/settings/trivy-db` (or fold into feeds)
---
# 1) Migration principles (minimize breaking links)
**Principle A — Keep old links working forever:**
Every old route either:
* **Redirects** to the new canonical route, or
* Remains as an **alias** that renders the same page/module.
**Principle B — Preserve identifiers and semantics:**
If `:scanId`, `:packId`, `:subjectDigest` exist today, do not change their format. New routes simply “re-home” them.
**Principle C — Use redirects only when mapping is 1:1:**
If old route needs **query params** (e.g., “filter type=audit”), use a **guard-based redirect** returning a `UrlTree` (so you can append query parameters safely).
**Principle D — Track legacy usage:**
Add telemetry: whenever a legacy route is hit, record `{ oldPath, newPath }`. This lets you quantify remaining legacy usage.
---
# 2) Old → new route migration map
Each entry includes: **Old route → New canonical route** + **strategy**.
Legend:
* **KEEP** = route stays as-is (canonical already good)
* **REDIRECT** = Angular router redirect (1:1 mapping)
* **SMART REDIRECT** = redirect via guard/matcher to add query params/open specific view
* **ALIAS** = old route still loads same module/component as new (no visible URL change)
---
## 2.1 Home & dashboard routes
| Old Route | New Route | Strategy | Notes |
| -------------------- | ------------------- | ---------------------- | ------------------------------------------------------------------------------------------ |
| `/` | `/` | KEEP (content changes) | Home becomes **Control Plane**. Preserve old “security dashboard” as `/security/overview`. |
| `/welcome` | `/welcome` | KEEP | Usually public. Keep stable. |
| `/dashboard/sources` | `/operations/feeds` | REDIRECT | Old “sources dashboard” becomes operational view of feeds/mirrors. |
Add a prominent navigation link: **Security Overview**`/security/overview` to avoid “we removed my dashboard” backlash.
---
## 2.2 Analyze routes → Security namespace
| Old Route | New Route | Strategy | Notes |
| ---------------------------------- | -------------------------------------- | ----------------- | --------------------------------------------------------------------- |
| `/findings` | `/security/findings` | REDIRECT | Findings become security impact-to-release view. |
| `/findings/:scanId` | `/security/scans/:scanId` | REDIRECT | Preserve deep links; scan detail page remains. |
| `/vulnerabilities` | `/security/vulnerabilities` | REDIRECT | CVE explorer moved under security. |
| `/vulnerabilities/:vulnId` | `/security/vulnerabilities/:vulnId` | REDIRECT | 1:1 mapping. |
| `/graph` | `/security/sbom/graph` | REDIRECT | SBOM graph belongs under Security. |
| `/lineage` | `/security/lineage` | REDIRECT | (Or `/releases/lineage`, choose one canonical; I recommend Security.) |
| `/lineage/:artifact/compare` | `/security/lineage/:artifact/compare` | ALIAS or REDIRECT | Keep params same. |
| `/lineage/compare` | `/security/lineage/compare` | REDIRECT | Stable. |
| `/reachability` | `/security/reachability` | REDIRECT | Reachability center is security analysis. |
| `/admin/vex-hub` | `/security/vex` | REDIRECT | VEX is not “admin-only”; move. |
| `/admin/vex-hub/search` | `/security/vex/search` | REDIRECT | Keep identical subroutes. |
| `/admin/vex-hub/search/detail/:id` | `/security/vex/search/detail/:id` | REDIRECT | 1:1. |
| `/admin/vex-hub/stats` | `/security/vex/stats` | REDIRECT | 1:1. |
| `/admin/vex-hub/consensus` | `/security/vex/consensus` | REDIRECT | 1:1. |
| `/admin/vex-hub/explorer` | `/security/vex/explorer` | REDIRECT | 1:1. |
| `/analyze/unknowns` | `/security/unknowns` | REDIRECT | 1:1. |
| `/analyze/patch-map` | `/security/patch-map` | REDIRECT | 1:1. |
| `/scans/:scanId` | `/security/scans/:scanId` | REDIRECT | Consolidate scan detail here. |
| `/compare/:currentId` | `/security/lineage/compare/:currentId` | REDIRECT | Preserve compare deep links. |
| `/cvss/receipts/:receiptId` | `/evidence/receipts/cvss/:receiptId` | REDIRECT | CVSS receipt is an **evidence artifact**. |
---
## 2.3 Triage routes → split between Security (artifact triage) and Policy/Evidence
| Old Route | New Route | Strategy | Notes |
| ------------------------------- | ---------------------------------- | -------------- | ------------------------------------------------------------------------------------------- |
| `/triage/artifacts` | `/security/artifacts` | REDIRECT | “Artifact workspace” becomes security artifact index (digest-first). |
| `/triage/artifacts/:artifactId` | `/security/artifacts/:artifactId` | REDIRECT | Preserve the triage workspace; it becomes “Artifact Detail”. |
| `/exceptions` | `/policy/exceptions` | REDIRECT | Exceptions are governance controls for gates. |
| `/triage/audit-bundles` | `/evidence?type=audit` | SMART REDIRECT | Needs query param. Alternatively create `/evidence/bundles/audit` to allow simple redirect. |
| `/triage/audit-bundles/new` | `/evidence/bundles/new?type=audit` | SMART REDIRECT | Needs query param. |
| `/risk` | `/security/risk` | REDIRECT | Risk dashboard becomes security analytics. |
**Recommendation to reduce SMART redirects:** create explicit canonical paths:
* `/evidence/bundles/audit`
* `/evidence/bundles/release`
* `/evidence/bundles/scan`
Then redirects are trivial and do not require query injection.
---
## 2.4 Policy routes (`/policy-studio/*` → `/policy/*`)
| Old Route | New Route | Strategy | Notes |
| --------------------------------------------- | -------------------------------------- | -------- | -------------------- |
| `/policy-studio/packs` | `/policy/packs` | REDIRECT | Rename for brevity. |
| `/policy-studio/packs/:packId/editor` | `/policy/packs/:packId/editor` | REDIRECT | 1:1. |
| `/policy-studio/packs/:packId/yaml` | `/policy/packs/:packId/yaml` | REDIRECT | 1:1. |
| `/policy-studio/packs/:packId/simulate` | `/policy/packs/:packId/simulate` | REDIRECT | 1:1. |
| `/policy-studio/packs/:packId/approvals` | `/policy/packs/:packId/approvals` | REDIRECT | 1:1. |
| `/policy-studio/packs/:packId/rules` | `/policy/packs/:packId/rules` | REDIRECT | 1:1. |
| `/policy-studio/packs/:packId/explain/:runId` | `/policy/packs/:packId/explain/:runId` | REDIRECT | 1:1. |
| `/policy-studio/packs/:packId/dashboard` | `/policy/packs/:packId/dashboard` | REDIRECT | 1:1. |
| `/orchestrator` | `/operations/orchestrator` | REDIRECT | Orchestrator is ops. |
| `/orchestrator/jobs` | `/operations/orchestrator/jobs` | REDIRECT | 1:1. |
| `/orchestrator/jobs/:jobId` | `/operations/orchestrator/jobs/:jobId` | REDIRECT | 1:1. |
| `/orchestrator/quotas` | `/operations/orchestrator/quotas` | REDIRECT | 1:1. |
---
## 2.5 Ops routes (`/ops/*` + `/scheduler/*` → `/operations/*`)
| Old Route | New Route | Strategy | Notes |
| ------------------------------------- | -------------------------------------- | ----------------- | ---------------------------------------------------------------------------------------- |
| `/sbom-sources` | `/settings/sbom-sources` | REDIRECT | This is configuration, not ops. |
| `/ops/quotas` | `/operations/quotas` | REDIRECT | 1:1. |
| `/ops/quotas/tenants` | `/operations/quotas/tenants` | REDIRECT | 1:1. |
| `/ops/quotas/tenants/:tenantId` | `/operations/quotas/tenants/:tenantId` | REDIRECT | 1:1. |
| `/ops/quotas/throttle` | `/operations/quotas/throttle` | REDIRECT | 1:1. |
| `/ops/quotas/alerts` | `/operations/quotas/alerts` | REDIRECT | 1:1. |
| `/ops/quotas/forecast` | `/operations/quotas/forecast` | REDIRECT | 1:1. |
| `/ops/quotas/reports` | `/operations/quotas/reports` | REDIRECT | 1:1. |
| `/ops/orchestrator/dead-letter` | `/operations/dead-letter` | REDIRECT | Flatten path; keep subroute for queue. |
| `/ops/orchestrator/dead-letter/queue` | `/operations/dead-letter/queue` | REDIRECT | 1:1. |
| `/ops/orchestrator/slo` | `/operations/slo` | REDIRECT | 1:1. |
| `/ops/orchestrator/slo/alerts` | `/operations/slo/alerts` | REDIRECT | 1:1. |
| `/ops/orchestrator/slo/definitions` | `/operations/slo/definitions` | REDIRECT | 1:1. |
| `/ops/health` | `/operations/health` | REDIRECT | 1:1. |
| `/ops/feeds` | `/operations/feeds` | REDIRECT | 1:1. |
| `/ops/feeds/mirror/:mirrorId` | `/operations/feeds/mirror/:mirrorId` | REDIRECT | 1:1. |
| `/ops/feeds/airgap/import` | `/operations/feeds/airgap/import` | REDIRECT | 1:1. |
| `/ops/feeds/airgap/export` | `/operations/feeds/airgap/export` | REDIRECT | 1:1. |
| `/ops/feeds/version-locks` | `/operations/feeds/version-locks` | REDIRECT | 1:1. |
| `/ops/offline-kit/*` | `/operations/offline-kit/*` | ALIAS or REDIRECT | Either keep the segment name to avoid churn, or canonicalize to `/operations/offline/*`. |
| `/ops/aoc/*` | `/operations/aoc/*` | REDIRECT | Keep short; avoid nested `/compliance/` unless you really need it. |
| `/ops/doctor` | `/operations/doctor` | REDIRECT | 1:1. |
| `/scheduler/*` | `/operations/scheduler/*` | REDIRECT | Fix inconsistent prefix. |
| `/ops/scanner/*` | `/operations/scanner/*` | REDIRECT | Scanner ops is now “security gate engine ops”. |
---
## 2.6 Notify
| Old Route | New Route | Strategy | Notes |
| --------- | --------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------- |
| `/notify` | `/operations/notifications` | REDIRECT | If `/notify` is history/dispatch, it belongs to operations. If it is configuration, redirect to `/settings/notifications`. |
---
## 2.7 Admin + Console routes → Settings namespace
| Old Route | New Route | Strategy | Notes |
| ------------------------------ | ------------------------------- | -------- | ---------------------------------------------------------- |
| `/console/profile` | `/settings/profile` | REDIRECT | Consolidate under settings. |
| `/console/status` | `/operations/status` | REDIRECT | Status is ops. |
| `/console/configuration` | `/settings/integrations` | REDIRECT | Configuration pane becomes integrations hub. |
| `/console/admin/tenants` | `/settings/admin/tenants` | REDIRECT | 1:1. |
| `/console/admin/users` | `/settings/admin/users` | REDIRECT | 1:1. |
| `/console/admin/roles` | `/settings/admin/roles` | REDIRECT | 1:1. |
| `/console/admin/clients` | `/settings/admin/clients` | REDIRECT | 1:1. |
| `/console/admin/tokens` | `/settings/admin/tokens` | REDIRECT | 1:1. |
| `/console/admin/audit` | `/evidence/audit` | REDIRECT | Audit is evidence. |
| `/console/admin/branding` | `/settings/admin/branding` | REDIRECT | 1:1. |
| `/admin/audit/*` | `/evidence/audit/*` | REDIRECT | Unified audit log belongs under evidence. |
| `/admin/trust/*` | `/settings/trust/*` | REDIRECT | Keys/issuers/certs/score config consolidated. |
| `/admin/registries` | `/settings/registries` | REDIRECT | Registry token service is configuration. |
| `/admin/issuers` | `/settings/trust/issuers` | REDIRECT | Fold into trust. |
| `/admin/notifications` | `/settings/notifications/admin` | REDIRECT | Admin notifications config. |
| `/admin/policy/governance` | `/settings/policy/governance` | REDIRECT | Governance is configuration. |
| `/admin/policy/simulation` | `/policy/simulation` | REDIRECT | Or keep `/settings/policy/simulation` if truly admin-only. |
| `/concelier/trivy-db-settings` | `/settings/trivy-db` | REDIRECT | Or fold into `/operations/feeds/trivy`. |
---
## 2.8 Release Orchestrator routes (`/release-orchestrator/*` → lifecycle roots)
| Old Route | New Route | Strategy | Notes |
| ------------------------------------ | --------------------------------------- | -------------- | ------------------------------------------------------------------------------- |
| `/release-orchestrator` | `/` | REDIRECT | Control plane becomes the orchestrator home. |
| `/release-orchestrator/environments` | `/environments` | REDIRECT | 1:1. |
| `/release-orchestrator/releases` | `/releases` | REDIRECT | 1:1. |
| `/release-orchestrator/workflows` | `/workflows` (or `/settings/workflows`) | REDIRECT | Decide: if workflows are editable config → settings; if used daily → top-level. |
| `/release-orchestrator/approvals` | `/approvals` | REDIRECT | 1:1. |
| `/release-orchestrator/deployments` | `/deployments` | REDIRECT | 1:1. |
| `/release-orchestrator/evidence` | `/evidence?type=release` | SMART REDIRECT | Better to create `/evidence/bundles/release` for simple redirect. |
---
## 2.9 Evidence routes (mostly keep)
| Old Route | New Route | Strategy | Notes |
| ------------------------- | --------------------------------- | ------------------- | -------------------------------------------------------- |
| `/evidence` | `/evidence` | KEEP | Already good. |
| `/evidence/bundles` | `/evidence` | ALIAS or REDIRECT | If you keep tabbed routes, you can keep it as alias. |
| `/evidence/export` | `/evidence/export` | KEEP | Stable. |
| `/evidence/replay` | `/evidence/replay` | KEEP | Stable. |
| `/evidence/provenance` | `/evidence/provenance` | KEEP | Stable. |
| `/evidence-packs` | `/evidence/packs` | REDIRECT | Normalize under evidence namespace. |
| `/evidence-packs/:packId` | `/evidence/packs/:packId` | REDIRECT | 1:1. |
| `/proofs/:subjectDigest` | `/evidence/proofs/:subjectDigest` | ALIAS (recommended) | Keep `/proofs/*` forever as a public-friendly shortlink. |
---
## 2.10 Integrations routes → Settings
| Old Route | New Route | Strategy | Notes |
| ------------------------------ | --------------------------------------- | -------- | ----------------------------------------------------------- |
| `/integrations` | `/settings/integrations` | REDIRECT | Canonicalize. |
| `/integrations/registries` | `/settings/integrations/registries` | REDIRECT | 1:1. |
| `/integrations/scm` | `/settings/integrations/scm` | REDIRECT | 1:1. |
| `/integrations/ci` | `/settings/integrations/ci` | REDIRECT | 1:1. |
| `/integrations/hosts` | `/settings/integrations/hosts` | REDIRECT | 1:1. |
| `/integrations/feeds` | `/settings/integrations/feeds` | REDIRECT | 1:1. |
| `/integrations/activity` | `/settings/integrations/activity` | REDIRECT | Or move to `/operations/integrations/activity` if you want. |
| `/integrations/:integrationId` | `/settings/integrations/:integrationId` | REDIRECT | 1:1. |
---
## 2.11 Other routes
| Old Route | New Route | Strategy | Notes |
| ----------------- | ---------------------------- | -------- | ----------------------------------------- |
| `/ai-runs` | `/operations/ai-runs` | REDIRECT | AI runs are operational telemetry. |
| `/ai-runs/:runId` | `/operations/ai-runs/:runId` | REDIRECT | 1:1. |
| `/change-trace` | `/evidence/change-trace` | REDIRECT | Change trace is evidence lineage. |
| `/setup` | `/setup` | KEEP | Installation wizard should remain stable. |
| `/auth/callback` | `/auth/callback` | KEEP | Must remain stable for OIDC. |
---
# 3) Redirect strategy (implementation plan that wont bite you)
## 3.1 Use a dedicated “Legacy Routes” layer (lowest priority in router)
**Order matters.** Put all legacy redirects **after** the new canonical route tree so you dont accidentally intercept new paths.
* `app.routes.ts`
1. New canonical routes
2. Legacy redirect/alias routes
3. `**` fallback
## 3.2 Three redirect mechanisms (use the right one)
### Mechanism 1 — Simple static redirect (`redirectTo`)
Use when mapping is clean and 1:1:
* `/findings``/security/findings`
* `/release-orchestrator/releases``/releases`
### Mechanism 2 — Param redirect (`redirectTo` with `:param`)
Use when its still 1:1 but has params:
* `/vulnerabilities/:vulnId``/security/vulnerabilities/:vulnId`
* `/findings/:scanId``/security/scans/:scanId`
### Mechanism 3 — SMART redirect (guard/matcher returning a UrlTree)
Use when you must:
* Add query params (e.g., `type=audit`)
* Switch tabs
* Open a drawer based on route
Examples:
* `/triage/audit-bundles``/evidence?type=audit`
* `/release-orchestrator/evidence``/evidence?type=release`
**Strong recommendation:** Avoid SMART redirects by giving evidence bundle types **real paths**:
* `/evidence/bundles/audit`
* `/evidence/bundles/release`
Then you can use simple redirects and remove complexity.
## 3.3 Preserve query params and fragments always
Legacy URLs in tickets often include query params. Your redirect logic must preserve:
* `?tab=...`
* `?filters=...`
* `#anchor`
In Angular, **guard-based UrlTree** redirects are the most reliable way to preserve and augment query params intentionally.
## 3.4 Keep “short links” as permanent aliases
Some paths are extremely convenient and should remain:
* `/proofs/:subjectDigest` (keep forever, even if canonical is under `/evidence/proofs/...`)
* Potentially `/deploy/:id` if you ever add it
This reduces friction when humans share links.
## 3.5 Add a “Legacy URL” banner (optional but useful)
On legacy-rendered aliases (not redirects), show a slim banner:
* “This URL has moved. Update bookmarks.”
* Button: “Go to new location”
* Include one-click copy of canonical URL
This is very effective during the transition without forcing redirects.
## 3.6 Instrument legacy hits
Emit a telemetry event:
* `legacy_route_hit`
* `oldPath`
* `newPath`
* `tenantId`
* `userId` (if available)
* `timestamp`
This tells you when its safe to remove legacy routes (if you ever choose to).
---
# 4) Practical redirect coverage checklist (to prevent surprises)
Before shipping, test these as **direct loads** (not SPA navigation):
1. `/admin/vex-hub/search/detail/123` loads and lands on `/security/vex/search/detail/123`
2. `/findings/SCAN-123` lands on scan detail
3. `/proofs/sha256:...` still works and lands on proof viewer
4. `/release-orchestrator/environments` lands on `/environments`
5. `/triage/audit-bundles` lands on the correct evidence bundle view (no empty state)
---