mirror of
https://github.com/azaion/ui.git
synced 2026-06-21 09:21:10 +00:00
[AZ-485] Add Public API barrels + STC-ARCH-01 (F4 close)
Closes architecture baseline finding F4. Every component now exposes its Public API through `src/<component>/index.ts`; cross-component imports go through the barrel. `scripts/check-arch-imports.mjs` plus `STC-ARCH-01` in the static profile enforce the rule; tests in `tests/architecture_imports.test.ts` cover AC-4/AC-5 + 2 exemption cases. One F3-pending exemption (`classColors`) is documented in 5 places (barrel, consumer, script, doc, test) to avoid a circular import. Phase B cycle 1 batch 1 of 2 (epic AZ-447). Batch 2 is AZ-486 (endpoint builders) — blocked on this commit landing. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2,9 +2,9 @@
|
||||
|
||||
**Status**: derived-from-code
|
||||
**Language**: typescript (React 19 + Vite + Tailwind)
|
||||
**Layout Convention**: custom (flat-features under `src/`; no per-component barrels)
|
||||
**Layout Convention**: custom (flat-features under `src/`; per-component barrels at `src/<component>/index.ts` since AZ-485)
|
||||
**Root**: `src/`
|
||||
**Last Updated**: 2026-05-10
|
||||
**Last Updated**: 2026-05-11
|
||||
|
||||
> Authoritative file-ownership map for the React UI workspace. Derived from
|
||||
> `_docs/02_document/00_discovery.md` (dependency graph) and the Step 2
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
1. Each component owns ONE OR MORE top-level directories (or top-level files) under `src/`. The mapping is NOT 1:1 — `00_foundation` owns three sibling directories (`src/types/`, `src/hooks/`, `src/i18n/`), `05_flights` spans `src/features/flights/` AND a separate `mission-planner/` port-source root, and `10_app-shell` owns top-level files (`App.tsx`, `main.tsx`, `index.css`, `vite-env.d.ts`).
|
||||
2. Shared code does **not** live under `src/shared/` today — there is no `shared/` directory. Two helper modules (`11_class-colors/classColors.ts` and `06_annotations/CanvasEditor.tsx`) are physically misplaced and consumed across components; both are flagged in the `## Verification Needed` block. A `src/shared/` directory is a Step 4 testability candidate.
|
||||
3. Public API per component: NO barrel `index.ts` exists at any component root. The only `index.ts` files are `src/types/index.ts` (a re-export hub for type aliases — used as the de-facto public API for `00_foundation` types) and `mission-planner/src/types/index.ts`. Until Step 4 introduces barrels, Public API is approximated as "every named export from any file under the component's owned directories". Cross-component imports ARE happening at file-name granularity (`import { api } from '../api/client'`, `import { CanvasEditor } from '../annotations/CanvasEditor'`).
|
||||
3. **Public API per component is the barrel `src/<component>/index.ts`** (AZ-485 / F4). Every component except `10_app-shell` (which is a top-level file collection — `App.tsx`, `main.tsx`, etc., never imported as a unit) exposes its Public API through a root barrel. Cross-component imports MUST go through the barrel — `import { api } from '../api'`, not `from '../api/client'`. The `STC-ARCH-01` static gate (`scripts/check-arch-imports.mjs`, wired into `scripts/run-tests.sh --static-only`) fails the build on cross-component deep imports. Intra-component imports (relative `./`) remain free. **One F3-pending exemption**: `src/features/annotations/classColors` is imported directly because the file is logically owned by `11_class-colors` but physically lives under `06_annotations`; re-exporting it through the `06_annotations` barrel creates a circular import (AnnotationsPage → DetectionClasses → 06_annotations barrel → AnnotationsPage). The exemption disappears when F3 moves the file.
|
||||
4. Cross-cutting concerns (logging, config, error handling, telemetry): no dedicated infrastructure today. `console.error` / silent catches are the closest thing — recorded in module findings.
|
||||
5. Tests: there are **zero tests** under `src/`. The only test file is `mission-planner/src/test/jsonImport.test.ts`, which can't run because Jest isn't installed (00_discovery.md §11.5). Test layout is therefore TBD; suggest `src/<component>/__tests__/` per the standard React convention when tests are added (autodev Step 5–6).
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
- **Epic**: TBD (set during autodev Step 4 / Decompose)
|
||||
- **Directories**: `src/types/`, `src/hooks/`, `src/i18n/`
|
||||
- **Public API** (de-facto, no barrel):
|
||||
- **Public API** (no `src/<component>/index.ts` barrel — `00_foundation` spans three sibling directories; the existing `src/types/index.ts` is the type-alias barrel and `src/hooks/` + `src/i18n/` are imported directly per file):
|
||||
- `src/types/index.ts` — every exported type alias (`Detection`, `Flight`, `MediaItem`, `User`, etc.)
|
||||
- `src/hooks/useDebounce.ts` — `useDebounce`
|
||||
- `src/hooks/useResizablePanel.ts` — `useResizablePanel`
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
- **Epic**: TBD
|
||||
- **Directories**: (none today — physical file lives at `src/features/annotations/classColors.ts`, which is owned by `06_annotations` on disk). Logical owner is this component; physical move to `src/shared/classColors.ts` (or `src/components/detection/classColors.ts`) is a Step 4 testability task.
|
||||
- **Public API**: `src/features/annotations/classColors.ts` exports `getClassColor`, `getClassNameFallback`, `getPhotoModeSuffix`, `FALLBACK_CLASS_NAMES`.
|
||||
- **Public API**: `getClassColor`, `getClassNameFallback`, `getPhotoModeSuffix`, `FALLBACK_CLASS_NAMES` — exported from `src/features/annotations/classColors.ts`. **No barrel** today because the file is physically inside `06_annotations`; consumers import the path directly under the F3-pending exemption documented in Layout Rule #3 and enforced by STC-ARCH-01. When F3 moves the file to its own component directory, a `src/<new-home>/index.ts` barrel will replace the direct path import and the STC-ARCH-01 exemption will be removed.
|
||||
- **Internal**: module-private `CLASS_COLORS` constant.
|
||||
- **Owns**: pending — see Verification Needed item #1.
|
||||
- **Imports from**: (none — Layer 0/1, no internal imports)
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
- **Epic**: TBD
|
||||
- **Directory**: `src/api/`
|
||||
- **Public API** (de-facto): `src/api/client.ts` exports `api` (fetch wrapper); `src/api/sse.ts` exports `subscribeSSE` / equivalent helper.
|
||||
- **Public API** (via `src/api/index.ts` barrel): `api`, `setToken`, `getToken`, `getApiBase`, `setNavigateToLogin`, `createSSE`.
|
||||
- **Internal**: none (both files are externally consumed)
|
||||
- **Owns**: `src/api/**`
|
||||
- **Imports from**: `00_foundation` (types)
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
- **Epic**: TBD
|
||||
- **Directory**: `src/auth/`
|
||||
- **Public API**: `src/auth/AuthContext.tsx` exports `AuthProvider`, `useAuth`. `src/auth/ProtectedRoute.tsx` exports `ProtectedRoute`.
|
||||
- **Public API** (via `src/auth/index.ts` barrel): `AuthProvider`, `useAuth`, `ProtectedRoute`.
|
||||
- **Internal**: none
|
||||
- **Owns**: `src/auth/**`
|
||||
- **Imports from**: `00_foundation`, `01_api-transport`
|
||||
@@ -70,7 +70,7 @@
|
||||
|
||||
- **Epic**: TBD
|
||||
- **Directory**: `src/components/`
|
||||
- **Public API** (de-facto, all are externally consumed):
|
||||
- **Public API** (via `src/components/index.ts` barrel — all symbols externally consumed):
|
||||
- `Header.tsx` → `Header`
|
||||
- `HelpModal.tsx` → `HelpModal`
|
||||
- `ConfirmDialog.tsx` → `ConfirmDialog`
|
||||
@@ -85,7 +85,7 @@
|
||||
|
||||
- **Epic**: TBD
|
||||
- **Directory**: `src/features/login/`
|
||||
- **Public API**: `LoginPage.tsx` → `LoginPage`
|
||||
- **Public API** (via `src/features/login/index.ts` barrel): `LoginPage`.
|
||||
- **Internal**: none (single-page component)
|
||||
- **Owns**: `src/features/login/**`
|
||||
- **Imports from**: `00_foundation`, `01_api-transport`, `02_auth`
|
||||
@@ -97,7 +97,7 @@
|
||||
- **Directories** (TWO physical roots):
|
||||
- `src/features/flights/` — deployed target tree (15 modules)
|
||||
- `mission-planner/` — port-source, NOT deployed (37 modules under `mission-planner/src/`). Documented inside this component per the user's Step 2 BLOCKING-gate decision (`_docs/02_document/state.json::component_05_flights_merge_2026-05-10`). The port direction is `mission-planner/` → `src/features/flights/`; module-layout treats both trees as owned by this component but only the target tree is in the layering table below.
|
||||
- **Public API** (target tree, de-facto): `FlightsPage.tsx` → `FlightsPage` (route component). Internal sub-components (`FlightMap`, `FlightParamsPanel`, `FlightListSidebar`, `WaypointList`, `AltitudeChart`, `AltitudeDialog`, `WindEffect`, `MiniMap`, `MapPoint`, `DrawControl`, `JsonEditorDialog`, `mapIcons`, `flightPlanUtils`, `types`) are NOT consumed outside the component.
|
||||
- **Public API** (target tree, via `src/features/flights/index.ts` barrel): `FlightsPage` (route component). Internal sub-components (`FlightMap`, `FlightParamsPanel`, `FlightListSidebar`, `WaypointList`, `AltitudeChart`, `AltitudeDialog`, `WindEffect`, `MiniMap`, `MapPoint`, `DrawControl`, `JsonEditorDialog`, `mapIcons`, `flightPlanUtils`, `types`) are NOT re-exported through the barrel.
|
||||
- **Public API** (port-source `mission-planner/`): not consumed at all by `src/` today (separate Vite entrypoint, `main.tsx` of its own). Effectively a private vendored sibling.
|
||||
- **Internal** (target tree): every file under `src/features/flights/` except `FlightsPage.tsx`
|
||||
- **Internal** (port-source): every file under `mission-planner/`
|
||||
@@ -109,9 +109,10 @@
|
||||
|
||||
- **Epic**: TBD
|
||||
- **Directory**: `src/features/annotations/`
|
||||
- **Public API** (de-facto):
|
||||
- `AnnotationsPage.tsx` → `AnnotationsPage` (route component)
|
||||
- `CanvasEditor.tsx` → `CanvasEditor` — **also imported by `07_dataset`** (cross-feature edge, see Verification Needed #3)
|
||||
- **Public API** (via `src/features/annotations/index.ts` barrel):
|
||||
- `AnnotationsPage` (route component)
|
||||
- `CanvasEditor` — **also imported by `07_dataset`** (cross-feature edge, see `architecture_compliance_baseline.md` F2). The barrel re-exports `CanvasEditor` to keep the consumer compliant with STC-ARCH-01 until F2 closes the edge.
|
||||
- **NOT re-exported** through this barrel: `classColors` symbols (`getClassColor`, `getClassNameFallback`, `getPhotoModeSuffix`, `FALLBACK_CLASS_NAMES`). Re-exporting them would create a circular barrel import (`AnnotationsPage → DetectionClasses → 06_annotations barrel → AnnotationsPage`). Consumers import `src/features/annotations/classColors` directly under the F3-pending exemption recorded in Layout Rule #3 and in STC-ARCH-01.
|
||||
- **Internal**: `MediaList.tsx`, `VideoPlayer.tsx`, `AnnotationsSidebar.tsx`
|
||||
- **Owns**: `src/features/annotations/**` EXCEPT `classColors.ts` (logically owned by `11_class-colors`; physical home pending refactor)
|
||||
- **Imports from**: `00_foundation`, `11_class-colors`, `01_api-transport`, `03_shared-ui`
|
||||
@@ -121,7 +122,7 @@
|
||||
|
||||
- **Epic**: TBD
|
||||
- **Directory**: `src/features/dataset/`
|
||||
- **Public API**: `DatasetPage.tsx` → `DatasetPage`
|
||||
- **Public API** (via `src/features/dataset/index.ts` barrel): `DatasetPage`.
|
||||
- **Internal**: none (single-page)
|
||||
- **Owns**: `src/features/dataset/**`
|
||||
- **Imports from**: `00_foundation`, `11_class-colors` (only when class-distribution chart is added — not in code yet), `01_api-transport`, `03_shared-ui`, **`06_annotations` (CanvasEditor cross-feature edge)**
|
||||
@@ -131,7 +132,7 @@
|
||||
|
||||
- **Epic**: TBD
|
||||
- **Directory**: `src/features/admin/`
|
||||
- **Public API**: `AdminPage.tsx` → `AdminPage`
|
||||
- **Public API** (via `src/features/admin/index.ts` barrel): `AdminPage`.
|
||||
- **Internal**: none (single-page)
|
||||
- **Owns**: `src/features/admin/**`
|
||||
- **Imports from**: `00_foundation`, `01_api-transport`, `03_shared-ui`
|
||||
@@ -141,7 +142,7 @@
|
||||
|
||||
- **Epic**: TBD
|
||||
- **Directory**: `src/features/settings/`
|
||||
- **Public API**: `SettingsPage.tsx` → `SettingsPage`
|
||||
- **Public API** (via `src/features/settings/index.ts` barrel): `SettingsPage`.
|
||||
- **Internal**: none (single-page)
|
||||
- **Owns**: `src/features/settings/**`
|
||||
- **Imports from**: `00_foundation`, `01_api-transport`, `03_shared-ui`
|
||||
@@ -151,7 +152,7 @@
|
||||
|
||||
- **Epic**: TBD
|
||||
- **Files** (no dedicated directory): `src/App.tsx`, `src/main.tsx`, `src/index.css`, `src/vite-env.d.ts`
|
||||
- **Public API**: `main.tsx` is the Vite entrypoint (no symbols are externally imported). `App.tsx` exports `App`.
|
||||
- **Public API**: `main.tsx` is the Vite entrypoint (no symbols are externally imported). `App.tsx` exports `App`. **No barrel** — the component is a top-level file collection, never imported as a unit. STC-ARCH-01's component allowlist intentionally omits `10_app-shell`.
|
||||
- **Internal**: `index.css` (global Tailwind base + `az-*` design-token CSS variables), `vite-env.d.ts` (type shim)
|
||||
- **Owns**: `src/App.tsx`, `src/main.tsx`, `src/index.css`, `src/vite-env.d.ts`
|
||||
- **Imports from**: every other component (it is the composition root)
|
||||
@@ -224,7 +225,7 @@ The following inferences could not be made cleanly from code alone. They are sur
|
||||
|
||||
2. **Physical home of `CanvasEditor.tsx`**. Same shape: it lives under `06_annotations` and is consumed cross-feature by `07_dataset`. Proposed: `src/components/canvas/CanvasEditor.tsx` (or a new `06b_canvas` component). **Decision needed**: keep the same-layer cross-feature edge, or schedule the lift?
|
||||
|
||||
3. **No barrel exports anywhere**. The codebase imports cross-component at file-name granularity (`import { api } from '../api/client'`). This means every internal file is *de-facto* Public API. Recommendation: Step 4 testability task to add `src/<component>/index.ts` barrels per component, locking the public surface. **Decision needed**: add barrels now or stay file-import?
|
||||
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`.
|
||||
|
||||
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).
|
||||
|
||||
@@ -240,4 +241,4 @@ The following inferences could not be made cleanly from code alone. They are sur
|
||||
|
||||
| Language | Root | Per-component path | Public API file | Test path |
|
||||
|----------|------|-------------------|-----------------|-----------|
|
||||
| TypeScript / React | `src/` | `src/<component>/` (this codebase deviates: features under `src/features/<feature>/`, shared chrome under `src/components/`) | `src/<component>/index.ts` (barrel — none exist today) | `src/<component>/__tests__/` (none exist today) |
|
||||
| TypeScript / React | `src/` | `src/<component>/` (this codebase deviates: features under `src/features/<feature>/`, shared chrome under `src/components/`) | `src/<component>/index.ts` (barrel; present for every component except `10_app-shell` — see Layout Rule #3) | `src/<component>/__tests__/` (none exist today) |
|
||||
|
||||
Reference in New Issue
Block a user