[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
+16 -1
View File
@@ -485,7 +485,21 @@ if [ "$RUN_STATIC" = "true" ]; then
# through the 06_annotations barrel would create a circular import
# AnnotationsPage → DetectionClasses → barrel → AnnotationsPage.)
static_check_no_cross_component_deep_imports() {
node "$PROJECT_ROOT/scripts/check-arch-imports.mjs"
node "$PROJECT_ROOT/scripts/check-arch-imports.mjs" --mode=arch-imports
}
# AZ-486 F7 — STC-ARCH-02: no hardcoded `/api/<service>/` literals in
# production source. After F7 the single source of truth for API paths is
# `src/api/endpoints.ts`; every production callsite of `api.*` / `createSSE`
# must use an `endpoints.*` builder. Flags string literals of the form
# '/api/admin/users'
# "/api/admin/auth/refresh"
# `/api/flights/${id}/waypoints`
# Allowed:
# - the contract owner itself: src/api/endpoints.ts
# - test files: *.test.ts / *.test.tsx (the test file IS the contract)
static_check_no_api_literals() {
node "$PROJECT_ROOT/scripts/check-arch-imports.mjs" --mode=api-literals
}
# AZ-479 NFT-PERF-01 / NFT-RES-LIM-01 — initial JS bundle ≤ 2 MB gzipped.
@@ -535,6 +549,7 @@ if [ "$RUN_STATIC" = "true" ]; then
run_static "STC-B1" "vite build succeeds" "AC-6" "n/a" static_check_vite_build
run_static "STC-S5" "mission-planner not in dist/" "AC-31" "n/a" static_check_dist_no_mission_planner
run_static "STC-ARCH-01" "no cross-component deep imports (barrel-only)" "F4" "AZ-485" static_check_no_cross_component_deep_imports
run_static "STC-ARCH-02" "no hardcoded /api/<service>/ literals in src/" "F7" "AZ-486" static_check_no_api_literals
run_static "STC-PERF01" "initial JS bundle ≤ 2 MB gz" "NFT-PERF-01" "40" static_check_bundle_size
run_static "STC-RES02" "nginx client_max_body_size 500M" "NFT-RES-LIM-02" "n/a" static_check_nginx_body_cap
run_static "STC-RES03" "Dockerfile final stage nginx:alpine no Node" "NFT-RES-LIM-03" "n/a" static_check_dockerfile_nginx_alpine