Merge branch 'main' into ui-density-mode

This commit is contained in:
2026-02-09 01:20:44 +00:00
4 changed files with 7 additions and 287 deletions

View File

@@ -5,6 +5,7 @@ server:
host: "0.0.0.0" host: "0.0.0.0"
port: 8080 port: 8080
base_url: "http://localhost:8080" base_url: "http://localhost:8080"
# read_only: false # Reject all write operations; toggle at runtime with SIGUSR1
database: database:
host: "psql.kindred.internal" host: "psql.kindred.internal"

View File

@@ -36,10 +36,10 @@ a blank field during a design review or procurement cycle.
## Design ## Design
The audit tool is a new page in the existing web UI (`/audit`), built with The audit tool is a page in the web UI (`/audit`), built with the React SPA
the same server-rendered Go templates + vanilla JS approach as the items and (same architecture as the items, projects, and schemas pages). It adds one
projects pages. It adds one new API endpoint for the completeness data and new API endpoint for the completeness data and reuses existing endpoints for
reuses existing endpoints for updates. updates.
### Completeness Scoring ### Completeness Scoring

View File

@@ -30,12 +30,14 @@ YAML values support environment variable expansion using `${VAR_NAME}` syntax. E
| `server.host` | string | `"0.0.0.0"` | Bind address | | `server.host` | string | `"0.0.0.0"` | Bind address |
| `server.port` | int | `8080` | HTTP port | | `server.port` | int | `8080` | HTTP port |
| `server.base_url` | string | — | External URL (e.g. `https://silo.example.com`). Used for OIDC callback URLs and session cookie domain. Required when OIDC is enabled. | | `server.base_url` | string | — | External URL (e.g. `https://silo.example.com`). Used for OIDC callback URLs and session cookie domain. Required when OIDC is enabled. |
| `server.read_only` | bool | `false` | Start in read-only mode. All write endpoints return 503. Can be toggled at runtime with `SIGUSR1`. |
```yaml ```yaml
server: server:
host: "0.0.0.0" host: "0.0.0.0"
port: 8080 port: 8080
base_url: "https://silo.example.com" base_url: "https://silo.example.com"
read_only: false
``` ```
--- ---

View File

@@ -1,283 +0,0 @@
# Repository Status Report
**Generated:** 2026-01-31
**Branch:** main
**Last Build:** `go build ./...` and `go vet ./...` pass clean
---
## Codebase Summary
| Category | Lines | Files |
|----------|-------|-------|
| Go source | ~6,644 | 20 |
| HTML templates | ~4,923 | 4 |
| SQL migrations | ~464 | 8 |
| **Total** | **~12,231** | **32** |
---
## Architecture
```
cmd/
silo/ CLI client (313 lines)
silod/ API server (126 lines)
internal/
api/ HTTP handlers, routes, middleware, templates (3,491 Go + 4,923 HTML)
config/ YAML config loading (132 lines)
db/ PostgreSQL repositories (1,634 lines)
migration/ Property migration framework (211 lines)
odoo/ Odoo ERP integration stubs (201 lines)
partnum/ Part number generator (180 lines)
schema/ YAML schema parser (235 lines)
storage/ MinIO S3 client (121 lines)
migrations/ Database DDL (8 files)
```
### Key Dependencies
- `go-chi/chi/v5` -- HTTP router
- `jackc/pgx/v5` -- PostgreSQL driver
- `minio/minio-go/v7` -- S3-compatible storage
- `rs/zerolog` -- Structured logging
- `sahilm/fuzzy` -- Fuzzy text matching
- `gopkg.in/yaml.v3` -- YAML parsing
---
## API Surface (38 Routes)
### Web UI
| Method | Path | Handler |
|--------|------|---------|
| GET | `/` | Items page |
| GET | `/projects` | Projects page |
| GET | `/schemas` | Schemas page |
### Items
| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/items` | List with filtering and pagination |
| POST | `/api/items` | Create item |
| GET | `/api/items/search` | Fuzzy search |
| GET | `/api/items/export.csv` | CSV export |
| POST | `/api/items/import` | CSV import |
| GET | `/api/items/template.csv` | CSV template |
| GET | `/api/items/{partNumber}` | Get item |
| PUT | `/api/items/{partNumber}` | Update item |
| DELETE | `/api/items/{partNumber}` | Archive item |
### Revisions
| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/items/{pn}/revisions` | List revisions |
| POST | `/api/items/{pn}/revisions` | Create revision |
| GET | `/api/items/{pn}/revisions/compare` | Compare two revisions |
| GET | `/api/items/{pn}/revisions/{rev}` | Get revision |
| PATCH | `/api/items/{pn}/revisions/{rev}` | Update status/label |
| POST | `/api/items/{pn}/revisions/{rev}/rollback` | Rollback |
### Files
| Method | Path | Description |
|--------|------|-------------|
| POST | `/api/items/{pn}/file` | Upload file |
| GET | `/api/items/{pn}/file` | Download latest |
| GET | `/api/items/{pn}/file/{rev}` | Download at revision |
### BOM
| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/items/{pn}/bom` | List children |
| POST | `/api/items/{pn}/bom` | Add child |
| GET | `/api/items/{pn}/bom/expanded` | Multi-level BOM |
| GET | `/api/items/{pn}/bom/where-used` | Where-used lookup |
| GET | `/api/items/{pn}/bom/export.csv` | BOM CSV export |
| POST | `/api/items/{pn}/bom/import` | BOM CSV import |
| PUT | `/api/items/{pn}/bom/{child}` | Update quantity/ref |
| DELETE | `/api/items/{pn}/bom/{child}` | Remove child |
### Projects
| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/projects` | List projects |
| POST | `/api/projects` | Create project |
| GET | `/api/projects/{code}` | Get project |
| PUT | `/api/projects/{code}` | Update project |
| DELETE | `/api/projects/{code}` | Delete project |
| GET | `/api/projects/{code}/items` | Items in project |
### Item-Project Associations
| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/items/{pn}/projects` | Item's projects |
| POST | `/api/items/{pn}/projects` | Tag item to project |
| DELETE | `/api/items/{pn}/projects/{code}` | Remove tag |
### Schemas
| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/schemas` | List schemas |
| GET | `/api/schemas/{name}` | Get schema |
| GET | `/api/schemas/{name}/properties` | Property definitions |
| POST | `/api/schemas/{name}/segments/{seg}/values` | Add enum value |
| PUT | `/api/schemas/{name}/segments/{seg}/values/{code}` | Update enum value |
| DELETE | `/api/schemas/{name}/segments/{seg}/values/{code}` | Delete enum value |
### Odoo Integration (Stubs)
| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/integrations/odoo/config` | Get config |
| PUT | `/api/integrations/odoo/config` | Update config |
| GET | `/api/integrations/odoo/sync-log` | Sync history |
| POST | `/api/integrations/odoo/test-connection` | Test connection |
| POST | `/api/integrations/odoo/sync/push/{pn}` | Push to Odoo |
| POST | `/api/integrations/odoo/sync/pull/{id}` | Pull from Odoo |
### Other
| Method | Path | Description |
|--------|------|-------------|
| GET | `/health` | Health probe |
| GET | `/ready` | Readiness probe (DB + MinIO) |
| POST | `/api/generate-part-number` | Generate next PN |
---
## Database Migrations
| # | File | Purpose |
|---|------|---------|
| 1 | `001_initial.sql` | Core schema: items, revisions, relationships, locations, inventory, sequences, projects, schemas |
| 2 | `002_sequence_by_name.sql` | Sequence naming changes |
| 3 | `003_remove_material.sql` | Schema cleanup |
| 4 | `004_cad_sync_state.sql` | CAD synchronization tracking |
| 5 | `005_property_schema_version.sql` | Property versioning framework |
| 6 | `006_project_tags.sql` | Many-to-many project-item relationships |
| 7 | `007_revision_status.sql` | Revision status and labels |
| 8 | `008_odoo_integration.sql` | Integrations + sync_log tables |
---
## Web UI Architecture
The web UI uses server-rendered Go templates with vanilla JavaScript (no framework).
### Items Page (`items.html`, 3718 lines)
Infor CloudSuite-style split-panel layout:
- **Horizontal mode** (default): item list on left, tabbed detail panel on right
- **Vertical mode**: tabbed detail panel on top, item list below
- **Detail tabs**: Main, Properties, Revisions, BOM, Where Used
- **Ctrl+F** opens in-page filter overlay with fuzzy search
- **Column config**: gear icon popover, separate settings per layout mode
- **Search scope**: All / Part Number / Description toggle pills
### Projects Page (`projects.html`, 345 lines)
- Full CRUD for project codes
- Item count per project
- Click project code to filter items page
### Schemas Page (`schemas.html`, 689 lines)
- Schema browsing and enum value management
### Base Template (`base.html`, 171 lines)
- 3-tab navigation: Items, Projects, Schemas
- Catppuccin Mocha dark theme
---
## Feature Stubs (Not Yet Implemented)
These are scaffolded but contain placeholder implementations.
### Odoo ERP Integration
All functions in `internal/odoo/` return "not yet implemented" errors:
| File | Function | Status |
|------|----------|--------|
| `client.go:30` | `Authenticate()` | Stub |
| `client.go:41` | `SearchRead()` | Stub |
| `client.go:51` | `Create()` | Stub |
| `client.go:60` | `Write()` | Stub |
| `client.go:70` | `TestConnection()` | Stub |
| `sync.go:27` | `PushItem()` | Stub (logs, returns nil) |
| `sync.go:36` | `PullProduct()` | Stub (logs, returns nil) |
API handlers at `odoo_handlers.go`:
- `HandleTestOdooConnection` (line 134) -- returns stub message
- `HandleOdooPush` (line 149) -- returns stub message
- `HandleOdooPull` (line 167) -- returns stub message
Config and sync-log CRUD handlers are functional.
### Part Number Date Segments
`internal/partnum/generator.go:102` -- `formatDate()` returns error. Date-based segments in schemas will fail at generation time.
### Location and Inventory APIs
Tables exist from migration 001 (`locations`, `inventory`) but no API handlers or repository methods are implemented. The database layer has no `LocationRepository` or `InventoryRepository`.
---
## Potential Issues
### Critical
1. **No authentication or authorization.** All API endpoints are publicly accessible. Single-user only. Adding LDAP/FreeIPA integration is required before multi-user deployment.
2. **No file locking.** Concurrent edits to the same item or file upload can cause data races. A pessimistic locking mechanism is needed for CAD file workflows.
3. **No unit tests.** Zero test coverage across the entire Go codebase. Regressions cannot be caught automatically.
### High
4. **Large monolithic template.** `items.html` is 3,718 lines with inline CSS and JavaScript. Changes risk unintended side effects. Consider extracting JavaScript into separate files or adopting a build step.
5. **No input validation middleware.** API handlers validate some fields inline but there is no systematic validation layer. Malformed requests may produce unclear errors or unexpected behavior.
6. **No rate limiting.** API has no request rate controls. A misbehaving client or script could overwhelm the server.
7. **Odoo handlers reference DB repositories not wired up.** `odoo_handlers.go` calls `s.db.IntegrationRepository()` but the `DB` struct in `db/db.go` does not expose an `IntegrationRepository` method. These handlers will panic if reached with a real database operation. Currently safe because config is stored in-memory and stubs short-circuit before DB calls.
### Medium
8. **No pagination on fuzzy search.** `HandleFuzzySearch` loads all items matching type/project filters into memory before fuzzy matching. Large datasets will cause high memory usage.
9. **CSV import lacks transaction rollback on partial failure.** If import fails mid-batch, already-imported items remain.
10. **No CSRF protection.** Web UI forms submit via `fetch()` but there are no CSRF tokens. Acceptable for single-user but a risk if authentication is added.
11. **MinIO connection not validated at startup.** The `/ready` endpoint checks MinIO, but the server starts regardless. A misconfigured MinIO will only fail on file operations.
12. **Property migration framework exists but has no registered migrations.** `internal/migration/properties.go` defines the framework but no concrete migrations use it yet.
---
## Recent Git History
```
8e44ed2 2026-01-29 Fix SIGSEGV: defer document open after dialog close
e2b3f12 2026-01-29 Fix API URL: only auto-append /api for bare hostnames
559f615 2026-01-29 Fix API URL handling and SSL certificate verification
f08ecc1 2026-01-29 feat(workbench): fix icon loading and add settings dialog
53b5edb 2026-01-29 update documentation and specs
5ee88a6 2026-01-26 update deploy.sh
93add05 2026-01-26 improve csv import handling
2d44b2a 2026-01-26 add free-ipa setup
```
---
## Deployment
### Supported Methods
- **Docker Compose** -- `deployments/docker-compose.yaml` (dev), `docker-compose.prod.yaml` (prod)
- **systemd** -- `deployments/systemd/silod.service`
- **Manual** -- `go build ./cmd/silod && ./silod -config config.yaml`
### Infrastructure Requirements
- PostgreSQL 15+ with `pg_trgm` and `uuid-ossp` extensions
- MinIO or S3-compatible storage
- Go 1.23+ for building