- 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>
7.8 KiB
7.8 KiB
API Surface
Health
GET /health
Registry
GET /assetsPOST /assetsGET /registry/assets/{id}PUT /registry/assets/{id}DELETE /registry/assets/{id}GET /componentsPOST /componentsGET /registry/components/{id}PUT /registry/components/{id}
Registry invariants:
- Assets do not carry
project_idin request/response contracts. - Registry
PUTmutations are history-backed (event + snapshot + projection update), not direct projection writes.
Ingest
POST /ingest/hardwarePOST /ingest/manual/csvGET /ingest/manual/csv/jobs/{id}
Manual CSV ingest contract:
POST /ingest/manual/csvis asynchronous and returns202 Acceptedwithjob_id.- Final result is read from
GET /ingest/manual/csv/jobs/{id}.
Timeline
GET /assets/{id}/timelineGET /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_typeand openinstallation.slot_namefrom historicalobservations.detailsinto history-first projections (parts,installations)
- idempotent operational backfill: copies
POST /api/history/admin/repair/all- best-effort admin repair flow (single action) that can restore missing timeline slots from
observationsand enqueue recompute jobs for affected entities
- best-effort admin repair flow (single action) that can restore missing timeline slots from
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)
- destructive cleanup of registry/projection/raw rows for assets/components that no longer have active history (
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
- previews soft-delete of history events by
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}/eventsGET /api/history/assets/{id}/eventsPOST /api/history/components/{id}/applyPOST /api/history/assets/{id}/applyGET /api/history/components/{id}/timelineGET /api/history/assets/{id}/timelineGET /api/history/components/{id}/timeline/cards/{card_id}/eventsGET /api/history/assets/{id}/timeline/cards/{card_id}/eventsGET /api/history/components/{id}/events/{timeline_event_id}/detailGET /api/history/assets/{id}/events/{timeline_event_id}/detailDELETE /api/history/components/{id}/events/{event_id}DELETE /api/history/assets/{id}/events/{event_id}POST /api/history/components/{id}/rollbackPOST /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
- returns enriched current component rows for asset page table (
POST /api/assets/{asset_id}/components/add/check- duplicate preflight by
vendor_serialandvendor_serial + model
- duplicate preflight by
POST /api/assets/{asset_id}/components/actions/addmode = create_and_attach | attach_existing- supports
force=truefor 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)
- lightweight component search for Add modal (
History API invariants:
POST /api/history/*/applyuses semantic dedupe (no-op changes do not create events/snapshots/timeline rows).- Delete/rollback/hard-restore are asynchronous and return
202 Acceptedwithjob_id. - Timeline endpoints are grouped by day by default (
UTC, optionaltzoverride). - 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) acceptstzand 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 .../rollbacksupportscompensatingandhard_restoremodes.- Asset page component mutating actions (
add/edit/remove) are history-backed and must not bypass history transaction flows.
Failures
GET /failuresPOST /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_eventsprojection row with sourcemanual_ui - returns resolved component/server summary and created IDs
UI Routes
GET /uiGET /ui/searchGET /ui/assetGET /ui/asset/{vendor}GET /ui/asset/{vendor}/{model}GET /ui/asset/{vendor}/{model}/{vendor_serial}GET /ui/componentGET /ui/component/{vendor}GET /ui/component/modelsGET /ui/component/{vendor}/{model}(model statistics page)GET /ui/component/{vendor}/{model}/{vendor_serial}GET /ui/failureGET /ui/failure/{failure_id}(failure detail page)GET /ui/failuresGET /ui/failures/{failure_id}(compatibility alias to failure detail page)GET /ui/ingestGET /ui/ingest/manual-template.csvGET /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,\rare 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-8Content-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.