Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions landing-zone-configurator/app/apps/api/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
12 changes: 12 additions & 0 deletions landing-zone-configurator/app/tests/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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();
Expand Down
7 changes: 7 additions & 0 deletions landing-zone-configurator/docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
Loading