Add docs/INSTALL.md with two installation paths:
- Option A: Docker Compose (all-in-one with PostgreSQL, MinIO,
OpenLDAP, and optional nginx)
- Option B: Daemon install (systemd with external services, links to
setup instructions for PostgreSQL, MinIO, FreeIPA, nginx)
Includes LDAP user/group management instructions, verification steps,
and upgrade procedures for both paths.
Update README.md Quick Start to point to INSTALL.md, add to docs table.
Add redirect banner to DEPLOYMENT.md for first-time users.
Add comments to docker-compose.prod.yaml noting unsupported env vars.
- setup-host.sh: add SILO_DB_HOST and SILO_MINIO_HOST env var
overrides, update Go version from 1.23 to 1.24, expand generated
silod.env template with session secret and admin password fields
- deploy.sh: add SILO_DEPLOY_TARGET and SILO_DB_HOST env var
overrides for target host and database host
- setup-ipa-nginx.sh: replace hardcoded hostname with SILO_HOSTNAME
env var (default: silo.example.internal), parameterize SILO_PORT,
use variable substitution in nginx config template
All scripts retain backward-compatible defaults.
Add docker-compose.allinone.yaml with five services:
- PostgreSQL 16 with auto-applied migrations
- MinIO for S3-compatible file storage
- OpenLDAP (bitnami/openldap:2.6) with memberOf overlay and
preconfigured silo-admins/silo-users/silo-viewers groups
- Silo API server built from Dockerfile
- Nginx reverse proxy (optional, via --profile nginx)
Add scripts/setup-docker.sh interactive helper that generates
deployments/.env and deployments/config.docker.yaml with random
credentials. Supports --non-interactive for CI.
Add deployments/ldap/ LDIF init scripts for memberOf overlay and
Silo role groups. Add deployments/nginx/ reverse proxy configs.
- Fix docker-compose.yaml: mount config.dev.yaml instead of nonexistent
configs/config.yaml
- Add deployments/config.dev.yaml with Docker service names and dev
defaults for zero-setup make docker-up
- Expand .env.example with all SILO_* and LDAP_* variables
- Update config.example.yaml hostnames to localhost with Docker comments
- Add deployments/config.docker.yaml to .gitignore (generated file)
- Update migration count from 11 to 13 across all docs (012_bom_source,
013_move_cost_sourcing_to_props)
- Update endpoint count from 75 to 78 across all docs
- Add 3 missing endpoints to SPECIFICATION.md section 11.1:
GET /api/events (SSE), GET /api/items/by-uuid/{uuid},
POST /api/items/{pn}/bom/merge
- Add migrations 012 and 013 to STATUS.md table
- Fix migration 010 description (sourcing_link and standard_cost moved
to revision properties in 013)
Replace all references to internal hostnames (silo.kindred.internal,
psql.kindred.internal, minio.kindred.internal, ipa.kindred.internal,
keycloak.kindred.internal) with example.internal equivalents.
Replace gitea.kindred.internal and git.kindred.internal with the public
git.kindred-systems.com instance. Also fix stale silo-0062 repo name
in setup-host.sh and DEPLOYMENT.md.
- frontend-spec.md: rewrite CreateItemPane spec for dynamic form
rendering from form descriptor, replace CategoryPicker three-column
spec with multi-stage domain/subcategory picker, replace useCategories
hook with useFormDescriptor, update form sections to dynamic field
groups, mark hierarchical categories as implemented, remove
sourcing_link/standard_cost from item-level DB columns, update types
and implementation order
- SPECIFICATION.md: rename /api/schemas/{name}/properties endpoint to
/api/schemas/{name}/form
- Add ui section to kindred-rd.yaml with category_picker (multi-stage),
item_fields, field_groups, category_field_groups, and field_overrides
- Add UIConfig structs to Go schema parser with full YAML/JSON tags
- Add ValidateUI() to validate field references against property schemas
- Add ValuesByDomain() helper to auto-derive subcategory picker stages
- Implement GET /api/schemas/{name}/form endpoint that returns resolved
form descriptor with field metadata, widget hints, and category picker
- Replace GET /api/schemas/{name}/properties route with /form
- Add FormDescriptor TypeScript types
- Create useFormDescriptor hook (replaces useCategories)
- Rewrite CreateItemPane to render all sections dynamically from descriptor
- Update CategoryPicker with multi-stage domain/subcategory selection
- Delete useCategories.ts (superseded by useFormDescriptor)
- Add migration 013 to copy sourcing_link/standard_cost values into
current revision properties JSONB and drop the columns from items table
- Remove SourcingLink/StandardCost from Go Item struct and all DB queries
(items.go, audit_queries.go, projects.go)
- Remove from API request/response structs and handlers
- Update CSV/ODS/BOM export/import to read these from revision properties
- Update audit handlers to score as regular property fields
- Remove from frontend Item type and hardcoded form fields
- MainTab now reads sourcing_link/standard_cost from item.properties
- CreateItemPane/EditItemPane no longer have dedicated fields for these;
they will be rendered as schema-driven property fields
The server's ReadTimeout (15s) was closing SSE connections shortly after
they were established, causing a rapid connect/disconnect loop. The handler
already disabled WriteTimeout but not ReadTimeout.
- Add source badges (assembly=teal, manual=blue) to BOM display rows
- Add info banner when assembly-sourced entries exist
- Change source input from text field to select dropdown
- Add merge response types to types.ts
Closes#47
Add file_count and files_total_size to item API responses, computed
via batch query on item_files table (no migration needed).
- Add BatchGetFileStats() to audit_queries.go (follows BatchCheckBOM pattern)
- Add file stats to ItemResponse, HandleListItems, HandleGetItem, HandleGetItemByUUID
- Add 'Files' column to ItemTable (default visible in vertical mode)
- Add has_files computed field to audit completeness scoring (weight 1 for manufactured)
Generated 2026-01-31, references HTML templates and 8 migrations
that are now outdated. Superseded by STATUS.md and SPECIFICATION.md.
API.md and silo-spec.md were already deleted in earlier commits.
Add BOM merge endpoint for syncing assembly-derived BOM entries from
FreeCAD's silo-mod plugin.
Merge rules:
- Added: entries in request but not in server BOM are auto-created
with source='assembly'
- Quantity changed: existing entries with different quantity are
auto-updated
- Unchanged: same part and quantity are skipped
- Unreferenced: assembly-sourced entries in server BOM but not in
request are flagged as warnings (never auto-deleted)
- Manual entries are silently ignored in unreferenced detection
Also emits SSE 'bom.merged' event on successful merge (#46).
Promote BOM source from metadata JSONB to a dedicated VARCHAR(20)
column with CHECK constraint ('manual' or 'assembly').
- Add migration 012_bom_source.sql (column, data migration, cleanup)
- Add Source field to Relationship and BOMEntry structs
- Update all SQL queries (GetBOM, GetWhereUsed, GetExpandedBOM, Create)
- Update API response/request types with source field
- Update CSV/ODS export to read e.Source instead of metadata
- Update CSV import to set source on relationship directly
- Update frontend types and BOMTab to use top-level source field
Closes#43
Adds a new read-only endpoint to resolve a Silo item UUID to its full
ItemResponse. Used by silo-mod to resolve FreeCAD document SiloUUID
properties to part numbers during BOM sync.
- Reuses existing ItemRepository.GetByID() (items.id is the stable UUID)
- Returns 404 for archived items
- Registered in viewer-accessible route group (no editor role required)
Implements #17, #18, #19, #20, #21
- Add CSS custom properties for density-dependent spacing (--d-* vars)
in theme.css with comfortable (default) and compact modes
- Create useDensity hook with localStorage persistence and DOM attribute sync
- Add FOUC prevention in main.tsx (sync density before first paint)
- Create shared PageFooter component merging stats + pagination
- Refactor AppShell to flex layout with density toggle button (COM/CMP)
- Consolidate inline pagination from ItemsPage/AuditPage into PageFooter
- Delete FooterStats.tsx (replaced by PageFooter)
- Replace all hardcoded padding/font/gap values in ItemTable, AuditTable,
ItemsToolbar, and AuditToolbar with var(--d-*) references
Comfortable mode is already tighter than the previous hardcoded values.
Compact mode reduces further for power-user density.
Add server-sent events at GET /api/events for live mutation
notifications. Add server mode (normal/read-only/degraded) exposed
via /health, /ready, and SSE server.state events.
New files:
- broker.go: SSE event hub with client management, non-blocking
fan-out, ring buffer history for Last-Event-ID replay, heartbeat
- servermode.go: mode state machine with periodic MinIO health
check and SIGUSR1 read-only toggle
- sse_handler.go: HTTP handler using http.Flusher and
ResponseController to disable WriteTimeout for long-lived SSE
- broker_test.go, servermode_test.go: 13 unit tests
Modified:
- handlers.go: Server struct gains broker/serverState fields,
Health/Ready include mode and sse_clients, write handlers
emit item.created/updated/deleted and revision.created events
- routes.go: register GET /api/events, add RequireWritable
middleware to all 8 editor-gated route groups
- middleware.go: RequireWritable returns 503 in read-only mode
- csv.go, ods.go: emit bulk item.created events after import
- storage.go: add Ping() method for health checks
- config.go: add ReadOnly field to ServerConfig
- main.go: create broker/state, start background goroutines,
SIGUSR1 handler, graceful shutdown sequence
Closes#38, closes#39