From ca762a658b82102509f5574cfae1b5583470d110 Mon Sep 17 00:00:00 2001 From: Michael Chus Date: Sat, 21 Feb 2026 20:37:10 +0300 Subject: [PATCH] docs: introduce architecture bible and migrate README/claude knowledge --- README.md | 86 +----------- bible/README.md | 20 +++ bible/architecture/api-surface.md | 46 +++++++ bible/architecture/data-model.md | 25 ++++ bible/architecture/runtime-flows.md | 89 +++++++++++++ bible/architecture/system-overview.md | 42 ++++++ .../ui-information-architecture.md | 32 +++++ bible/decisions/README.md | 17 +++ bible/governance/documentation-policy.md | 20 +++ claude.md | 125 +----------------- 10 files changed, 294 insertions(+), 208 deletions(-) create mode 100644 bible/README.md create mode 100644 bible/architecture/api-surface.md create mode 100644 bible/architecture/data-model.md create mode 100644 bible/architecture/runtime-flows.md create mode 100644 bible/architecture/system-overview.md create mode 100644 bible/architecture/ui-information-architecture.md create mode 100644 bible/decisions/README.md create mode 100644 bible/governance/documentation-policy.md diff --git a/README.md b/README.md index 94f600c..32db7fa 100644 --- a/README.md +++ b/README.md @@ -1,87 +1,5 @@ # Reanimator Core -Reanimator Core is a Go service for hardware inventory ingest and operational reliability workflows. +Architecture documentation was moved to the Project Bible: -## Active Scope - -The project currently includes: - -- Projects registry -- Assets registry -- Components registry -- Hardware ingest -- Failure ingest and failure views -- Timeline events for assets/components -- Web UI for dashboard, assets, components, failures, ingest - -The following legacy modules were removed from `main`: - -- LOT -- Customers -- Locations -- Tickets -- Analytics - -## API Endpoints - -### Health - -- `GET /health` - -### Registry - -- `GET /projects` -- `POST /projects` -- `GET /projects/{id}` -- `GET /assets` -- `POST /assets` -- `GET /registry/assets/{id}` -- `DELETE /registry/assets/{id}` -- `GET /components` -- `POST /components` - -### Ingest - -- `POST /ingest/hardware` - -### Timeline - -- `GET /assets/{id}/timeline` -- `GET /components/{id}/timeline` - -### Failures - -- `GET /failures` -- `POST /failures` - -## UI Routes - -- `GET /ui` -- `GET /ui/assets` -- `GET /ui/assets/{id}` -- `GET /ui/components` -- `GET /ui/components/{id}` -- `GET /ui/failures` -- `GET /ui/ingest` - -## Local Run - -```bash -make run -``` - -or - -```bash -go run ./cmd/reanimator-api -``` - -## Tests - -```bash -go test ./... -``` - -## Migrations - -Schema migrations are located in `migrations/` and are applied at startup. +- `bible/README.md` diff --git a/bible/README.md b/bible/README.md new file mode 100644 index 0000000..73ac3c6 --- /dev/null +++ b/bible/README.md @@ -0,0 +1,20 @@ +# Project Bible + +The Bible is the single source of truth for this project's architecture. + +## Documentation Rules + +- All architecture decisions must be recorded in this Bible. +- The documentation language is English only. +- If a decision is superseded, update the Bible immediately and remove or mark obsolete content. +- Do not duplicate architecture documentation in `README.md`, `claude.md`, or other files. + +## Structure + +- `governance/documentation-policy.md` - mandatory rules for maintaining architecture docs. +- `architecture/system-overview.md` - current scope, boundaries, and high-level system composition. +- `architecture/api-surface.md` - HTTP API and UI route contracts. +- `architecture/runtime-flows.md` - ingest, timeline, status, and failure invariants. +- `architecture/ui-information-architecture.md` - required UI structure and semantics. +- `architecture/data-model.md` - domain language, core tables, and migration boundaries. +- `decisions/README.md` - how to capture new and updated architecture decisions. diff --git a/bible/architecture/api-surface.md b/bible/architecture/api-surface.md new file mode 100644 index 0000000..ee768f7 --- /dev/null +++ b/bible/architecture/api-surface.md @@ -0,0 +1,46 @@ +# API Surface + +## Health + +- `GET /health` + +## Registry + +- `GET /projects` +- `POST /projects` +- `GET /projects/{id}` +- `GET /assets` +- `POST /assets` +- `GET /registry/assets/{id}` +- `DELETE /registry/assets/{id}` +- `GET /components` +- `POST /components` + +## Ingest + +- `POST /ingest/hardware` + +## Timeline + +- `GET /assets/{id}/timeline` +- `GET /components/{id}/timeline` + +## Failures + +- `GET /failures` +- `POST /failures` + +## UI Routes + +- `GET /ui` +- `GET /ui/assets` +- `GET /ui/assets/{id}` +- `GET /ui/components` +- `GET /ui/components/{id}` +- `GET /ui/failures` +- `GET /ui/ingest` + +## 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`. diff --git a/bible/architecture/data-model.md b/bible/architecture/data-model.md new file mode 100644 index 0000000..822cd1a --- /dev/null +++ b/bible/architecture/data-model.md @@ -0,0 +1,25 @@ +# Data Model And Migration Boundaries + +## Naming Model + +- Internal canonical naming uses `Machine` and `Part`. +- API/UI compatibility keeps `asset` and `component` terminology where already exposed. +- In domain aliases: + - `type Asset = Machine` + - `type Component = Part` + +## Core Persistence Areas + +- Asset registry: `machines` +- Component registry: `parts` +- Installations: `installations` +- Observations: `observations` +- Timeline: `timeline_events` +- Failures: `failure_events` +- Asset firmware state: `machine_firmware_states` + +## Migration Policy + +- Migrations are stored in `migrations/`. +- Schema migrations are applied at startup. +- Legacy entities removed in migration `0016_remove_legacy_features` remain out of active scope. diff --git a/bible/architecture/runtime-flows.md b/bible/architecture/runtime-flows.md new file mode 100644 index 0000000..fdbe460 --- /dev/null +++ b/bible/architecture/runtime-flows.md @@ -0,0 +1,89 @@ +# Runtime Flows And Invariants + +## Event Time Source Priority + +Use component event time over ingest time whenever possible. + +- `eventFallbackTime(actual, ingestedAt, collectedAt)`: +1. `actual` +2. `ingestedAt` +3. `collectedAt` + +- `collectedFallbackTime(collectedAt, ingestedAt)`: +1. `collectedAt` +2. `ingestedAt` + +## Status Event Time Parsing Order + +`parseComponentStatusEventTime` resolves time in this order: + +1. `status_changed_at` +2. Latest matching `status_history` item for current status +3. Latest parseable `status_history` item +4. `status_checked_at` + +## Failure Event Rules + +For critical components: + +- Timeline event type: `COMPONENT_FAILED` +- `failure_events.failure_time` uses resolved failure time (not raw ingest time) +- `failure_events.external_id` includes the same failure timestamp + +## First Seen Rules + +`parts.first_seen_at` must be the earliest known ingest-derived component time. + +Candidate sources: + +1. Parseable `status_history[].changed_at` +2. `status_changed_at` +3. `status_checked_at` +4. `eventFallbackTime(nil, ingestedAt, collectedAt)` + +Persistence rule: + +- Keep the minimum value over time. +- If incoming is earlier than stored value, overwrite with incoming value. + +## Component Health Computation In UI + +Component health is derived only from the latest status event among: + +- `COMPONENT_FAILED` +- `COMPONENT_WARNING` +- `COMPONENT_OK` + +Non-status timeline events (`INSTALLED`, `REMOVED`, `FIRMWARE_CHANGED`, `FIRMWARE_INSTALLED`, etc.) must not change health status. + +## Firmware Timeline Rules + +For component firmware observations: + +- First observed version -> `FIRMWARE_INSTALLED` (asset + component timeline pair) +- Later version change -> `FIRMWARE_CHANGED` (asset + component timeline pair) + +Storage details: + +- `FIRMWARE_INSTALLED` stores transition string in `timeline_events.firmware_version`: `- -> ` +- `FIRMWARE_CHANGED` stores installed/new firmware value + +Detection details: + +- Previous observation lookup: `ORDER BY observed_at DESC, id DESC LIMIT 1 OFFSET 1` + +## Timeline Color Semantics + +- `REMOVED` -> yellow +- `COMPONENT_FAILED` -> red +- `COMPONENT_WARNING` and related warning semantics follow `timelineEventClass` + +## Regression Guardrails + +Do not reintroduce these regressions: + +- Using ingest timestamp when payload provides better event/failure timestamp +- Letting `INSTALLED` mark failed components as healthy +- Missing `Previous Components` section on asset page +- Missing installation history on component page +- Missing firmware information on component page timeline diff --git a/bible/architecture/system-overview.md b/bible/architecture/system-overview.md new file mode 100644 index 0000000..cd376bf --- /dev/null +++ b/bible/architecture/system-overview.md @@ -0,0 +1,42 @@ +# System Overview + +## Product + +Reanimator Core is a Go service for hardware inventory ingest and operational reliability workflows. + +## Active Scope + +- Projects registry +- Assets registry (domain model: `Machine`, API surface keeps `asset` naming) +- Components registry (domain model: `Part`, API surface keeps `component` naming) +- Hardware ingest +- Failure ingest and failure views +- Timeline events for assets/components +- Web UI for dashboard, assets, components, failures, ingest + +## Explicitly Removed Legacy Scope + +These modules are not part of the active architecture: + +- LOT +- Customers +- Locations +- Tickets +- Analytics + +## Runtime Composition + +- HTTP server: `internal/api` +- Ingest orchestration: `internal/ingest` +- Persistence: `internal/repository/*` +- Domain types: `internal/domain` +- Migrations: `migrations/` + +## Local Execution + +- `make run` +- `go run ./cmd/reanimator-api` + +## Verification + +- `go test ./...` diff --git a/bible/architecture/ui-information-architecture.md b/bible/architecture/ui-information-architecture.md new file mode 100644 index 0000000..1040eea --- /dev/null +++ b/bible/architecture/ui-information-architecture.md @@ -0,0 +1,32 @@ +# UI Information Architecture + +## Asset Page + +Required section order: + +1. `Current Components` +2. `Previous Components` (directly below Current Components) +3. `Movement & Events` + +`Previous Components` lists components that were previously installed on the asset and are currently removed. + +## Component Page + +Required content: + +- Component card including current firmware +- Installation history table with: + - Asset + - Installed At + - Removed At +- Timeline metadata equivalent to asset timeline: + - Type + - Location + - Model + - Firmware (fallback to latest known component firmware when event value is empty) + +## Supporting Repositories Required By UI + +- `timeline.EventRepository.ListLatestBySubjectsAndEventTypes(...)` +- `registry.InstallationRepository.ListPreviousComponentsByAsset(...)` +- `registry.InstallationRepository.ListInstallationHistoryByComponent(...)` diff --git a/bible/decisions/README.md b/bible/decisions/README.md new file mode 100644 index 0000000..de598c9 --- /dev/null +++ b/bible/decisions/README.md @@ -0,0 +1,17 @@ +# Architecture Decision Records + +Use this directory to capture architecture decisions and significant updates. + +## Required + +- Every architecture decision must be recorded in the Bible. +- If a decision replaces an older one, update the older document in the same change. +- Keep entries short, explicit, and linked to the affected architecture files. + +## Minimal Entry Template + +- Date (`YYYY-MM-DD`) +- Decision +- Context +- Consequences +- Supersedes (if any) diff --git a/bible/governance/documentation-policy.md b/bible/governance/documentation-policy.md new file mode 100644 index 0000000..7106644 --- /dev/null +++ b/bible/governance/documentation-policy.md @@ -0,0 +1,20 @@ +# Documentation Policy + +## Purpose + +This policy defines how architectural knowledge is captured and maintained. + +## Mandatory Rules + +- Record every architecture decision in the Bible before or together with implementation. +- Use English for all architecture documentation. +- Keep only current architecture in active sections. +- When a solution is replaced, update or remove obsolete guidance in the same change. +- Keep architecture details centralized in `bible/`; other top-level docs should only reference it. + +## Change Workflow + +1. Update the relevant file(s) in `bible/architecture/`. +2. If behavior changed, add or update a decision note in `bible/decisions/`. +3. Remove duplicated or outdated statements from non-Bible docs. +4. Validate consistency against code paths in `internal/api`, `internal/ingest`, and `internal/repository`. diff --git a/claude.md b/claude.md index 5d97929..9381c1a 100644 --- a/claude.md +++ b/claude.md @@ -1,124 +1 @@ -# Reanimator AI Memory (Timeline + UI Rules) - -This file is the source of truth for timeline behavior, status logic, and related UI expectations. -Any future AI change must preserve these rules unless explicitly changed by user request. - -## 1. Event Time Source Priority - -Use the real component event time, not ingest time, whenever available. - -- `eventFallbackTime(actual, ingestedAt, collectedAt)` priority: -1. `actual` (status/event timestamp from payload) -2. `ingestedAt` -3. `collectedAt` (last fallback) - -- `collectedFallbackTime(collectedAt, ingestedAt)` is only for collected timestamp fields: -1. `collectedAt` -2. `ingestedAt` - -## 2. Status Event Time Parsing - -Component status event time must be resolved in this order: - -1. `status_changed_at` -2. latest matching entry in `status_history` for current status -3. latest parseable entry in `status_history` -4. `status_checked_at` - -## 3. Failure Event Time Rules - -For `Critical` components: - -- timeline status event type: `COMPONENT_FAILED` -- `failure_events.failure_time` must use resolved failure time (not raw ingest time) -- failure `external_id` includes that same failure time - -## 4. First Seen Logic - -`parts.first_seen_at` must always equal the earliest known ingest-derived component time. - -- Candidate timestamps: -1. `status_history[].changed_at` (all parseable entries) -2. `status_changed_at` -3. `status_checked_at` -4. fallback via `eventFallbackTime(nil, ingestedAt, collectedAt)` if none exists - -- DB update rule: keep minimum value over time -- If existing value is newer, overwrite with earlier incoming value - -## 5. Component Status Calculation (UI) - -`INSTALLED` and other non-status timeline events must never "heal" a failed component. - -- Component status is computed only from the latest status event among: - - `COMPONENT_FAILED` - - `COMPONENT_WARNING` - - `COMPONENT_OK` -- `INSTALLED`, `REMOVED`, `FIRMWARE_CHANGED`, `FIRMWARE_INSTALLED`, etc. do not change component health state. - -## 6. Firmware Timeline Events - -For component firmware events: - -- First observed firmware version: create `FIRMWARE_INSTALLED` (asset + component timeline pair) -- Later version change: create `FIRMWARE_CHANGED` (asset + component timeline pair) - -Details: - -- For `FIRMWARE_INSTALLED`, `timeline_events.firmware_version` stores transition string: - - `- -> ` -- For `FIRMWARE_CHANGED`, `timeline_events.firmware_version` stores installed/new version value. -- Firmware change detection reads previous observation with: - - `ORDER BY observed_at DESC, id DESC LIMIT 1 OFFSET 1` - - (current observation is already inserted in the same ingest transaction) - -## 7. Timeline Visual Semantics - -Color coding requirements: - -- `REMOVED` must be yellow -- `COMPONENT_FAILED` must be red -- Warning/failure classes follow existing `timelineEventClass` rules - -## 8. Asset Page Structure - -Asset page must contain: - -1. `Current Components` -2. `Previous Components` (directly below Current Components) -3. `Movement & Events` - -`Previous Components` includes components previously installed on this asset and currently removed. - -## 9. Component Page Requirements - -Component page must include: - -- Component card with current `Firmware` -- Installation history table: - - Asset - - Installed At - - Removed At -- Timeline metadata equivalent to asset timeline: - - Type - - Location - - Model - - Firmware (with fallback to latest known component firmware) - -## 10. Repository APIs Added for This Behavior - -- `timeline.EventRepository.ListLatestBySubjectsAndEventTypes(...)` -- `registry.InstallationRepository.ListPreviousComponentsByAsset(...)` -- `registry.InstallationRepository.ListInstallationHistoryByComponent(...)` - -These methods are part of expected data flow for UI and status logic. - -## 11. Regression Guardrails - -Do not reintroduce any of these regressions: - -- using ingest timestamp instead of real failure/event time when payload has a better timestamp -- letting `INSTALLED` mark failed components as healthy -- missing `Previous Components` section on asset page -- missing installation history on component page -- missing firmware information on component page timeline +Read and follow `/Users/mchusavitin/Documents/git/core/bible/README.md` as the architecture source of truth.