feat(modernization): full architecture blueprint with hardening follow-up

Implement phased modernization infrastructure for transitioning from
multi-page legacy routing to SPA portal-shell architecture, plus
post-delivery hardening fixes for policy loading, fallback consistency,
and governance drift detection.

Key changes:
- Add route contract enrichment with scope/visibility/compatibility policies
- Canonical 302 redirects from legacy direct-entry to /portal-shell/ routes
- Asset readiness enforcement and runtime fallback retirement for in-scope routes
- Shared feature-flag helpers (env > config > default) replacing duplicated _to_bool
- Defensive copy for lru_cached policy payloads preventing mutation corruption
- Unified retired-fallback response helper across app and blueprint routes
- Frontend/backend route-contract cross-validation in governance gates
- Shell CSS token fallback values for routes rendered outside shell scope
- Local-safe .env.example defaults with production recommendation comments
- Legacy contract fallback warning logging and single-hop redirect optimization

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
egg
2026-02-12 11:26:02 +08:00
parent 2c8d80afe6
commit 7cb0985b12
113 changed files with 4577 additions and 582 deletions

View File

@@ -130,14 +130,21 @@ class TestWipAndHoldPagesE2E:
back_href = page.locator("a.btn-back").get_attribute("href") or ""
parsed = urlparse(back_href)
params = parse_qs(parsed.query)
assert parsed.path == "/wip-overview"
assert parsed.path in {"/wip-overview", "/portal-shell/wip-overview"}
assert params.get("type", [None])[0] == "PJA3460"
assert params.get("status", [None])[0] in {"queue", "QUEUE"}
def test_hold_detail_without_reason_redirects_to_overview(self, page: Page, app_server: str):
nav_resp = _get_with_retry(f"{app_server}/api/portal/navigation", attempts=3, timeout=10.0)
nav_payload = nav_resp.json() if nav_resp.ok else {}
spa_enabled = bool(nav_payload.get("portal_spa_enabled"))
response = _get_with_retry(f"{app_server}/hold-detail", attempts=3, timeout=10.0)
assert response.status_code == 302
assert response.headers.get("Location") == "/wip-overview"
if spa_enabled:
assert response.headers.get("Location") == "/portal-shell/wip-overview"
else:
assert response.headers.get("Location") == "/wip-overview"
def test_hold_detail_calls_summary_distribution_and_lots(self, page: Page, app_server: str):
reason = _pick_hold_reason(app_server)