[AZ-486] F7 endpoint builders + STC-ARCH-02 (cycle 1 close)

Single source of truth for every /api/<service>/... URL the UI talks to:
src/api/endpoints.ts (25 typed builders) re-exported via the F4 barrel.
Migrates 13 production callsites in admin / annotations / flights /
settings / dataset / auth / api-client / FlightContext / DetectionClasses
to endpoints.* . Adds the STC-ARCH-02 static gate (--mode=api-literals
in scripts/check-arch-imports.mjs, wired into scripts/run-tests.sh)
that fails any new hardcoded /api/<service>/ literal in src/ outside
endpoints.ts and *.test.tsx? files.

Tests: +36 contract assertions in src/api/endpoints.test.ts (every
builder, character-identical), +6 STC-ARCH-02 architecture cases in
tests/architecture_imports.test.ts (single / double / template literal
fail paths, *.test.* exemption, line-comment skip, migrated codebase
pass). Fast profile 167 -> 209 PASS / 13 SKIP / 0 FAIL, +42 new,
0 regressions. Static profile 31 / 31 PASS.

Closes architecture baseline finding F7. Cycle 1 of Phase B closed.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-11 23:03:45 +03:00
parent 23746ec61d
commit 8a461a2051
23 changed files with 777 additions and 127 deletions
+4 -2
View File
@@ -50,8 +50,8 @@
- **Epic**: TBD
- **Directory**: `src/api/`
- **Public API** (via `src/api/index.ts` barrel): `api`, `setToken`, `getToken`, `getApiBase`, `setNavigateToLogin`, `createSSE`.
- **Internal**: none (both files are externally consumed)
- **Public API** (via `src/api/index.ts` barrel): `api`, `setToken`, `getToken`, `getApiBase`, `setNavigateToLogin`, `createSSE`, `endpoints` (the typed URL-builder object that is the single source of truth for every `/api/<service>/...` path the UI talks to today — AZ-486 / F7; `STC-ARCH-02` enforces it).
- **Internal**: none (every file is externally consumed; the colocated `endpoints.test.ts` IS the wire-contract documentation per `module-layout.md`'s "code-derived documentation" pattern).
- **Owns**: `src/api/**`
- **Imports from**: `00_foundation` (types)
- **Consumed by**: `02_auth`, `03_shared-ui`, every feature page (04, 05, 06, 07, 08, 09)
@@ -227,6 +227,8 @@ The following inferences could not be made cleanly from code alone. They are sur
3. ~~No barrel exports anywhere~~**resolved by AZ-485 (F4)**. Every component now exposes a `src/<component>/index.ts` barrel; cross-component imports go through it; `STC-ARCH-01` enforces it. One F3-pending exemption (`classColors`) remains documented in Layout Rule #3 above and in `architecture_compliance_baseline.md`.
3a. ~~Hardcoded `/api/<service>/` URLs scattered across callsites~~**resolved by AZ-486 (F7)**. The single source of truth is `src/api/endpoints.ts` (re-exported via the `01_api-transport` barrel from rule #3). Every production callsite of `api.*` and `createSSE()` uses an `endpoints.*` builder; the colocated `src/api/endpoints.test.ts` pins every URL string and serves as the wire-contract documentation. The `STC-ARCH-02` static gate (`scripts/check-arch-imports.mjs --mode=api-literals`, wired into `scripts/run-tests.sh --static-only`) fails the build on any new hardcoded `/api/<service>/` literal under `src/`. Exemptions: `src/api/endpoints.ts` (the contract owner) and any `*.test.ts` / `*.test.tsx` under `src/` (test files are exempt because tests legitimately assert URL strings — MSW handlers, contract tests, etc.).
4. **`mission-planner/` is owned by `05_flights` but lives at the repo root** (not under `src/`). Layout rule #1 says one component owns one or more top-level directories — this satisfies the rule (it owns two: `src/features/flights/` AND `mission-planner/`). Implement-skill consumers must include `mission-planner/**` in `05_flights`'s OWNED glob. **Decision needed**: confirm the implement skill should treat `mission-planner/**` as OWNED by 05_flights (otherwise it's FORBIDDEN by default).
5. **`05_flights` cycle inside the port-source**. `mission-planner/src/flightPlanning/MapView.tsx ↔ MiniMap.tsx` form a circular import (named-handle, see `00_discovery.md` §7 footnote). They were analyzed together in batch MP-B6. The cycle is internal to the component and does not cross component boundaries; flagged here for completeness.