Harden live route ownership verification
This commit is contained in:
@@ -20,7 +20,7 @@
|
|||||||
## Delivery Tracker
|
## Delivery Tracker
|
||||||
|
|
||||||
### FE-RELEASE-ENV-001 - Restore canonical Releases ownership for environment inventory
|
### FE-RELEASE-ENV-001 - Restore canonical Releases ownership for environment inventory
|
||||||
Status: DOING
|
Status: DONE
|
||||||
Dependency: none
|
Dependency: none
|
||||||
Owners: QA, 3rd Line Support, Product Manager, Architect, Developer
|
Owners: QA, 3rd Line Support, Product Manager, Architect, Developer
|
||||||
Task description:
|
Task description:
|
||||||
@@ -28,20 +28,23 @@ Task description:
|
|||||||
- The old release-orchestrator environment pages are not safe to restore: they are placeholder-heavy, contain stale links, and would reintroduce broken actions. The correct fix is to keep the working topology-backed inventory/detail pages and mount them directly under Releases.
|
- The old release-orchestrator environment pages are not safe to restore: they are placeholder-heavy, contain stale links, and would reintroduce broken actions. The correct fix is to keep the working topology-backed inventory/detail pages and mount them directly under Releases.
|
||||||
|
|
||||||
Completion criteria:
|
Completion criteria:
|
||||||
- [ ] `/releases/environments` and `/releases/environments/:environmentId` resolve under `/releases/*` without redirecting to Operations.
|
- [x] `/releases/environments` and `/releases/environments/:environmentId` resolve under `/releases/*` without redirecting to Operations.
|
||||||
- [ ] Legacy release environment aliases redirect to `/releases/environments`.
|
- [x] Legacy release environment aliases redirect to `/releases/environments`.
|
||||||
- [ ] Route ownership specs and live ownership harness match the restored contract.
|
- [x] Route ownership specs and live ownership harness match the restored contract.
|
||||||
- [ ] Rebuilt live web passes the canonical route sweep with zero failed routes.
|
- [x] Rebuilt live web passes the canonical route sweep with zero failed routes.
|
||||||
|
|
||||||
## Execution Log
|
## Execution Log
|
||||||
| Date (UTC) | Update | Owner |
|
| Date (UTC) | Update | Owner |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| 2026-03-10 | Sprint created after the live canonical Playwright sweep dropped to a single failure: `/releases/environments` redirected to `/ops/operations/environments`. Root-cause audit confirmed the redirect was architectural drift, not a component/runtime failure. | Developer |
|
| 2026-03-10 | Sprint created after the live canonical Playwright sweep dropped to a single failure: `/releases/environments` redirected to `/ops/operations/environments`. Root-cause audit confirmed the redirect was architectural drift, not a component/runtime failure. | Developer |
|
||||||
|
| 2026-03-10 | Restored `/releases/environments` and `/releases/environments/:environmentId` as Releases-mounted topology surfaces, retargeted the legacy release environment aliases to `/releases/environments`, and updated the route-ownership test/harness expectations to match the canonical contract. | Developer |
|
||||||
|
| 2026-03-10 | `npx ng test --watch=false --progress=false --ts-config tsconfig.spec.json --include src/app/routes/route-surface-ownership.spec.ts` passed `5/5`; `npm run build` passed; the rebuilt bundle was synced into `compose_console-dist`; `node ./scripts/live-frontdoor-canonical-route-sweep.mjs` passed `111/111`; `node ./scripts/live-route-surface-ownership-check.mjs` passed with `failedActionCount=0` and `runtimeIssueCount=0`. | QA |
|
||||||
|
|
||||||
## Decisions & Risks
|
## Decisions & Risks
|
||||||
- Decision: supersede the earlier Operations-only redirect decision from `SPRINT_20260310_028_FE_route_surface_ownership_alignment.md`; the canonical Releases contract wins because the live route matrix and Pack 22 both depend on `/releases/environments`.
|
- Decision: supersede the earlier Operations-only redirect decision from `SPRINT_20260310_028_FE_route_surface_ownership_alignment.md`; the canonical Releases contract wins because the live route matrix and Pack 22 both depend on `/releases/environments`.
|
||||||
- Decision: do not revive `features/release-orchestrator/environments/**` in this slice. Those components remain non-canonical and need separate revival work if they are ever to return.
|
- Decision: do not revive `features/release-orchestrator/environments/**` in this slice. Those components remain non-canonical and need separate revival work if they are ever to return.
|
||||||
- Risk: the route-ownership Playwright harness still contains stale expectations for `/setup/notifications` and release environment aliases. It must be updated together with the route change or it will produce false failures.
|
- Decision: keep the topology-backed environment inventory/detail pages as the shared implementation behind both Releases and Operations rather than forking a second environment inventory surface.
|
||||||
|
- Decision: hardened `live-route-surface-ownership-check.mjs` to retry watchlist return-label checks when the trust shell briefly reports the blank `StellaOps` transition title; direct Playwright repro proved the underlying product flow was healthy and the prior failure was a harness race.
|
||||||
|
|
||||||
## Next Checkpoints
|
## Next Checkpoints
|
||||||
- Land the Releases route and legacy alias contract update.
|
- Land the Releases route and legacy alias contract update.
|
||||||
|
|||||||
@@ -190,6 +190,16 @@ async function runSidebarCheck(page) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function runWatchlistLabelCheck(page, returnTo, expectedLabel) {
|
async function runWatchlistLabelCheck(page, returnTo, expectedLabel) {
|
||||||
|
const evaluate = async () => {
|
||||||
|
const labelVisible = await page.getByText(`Return to ${expectedLabel}`, { exact: false }).first().isVisible().catch(() => false);
|
||||||
|
const snapshot = await captureSnapshot(page, `watchlist-return:${expectedLabel}`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
ok: labelVisible,
|
||||||
|
snapshot,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
await page.goto(
|
await page.goto(
|
||||||
`https://stella-ops.local/setup/trust-signing/watchlist/alerts?${scopeQuery}&alertId=alert-001&scope=tenant&tab=alerts&returnTo=${encodeURIComponent(returnTo)}`,
|
`https://stella-ops.local/setup/trust-signing/watchlist/alerts?${scopeQuery}&alertId=alert-001&scope=tenant&tab=alerts&returnTo=${encodeURIComponent(returnTo)}`,
|
||||||
{
|
{
|
||||||
@@ -199,14 +209,22 @@ async function runWatchlistLabelCheck(page, returnTo, expectedLabel) {
|
|||||||
);
|
);
|
||||||
await settle(page);
|
await settle(page);
|
||||||
|
|
||||||
const labelVisible = await page.getByText(`Return to ${expectedLabel}`, { exact: false }).first().isVisible().catch(() => false);
|
let result = await evaluate();
|
||||||
|
if (
|
||||||
|
!result.ok
|
||||||
|
&& new URL(page.url()).pathname === '/setup/trust-signing/watchlist/alerts'
|
||||||
|
&& (result.snapshot.title === 'StellaOps' || !result.snapshot.heading)
|
||||||
|
) {
|
||||||
|
await page.waitForTimeout(2_000);
|
||||||
|
result = await evaluate();
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
kind: 'watchlist-return',
|
kind: 'watchlist-return',
|
||||||
route: page.url(),
|
route: page.url(),
|
||||||
ok: labelVisible,
|
ok: result.ok,
|
||||||
expectedLabel,
|
expectedLabel,
|
||||||
snapshot: await captureSnapshot(page, `watchlist-return:${expectedLabel}`),
|
snapshot: result.snapshot,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user