diff --git a/landing-zone-configurator/app/apps/api/src/app.ts b/landing-zone-configurator/app/apps/api/src/app.ts index 5001657..a70af9f 100644 --- a/landing-zone-configurator/app/apps/api/src/app.ts +++ b/landing-zone-configurator/app/apps/api/src/app.ts @@ -270,11 +270,16 @@ export function buildApp( if (options.webRoot) { // Explicit SPA routes only: API/auth errors and missing assets must remain errors. for (const path of [ + "/workspaces", "/templates", "/repositories", "/configurations", "/credentials", "/deployments", + "/deployments/preparation", + "/deployments/plan", + "/deployments/apply", + "/deployments/history", "/organisation", "/applications", "/configurations/edit", diff --git a/landing-zone-configurator/app/tests/api.test.ts b/landing-zone-configurator/app/tests/api.test.ts index 567341b..5889a0c 100644 --- a/landing-zone-configurator/app/tests/api.test.ts +++ b/landing-zone-configurator/app/tests/api.test.ts @@ -48,6 +48,15 @@ it("serves the compiled UI without bypassing API authentication", async () => { "/repositories", "/configurations", "/configurations/edit/review", + "/deployments", + "/deployments/preparation", + "/deployments/plan", + "/deployments/apply", + "/deployments/history", + "/workspaces", + "/applications", + "/credentials", + "/organisation", ]) { const response = await app.inject(path); expect(response.statusCode).toBe(200); @@ -57,6 +66,9 @@ it("serves the compiled UI without bypassing API authentication", async () => { expect((await app.inject("/api/v1/unknown")).statusCode).toBe(404); expect((await app.inject("/assets/missing.js")).statusCode).toBe(404); expect((await app.inject("/templates/unknown")).statusCode).toBe(404); + expect((await app.inject("/deployments/unknown")).statusCode).toBe(404); + expect((await app.inject("/deployments/apply/extra")).statusCode).toBe(404); + expect((await app.inject("/workspaces/unknown")).statusCode).toBe(404); expect((await app.inject("/api/v1/unknown")).statusCode).not.toBe(200); } finally { await app.close(); diff --git a/landing-zone-configurator/docs/development.md b/landing-zone-configurator/docs/development.md index 8fe0ece..898d5a0 100644 --- a/landing-zone-configurator/docs/development.md +++ b/landing-zone-configurator/docs/development.md @@ -35,6 +35,13 @@ it cannot detach a focused input. Actual identity/workspace changes still reset the draft and scoped catalogue provider; never retain private catalogues across those boundaries. +Keep frontend navigation and the API's explicit SPA route allowlist aligned, +including workspace and deployment-phase URLs. Direct loads and reloads must +serve the compiled UI through the API, not just the development server's history +fallback. The static-serving API regression covers these paths while retaining +404 responses for unknown routes, API/auth paths and missing assets; do not +replace the allowlist with a catch-all. + ## Validation versus cloud operations | Workflow | Trigger and purpose |