Add shared bible submodule, rename local bible to bible-local

- Add bible.git as submodule at bible/
- Rename bible/ → bible-local/ (project-specific architecture)
- Update CLAUDE.md to reference both bible/ and bible-local/
- Add AGENTS.md for Codex with same structure

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-01 16:37:10 +03:00
parent 09593019b1
commit c5d253a9df
20 changed files with 26 additions and 1 deletions

View File

@@ -0,0 +1,172 @@
# API Surface
## Health
- `GET /health`
## Registry
- `GET /assets`
- `POST /assets`
- `GET /registry/assets/{id}`
- `PUT /registry/assets/{id}`
- `DELETE /registry/assets/{id}`
- `GET /components`
- `POST /components`
- `GET /registry/components/{id}`
- `PUT /registry/components/{id}`
Registry invariants:
- Assets do not carry `project_id` in request/response contracts.
- Registry `PUT` mutations are history-backed (event + snapshot + projection update), not direct projection writes.
## Ingest
- `POST /ingest/hardware`
- `POST /ingest/manual/csv`
- `GET /ingest/manual/csv/jobs/{id}`
Manual CSV ingest contract:
- `POST /ingest/manual/csv` is asynchronous and returns `202 Accepted` with `job_id`.
- Final result is read from `GET /ingest/manual/csv/jobs/{id}`.
## Timeline
- `GET /assets/{id}/timeline`
- `GET /components/{id}/timeline`
- These routes now return the same structured **timeline cards** contract as history timeline endpoints (breaking change accepted).
## History API
- `POST /api/history/admin/backfill/current-from-observations`
- idempotent operational backfill: copies `component_type` and open `installation.slot_name` from historical `observations.details` into history-first projections (`parts`, `installations`)
- `POST /api/history/admin/repair/all`
- best-effort admin repair flow (single action) that can restore missing timeline slots from `observations` and enqueue recompute jobs for affected entities
- `POST /api/history/admin/cleanup-orphaned-projections/preview`
- lightweight count preview for orphan cleanup candidates
- `POST /api/history/admin/cleanup-orphaned-projections`
- destructive cleanup of registry/projection/raw rows for assets/components that no longer have active history (`is_deleted = FALSE`)
- `POST /api/history/admin/cancel-by-source/preview`
- previews soft-delete of history events by `source_type` (`ingest_json`, `ingest_csv`, `user`, `system`) and optional date/source_ref filters
- `POST /api/history/admin/cancel-by-source`
- soft-deletes matched history events and queues recompute jobs for affected assets/components
- `GET /api/history/jobs/{id}`
- `GET /api/history/components/{id}/events`
- `GET /api/history/assets/{id}/events`
- `POST /api/history/components/{id}/apply`
- `POST /api/history/assets/{id}/apply`
- `GET /api/history/components/{id}/timeline`
- `GET /api/history/assets/{id}/timeline`
- `GET /api/history/components/{id}/timeline/cards/{card_id}/events`
- `GET /api/history/assets/{id}/timeline/cards/{card_id}/events`
- `GET /api/history/components/{id}/events/{timeline_event_id}/detail`
- `GET /api/history/assets/{id}/events/{timeline_event_id}/detail`
- `DELETE /api/history/components/{id}/events/{event_id}`
- `DELETE /api/history/assets/{id}/events/{event_id}`
- `POST /api/history/components/{id}/rollback`
- `POST /api/history/assets/{id}/rollback`
## Asset Page Component Management API (Current Components)
- `GET /api/assets/{asset_id}/current-components`
- returns enriched current component rows for asset page table (`status`, `type`, `slot`, `vendor/model`, firmware) and filter options
- `POST /api/assets/{asset_id}/components/add/check`
- duplicate preflight by `vendor_serial` and `vendor_serial + model`
- `POST /api/assets/{asset_id}/components/actions/add`
- `mode = create_and_attach | attach_existing`
- supports `force=true` for moving an existing component from another asset to current asset
- `POST /api/assets/{asset_id}/components/actions/edit`
- bulk edit selected components on current asset (history-backed)
- multi-select rejects unique fields (`vendor_serial`, `slot`)
- `POST /api/assets/{asset_id}/components/actions/remove`
- remove is **de-assert only**
- requires `deassert_status = working | not_working | unknown`
- `GET /api/components/search-lite`
- lightweight component search for Add modal (`vendor_serial`, vendor/model, current installation, status)
History API invariants:
- `POST /api/history/*/apply` uses semantic dedupe (no-op changes do not create events/snapshots/timeline rows).
- Delete/rollback/hard-restore are asynchronous and return `202 Accepted` with `job_id`.
- Timeline endpoints are grouped by day by default (`UTC`, optional `tz` override).
- Timeline endpoints return **cards** (single/dedup/bulk), not raw rows.
- Timeline supports server-side filters via query parameters: `date_from`, `date_to`, `action`, `source`, `device`, `slot`, `part_number` (mapped to model), `serial`.
- Card drilldown endpoint (`.../timeline/cards/{card_id}/events`) accepts `tz` and must use the same timezone as the timeline cards response used to render the card.
- `DELETE .../events/{event_id}` is soft-delete + recompute enqueue (not physical delete).
- `POST .../rollback` supports `compensating` and `hard_restore` modes.
- Asset page component mutating actions (`add/edit/remove`) are history-backed and must not bypass history transaction flows.
## Failures
- `GET /failures`
- `POST /failures`
`POST /failures` (manual UI registration) request:
- `component_serial` (required, exact component serial)
- `server_serial` (optional, used for validation/binding; submit without component serial is rejected)
- `failure_date` (required, `YYYY-MM-DD`)
- `description` (optional)
`POST /failures` behavior:
- resolves component by serial
- records component failure status via history (`COMPONENT_STATUS_SET` -> `FAILED`)
- writes/updates `failure_events` projection row with source `manual_ui`
- returns resolved component/server summary and created IDs
## UI Routes
- `GET /ui`
- `GET /ui/search`
- `GET /ui/asset`
- `GET /ui/asset/{vendor}`
- `GET /ui/asset/{vendor}/{model}`
- `GET /ui/asset/{vendor}/{model}/{vendor_serial}`
- `GET /ui/component`
- `GET /ui/component/{vendor}`
- `GET /ui/component/models`
- `GET /ui/component/{vendor}/{model}` (model statistics page)
- `GET /ui/component/{vendor}/{model}/{vendor_serial}`
- `GET /ui/failure`
- `GET /ui/failure/{failure_id}` (failure detail page)
- `GET /ui/failures`
- `GET /ui/failures/{failure_id}` (compatibility alias to failure detail page)
- `GET /ui/ingest`
- `GET /ui/ingest/manual-template.csv`
- `GET /ui/history-admin`
UI/admin notes:
- Destructive registry action `DELETE /registry/assets/{id}` ("Asset -> Delete with details") is operated from the Data Admin UI, not from the regular asset page.
- UI routes are **semantic-first and singular** (`/ui/asset`, `/ui/component`, `/ui/failure`); legacy plural/ID-based UI fallback routes are intentionally removed.
- Failure detail page supports both singular and plural ID routes for compatibility (`/ui/failure/{id}` primary, `/ui/failures/{id}` alias).
## CSV Export Contract
Route: `GET /ui/ingest/manual-template.csv`
Rules:
- Encoding: UTF-8.
- UTF-8 BOM is included at file start for Excel compatibility.
- Delimiter: `;`.
- Line endings: `\r\n`.
- Escaping: RFC4180-compatible (fields with `;`, `"`, `\n`, `\r` are quoted; inner `"` is doubled).
- Header row is always present.
- Stable column order (deterministic, no map-driven order).
- Exported header order:
- ата_осмотра`
- `серийный_номер_сервера`
- `вендор`
- `p/n_устройства`
- `s/n_устройства`
- окейшн_в_сервере`
- ерсия_прошивки`
- `состояние_оборудования`
- Identifier-like columns are exported with Excel-safe text protection (to preserve leading zeros/codes).
- Empty values are exported as empty cells (no `null`/`undefined`).
- HTTP headers:
- `Content-Type: text/csv; charset=utf-8`
- `Content-Disposition: attachment; filename="manual-import-template.csv"`
## Routing Notes
- API router is registered in `internal/api/server.go`.
- Registry, ingest, failures, asset/component pages, and UI routes are attached to `http.ServeMux`.
- History API routes and background history worker are also wired from `internal/api/server.go`.