[AZ-485] [AZ-486] Cycle 1 docs refresh (Step 13)
ci/woodpecker/push/build-arm Pipeline was successful

Phase B cycle 1 was a structural refactor only: F4 (barrel imports +
STC-ARCH-01) and F7 (endpoint builders + STC-ARCH-02). This commit
brings docs in line with source after the cycle, no code changes.

Module docs (12 consumers): swap every /api/<service>/... literal in
code snippets and integration tables for the matching endpoints.*
builder; note the barrel import migration in Dependencies.

New module doc: src__api__endpoints.md (public surface, F4 barrel
re-export note, STC-ARCH-02 enforcement, contract-test reference).

Architecture compliance baseline: mark F4 + F7 CLOSED with commit
hashes (23746ec, 8a461a2).

01_api-transport component description: add endpoints.ts + barrel to
Internal Interfaces, close the F7 caveat, extend Module Inventory.

ripple_log_cycle1.md: Task Step 0.5 reverse-dep analysis records the
import-graph closure (no extra docs needed beyond the direct set).

Carry-over reports landed alongside the docs:
- test_run_report_phase_b_cycle1.md (Step 11 outcome)
- implementation_report_refactor_phase_b_cycle1.md (cycle summary)

State file: trimmed to the autodev <30-line target; Steps 14 + 15
recorded as SKIPPED with rationale (no security or perf surface
changed in this cycle); pointer moved to Step 16 (Deploy).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-12 00:01:04 +03:00
parent 8a461a2051
commit 17d5bb45e7
17 changed files with 456 additions and 172 deletions
@@ -40,9 +40,9 @@ No props. Reads everything via `api/client` and local state.
- **Bootstrap effect** (`useEffect([])` — runs once at mount):
```ts
api.get<DetectionClass[]>('/api/annotations/classes').then(setClasses).catch(() => {})
api.get<Aircraft[]>('/api/flights/aircrafts').then(setAircrafts).catch(() => {})
api.get<User[]>('/api/admin/users').then(setUsers).catch(() => {})
api.get<DetectionClass[]>(endpoints.annotations.classes()).then(setClasses).catch(() => {})
api.get<Aircraft[]>(endpoints.flights.aircrafts()).then(setAircrafts).catch(() => {})
api.get<User[]>(endpoints.admin.users()).then(setUsers).catch(() => {})
```
Three independent calls, all silently swallowed on error. No retry,
@@ -51,10 +51,11 @@ No props. Reads everything via `api/client` and local state.
`_docs/ui_design/README.md`.
- **`handleAddClass()`**:
1. Guard: `if (!newClass.name) return`.
2. `await api.post('/api/admin/classes', newClass)`.
3. Refetch via `api.get('/api/annotations/classes')` — note the
**read** path is the public `annotations/` endpoint, while the
**write** path is the `admin/` endpoint. Architectural caveat:
2. `await api.post(endpoints.admin.classes(), newClass)` (= `/api/admin/classes`).
3. Refetch via `api.get(endpoints.annotations.classes())` — note the
**read** path is the public `annotations/` endpoint
(`/api/annotations/classes`), while the **write** path is the
`admin/` endpoint (`/api/admin/classes`). Architectural caveat:
two different services own the same logical entity. Document in
`architecture.md` §integration-points (Step 3a).
4. Reset `newClass` to its initial values.
@@ -62,25 +63,26 @@ No props. Reads everything via `api/client` and local state.
non-2xx); the throw is uncaught and reaches React's error boundary
(none configured). Flag.
- **`handleDeleteClass(id)`**: optimistic local update —
`await api.delete('/api/admin/classes/${id}')` then
`setClasses(prev => prev.filter(c => c.id !== id))`. **No
`await api.delete(endpoints.admin.class(id))` (= `/api/admin/classes/${id}`)
then `setClasses(prev => prev.filter(c => c.id !== id))`. **No
ConfirmDialog** despite this being destructive. Inconsistent with
the user-deactivation flow which uses ConfirmDialog. Flag for Step 4
against `_docs/ui_design/README.md` confirmation-dialog spec.
- **`handleAddUser()`** — analogous to `handleAddClass` against
`POST /api/admin/users` and `GET /api/admin/users`. Guards on
`email && password`.
`POST endpoints.admin.users()` and `GET endpoints.admin.users()`
(both → `/api/admin/users`). Guards on `email && password`.
- **`handleDeactivate()`** — fired from the ConfirmDialog confirm:
1. `PATCH /api/admin/users/${deactivateId}` with `{ isActive: false }`.
1. `PATCH endpoints.admin.user(deactivateId)` (= `/api/admin/users/${deactivateId}`) with `{ isActive: false }`.
2. Optimistic local update: marks the row inactive.
3. Closes the dialog (`setDeactivateId(null)`).
No "reactivate" path — once `isActive: false`, the row only renders
the badge and no Deactivate button. Verify with `admin/` service:
is reactivation an admin task or out of scope?
- **`handleToggleDefault(a)`** — `PATCH /api/flights/aircrafts/${a.id}`
with `{ isDefault: !a.isDefault }`, then optimistic local flip. Note
this allows multiple `isDefault: true` aircraft to coexist (the
backend should enforce exclusivity; the UI does not).
- **`handleToggleDefault(a)`** — `PATCH endpoints.flights.aircraft(a.id)`
(= `/api/flights/aircrafts/${a.id}`) with `{ isDefault: !a.isDefault }`,
then optimistic local flip. Note this allows multiple `isDefault:
true` aircraft to coexist (the backend should enforce exclusivity;
the UI does not).
- **Layout** (left → center → right, all in one horizontal flex):
- **Left column** (`w-[340px]`): detection-classes table + add row.
- **Center column** (`flex-1 max-w-md`): AI settings form, GPS
@@ -93,7 +95,7 @@ No props. Reads everything via `api/client` and local state.
## Dependencies
- **Internal**:
- `../../api/client` — `api`.
- `../../api` (barrel) — `api`, `endpoints`. (Since AZ-485 / F4 + AZ-486 / F7.)
- `../../components/ConfirmDialog` — for user deactivation.
- `../../types` — `DetectionClass`, `Aircraft`, `User`.
- **External**: `react` (`useState`, `useEffect`),
@@ -137,19 +139,18 @@ backend assigns `id` and other server-managed fields.
## External integrations
| Method | Path | Purpose |
| Method | Builder → Path | Purpose |
|---|---|---|
| `GET` | `/api/annotations/classes` | List detection classes (read path uses annotations service) |
| `POST` | `/api/admin/classes` | Create detection class (write path uses admin service) |
| `DELETE` | `/api/admin/classes/{id}` | Delete detection class |
| `GET` | `/api/flights/aircrafts` | List aircraft |
| `PATCH` | `/api/flights/aircrafts/{id}` | Toggle `isDefault` |
| `GET` | `/api/admin/users` | List users |
| `POST` | `/api/admin/users` | Create user |
| `PATCH` | `/api/admin/users/{id}` | Set `isActive: false` (deactivate) |
| `GET` | `endpoints.annotations.classes()` → `/api/annotations/classes` | List detection classes (read path uses annotations service) |
| `POST` | `endpoints.admin.classes()` → `/api/admin/classes` | Create detection class (write path uses admin service) |
| `DELETE` | `endpoints.admin.class(id)` → `/api/admin/classes/{id}` | Delete detection class |
| `GET` | `endpoints.flights.aircrafts()` → `/api/flights/aircrafts` | List aircraft |
| `PATCH` | `endpoints.flights.aircraft(id)` → `/api/flights/aircrafts/{id}` | Toggle `isDefault` |
| `GET` | `endpoints.admin.users()` → `/api/admin/users` | List users |
| `POST` | `endpoints.admin.users()` → `/api/admin/users` | Create user |
| `PATCH` | `endpoints.admin.user(id)` → `/api/admin/users/{id}` | Set `isActive: false` (deactivate) |
Routed by `nginx.conf` to `admin/`, `annotations/`, `flights/`
backends.
Path builders live in `src/api/endpoints.ts` (since AZ-486 / F7). Routed by `nginx.conf` to `admin/`, `annotations/`, `flights/` backends.
## Security