From 30bb3ee56ec9e60e5bd38ae21896371f8623366f Mon Sep 17 00:00:00 2001 From: Forbes Date: Fri, 13 Feb 2026 12:43:24 -0600 Subject: [PATCH 01/43] docs: integrate root ROADMAP.md into docs/ROADMAP.md Merge the tactical root ROADMAP.md (SOLIDWORKS PDM gap analysis, Phase 1-6 timelines, project inventory) with the visionary docs/ROADMAP.md (modular platform architecture, .kc format, dependency tiers) into a single unified document at docs/ROADMAP.md. - Adopt dependency tier structure (Tier 0-6) as the organizing spine - Add Status column to each tier table from project inventory - Replace Phase 1-6 calendar timelines with Near-Term Priorities section - Migrate 9 SOLIDWORKS PDM comparison tables to docs/GAP_ANALYSIS.md - Migrate Feature Comparison Matrix to docs/GAP_ANALYSIS.md - Preserve Phase 1 task checklists and success metrics as appendices - Update README.md link from ROADMAP.md to docs/ROADMAP.md - Delete root ROADMAP.md --- README.md | 2 +- ROADMAP.md | 536 ------------------------------------------- docs/GAP_ANALYSIS.md | 170 +++++++++++++- docs/ROADMAP.md | 442 +++++++++++++++++++++++++++++++++++ 4 files changed, 609 insertions(+), 541 deletions(-) delete mode 100644 ROADMAP.md create mode 100644 docs/ROADMAP.md diff --git a/README.md b/README.md index 2dce04e..3262f06 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ The server provides the REST API and ODS endpoints consumed by these clients. | [docs/AUTH_USER_GUIDE.md](docs/AUTH_USER_GUIDE.md) | User guide for login, tokens, and roles | | [docs/GAP_ANALYSIS.md](docs/GAP_ANALYSIS.md) | Gap analysis and revision control roadmap | | [docs/COMPONENT_AUDIT.md](docs/COMPONENT_AUDIT.md) | Component audit tool design | -| [ROADMAP.md](ROADMAP.md) | Feature roadmap and SOLIDWORKS PDM comparison | +| [docs/ROADMAP.md](docs/ROADMAP.md) | Platform roadmap, dependency tiers, and gap summary | | [frontend-spec.md](frontend-spec.md) | React SPA frontend specification | ## License diff --git a/ROADMAP.md b/ROADMAP.md deleted file mode 100644 index dc6db61..0000000 --- a/ROADMAP.md +++ /dev/null @@ -1,536 +0,0 @@ -# Silo Roadmap - -**Version:** 1.1 -**Date:** February 2026 -**Purpose:** Project inventory, SOLIDWORKS PDM gap analysis, and development roadmap - ---- - -## Table of Contents - -1. [Executive Summary](#executive-summary) -2. [Current Project Inventory](#current-project-inventory) -3. [SOLIDWORKS PDM Gap Analysis](#solidworks-pdm-gap-analysis) -4. [Feature Roadmap](#feature-roadmap) -5. [Implementation Phases](#implementation-phases) - ---- - -## Executive Summary - -Silo is an R&D-oriented item database and part management system. It provides configurable part number generation, revision tracking, BOM management, and file versioning through MinIO storage. CAD integration (FreeCAD workbench, LibreOffice Calc extension) is maintained in separate repositories ([silo-mod](https://git.kindred-systems.com/kindred/silo-mod), [silo-calc](https://git.kindred-systems.com/kindred/silo-calc)). - -This document compares Silo's current capabilities against SOLIDWORKS PDM—the industry-leading product data management solution—to identify gaps and prioritize future development. - -### Key Differentiators - -| Aspect | Silo | SOLIDWORKS PDM | -|--------|------|----------------| -| **Target CAD** | FreeCAD / Kindred Create (open source) | SOLIDWORKS (proprietary) | -| **Part Numbering** | Schema-as-configuration (YAML) | Fixed format with some customization | -| **Licensing** | Open source / Kindred Proprietary | Commercial ($3,000-$10,000+ per seat) | -| **Storage** | PostgreSQL + MinIO (S3-compatible) | SQL Server + File Archive | -| **Philosophy** | R&D-oriented, lightweight | Enterprise-grade, comprehensive | - ---- - -## Current Project Inventory - -### Implemented Features (MVP Complete) - -#### Core Database System -- PostgreSQL schema with 13 migrations -- UUID-based identifiers throughout -- Soft delete support via `archived_at` timestamps -- Atomic sequence generation for part numbers - -#### Part Number Generation -- YAML schema parser with validation -- Segment types: `string`, `enum`, `serial`, `constant` -- Scope templates for serial counters (e.g., `{category}`, `{project}`) -- Format templates for custom output - -#### Item Management -- Full CRUD operations for items -- Item types: part, assembly, drawing, document, tooling, purchased, electrical, software -- Custom properties via JSONB storage -- Project tagging with many-to-many relationships - -#### Revision Control -- Append-only revision history -- Revision metadata: properties, file reference, checksum, comment -- Status tracking: draft, review, released, obsolete -- Labels/tags per revision -- Revision comparison (diff) -- Rollback functionality - -#### File Management -- MinIO integration with versioning -- File upload/download via REST API -- SHA256 checksums for integrity -- Storage path: `items/{partNumber}/rev{N}.FCStd` - -#### Bill of Materials (BOM) -- Relationship types: component, alternate, reference -- Multi-level BOM (recursive expansion with configurable depth) -- Where-used queries (reverse parent lookup) -- BOM CSV and ODS export/import with cycle detection -- Reference designators for electronics -- Quantity tracking with units -- Revision-specific child linking - -#### Project Management -- Project CRUD operations -- Unique project codes (2-10 characters) -- Item-to-project tagging -- Project-filtered queries - -#### Data Import/Export -- CSV export with configurable properties -- CSV import with dry-run validation -- ODS spreadsheet import/export (items, BOMs, project sheets) -- Template generation for import formatting - -#### API & Web Interface -- REST API with 78 endpoints -- Authentication: local (bcrypt), LDAP/FreeIPA, OIDC/Keycloak -- Role-based access control (admin > editor > viewer) -- API token management (SHA-256 hashed) -- Session management (PostgreSQL-backed, 24h lifetime) -- CSRF protection (nosurf on web forms) -- Middleware: logging, CORS, recovery, request ID -- Web UI — React SPA (Vite + TypeScript, Catppuccin Mocha theme) -- Fuzzy search -- Health and readiness probes - -#### Audit & Completeness -- Audit logging (database table with user/action/resource tracking) -- Item completeness scoring with weighted fields -- Category-specific property validation -- Tier classification (critical/low/partial/good/complete) - -#### Configuration -- YAML configuration with environment variable overrides -- Multi-schema support -- Docker Compose deployment ready - -### Partially Implemented - -| Feature | Status | Notes | -|---------|--------|-------| -| Odoo ERP integration | Partial | Config and sync-log CRUD functional; push/pull sync operations are stubs | -| Date segment type | Not started | Schema parser placeholder exists | -| Part number validation | Not started | API accepts but doesn't validate format | -| Location hierarchy CRUD | Schema only | Tables exist, no API endpoints | -| Inventory tracking | Schema only | Tables exist, no API endpoints | -| Unit tests | Partial | 9 Go test files across api, db, ods, partnum, schema packages | - -### Infrastructure Status - -| Component | Status | -|-----------|--------| -| PostgreSQL | Running (psql.example.internal) | -| MinIO | Configured in Docker Compose | -| Silo API Server | Builds successfully | -| Docker Compose | Complete (dev and production) | -| systemd service | Unit file and env template ready | -| Deployment scripts | setup-host, deploy, init-db, setup-ipa-nginx | - ---- - -## SOLIDWORKS PDM Gap Analysis - -This section compares Silo's capabilities against SOLIDWORKS PDM features. Gaps are categorized by priority and implementation complexity. - -### Legend -- **Silo Status:** Full / Partial / None -- **Priority:** Critical / High / Medium / Low -- **Complexity:** Simple / Moderate / Complex - ---- - -### 1. Version Control & Revision Management - -| Feature | SOLIDWORKS PDM | Silo Status | Priority | Complexity | -|---------|---------------|-------------|----------|------------| -| Check-in/check-out | Full pessimistic locking | None | High | Moderate | -| Version history | Complete with branching | Full (linear) | - | - | -| Revision labels | A, B, C or custom schemes | Full (custom labels) | - | - | -| Rollback/restore | Full | Full | - | - | -| Compare revisions | Visual + metadata diff | Metadata diff only | Medium | Complex | -| Get Latest Revision | One-click retrieval | Partial (API only) | Medium | Simple | - -**Gap Analysis:** -Silo lacks pessimistic locking (check-out), which is critical for multi-user CAD environments where file merging is impractical. Visual diff comparison would require FreeCAD integration for CAD file visualization. - ---- - -### 2. Workflow Management - -| Feature | SOLIDWORKS PDM | Silo Status | Priority | Complexity | -|---------|---------------|-------------|----------|------------| -| Custom workflows | Full visual designer | None | Critical | Complex | -| State transitions | Configurable with permissions | Basic (status field only) | Critical | Complex | -| Parallel approvals | Multiple approvers required | None | High | Complex | -| Automatic transitions | Timer/condition-based | None | Medium | Moderate | -| Email notifications | On state change | None | High | Moderate | -| ECO process | Built-in change management | None | High | Complex | -| Child state conditions | Block parent if children invalid | None | Medium | Moderate | - -**Gap Analysis:** -Workflow management is the largest functional gap. SOLIDWORKS PDM offers sophisticated state machines with parallel approvals, automatic transitions, and deep integration with engineering change processes. Silo currently has only a simple status field (draft/review/released/obsolete) with no transition rules or approval processes. - ---- - -### 3. User Management & Security - -| Feature | SOLIDWORKS PDM | Silo Status | Priority | Complexity | -|---------|---------------|-------------|----------|------------| -| User authentication | Windows AD, LDAP | Full (local, LDAP, OIDC) | - | - | -| Role-based permissions | Granular per folder/state | Partial (3-tier role model) | Medium | Moderate | -| Group management | Full | None | Medium | Moderate | -| Folder permissions | Read/write/delete per folder | None | Medium | Moderate | -| State permissions | Actions allowed per state | None | High | Moderate | -| Audit trail | Complete action logging | Full | - | - | -| Private files | Pre-check-in visibility control | None | Low | Simple | - -**Gap Analysis:** -Authentication is implemented with three backends (local, LDAP/FreeIPA, OIDC/Keycloak) and a 3-tier role model (admin > editor > viewer). Audit logging captures user actions. Remaining gaps: group management, folder-level permissions, and state-based permission rules. - ---- - -### 4. Search & Discovery - -| Feature | SOLIDWORKS PDM | Silo Status | Priority | Complexity | -|---------|---------------|-------------|----------|------------| -| Metadata search | Full with custom cards | Partial (API query params + fuzzy) | High | Moderate | -| Full-text content search | iFilters for Office, CAD | None | Medium | Complex | -| Quick search | Toolbar with history | Partial (fuzzy search API) | Medium | Simple | -| Saved searches | User-defined favorites | None | Medium | Simple | -| Advanced operators | AND, OR, NOT, wildcards | None | Medium | Simple | -| Multi-variable search | Search across multiple fields | None | Medium | Simple | -| Where-used search | Find all assemblies using part | Full | - | - | - -**Gap Analysis:** -Silo has API-level filtering, fuzzy search, and where-used queries. Remaining gaps: saved searches, advanced search operators, and a richer search UI. Content search (searching within CAD files) is not planned for the server. - ---- - -### 5. BOM Management - -| Feature | SOLIDWORKS PDM | Silo Status | Priority | Complexity | -|---------|---------------|-------------|----------|------------| -| Single-level BOM | Yes | Full | - | - | -| Multi-level BOM | Indented/exploded views | Full (recursive, configurable depth) | - | - | -| BOM comparison | Between revisions | None | Medium | Moderate | -| BOM export | Excel, XML, ERP formats | Full (CSV, ODS) | - | - | -| BOM import | Bulk BOM loading | Full (CSV with upsert) | - | - | -| Calculated BOMs | Quantities rolled up | None | Medium | Moderate | -| Reference designators | Full support | Full | - | - | -| Alternate parts | Substitute tracking | Full | - | - | - -**Gap Analysis:** -Multi-level BOM retrieval (recursive CTE with configurable depth) and BOM export (CSV, ODS) are implemented. BOM import supports CSV with upsert and cycle detection. Remaining gap: BOM comparison between revisions. - ---- - -### 6. CAD Integration - -| Feature | SOLIDWORKS PDM | Silo Status | Priority | Complexity | -|---------|---------------|-------------|----------|------------| -| Native CAD add-in | Deep SOLIDWORKS integration | FreeCAD workbench (silo-mod) | Medium | Complex | -| Property mapping | Bi-directional sync | Planned (silo-mod) | Medium | Moderate | -| Task pane | Embedded in CAD UI | Auth dock panel (silo-mod) | Medium | Complex | -| Lightweight components | Handle without full load | N/A | - | - | -| Drawing/model linking | Automatic association | Manual | Medium | Moderate | -| Multi-CAD support | Third-party formats | FreeCAD only | Low | - | - -**Gap Analysis:** -CAD integration is maintained in separate repositories ([silo-mod](https://git.kindred-systems.com/kindred/silo-mod), [silo-calc](https://git.kindred-systems.com/kindred/silo-calc)). The Silo server provides the REST API endpoints consumed by those clients. - ---- - -### 7. External Integrations - -| Feature | SOLIDWORKS PDM | Silo Status | Priority | Complexity | -|---------|---------------|-------------|----------|------------| -| ERP integration | SAP, Dynamics, etc. | Partial (Odoo stubs) | Medium | Complex | -| API access | Full COM/REST API | Full REST API (78 endpoints) | - | - | -| Dispatch scripts | Automation without coding | None | Medium | Moderate | -| Task scheduler | Background processing | None | Medium | Moderate | -| Email system | SMTP integration | None | High | Simple | -| Web portal | Browser access | Full (React SPA + auth) | - | - | - -**Gap Analysis:** -Silo has a comprehensive REST API (78 endpoints) and a full web UI with authentication. Odoo ERP integration has config/sync-log scaffolding but push/pull operations are stubs. Remaining gaps: email notifications, task scheduler, dispatch automation. - ---- - -### 8. Reporting & Analytics - -| Feature | SOLIDWORKS PDM | Silo Status | Priority | Complexity | -|---------|---------------|-------------|----------|------------| -| Standard reports | Inventory, usage, activity | None | Medium | Moderate | -| Custom reports | User-defined queries | None | Medium | Moderate | -| Dashboard | Visual KPIs | None | Low | Moderate | -| Export formats | PDF, Excel, CSV | CSV and ODS | Medium | Simple | - -**Gap Analysis:** -Reporting capabilities are absent. Basic reports (item counts, revision activity, where-used) would provide immediate value. - ---- - -### 9. File Handling - -| Feature | SOLIDWORKS PDM | Silo Status | Priority | Complexity | -|---------|---------------|-------------|----------|------------| -| File versioning | Automatic | Full (MinIO) | - | - | -| File preview | Thumbnails, 3D preview | None | Medium | Complex | -| File conversion | PDF, DXF generation | None | Medium | Complex | -| Replication | Multi-site sync | None | Low | Complex | -| File copy with refs | Copy tree with references | None | Medium | Moderate | - -**Gap Analysis:** -File storage works well. Thumbnail generation and file preview would significantly improve the web UI experience. Automatic conversion to PDF/DXF is valuable for sharing with non-CAD users. - ---- - -### Gap Summary by Priority - -#### Completed (Previously Critical/High) -1. ~~**User authentication**~~ - Implemented: local, LDAP, OIDC -2. ~~**Role-based permissions**~~ - Implemented: 3-tier role model (admin/editor/viewer) -3. ~~**Audit trail**~~ - Implemented: audit_log table with completeness scoring -4. ~~**Where-used search**~~ - Implemented: reverse parent lookup API -5. ~~**Multi-level BOM API**~~ - Implemented: recursive expansion with configurable depth -6. ~~**BOM export**~~ - Implemented: CSV and ODS formats - -#### Critical Gaps (Required for Team Use) -1. **Workflow engine** - State machines with transitions and approvals -2. **Check-out locking** - Pessimistic locking for CAD files - -#### High Priority Gaps (Significant Value) -1. **Email notifications** - Alert users on state changes -2. **Web UI search** - Advanced search interface with saved searches -3. **Folder/state permissions** - Granular access control beyond role model - -#### Medium Priority Gaps (Nice to Have) -1. **Saved searches** - Frequently used queries -2. **File preview/thumbnails** - Visual browsing -3. **Reporting** - Activity and inventory reports -4. **Scheduled tasks** - Background automation -5. **BOM comparison** - Revision diff for assemblies - ---- - -## Feature Roadmap - -### Phase 1: Foundation (Current - Q2 2026) -*Complete MVP and stabilize core functionality* - -| Feature | Description | Status | -|---------|-------------|--------| -| MinIO integration | File upload/download with versioning and checksums | Complete | -| Revision control | Rollback, comparison, status/labels | Complete | -| CSV import/export | Dry-run validation, template generation | Complete | -| ODS import/export | Items, BOMs, project sheets, templates | Complete | -| Project management | CRUD, many-to-many item tagging | Complete | -| Multi-level BOM | Recursive expansion, where-used, export | Complete | -| Authentication | Local, LDAP, OIDC with role-based access | Complete | -| Audit logging | Action logging, completeness scoring | Complete | -| Unit tests | Core API and database operations | Not Started | -| Date segment type | Support date-based part number segments | Not Started | -| Part number validation | Validate format on creation | Not Started | -| Location CRUD API | Expose location hierarchy via REST | Not Started | -| Inventory API | Expose inventory operations via REST | Not Started | - -### Phase 2: Multi-User (Q2-Q3 2026) -*Enable team collaboration* - -| Feature | Description | Status | -|---------|-------------|--------| -| LDAP authentication | Integrate with FreeIPA/Active Directory | **Complete** | -| OIDC authentication | Keycloak / OpenID Connect | **Complete** | -| Audit logging | Record all user actions with timestamps | **Complete** | -| Session management | Token-based and session-based API authentication | **Complete** | -| User/group management | Create, assign, manage users and groups | Not Started | -| Folder permissions | Read/write/delete per folder hierarchy | Not Started | -| Check-out locking | Pessimistic locks with timeout | Not Started | - -### Phase 3: Workflow Engine (Q3-Q4 2026) -*Implement engineering change processes* - -| Feature | Description | Complexity | -|---------|-------------|------------| -| Workflow designer | YAML-defined state machines | Complex | -| State transitions | Configurable transition rules | Complex | -| Transition permissions | Who can execute which transitions | Moderate | -| Single approvals | Basic approval workflow | Moderate | -| Parallel approvals | Multi-approver gates | Complex | -| Automatic transitions | Timer and condition-based | Complex | -| Email notifications | SMTP integration for alerts | Simple | -| Child state conditions | Block parent transitions | Moderate | - -### Phase 4: Search & Discovery (Q4 2026 - Q1 2027) -*Improve findability and navigation* - -| Feature | Description | Status | -|---------|-------------|--------| -| Where-used queries | Find parent assemblies | **Complete** | -| Fuzzy search | Quick search across items | **Complete** | -| Advanced search UI | Web interface with filters | Not Started | -| Search operators | AND, OR, NOT, wildcards | Not Started | -| Saved searches | User favorites | Not Started | -| Content search | Search within file content | Not Started | - -### Phase 5: BOM & Reporting (Q1-Q2 2027) -*Enhanced BOM management and analytics* - -| Feature | Description | Status | -|---------|-------------|--------| -| Multi-level BOM API | Recursive assembly retrieval | **Complete** | -| BOM export | CSV and ODS formats | **Complete** | -| BOM import | CSV with upsert and cycle detection | **Complete** | -| BOM comparison | Diff between revisions | Not Started | -| Standard reports | Activity, inventory, usage | Not Started | -| Custom queries | User-defined report builder | Not Started | -| Dashboard | Visual KPIs and metrics | Not Started | - -### Phase 6: Advanced Features (Q2-Q4 2027) -*Enterprise capabilities* - -| Feature | Description | Complexity | -|---------|-------------|------------| -| File preview | Thumbnail generation | Complex | -| File conversion | Auto-generate PDF/DXF | Complex | -| ERP integration | Adapter framework | Complex | -| Task scheduler | Background job processing | Moderate | -| Webhooks | Event notifications to external systems | Moderate | -| API rate limiting | Protect against abuse | Simple | - ---- - -## Implementation Phases - -### Phase 1 Detailed Tasks - -#### 1.1 MinIO Integration -- COMPLETE -- [x] MinIO service configured in Docker Compose -- [x] File upload via REST API -- [x] File download via REST API (latest and by revision) -- [x] SHA256 checksums on upload - -#### 1.2 Authentication & Authorization -- COMPLETE -- [x] Local authentication (bcrypt) -- [x] LDAP/FreeIPA authentication -- [x] OIDC/Keycloak authentication -- [x] Role-based access control (admin/editor/viewer) -- [x] API token management (SHA-256 hashed) -- [x] Session management (PostgreSQL-backed) -- [x] CSRF protection (nosurf) -- [x] Audit logging (database table) - -#### 1.3 Multi-level BOM & Export -- COMPLETE -- [x] Recursive BOM expansion with configurable depth -- [x] Where-used reverse lookup -- [x] BOM CSV export/import with cycle detection -- [x] BOM ODS export -- [x] ODS item export/import/template - -#### 1.4 Unit Test Suite -- [ ] Database connection and transaction tests -- [ ] Item CRUD operation tests -- [ ] Revision creation and retrieval tests -- [ ] Part number generation tests -- [ ] File upload/download tests -- [ ] CSV import/export tests -- [ ] API endpoint tests - -#### 1.5 Missing Segment Types -- [ ] Implement date segment type -- [ ] Add strftime-style format support - -#### 1.6 Location & Inventory APIs -- [ ] `GET /api/locations` - List locations -- [ ] `POST /api/locations` - Create location -- [ ] `GET /api/locations/{path}` - Get location -- [ ] `DELETE /api/locations/{path}` - Delete location -- [ ] `GET /api/inventory/{partNumber}` - Get inventory -- [ ] `POST /api/inventory/{partNumber}/adjust` - Adjust quantity -- [ ] `POST /api/inventory/{partNumber}/move` - Move between locations - ---- - -## Success Metrics - -### Phase 1 (Foundation) -- All existing tests pass -- File upload/download works end-to-end -- FreeCAD users can checkout, modify, commit parts - -### Phase 2 (Multi-User) -- 5+ concurrent users supported -- No data corruption under concurrent access -- Audit log captures all modifications - -### Phase 3 (Workflow) -- Engineering change process completable in Silo -- Email notifications delivered reliably -- Workflow state visible in web UI - -### Phase 4+ (Advanced) -- Search returns results in <2 seconds -- Where-used queries complete in <5 seconds -- BOM export matches assembly structure - ---- - -## References - -### SOLIDWORKS PDM Documentation -- [SOLIDWORKS PDM Product Page](https://www.solidworks.com/product/solidworks-pdm) -- [What's New in SOLIDWORKS PDM 2025](https://blogs.solidworks.com/solidworksblog/2024/10/whats-new-in-solidworks-pdm-2025.html) -- [Top 5 Enhancements in SOLIDWORKS PDM 2024](https://blogs.solidworks.com/solidworksblog/2023/10/top-5-enhancements-in-solidworks-pdm-2024.html) -- [SOLIDWORKS PDM Workflow Transitions](https://help.solidworks.com/2023/english/EnterprisePDM/Admin/c_workflow_transition.htm) -- [Ultimate Guide to SOLIDWORKS PDM Permissions](https://www.goengineer.com/blog/ultimate-guide-to-solidworks-pdm-permissions) -- [Searching in SOLIDWORKS PDM](https://help.solidworks.com/2021/english/EnterprisePDM/fileexplorer/c_searches.htm) -- [SOLIDWORKS PDM API Getting Started](https://3dswym.3dexperience.3ds.com/wiki/solidworks-news-info/getting-started-with-the-solidworks-pdm-api-solidpractices_gBCYaM75RgORBcpSO1m_Mw) - -### Silo Documentation -- [Specification](docs/SPECIFICATION.md) -- [Development Status](docs/STATUS.md) -- [Deployment Guide](docs/DEPLOYMENT.md) -- [Gap Analysis](docs/GAP_ANALYSIS.md) - ---- - -## Appendix: Feature Comparison Matrix - -| Category | Feature | SW PDM Standard | SW PDM Pro | Silo Current | Silo Planned | -|----------|---------|-----------------|------------|--------------|--------------| -| **Version Control** | Check-in/out | Yes | Yes | No | Phase 2 | -| | Version history | Yes | Yes | Yes | - | -| | Rollback | Yes | Yes | Yes | - | -| | Revision labels/status | Yes | Yes | Yes | - | -| | Revision comparison | Yes | Yes | Yes (metadata) | - | -| **Workflow** | Custom workflows | Limited | Yes | No | Phase 3 | -| | Parallel approval | No | Yes | No | Phase 3 | -| | Notifications | No | Yes | No | Phase 3 | -| **Security** | User auth | Windows | Windows/LDAP | Yes (local, LDAP, OIDC) | - | -| | Permissions | Basic | Granular | Partial (role-based) | Phase 2 | -| | Audit trail | Basic | Full | Yes | - | -| **Search** | Metadata search | Yes | Yes | Partial (API + fuzzy) | Phase 4 | -| | Content search | No | Yes | No | Phase 4 | -| | Where-used | Yes | Yes | Yes | - | -| **BOM** | Single-level | Yes | Yes | Yes | - | -| | Multi-level | Yes | Yes | Yes (recursive) | - | -| | BOM export | Yes | Yes | Yes (CSV, ODS) | - | -| **Data** | CSV import/export | Yes | Yes | Yes | - | -| | ODS import/export | No | No | Yes | - | -| | Project management | Yes | Yes | Yes | - | -| **Integration** | API | Limited | Full | Full REST (75) | - | -| | ERP connectors | No | Yes | Partial (Odoo stubs) | Phase 6 | -| | Web access | No | Yes | Yes (React SPA + auth) | - | -| **Files** | Versioning | Yes | Yes | Yes | - | -| | Preview | Yes | Yes | No | Phase 6 | -| | Multi-site | No | Yes | No | Not Planned | diff --git a/docs/GAP_ANALYSIS.md b/docs/GAP_ANALYSIS.md index bf0c0c7..4da230a 100644 --- a/docs/GAP_ANALYSIS.md +++ b/docs/GAP_ANALYSIS.md @@ -1,13 +1,15 @@ -# Silo Gap Analysis and Revision Control Roadmap +# Silo Gap Analysis -**Date:** 2026-02-08 +**Date:** 2026-02-13 **Status:** Analysis Complete (Updated) --- ## Executive Summary -This document analyzes the current state of the Silo project against its specification, identifies documentation and feature gaps, and outlines a roadmap for enhanced revision control capabilities. +This document analyzes the current state of the Silo project against its specification and against SOLIDWORKS PDM (the industry-leading product data management solution). It identifies documentation gaps, feature gaps, and outlines a roadmap for enhanced revision control capabilities. + +See [ROADMAP.md](ROADMAP.md) for the platform roadmap and dependency tier structure. --- @@ -25,7 +27,7 @@ This document analyzes the current state of the Silo project against its specifi | `docs/AUTH.md` | Authentication system design | Current | | `docs/AUTH_USER_GUIDE.md` | User guide for login, tokens, and roles | Current | | `docs/GAP_ANALYSIS.md` | Revision control roadmap | Current | -| `ROADMAP.md` | Feature roadmap and SOLIDWORKS PDM comparison | Current | +| `docs/ROADMAP.md` | Platform roadmap and dependency tiers | Current | | `frontend-spec.md` | React SPA frontend specification | Current | ### 1.2 Documentation Gaps (Priority Order) @@ -450,3 +452,163 @@ GET /api/releases/{name} # Get release details POST /api/releases/{name}/items # Add items to release GET /api/items/{pn}/thumbnail/{rev} # Get thumbnail ``` + +--- + +## Appendix C: SOLIDWORKS PDM Comparison + +This section compares Silo's capabilities against SOLIDWORKS PDM features. Gaps are categorized by priority and implementation complexity. + +**Legend:** Silo Status = Full / Partial / None | Priority = Critical / High / Medium / Low | Complexity = Simple / Moderate / Complex + +### C.1 Version Control & Revision Management + +| Feature | SOLIDWORKS PDM | Silo Status | Priority | Complexity | +|---------|---------------|-------------|----------|------------| +| Check-in/check-out | Full pessimistic locking | None | High | Moderate | +| Version history | Complete with branching | Full (linear) | - | - | +| Revision labels | A, B, C or custom schemes | Full (custom labels) | - | - | +| Rollback/restore | Full | Full | - | - | +| Compare revisions | Visual + metadata diff | Metadata diff only | Medium | Complex | +| Get Latest Revision | One-click retrieval | Partial (API only) | Medium | Simple | + +Silo lacks pessimistic locking (check-out), which is critical for multi-user CAD environments where file merging is impractical. Visual diff comparison would require FreeCAD integration for CAD file visualization. + +### C.2 Workflow Management + +| Feature | SOLIDWORKS PDM | Silo Status | Priority | Complexity | +|---------|---------------|-------------|----------|------------| +| Custom workflows | Full visual designer | None | Critical | Complex | +| State transitions | Configurable with permissions | Basic (status field only) | Critical | Complex | +| Parallel approvals | Multiple approvers required | None | High | Complex | +| Automatic transitions | Timer/condition-based | None | Medium | Moderate | +| Email notifications | On state change | None | High | Moderate | +| ECO process | Built-in change management | None | High | Complex | +| Child state conditions | Block parent if children invalid | None | Medium | Moderate | + +Workflow management is the largest functional gap. SOLIDWORKS PDM offers sophisticated state machines with parallel approvals, automatic transitions, and deep integration with engineering change processes. Silo currently has only a simple status field (draft/review/released/obsolete) with no transition rules or approval processes. + +### C.3 User Management & Security + +| Feature | SOLIDWORKS PDM | Silo Status | Priority | Complexity | +|---------|---------------|-------------|----------|------------| +| User authentication | Windows AD, LDAP | Full (local, LDAP, OIDC) | - | - | +| Role-based permissions | Granular per folder/state | Partial (3-tier role model) | Medium | Moderate | +| Group management | Full | None | Medium | Moderate | +| Folder permissions | Read/write/delete per folder | None | Medium | Moderate | +| State permissions | Actions allowed per state | None | High | Moderate | +| Audit trail | Complete action logging | Full | - | - | +| Private files | Pre-check-in visibility control | None | Low | Simple | + +Authentication is implemented with three backends (local, LDAP/FreeIPA, OIDC/Keycloak) and a 3-tier role model (admin > editor > viewer). Audit logging captures user actions. Remaining gaps: group management, folder-level permissions, and state-based permission rules. + +### C.4 Search & Discovery + +| Feature | SOLIDWORKS PDM | Silo Status | Priority | Complexity | +|---------|---------------|-------------|----------|------------| +| Metadata search | Full with custom cards | Partial (API query params + fuzzy) | High | Moderate | +| Full-text content search | iFilters for Office, CAD | None | Medium | Complex | +| Quick search | Toolbar with history | Partial (fuzzy search API) | Medium | Simple | +| Saved searches | User-defined favorites | None | Medium | Simple | +| Advanced operators | AND, OR, NOT, wildcards | None | Medium | Simple | +| Multi-variable search | Search across multiple fields | None | Medium | Simple | +| Where-used search | Find all assemblies using part | Full | - | - | + +Silo has API-level filtering, fuzzy search, and where-used queries. Remaining gaps: saved searches, advanced search operators, and a richer search UI. Content search (searching within CAD files) is not planned for the server. + +### C.5 BOM Management + +| Feature | SOLIDWORKS PDM | Silo Status | Priority | Complexity | +|---------|---------------|-------------|----------|------------| +| Single-level BOM | Yes | Full | - | - | +| Multi-level BOM | Indented/exploded views | Full (recursive, configurable depth) | - | - | +| BOM comparison | Between revisions | None | Medium | Moderate | +| BOM export | Excel, XML, ERP formats | Full (CSV, ODS) | - | - | +| BOM import | Bulk BOM loading | Full (CSV with upsert) | - | - | +| Calculated BOMs | Quantities rolled up | None | Medium | Moderate | +| Reference designators | Full support | Full | - | - | +| Alternate parts | Substitute tracking | Full | - | - | + +Multi-level BOM retrieval (recursive CTE with configurable depth) and BOM export (CSV, ODS) are implemented. BOM import supports CSV with upsert and cycle detection. Remaining gap: BOM comparison between revisions. + +### C.6 CAD Integration + +| Feature | SOLIDWORKS PDM | Silo Status | Priority | Complexity | +|---------|---------------|-------------|----------|------------| +| Native CAD add-in | Deep SOLIDWORKS integration | FreeCAD workbench (silo-mod) | Medium | Complex | +| Property mapping | Bi-directional sync | Planned (silo-mod) | Medium | Moderate | +| Task pane | Embedded in CAD UI | Auth dock panel (silo-mod) | Medium | Complex | +| Lightweight components | Handle without full load | N/A | - | - | +| Drawing/model linking | Automatic association | Manual | Medium | Moderate | +| Multi-CAD support | Third-party formats | FreeCAD only | Low | - | + +CAD integration is maintained in separate repositories ([silo-mod](https://git.kindred-systems.com/kindred/silo-mod), [silo-calc](https://git.kindred-systems.com/kindred/silo-calc)). The Silo server provides the REST API endpoints consumed by those clients. + +### C.7 External Integrations + +| Feature | SOLIDWORKS PDM | Silo Status | Priority | Complexity | +|---------|---------------|-------------|----------|------------| +| ERP integration | SAP, Dynamics, etc. | Partial (Odoo stubs) | Medium | Complex | +| API access | Full COM/REST API | Full REST API (78 endpoints) | - | - | +| Dispatch scripts | Automation without coding | None | Medium | Moderate | +| Task scheduler | Background processing | None | Medium | Moderate | +| Email system | SMTP integration | None | High | Simple | +| Web portal | Browser access | Full (React SPA + auth) | - | - | + +Silo has a comprehensive REST API (78 endpoints) and a full web UI with authentication. Odoo ERP integration has config/sync-log scaffolding but push/pull operations are stubs. Remaining gaps: email notifications, task scheduler, dispatch automation. + +### C.8 Reporting & Analytics + +| Feature | SOLIDWORKS PDM | Silo Status | Priority | Complexity | +|---------|---------------|-------------|----------|------------| +| Standard reports | Inventory, usage, activity | None | Medium | Moderate | +| Custom reports | User-defined queries | None | Medium | Moderate | +| Dashboard | Visual KPIs | None | Low | Moderate | +| Export formats | PDF, Excel, CSV | CSV and ODS | Medium | Simple | + +Reporting capabilities are absent. Basic reports (item counts, revision activity, where-used) would provide immediate value. + +### C.9 File Handling + +| Feature | SOLIDWORKS PDM | Silo Status | Priority | Complexity | +|---------|---------------|-------------|----------|------------| +| File versioning | Automatic | Full (MinIO) | - | - | +| File preview | Thumbnails, 3D preview | None | Medium | Complex | +| File conversion | PDF, DXF generation | None | Medium | Complex | +| Replication | Multi-site sync | None | Low | Complex | +| File copy with refs | Copy tree with references | None | Medium | Moderate | + +File storage works well. Thumbnail generation and file preview would significantly improve the web UI experience. Automatic conversion to PDF/DXF is valuable for sharing with non-CAD users. + +--- + +## Appendix D: Feature Comparison Matrix + +| Category | Feature | SW PDM Standard | SW PDM Pro | Silo Current | Silo Planned | +|----------|---------|-----------------|------------|--------------|--------------| +| **Version Control** | Check-in/out | Yes | Yes | No | Tier 1 | +| | Version history | Yes | Yes | Yes | - | +| | Rollback | Yes | Yes | Yes | - | +| | Revision labels/status | Yes | Yes | Yes | - | +| | Revision comparison | Yes | Yes | Yes (metadata) | - | +| **Workflow** | Custom workflows | Limited | Yes | No | Tier 4 | +| | Parallel approval | No | Yes | No | Tier 4 | +| | Notifications | No | Yes | No | Tier 1 | +| **Security** | User auth | Windows | Windows/LDAP | Yes (local, LDAP, OIDC) | - | +| | Permissions | Basic | Granular | Partial (role-based) | Tier 4 | +| | Audit trail | Basic | Full | Yes | - | +| **Search** | Metadata search | Yes | Yes | Partial (API + fuzzy) | Tier 0 | +| | Content search | No | Yes | No | Tier 2 | +| | Where-used | Yes | Yes | Yes | - | +| **BOM** | Single-level | Yes | Yes | Yes | - | +| | Multi-level | Yes | Yes | Yes (recursive) | - | +| | BOM export | Yes | Yes | Yes (CSV, ODS) | - | +| **Data** | CSV import/export | Yes | Yes | Yes | - | +| | ODS import/export | No | No | Yes | - | +| | Project management | Yes | Yes | Yes | - | +| **Integration** | API | Limited | Full | Full REST (78) | - | +| | ERP connectors | No | Yes | Partial (Odoo stubs) | Tier 6 | +| | Web access | No | Yes | Yes (React SPA + auth) | - | +| **Files** | Versioning | Yes | Yes | Yes | - | +| | Preview | Yes | Yes | No | Tier 2 | +| | Multi-site | No | Yes | No | Not Planned | diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md new file mode 100644 index 0000000..f68a5a7 --- /dev/null +++ b/docs/ROADMAP.md @@ -0,0 +1,442 @@ +# Silo Platform Roadmap + +**Version:** 2.0 +**Date:** February 2026 + +Silo is the server component of the Kindred ecosystem. Its core function is storing and version-controlling engineering data (parts, assemblies, BOMs). This roadmap describes the expansion of Silo from a PDM server into a modular platform -- comparable to how Gitea/GitHub extend Git hosting with Actions, Wikis, Packages, and webhooks. + +For a detailed comparison against SOLIDWORKS PDM, see [GAP_ANALYSIS.md](GAP_ANALYSIS.md). + +--- + +## Guiding Principles + +- **Modular architecture.** Every capability beyond core PDM is a module. Modules register against a central API endpoint registry and declare their menu entries, views, dependencies, and routes via a module manifest. +- **Odoo-aligned UX.** The web UI follows Odoo's navigation patterns: a top-level app launcher grid, breadcrumb navigation (`Module > List > Record > Sub-view`), and standard view types (list, form, kanban, calendar, pivot). This alignment provides a familiar experience for shops already using Odoo as their ERP, and a clean integration path for those who adopt it later. +- **Open by default.** Silo and all modules are open-source. Enterprise customers can fork, extend, and self-host. Developer tools for building and distributing custom Create forks are available to everyone, not just Kindred. +- **Odoo as reference ERP.** For shops on Odoo, a bridge module syncs Silo data to Odoo models (`mrp.bom`, `mrp.production`, `quality.check`, etc.). For shops on other ERPs, the open API serves as a documented integration surface. Silo's web UI is fully self-sufficient with no ERP dependency required. + +--- + +## Foundational Contracts + +### The .kc File Format + +Silo introduces the `.kc` file format as an enhanced superset of FreeCAD's `.fcstd`. Both are ZIP bundles. A `.kc` file contains everything an `.fcstd` does, plus a `silo/` directory with platform metadata. + +#### Standard FCStd contents (preserved as-is) + +- `Document.xml`, `GuiDocument.xml` +- BREP geometry files (`.brp`) +- `thumbnails/` + +#### Added .kc entries + +| Path | Purpose | +|------|---------| +| `silo/manifest.json` | Silo instance origin, part UUID, revision hash, .kc schema version | +| `silo/metadata.json` | Custom schema field values, tags, lifecycle state | +| `silo/history.json` | Local revision log (lightweight; full history is server-side) | +| `silo/approvals.json` | ECO/approval state snapshot | +| `silo/dependencies.json` | Assembly link references by Silo UUID (not filepath) | +| `silo/macros/` | Embedded macro references or inline scripts bound to this part | +| `silo/inspection/` | GD&T annotations, tolerance data, CMM linkage metadata | +| `silo/thumbnails/` | Silo-generated renderings (separate from FreeCAD's built-in thumbnail) | + +#### Interoperability + +- **FCStd -> Silo:** On import, the `silo/` directory is generated with defaults. A UUID is assigned and the user is prompted for schema fields. +- **Silo -> FCStd:** On export, the `silo/` directory is stripped. The remaining contents are a valid `.fcstd`. +- **Round-trip safety:** FreeCAD ignores the `silo/` directory on save, so there is no risk of FreeCAD corrupting Silo metadata. +- **Schema versioning:** `silo/manifest.json` carries a format version for forward-compatible migrations. + +### Module Manifest + +Each module ships a manifest declaring its integration surface: + +``` +id, name, version, description +dependencies (other module IDs) +menu_entries (app launcher icon, label, route) +view_declarations (list, form, kanban, etc.) +api_routes (REST endpoints the module registers) +hooks (events the module listens to or emits) +permissions (required roles/scopes) +``` + +The exact format (JSON, TOML, or Python-based a la Odoo's `__manifest__.py`) is TBD. The contract is: a module is anything that provides a valid manifest and registers against the endpoint registry. + +### Web UI Shell + +The Silo web application provides the chrome that all modules render within. + +- **App launcher:** Top-level grid of installed module icons. Driven by the API endpoint registry -- only enabled modules appear. Disabled modules show greyed with an "Enable" action for discoverability. +- **Breadcrumbs:** Every view follows `Module > List > Record > Sub-view`. Consistent across all modules. +- **View types:** List, form, kanban, calendar, pivot/reporting. Modules declare supported views in their manifest. +- **Schema-driven forms:** The user-customizable schema engine maps directly to form views, enabling end-users to define part metadata fields through the web UI without code changes. + +--- + +## Dependency Tiers + +Modules are organized into tiers based on what they depend on. Lower tiers must be stable before higher tiers are built. + +### Tier 0 -- Foundation + +Everything depends on these. They define what Silo *is*. + +| Component | Description | Status | +|-----------|-------------|--------| +| **Core Silo** | Part/assembly storage, version control, auth, base REST API | Complete | +| **.kc Format Spec** | File format contract between Create and Silo | Not Started | +| **API Endpoint Registry** | Module discovery, dynamic UI rendering, health checks | Not Started | +| **Web UI Shell** | App launcher, breadcrumbs, view framework, module rendering | Partial | +| **Python Scripting Engine** | Server-side hook execution, module extension point | Not Started | +| **Job Queue Infrastructure** | Redis/NATS shared async service for all compute modules | Not Started | + +### Tier 1 -- Core Services + +Broad downstream dependencies. These should be built early because retrofitting is painful. + +| Module | Description | Depends On | Status | +|--------|-------------|------------|--------| +| **Headless Create** | API-driven FreeCAD instance for file manipulation, geometry queries, format conversion, rendering | Core Silo, Job Queue | Not Started | +| **Notifications & Subscriptions** | Per-part watch lists, lifecycle event hooks, webhook delivery | Core Silo, Registry | Not Started | +| **Audit Trail / Compliance** | ITAR, ISO 9001, AS9100 traceability; module-level event journaling | Core Silo | Partial | + +### Tier 2 -- File Intelligence & Collaboration + +High-visibility features. Mostly low-hanging fruit once Tier 1 is solid. + +| Module | Description | Depends On | Status | +|--------|-------------|------------|--------| +| **Intelligent FCStd Diffing** | XML-based structural diff of .kc bundles | Headless Create | Not Started | +| **Thumbnail Generation** | Auto-rendered part/assembly previews | Headless Create | Not Started | +| **Macro Store** | Shared macro library across Create instances | Core Silo, Registry | Not Started | +| **Theme & Addon Manager** | Centralized distribution of UI themes and workbench addons | Core Silo, Registry | Not Started | +| **User-Customizable Schemas** | End-user defined part/form metadata via web UI | Core Silo, Scripting Engine | Not Started | + +### Tier 3 -- Compute + +Heavy async workloads. All route through the shared job queue. + +| Module | Description | Depends On | Status | +|--------|-------------|------------|--------| +| **Batch Jobs (CPU/GPU)** | FEA, CFD, rendering, bulk export | Job Queue, Headless Create | Not Started | +| **AI Broker** | LLM tasks (Ollama), GNN constraint optimization, appearance AI | Job Queue | Not Started | +| **Reporting & Analytics** | Part reuse, revision frequency, compute usage dashboards, cost roll-ups | Audit Trail, Core Silo | Not Started | + +### Tier 4 -- Engineering Workflow + +Process modules that formalize how engineering work moves through an organization. + +| Module | Description | Depends On | Status | +|--------|-------------|------------|--------| +| **Approval / ECO Workflow** | Engineering change orders, multi-stage review gates, digital signatures | Notifications, Audit Trail, Schemas | Not Started | +| **Shop Floor Drawing Distribution** | Controlled push-to-production drawings; web-based appliance displays on the floor | Headless Create, Approval Workflow | Not Started | +| **Import/Export Bridge** | STEP, IGES, 3MF connectors; SOLIDWORKS migration tooling; ERP adapters | Headless Create | Not Started | +| **Multi-tenant / Org Management** | Org boundaries, role-based permissioning, storage quotas | Core Auth, Audit Trail | Not Started | + +### Tier 5 -- Manufacturing & Quality + +Deep domain modules. Heavy spec work required independent of software dependencies. + +| Module | Description | Depends On | Status | +|--------|-------------|------------|--------| +| **MES Module** | Manufacturing execution -- internal module or bridge to external MES | Approval Workflow, Schemas, Shop Floor Drawings | Not Started | +| **Quality / Tolerance Stackup** | Inspection data ingestion, CMM device linking, statistical tolerance analysis, material mapping | Schemas, Import Bridge | Not Started | +| **Inspection Plan Generator** | Auto-generate CMM programs or inspection checklists from GD&T drawings | Headless Create, Quality Module | Not Started | +| **BIM Inventory / Receiving** | Live facility model with real-time inventory location, explorable in a custom BIM-MES workbench in Create | Custom BIM-MES Workbench, Schemas, Notifications | Not Started | + +### Tier 6 -- Platform & Ecosystem + +Modules that serve the broader community and long-horizon use cases. + +| Module | Description | Depends On | Status | +|--------|-------------|------------|--------| +| **Developer Tools** | Managed Gitea instance for in-house Create fork development; CI/CD to build and distribute fork updates to configured clients | Tier 0-1 stability | Not Started | +| **Digital Twin Sync** | Live sensor data mapped onto BIM/assembly models; operational monitoring | BIM Inventory, Reporting | Not Started | +| **ERP Adapters (Odoo, SAP, etc.)** | Bidirectional sync of parts, BOMs, ECOs, production orders to external ERP | Import/Export Bridge, MES, Schemas | Partial (Odoo stubs) | + +--- + +## Near-Term Priorities + +These are the concrete tasks that map to Tier 0 completion and the first steps into Tier 1. They replace the older Phase 1-6 calendar-based timelines. + +### Tier 0 Completion + +Complete MVP and stabilize core functionality. + +| Task | Description | Status | +|------|-------------|--------| +| Unit test suite | Core API, database, partnum, file, CSV/ODS handler tests | Partial (~40%) | +| Date segment type | Implement `date` segment with strftime-style formatting | Not Started | +| Part number validation | Validate format against schema on creation | Not Started | +| Location CRUD API | Expose location hierarchy via REST | Not Started | +| Inventory API | Expose inventory operations via REST | Not Started | + +**Success metrics:** +- All existing tests pass +- File upload/download works end-to-end +- FreeCAD users can checkout, modify, commit parts + +### Multi-User Enablement + +Enable team collaboration (feeds into Tier 1 and Tier 4). + +| Task | Description | Status | +|------|-------------|--------| +| Check-out locking | Pessimistic locks with timeout | Not Started | +| User/group management | Create, assign, manage users and groups | Not Started | +| Folder permissions | Read/write/delete per folder hierarchy | Not Started | + +**Success metrics:** +- 5+ concurrent users supported +- No data corruption under concurrent access +- Audit log captures all modifications + +### Workflow Engine + +Implement engineering change processes (Tier 4: Approval/ECO Workflow). + +| Task | Description | Status | +|------|-------------|--------| +| Workflow designer | YAML-defined state machines | Not Started | +| State transitions | Configurable transition rules with permissions | Not Started | +| Approval workflows | Single and parallel approver gates | Not Started | +| Email notifications | SMTP integration for alerts on state changes | Not Started | + +**Success metrics:** +- Engineering change process completable in Silo +- Email notifications delivered reliably +- Workflow state visible in web UI + +### Search & Discovery + +Improve findability and navigation (Tier 0 Web UI Shell). + +| Task | Description | Status | +|------|-------------|--------| +| Advanced search UI | Web interface with filters and operators | Not Started | +| Saved searches | User-defined query favorites | Not Started | + +**Success metrics:** +- Search returns results in <2 seconds +- Where-used queries complete in <5 seconds + +--- + +## Gap Summary + +For full SOLIDWORKS PDM comparison tables, see [GAP_ANALYSIS.md Appendix C](GAP_ANALYSIS.md#appendix-c-solidworks-pdm-comparison). + +### Completed (Previously Critical/High) + +1. ~~User authentication~~ -- local, LDAP, OIDC +2. ~~Role-based permissions~~ -- 3-tier role model (admin/editor/viewer) +3. ~~Audit trail~~ -- audit_log table with completeness scoring +4. ~~Where-used search~~ -- reverse parent lookup API +5. ~~Multi-level BOM API~~ -- recursive expansion with configurable depth +6. ~~BOM export~~ -- CSV and ODS formats + +### Critical Gaps (Required for Team Use) + +1. **Workflow engine** -- state machines with transitions and approvals +2. **Check-out locking** -- pessimistic locking for CAD files + +### High Priority Gaps (Significant Value) + +1. **Email notifications** -- alert users on state changes +2. **Web UI search** -- advanced search interface with saved searches +3. **Folder/state permissions** -- granular access control beyond role model + +### Medium Priority Gaps (Nice to Have) + +1. **Saved searches** -- frequently used queries +2. **File preview/thumbnails** -- visual browsing +3. **Reporting** -- activity and inventory reports +4. **Scheduled tasks** -- background automation +5. **BOM comparison** -- revision diff for assemblies + +--- + +## Priority Notes + +- **Headless Create** is the single highest-leverage Tier 1 item. It unblocks diffing, thumbnails, batch export, drawing distribution, and inspection plan generation. +- **Audit Trail** is unglamorous but critical to build early. Retrofitting compliance logging after modules ship is expensive and error-prone. +- **Tier 2** delivers visible, demo-able value quickly -- diffing, thumbnails, and the macro store are features users immediately understand. +- **Tiers 5-6** carry heavy domain complexity. They need detailed specification and industry consultation well before implementation begins. +- The **.kc format** and **module manifest** are the two foundational contracts. Getting these right determines how cleanly everything above them composes. + +--- + +## Open Questions + +1. **Module manifest format** -- JSON, TOML, or Python-based? Tradeoffs between simplicity and expressiveness. +2. **.kc thumbnail policy** -- Single canonical thumbnail vs. multi-view renders. Impacts file size and generation cost. +3. **Job queue technology** -- Redis Streams vs. NATS. Redis is already in the stack; NATS offers better pub/sub semantics for event-driven modules. +4. **Headless Create deployment** -- Sidecar container per Silo instance, or pool of workers behind the job queue? +5. **BIM-MES workbench scope** -- How much of FreeCAD BIM is reusable vs. needs to be purpose-built for inventory/facility modeling? +6. **Offline .kc workflow** -- How much of the `silo/` metadata is authoritative when disconnected? Reconciliation strategy on reconnect. + +--- + +## Appendix A: Current Project Inventory + +### Implemented Features (MVP Complete) + +#### Core Database System +- PostgreSQL schema with 13 migrations +- UUID-based identifiers throughout +- Soft delete support via `archived_at` timestamps +- Atomic sequence generation for part numbers + +#### Part Number Generation +- YAML schema parser with validation +- Segment types: `string`, `enum`, `serial`, `constant` +- Scope templates for serial counters (e.g., `{category}`, `{project}`) +- Format templates for custom output + +#### Item Management +- Full CRUD operations for items +- Item types: part, assembly, drawing, document, tooling, purchased, electrical, software +- Custom properties via JSONB storage +- Project tagging with many-to-many relationships + +#### Revision Control +- Append-only revision history +- Revision metadata: properties, file reference, checksum, comment +- Status tracking: draft, review, released, obsolete +- Labels/tags per revision +- Revision comparison (diff) +- Rollback functionality + +#### File Management +- MinIO integration with versioning +- File upload/download via REST API +- SHA256 checksums for integrity +- Storage path: `items/{partNumber}/rev{N}.FCStd` + +#### Bill of Materials (BOM) +- Relationship types: component, alternate, reference +- Multi-level BOM (recursive expansion with configurable depth) +- Where-used queries (reverse parent lookup) +- BOM CSV and ODS export/import with cycle detection +- Reference designators for electronics +- Quantity tracking with units +- Revision-specific child linking + +#### Project Management +- Project CRUD operations +- Unique project codes (2-10 characters) +- Item-to-project tagging +- Project-filtered queries + +#### Data Import/Export +- CSV export with configurable properties +- CSV import with dry-run validation +- ODS spreadsheet import/export (items, BOMs, project sheets) +- Template generation for import formatting + +#### API & Web Interface +- REST API with 78 endpoints +- Authentication: local (bcrypt), LDAP/FreeIPA, OIDC/Keycloak +- Role-based access control (admin > editor > viewer) +- API token management (SHA-256 hashed) +- Session management (PostgreSQL-backed, 24h lifetime) +- CSRF protection (nosurf on web forms) +- Middleware: logging, CORS, recovery, request ID +- Web UI -- React SPA (Vite + TypeScript, Catppuccin Mocha theme) +- Fuzzy search +- Health and readiness probes + +#### Audit & Completeness +- Audit logging (database table with user/action/resource tracking) +- Item completeness scoring with weighted fields +- Category-specific property validation +- Tier classification (critical/low/partial/good/complete) + +#### Configuration +- YAML configuration with environment variable overrides +- Multi-schema support +- Docker Compose deployment ready + +### Partially Implemented + +| Feature | Status | Notes | +|---------|--------|-------| +| Odoo ERP integration | Partial | Config and sync-log CRUD functional; push/pull sync operations are stubs | +| Date segment type | Not started | Schema parser placeholder exists | +| Part number validation | Not started | API accepts but doesn't validate format | +| Location hierarchy CRUD | Schema only | Tables exist, no API endpoints | +| Inventory tracking | Schema only | Tables exist, no API endpoints | +| Unit tests | Partial | 11 Go test files across api, db, ods, partnum, schema packages | + +--- + +## Appendix B: Phase 1 Detailed Tasks + +### 1.1 MinIO Integration -- COMPLETE +- [x] MinIO service configured in Docker Compose +- [x] File upload via REST API +- [x] File download via REST API (latest and by revision) +- [x] SHA256 checksums on upload + +### 1.2 Authentication & Authorization -- COMPLETE +- [x] Local authentication (bcrypt) +- [x] LDAP/FreeIPA authentication +- [x] OIDC/Keycloak authentication +- [x] Role-based access control (admin/editor/viewer) +- [x] API token management (SHA-256 hashed) +- [x] Session management (PostgreSQL-backed) +- [x] CSRF protection (nosurf) +- [x] Audit logging (database table) + +### 1.3 Multi-level BOM & Export -- COMPLETE +- [x] Recursive BOM expansion with configurable depth +- [x] Where-used reverse lookup +- [x] BOM CSV export/import with cycle detection +- [x] BOM ODS export +- [x] ODS item export/import/template + +### 1.4 Unit Test Suite +- [ ] Database connection and transaction tests +- [ ] Item CRUD operation tests +- [ ] Revision creation and retrieval tests +- [ ] Part number generation tests +- [ ] File upload/download tests +- [ ] CSV import/export tests +- [ ] API endpoint tests + +### 1.5 Missing Segment Types +- [ ] Implement date segment type +- [ ] Add strftime-style format support + +### 1.6 Location & Inventory APIs +- [ ] `GET /api/locations` - List locations +- [ ] `POST /api/locations` - Create location +- [ ] `GET /api/locations/{path}` - Get location +- [ ] `DELETE /api/locations/{path}` - Delete location +- [ ] `GET /api/inventory/{partNumber}` - Get inventory +- [ ] `POST /api/inventory/{partNumber}/adjust` - Adjust quantity +- [ ] `POST /api/inventory/{partNumber}/move` - Move between locations + +--- + +## Appendix C: References + +### SOLIDWORKS PDM Documentation +- [SOLIDWORKS PDM Product Page](https://www.solidworks.com/product/solidworks-pdm) +- [What's New in SOLIDWORKS PDM 2025](https://blogs.solidworks.com/solidworksblog/2024/10/whats-new-in-solidworks-pdm-2025.html) +- [Top 5 Enhancements in SOLIDWORKS PDM 2024](https://blogs.solidworks.com/solidworksblog/2023/10/top-5-enhancements-in-solidworks-pdm-2024.html) +- [SOLIDWORKS PDM Workflow Transitions](https://help.solidworks.com/2023/english/EnterprisePDM/Admin/c_workflow_transition.htm) +- [Ultimate Guide to SOLIDWORKS PDM Permissions](https://www.goengineer.com/blog/ultimate-guide-to-solidworks-pdm-permissions) +- [Searching in SOLIDWORKS PDM](https://help.solidworks.com/2021/english/EnterprisePDM/fileexplorer/c_searches.htm) +- [SOLIDWORKS PDM API Getting Started](https://3dswym.3dexperience.3ds.com/wiki/solidworks-news-info/getting-started-with-the-solidworks-pdm-api-solidpractices_gBCYaM75RgORBcpSO1m_Mw) + +### Silo Documentation +- [Specification](SPECIFICATION.md) +- [Development Status](STATUS.md) +- [Deployment Guide](DEPLOYMENT.md) +- [Gap Analysis](GAP_ANALYSIS.md) From d4ea6d2739514393a573ce2ddd3c566ef82e2d2e Mon Sep 17 00:00:00 2001 From: Forbes Date: Fri, 13 Feb 2026 13:09:41 -0600 Subject: [PATCH 02/43] fix(web): align item type badge colors with style guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #65 - Part: blue → green (--ctp-green) - Assembly: green → mauve (--ctp-mauve) - Document: yellow → blue (--ctp-blue) - Add purchased (--ctp-peach) and phantom (--ctp-overlay1) - Keep tooling as red (--ctp-red) --- web/src/components/items/ItemDetail.tsx | 8 +++++--- web/src/components/items/ItemTable.tsx | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/web/src/components/items/ItemDetail.tsx b/web/src/components/items/ItemDetail.tsx index 7e78a52..f7fdf39 100644 --- a/web/src/components/items/ItemDetail.tsx +++ b/web/src/components/items/ItemDetail.tsx @@ -64,9 +64,11 @@ export function ItemDetail({ } const typeColors: Record = { - part: { bg: "rgba(137,180,250,0.2)", color: "var(--ctp-blue)" }, - assembly: { bg: "rgba(166,227,161,0.2)", color: "var(--ctp-green)" }, - document: { bg: "rgba(249,226,175,0.2)", color: "var(--ctp-yellow)" }, + part: { bg: "rgba(166,227,161,0.2)", color: "var(--ctp-green)" }, + assembly: { bg: "rgba(203,166,247,0.2)", color: "var(--ctp-mauve)" }, + document: { bg: "rgba(137,180,250,0.2)", color: "var(--ctp-blue)" }, + purchased: { bg: "rgba(250,179,135,0.2)", color: "var(--ctp-peach)" }, + phantom: { bg: "rgba(127,132,156,0.2)", color: "var(--ctp-overlay1)" }, tooling: { bg: "rgba(243,139,168,0.2)", color: "var(--ctp-red)" }, }; const tc = typeColors[item.item_type] ?? { diff --git a/web/src/components/items/ItemTable.tsx b/web/src/components/items/ItemTable.tsx index 504f7bb..a8941a4 100644 --- a/web/src/components/items/ItemTable.tsx +++ b/web/src/components/items/ItemTable.tsx @@ -49,9 +49,11 @@ interface ItemTableProps { } const typeColors: Record = { - part: { bg: "rgba(137,180,250,0.2)", color: "var(--ctp-blue)" }, - assembly: { bg: "rgba(166,227,161,0.2)", color: "var(--ctp-green)" }, - document: { bg: "rgba(249,226,175,0.2)", color: "var(--ctp-yellow)" }, + part: { bg: "rgba(166,227,161,0.2)", color: "var(--ctp-green)" }, + assembly: { bg: "rgba(203,166,247,0.2)", color: "var(--ctp-mauve)" }, + document: { bg: "rgba(137,180,250,0.2)", color: "var(--ctp-blue)" }, + purchased: { bg: "rgba(250,179,135,0.2)", color: "var(--ctp-peach)" }, + phantom: { bg: "rgba(127,132,156,0.2)", color: "var(--ctp-overlay1)" }, tooling: { bg: "rgba(243,139,168,0.2)", color: "var(--ctp-red)" }, }; From 648c659e2beea701ef0784477bf9082538607ad8 Mon Sep 17 00:00:00 2001 From: Forbes Date: Fri, 13 Feb 2026 13:09:56 -0600 Subject: [PATCH 03/43] fix(web): use system font stack per style guide Fixes #66 Remove Inter and Roboto from font-family. The style guide specifies system fonts only: -apple-system, BlinkMacSystemFont, Segoe UI, system-ui, sans-serif. --- web/src/styles/global.css | 45 +++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/web/src/styles/global.css b/web/src/styles/global.css index 9d1e6bb..0713022 100644 --- a/web/src/styles/global.css +++ b/web/src/styles/global.css @@ -1,51 +1,54 @@ -@import './theme.css'; +@import "./theme.css"; *, *::before, *::after { - margin: 0; - padding: 0; - box-sizing: border-box; + margin: 0; + padding: 0; + box-sizing: border-box; } body { - font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; - background-color: var(--ctp-base); - color: var(--ctp-text); - line-height: 1.6; - min-height: 100vh; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif; + background-color: var(--ctp-base); + color: var(--ctp-text); + line-height: 1.6; + min-height: 100vh; } a { - color: var(--ctp-sapphire); - text-decoration: none; + color: var(--ctp-sapphire); + text-decoration: none; } a:hover { - color: var(--ctp-sky); - text-decoration: underline; + color: var(--ctp-sky); + text-decoration: underline; } /* Scrollbar */ ::-webkit-scrollbar { - width: 8px; - height: 8px; + width: 8px; + height: 8px; } ::-webkit-scrollbar-track { - background: var(--ctp-mantle); + background: var(--ctp-mantle); } ::-webkit-scrollbar-thumb { - background: var(--ctp-surface1); - border-radius: 4px; + background: var(--ctp-surface1); + border-radius: 4px; } ::-webkit-scrollbar-thumb:hover { - background: var(--ctp-surface2); + background: var(--ctp-surface2); } /* Monospace */ -code, pre, .mono { - font-family: 'JetBrains Mono', 'Fira Code', monospace; +code, +pre, +.mono { + font-family: "JetBrains Mono", "Fira Code", monospace; } From 1f7960db5087285270259d39cae4c55dc3c8784e Mon Sep 17 00:00:00 2001 From: Forbes Date: Fri, 13 Feb 2026 13:10:57 -0600 Subject: [PATCH 04/43] feat: implement date segment type for part number generation Fixes #79 Implement the date segment type in the part number generator. Uses Go's time.Format with the segment's Value field as the layout string. - Default format: 20060102 (YYYYMMDD) when no Value is specified - Custom formats via Value field: "0601" (YYMM), "2006" (YYYY), etc. - Always uses UTC time - Add 3 tests: default format, custom YYMM format, year-only format --- internal/partnum/generator.go | 8 ++- internal/partnum/generator_test.go | 86 ++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 2 deletions(-) diff --git a/internal/partnum/generator.go b/internal/partnum/generator.go index 9cc7d21..31b3776 100644 --- a/internal/partnum/generator.go +++ b/internal/partnum/generator.go @@ -6,6 +6,7 @@ import ( "fmt" "regexp" "strings" + "time" "github.com/kindredsystems/silo/internal/schema" ) @@ -99,8 +100,11 @@ func (g *Generator) resolveSegment( return g.formatSerial(seg, next), nil case "date": - // TODO: implement date formatting - return "", fmt.Errorf("date segments not yet implemented") + layout := seg.Value + if layout == "" { + layout = "20060102" + } + return time.Now().UTC().Format(layout), nil default: return "", fmt.Errorf("unknown segment type: %s", seg.Type) diff --git a/internal/partnum/generator_test.go b/internal/partnum/generator_test.go index 00dcf2b..0e63ccb 100644 --- a/internal/partnum/generator_test.go +++ b/internal/partnum/generator_test.go @@ -3,7 +3,9 @@ package partnum import ( "context" "fmt" + "regexp" "testing" + "time" "github.com/kindredsystems/silo/internal/schema" ) @@ -165,3 +167,87 @@ func TestGenerateConstantSegment(t *testing.T) { t.Errorf("got %q, want %q", pn, "KS-0001") } } + +func TestGenerateDateSegmentDefault(t *testing.T) { + s := &schema.Schema{ + Name: "date-test", + Version: 1, + Separator: "-", + Segments: []schema.Segment{ + {Name: "date", Type: "date"}, + {Name: "serial", Type: "serial", Length: 3}, + }, + } + gen := NewGenerator(map[string]*schema.Schema{"date-test": s}, &mockSeqStore{}) + + pn, err := gen.Generate(context.Background(), Input{ + SchemaName: "date-test", + Values: map[string]string{}, + }) + if err != nil { + t.Fatalf("Generate returned error: %v", err) + } + + // Default format: YYYYMMDD-NNN + want := time.Now().UTC().Format("20060102") + "-001" + if pn != want { + t.Errorf("got %q, want %q", pn, want) + } +} + +func TestGenerateDateSegmentCustomFormat(t *testing.T) { + s := &schema.Schema{ + Name: "date-custom", + Version: 1, + Separator: "-", + Segments: []schema.Segment{ + {Name: "date", Type: "date", Value: "0601"}, + {Name: "serial", Type: "serial", Length: 4}, + }, + } + gen := NewGenerator(map[string]*schema.Schema{"date-custom": s}, &mockSeqStore{}) + + pn, err := gen.Generate(context.Background(), Input{ + SchemaName: "date-custom", + Values: map[string]string{}, + }) + if err != nil { + t.Fatalf("Generate returned error: %v", err) + } + + // Format "0601" produces YYMM + if matched, _ := regexp.MatchString(`^\d{4}-\d{4}$`, pn); !matched { + t.Errorf("got %q, want pattern YYMM-NNNN", pn) + } + + want := time.Now().UTC().Format("0601") + "-0001" + if pn != want { + t.Errorf("got %q, want %q", pn, want) + } +} + +func TestGenerateDateSegmentYearOnly(t *testing.T) { + s := &schema.Schema{ + Name: "date-year", + Version: 1, + Separator: "-", + Segments: []schema.Segment{ + {Name: "year", Type: "date", Value: "2006"}, + {Name: "serial", Type: "serial", Length: 4}, + }, + } + gen := NewGenerator(map[string]*schema.Schema{"date-year": s}, &mockSeqStore{}) + + pn, err := gen.Generate(context.Background(), Input{ + SchemaName: "date-year", + Values: map[string]string{}, + }) + if err != nil { + t.Fatalf("Generate returned error: %v", err) + } + + want := time.Now().UTC().Format("2006") + "-0001" + if pn != want { + t.Errorf("got %q, want %q", pn, want) + } +} From 2585305590e8e4519e630a57f31bb77711226057 Mon Sep 17 00:00:00 2001 From: Forbes Date: Fri, 13 Feb 2026 13:21:54 -0600 Subject: [PATCH 05/43] fix(web): standardize button borderRadius, fontSize, fontWeight (#68) All button style objects now use: - borderRadius: 0.375rem - fontSize: 0.75rem - fontWeight: 500 Files: CreateItemPane, EditItemPane, DeleteItemPane, BOMTab, CategoryPicker, ProjectsPage, SchemasPage, LoginPage, ItemsToolbar, SettingsPage, ImportItemsPane, ItemTable Closes #68 --- docs/STYLE.md | 515 +++++++++++++++++++ web/src/components/items/BOMTab.tsx | 13 +- web/src/components/items/CategoryPicker.tsx | 6 +- web/src/components/items/CreateItemPane.tsx | 9 +- web/src/components/items/DeleteItemPane.tsx | 152 ++++-- web/src/components/items/EditItemPane.tsx | 9 +- web/src/components/items/ImportItemsPane.tsx | 14 +- web/src/components/items/ItemTable.tsx | 5 +- web/src/components/items/ItemsToolbar.tsx | 10 +- web/src/pages/LoginPage.tsx | 12 +- web/src/pages/ProjectsPage.tsx | 27 +- web/src/pages/SchemasPage.tsx | 7 +- web/src/pages/SettingsPage.tsx | 27 +- 13 files changed, 716 insertions(+), 90 deletions(-) create mode 100644 docs/STYLE.md diff --git a/docs/STYLE.md b/docs/STYLE.md new file mode 100644 index 0000000..cc17466 --- /dev/null +++ b/docs/STYLE.md @@ -0,0 +1,515 @@ +# Silo Style Guide + +> Living reference for the Silo web UI. All modules must follow these conventions to maintain visual consistency across the platform. + +--- + +## Color System + +Silo uses the [Catppuccin Mocha](https://github.com/catppuccin/catppuccin) palette exclusively. All colors are referenced via CSS custom properties defined at `:root`. + +### Palette + +``` +--ctp-rosewater: #f5e0dc +--ctp-flamingo: #f2cdcd +--ctp-pink: #f5c2e7 +--ctp-mauve: #cba6f7 +--ctp-red: #f38ba8 +--ctp-maroon: #eba0ac +--ctp-peach: #fab387 +--ctp-yellow: #f9e2af +--ctp-green: #a6e3a1 +--ctp-teal: #94e2d5 +--ctp-sky: #89dceb +--ctp-sapphire: #74c7ec +--ctp-blue: #89b4fa +--ctp-lavender: #b4befe +--ctp-text: #cdd6f4 +--ctp-subtext1: #bac2de +--ctp-subtext0: #a6adc8 +--ctp-overlay2: #9399b2 +--ctp-overlay1: #7f849c +--ctp-overlay0: #6c7086 +--ctp-surface2: #585b70 +--ctp-surface1: #45475a +--ctp-surface0: #313244 +--ctp-base: #1e1e2e +--ctp-mantle: #181825 +--ctp-crust: #11111b +``` + +### Semantic Roles + +| Role | Token | Usage | +|------|-------|-------| +| Page background | `--ctp-base` | Main content area | +| Panel background | `--ctp-mantle` | Sidebars, detail panes, headers | +| Inset/input background | `--ctp-crust` | Form inputs, code blocks, drop zones | +| Primary accent | `--ctp-mauve` | Primary buttons, active states, links, selection highlights | +| Secondary accent | `--ctp-blue` | Informational highlights, secondary actions | +| Success | `--ctp-green` | Confirmations, positive status | +| Warning | `--ctp-yellow` | Caution states, pending actions | +| Danger | `--ctp-red` | Destructive actions, errors, required indicators | +| Informational | `--ctp-teal` | Auto-generated metadata, system-assigned values | +| Body text | `--ctp-text` | Primary content | +| Secondary text | `--ctp-subtext1` | Descriptions, timestamps | +| Muted text | `--ctp-overlay1` | Placeholders, disabled states | +| Borders | `--ctp-surface0` | Dividers, panel edges | +| Hover borders | `--ctp-surface1` | Interactive element borders, row separators | +| Focus ring | `rgba(203, 166, 247, 0.25)` | `box-shadow` on focused inputs (mauve at 25%) | + +### Accent Usage for Data Types + +| Data type | Color | Token | +|-----------|-------|-------| +| Assembly | `--ctp-mauve` | Badge, icon tint | +| Part | `--ctp-green` | Badge, icon tint | +| Document | `--ctp-blue` | Badge, icon tint | +| Purchased | `--ctp-peach` | Badge, icon tint | +| Phantom | `--ctp-overlay1` | Badge, icon tint | + +These mappings are used anywhere item types appear: list badges, detail pane headers, BOM entries, tree views. + +--- + +## Typography + +### Scale + +| Role | Size | Weight | Token/Color | Transform | +|------|------|--------|-------------|-----------| +| Page title | 1.1rem | 600 | `--ctp-text` | None | +| Section header | 11px | 600 | `--ctp-overlay0` | Uppercase, `letter-spacing: 0.06em` | +| Form label | 11px | 600 | `--ctp-overlay1` | Uppercase, `letter-spacing: 0.05em` | +| Body text | 13px | 400 | `--ctp-text` | None | +| Table cell | 12px | 400 | `--ctp-text` | None | +| Caption / metadata | 11px | 400 | `--ctp-subtext0` | None | +| Badge text | 10px | 600 | Varies | Uppercase | +| Breadcrumb segment | 13px | 500 | `--ctp-subtext1` | None | +| Breadcrumb active | 13px | 600 | `--ctp-text` | None | + +### Font Stack + +```css +font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; +``` + +No external font dependencies. System fonts ensure fast rendering and native feel across platforms. + +### Rules + +- Never use font sizes below 10px. +- Use `font-weight: 600` for emphasis instead of bold (700). Reserve 700 for page titles only when extra weight is needed. +- `text-transform: uppercase` is reserved for section headers, form labels, and badges. Never uppercase body text or descriptions. + +--- + +## Spacing + +Base unit: **4px**. All spacing values are multiples of 4. + +| Token | Value | Usage | +|-------|-------|-------| +| `xs` | 4px (0.25rem) | Tight gaps: icon-to-label, tag internal padding | +| `sm` | 8px (0.5rem) | Compact spacing: between related fields, badge padding | +| `md` | 12px (0.75rem) | Standard: form group gaps, sidebar section padding | +| `lg` | 16px (1rem) | Section separation, card padding | +| `xl` | 24px (1.5rem) | Page-level padding, major section breaks | +| `2xl` | 32px (2rem) | Page horizontal padding | + +### Application + +- **Page padding:** `1.5rem 2rem` (24px vertical, 32px horizontal) +- **Sidebar section padding:** `1rem 1.25rem` +- **Form grid gap:** `1.25rem 1.5rem` (row gap × column gap) +- **Table row height:** 36px minimum (padding included) +- **Table cell padding:** `0.4rem 0.75rem` + +--- + +## Layout + +### Page Structure + +Every module page follows the same shell: + +``` +┌─────────────────────────────────────────────────┐ +│ Top Nav (52px) │ +├──────────┬──────────────────────────────────────┤ +│ App Menu │ Page Header (58px) │ +│ (icons) ├──────────────────────┬───────────────┤ +│ │ Content Area │ Detail Pane │ +│ │ │ (360px) │ +│ │ │ │ +│ │ │ │ +└──────────┴──────────────────────┴───────────────┘ +``` + +- **Top nav:** `52px` height, `--ctp-mantle` background, `1px solid --ctp-surface0` bottom border. +- **App menu sidebar:** Icon strip on the left. Module icons, tooltips on hover. Active module highlighted with `--ctp-mauve` indicator. +- **Page header:** `58px` height, `--ctp-mantle` background. Contains page title (with module icon), action buttons right-aligned. +- **Content area:** `--ctp-base` background. Scrollable. Contains list views, kanban boards, or other primary content. +- **Detail pane:** `360px` fixed width, `--ctp-mantle` background, `1px solid --ctp-surface0` left border. Appears on record selection. + +### Grid Patterns + +**Two-column form:** +```css +display: grid; +grid-template-columns: 1fr 1fr; +gap: 1.25rem 1.5rem; +max-width: 800px; +``` + +**List + detail:** +```css +display: grid; +grid-template-columns: 1fr 360px; +min-height: calc(100vh - 52px - 58px); +``` + +### Breakpoints + +Not currently required. Silo targets desktop browsers on engineering workstations. If mobile support is added later, breakpoints will be defined at `768px` and `1024px`. + +--- + +## Components + +### Buttons + +Four tiers. All buttons share a base style: + +```css +display: inline-flex; +align-items: center; +gap: 0.35rem; +padding: 0.4rem 0.85rem; +border-radius: 6px; +font-size: 12px; +font-weight: 500; +cursor: pointer; +transition: all 0.15s; +``` + +| Tier | Name | Background | Border | Text | Hover | +|------|------|-----------|--------|------|-------| +| Primary | `.btn-primary` | `--ctp-mauve` | `--ctp-mauve` | `--ctp-crust` | `--ctp-lavender` bg + border | +| Secondary | `.btn` (default) | `--ctp-surface0` | `--ctp-surface1` | `--ctp-text` | `--ctp-surface1` bg, `--ctp-overlay0` border | +| Ghost | `.btn-ghost` | transparent | transparent | `--ctp-subtext0` | `--ctp-surface0` bg, `--ctp-text` text | +| Danger | `.btn-danger` | transparent | `--ctp-surface1` | `--ctp-red` | `rgba(243, 139, 168, 0.1)` bg, `--ctp-red` border | + +Primary is used once per visible context (the main action). All other actions use secondary or ghost. Danger is only for destructive actions and always requires confirmation. + +### Badges + +Used for type indicators, status labels, and tags. + +```css +display: inline-flex; +align-items: center; +padding: 0.15rem 0.5rem; +border-radius: 4px; +font-size: 10px; +font-weight: 600; +text-transform: uppercase; +letter-spacing: 0.03em; +``` + +Badges use a translucent background derived from their accent color: + +```css +/* Example: assembly badge */ +background: rgba(203, 166, 247, 0.15); /* --ctp-mauve at 15% */ +color: var(--ctp-mauve); +``` + +Standard badge colors follow the [accent usage table](#accent-usage-for-data-types). Status badges: + +| Status | Color | +|--------|-------| +| Active / Released | `--ctp-green` | +| Draft / In Progress | `--ctp-blue` | +| Review / Pending | `--ctp-yellow` | +| Obsolete / Rejected | `--ctp-red` | +| Locked | `--ctp-overlay1` | + +### Form Inputs + +All inputs share a base style: + +```css +background: var(--ctp-crust); +border: 1px solid var(--ctp-surface1); +border-radius: 6px; +padding: 0.45rem 0.65rem; +font-size: 12px; +color: var(--ctp-text); +transition: border-color 0.15s; +``` + +| State | Border | Shadow | +|-------|--------|--------| +| Default | `--ctp-surface1` | None | +| Hover | `--ctp-overlay0` | None | +| Focus | `--ctp-mauve` | `0 0 0 0.2rem rgba(203, 166, 247, 0.25)` | +| Error | `--ctp-red` | `0 0 0 0.2rem rgba(243, 139, 168, 0.15)` | +| Disabled | `--ctp-surface0` | None, `opacity: 0.5` | + +Placeholder text: `--ctp-overlay0`. Labels sit above inputs (never inline or floating). + +### Tag Input + +Used for multi-value fields (projects, tags): + +```css +display: flex; +flex-wrap: wrap; +gap: 0.3rem; +padding: 0.35rem 0.5rem; +background: var(--ctp-crust); +border: 1px solid var(--ctp-surface1); +border-radius: 6px; +min-height: 36px; +``` + +Individual tags use the badge pattern: `rgba(accent, 0.15)` background with accent text. Remove button (×) at `opacity: 0.6`, `1.0` on hover. + +### Tables + +```css +width: 100%; +border-collapse: collapse; +font-size: 12px; +``` + +| Element | Style | +|---------|-------| +| Header row | `background: --ctp-mantle`, `font-size: 11px`, uppercase, `--ctp-overlay1` text | +| Body row | `border-bottom: 1px solid --ctp-surface0` | +| Row hover | `background: --ctp-surface0` | +| Row selected | `background: rgba(203, 166, 247, 0.08)` | +| Cell padding | `0.4rem 0.75rem` | +| Text columns | Left-aligned | +| Number columns | Right-aligned | +| Date columns | Right-aligned | +| Action columns | Center-aligned | + +Row actions use icon buttons (not text links). Icons at 14px, `--ctp-overlay1` default, `--ctp-text` on hover. + +### Tabs + +Used in detail panes and module sub-views: + +```css +display: flex; +gap: 0; +border-bottom: 2px solid var(--ctp-surface0); +``` + +| State | Style | +|-------|-------| +| Default | `padding: 0.5rem 1rem`, `--ctp-subtext0` text, no border | +| Hover | `--ctp-text` text | +| Active | `--ctp-text` text, `font-weight: 600`, `border-bottom: 2px solid --ctp-mauve` (overlaps container border) | + +### Section Dividers + +Used to visually group form fields: + +```css +display: flex; +align-items: center; +gap: 0.75rem; +grid-column: 1 / -1; /* span full form grid */ +margin-top: 0.75rem; +``` + +Contains a label (`11px`, uppercase, `--ctp-overlay0`) and a horizontal line (`flex: 1`, `1px solid --ctp-surface0`). + +### Sidebar Sections + +Stacked vertically within detail panes: + +```css +padding: 1rem 1.25rem; +border-bottom: 1px solid var(--ctp-surface0); +``` + +Last section has no bottom border. Section titles follow the section header typography (11px, uppercase, `--ctp-overlay0`). + +### Tooltips + +Appear on hover after a 300ms delay. Position: above the target element by default, flip below if insufficient space. + +```css +background: var(--ctp-surface0); +border: 1px solid var(--ctp-surface1); +border-radius: 4px; +padding: 0.3rem 0.6rem; +font-size: 11px; +color: var(--ctp-text); +box-shadow: 0 4px 12px rgba(17, 17, 27, 0.4); +``` + +### Breadcrumbs + +Module navigation breadcrumbs: + +``` +Module Name > List View > Record Name > Sub-view +``` + +Separator: `>` character in `--ctp-overlay0`. Segments are clickable links in `--ctp-subtext1`. Active (final) segment is `--ctp-text` at `font-weight: 600`. + +### Dropdowns / Selects + +Follow the input base style. The dropdown menu: + +```css +background: var(--ctp-surface0); +border: 1px solid var(--ctp-surface1); +border-radius: 6px; +box-shadow: 0 8px 24px rgba(17, 17, 27, 0.5); +padding: 0.25rem; +max-height: 240px; +overflow-y: auto; +``` + +Menu items: + +```css +padding: 0.4rem 0.65rem; +border-radius: 4px; +font-size: 12px; +color: var(--ctp-text); +cursor: pointer; +``` + +Hover: `background: --ctp-surface1`. Selected: `background: rgba(203, 166, 247, 0.12)`, `color: --ctp-mauve`, `font-weight: 600`. + +--- + +## Icons + +Use [Lucide](https://lucide.dev) icons. Size: 14px for inline/table contexts, 16px for buttons and navigation, 20px for page headers and empty states. + +Stroke width: 1.5px (Lucide default). Color inherits from parent text color unless explicitly set. + +Do not mix icon libraries. If Lucide does not have a suitable icon, request one be added or create a custom SVG following Lucide's 24×24 grid and stroke conventions. + +--- + +## Transitions & Animation + +All interactive state changes use `transition: all 0.15s ease`. This applies to hover, focus, active, and open/close states. + +No entrance animations on page load. Content renders immediately. Skeleton loaders are acceptable for async data using a pulsing `--ctp-surface0` → `--ctp-surface1` gradient. + +Dropdown menus and tooltips appear instantly (no slide/fade). Collapse/expand panels (if used) transition `max-height` at `0.2s ease`. + +--- + +## Styling Implementation + +Silo's React frontend uses **inline `React.CSSProperties` objects** with `var(--ctp-*)` token references. This is the project convention and must not be changed. + +### Rules + +- No CSS modules, no Tailwind, no external CSS-in-JS libraries. +- Styles are defined as `const` objects at the top of each component file. +- Shared style patterns (button base, input base) can be extracted to a `styles/` directory as exported `CSSProperties` objects. +- Use `as const` or `as React.CSSProperties` for type safety. +- Pseudo-classes (`:hover`, `:focus`) require state-driven inline styles or a thin CSS file for the base pseudo-class rules. + +### Example + +```typescript +const styles = { + container: { + display: 'grid', + gridTemplateColumns: '1fr 360px', + height: '100%', + overflow: 'hidden', + } as React.CSSProperties, + + sidebar: { + background: 'var(--ctp-mantle)', + borderLeft: '1px solid var(--ctp-surface0)', + display: 'flex', + flexDirection: 'column' as const, + overflowY: 'auto' as const, + } as React.CSSProperties, +}; +``` + +### Pseudo-class CSS + +A single `silo-base.css` file provides pseudo-class rules that cannot be expressed inline: + +```css +/* Hover, focus, and active states for core interactive elements */ +.silo-input:hover { border-color: var(--ctp-overlay0); } +.silo-input:focus { border-color: var(--ctp-mauve); box-shadow: 0 0 0 0.2rem rgba(203, 166, 247, 0.25); } +.silo-btn:hover { /* per-tier overrides */ } +.silo-row:hover { background: var(--ctp-surface0); } +``` + +Components apply the corresponding class names alongside their inline styles. This is the only place class-based styling is used. + +--- + +## Do / Don't + +| Do | Don't | +|----|-------| +| Use `var(--ctp-*)` for every color | Hardcode hex values | +| Use the 4px spacing scale | Use arbitrary padding/margins | +| Use Lucide icons at standard sizes | Mix icon libraries | +| Use inline `CSSProperties` | Use CSS modules or Tailwind | +| One primary button per visible context | Multiple competing primary buttons | +| Use translucent accent backgrounds for badges | Use solid bright backgrounds for badges | +| Use icon buttons for row-level table actions | Use text links in table rows | +| Define styles as `const` at file top | Inline style objects in JSX | +| Show tooltips on icon-only buttons | Leave icon buttons unlabeled | +| Use section dividers to group form fields | Use cards or borders around field groups | +| Follow the breadcrumb pattern for navigation | Use nested tab bars | + +--- + +## Appendix: CSS Custom Properties Block + +Paste this at the root of the application stylesheet: + +```css +:root { + --ctp-rosewater: #f5e0dc; + --ctp-flamingo: #f2cdcd; + --ctp-pink: #f5c2e7; + --ctp-mauve: #cba6f7; + --ctp-red: #f38ba8; + --ctp-maroon: #eba0ac; + --ctp-peach: #fab387; + --ctp-yellow: #f9e2af; + --ctp-green: #a6e3a1; + --ctp-teal: #94e2d5; + --ctp-sky: #89dceb; + --ctp-sapphire: #74c7ec; + --ctp-blue: #89b4fa; + --ctp-lavender: #b4befe; + --ctp-text: #cdd6f4; + --ctp-subtext1: #bac2de; + --ctp-subtext0: #a6adc8; + --ctp-overlay2: #9399b2; + --ctp-overlay1: #7f849c; + --ctp-overlay0: #6c7086; + --ctp-surface2: #585b70; + --ctp-surface1: #45475a; + --ctp-surface0: #313244; + --ctp-base: #1e1e2e; + --ctp-mantle: #181825; + --ctp-crust: #11111b; +} +``` diff --git a/web/src/components/items/BOMTab.tsx b/web/src/components/items/BOMTab.tsx index b9f6352..f6a5b73 100644 --- a/web/src/components/items/BOMTab.tsx +++ b/web/src/components/items/BOMTab.tsx @@ -422,9 +422,10 @@ const tdStyle: React.CSSProperties = { const toolBtnStyle: React.CSSProperties = { padding: "0.25rem 0.5rem", - fontSize: "0.8rem", + fontSize: "0.75rem", + fontWeight: 500, border: "none", - borderRadius: "0.3rem", + borderRadius: "0.375rem", backgroundColor: "var(--ctp-surface1)", color: "var(--ctp-text)", cursor: "pointer", @@ -436,14 +437,17 @@ const actionBtnStyle: React.CSSProperties = { color: "var(--ctp-subtext1)", cursor: "pointer", fontSize: "0.75rem", + fontWeight: 500, padding: "0.1rem 0.3rem", + borderRadius: "0.375rem", }; const saveBtnStyle: React.CSSProperties = { padding: "0.2rem 0.4rem", fontSize: "0.75rem", + fontWeight: 500, border: "none", - borderRadius: "0.25rem", + borderRadius: "0.375rem", backgroundColor: "var(--ctp-green)", color: "var(--ctp-crust)", cursor: "pointer", @@ -472,8 +476,9 @@ const manualBadge: React.CSSProperties = { const cancelBtnStyle: React.CSSProperties = { padding: "0.2rem 0.4rem", fontSize: "0.75rem", + fontWeight: 500, border: "none", - borderRadius: "0.25rem", + borderRadius: "0.375rem", backgroundColor: "var(--ctp-surface1)", color: "var(--ctp-subtext1)", cursor: "pointer", diff --git a/web/src/components/items/CategoryPicker.tsx b/web/src/components/items/CategoryPicker.tsx index 07b1910..48858c7 100644 --- a/web/src/components/items/CategoryPicker.tsx +++ b/web/src/components/items/CategoryPicker.tsx @@ -96,10 +96,10 @@ export function CategoryPicker({ }} style={{ padding: "0.2rem 0.5rem", - fontSize: "0.7rem", - fontWeight: isActive ? 600 : 400, + fontSize: "0.75rem", + fontWeight: 500, border: "none", - borderRadius: "0.25rem", + borderRadius: "0.375rem", cursor: "pointer", backgroundColor: isActive ? "rgba(203,166,247,0.2)" diff --git a/web/src/components/items/CreateItemPane.tsx b/web/src/components/items/CreateItemPane.tsx index 226f74e..800a8ac 100644 --- a/web/src/components/items/CreateItemPane.tsx +++ b/web/src/components/items/CreateItemPane.tsx @@ -671,9 +671,10 @@ const headerStyle: React.CSSProperties = { const actionBtnStyle: React.CSSProperties = { padding: "0.3rem 0.75rem", - fontSize: "0.8rem", + fontSize: "0.75rem", + fontWeight: 500, border: "none", - borderRadius: "0.3rem", + borderRadius: "0.375rem", color: "var(--ctp-crust)", cursor: "pointer", }; @@ -683,8 +684,10 @@ const cancelBtnStyle: React.CSSProperties = { border: "none", cursor: "pointer", color: "var(--ctp-subtext1)", - fontSize: "0.8rem", + fontSize: "0.75rem", + fontWeight: 500, padding: "0.2rem 0.4rem", + borderRadius: "0.375rem", }; const inputStyle: React.CSSProperties = { diff --git a/web/src/components/items/DeleteItemPane.tsx b/web/src/components/items/DeleteItemPane.tsx index c52e232..9b0026a 100644 --- a/web/src/components/items/DeleteItemPane.tsx +++ b/web/src/components/items/DeleteItemPane.tsx @@ -1,5 +1,5 @@ -import { useState } from 'react'; -import { del } from '../../api/client'; +import { useState } from "react"; +import { del } from "../../api/client"; interface DeleteItemPaneProps { partNumber: string; @@ -7,7 +7,11 @@ interface DeleteItemPaneProps { onCancel: () => void; } -export function DeleteItemPane({ partNumber, onDeleted, onCancel }: DeleteItemPaneProps) { +export function DeleteItemPane({ + partNumber, + onDeleted, + onCancel, +}: DeleteItemPaneProps) { const [deleting, setDeleting] = useState(false); const [error, setError] = useState(null); @@ -18,59 +22,133 @@ export function DeleteItemPane({ partNumber, onDeleted, onCancel }: DeleteItemPa await del(`/api/items/${encodeURIComponent(partNumber)}`); onDeleted(); } catch (e) { - setError(e instanceof Error ? e.message : 'Failed to delete item'); + setError(e instanceof Error ? e.message : "Failed to delete item"); } finally { setDeleting(false); } }; return ( -
-
- Delete Item +
+
+ + Delete Item + - +
-
+
{error && ( -
+
{error}
)} -
-

+

+

Permanently delete item

-

+

{partNumber}

-

- This will permanently remove this item, all its revisions, BOM entries, and file attachments. This action cannot be undone. +

+ This will permanently remove this item, all its revisions, BOM + entries, and file attachments. This action cannot be undone.

-
- -
@@ -79,6 +157,12 @@ export function DeleteItemPane({ partNumber, onDeleted, onCancel }: DeleteItemPa } const headerBtnStyle: React.CSSProperties = { - background: 'none', border: 'none', cursor: 'pointer', - color: 'var(--ctp-subtext1)', fontSize: '0.8rem', padding: '0.2rem 0.4rem', + background: "none", + border: "none", + cursor: "pointer", + color: "var(--ctp-subtext1)", + fontSize: "0.75rem", + fontWeight: 500, + padding: "0.2rem 0.4rem", + borderRadius: "0.375rem", }; diff --git a/web/src/components/items/EditItemPane.tsx b/web/src/components/items/EditItemPane.tsx index 19d5d4e..5bc6709 100644 --- a/web/src/components/items/EditItemPane.tsx +++ b/web/src/components/items/EditItemPane.tsx @@ -90,9 +90,10 @@ export function EditItemPane({ disabled={saving} style={{ padding: "0.3rem 0.75rem", - fontSize: "0.8rem", + fontSize: "0.75rem", + fontWeight: 500, border: "none", - borderRadius: "0.3rem", + borderRadius: "0.375rem", backgroundColor: "var(--ctp-blue)", color: "var(--ctp-crust)", cursor: "pointer", @@ -215,6 +216,8 @@ const headerBtnStyle: React.CSSProperties = { border: "none", cursor: "pointer", color: "var(--ctp-subtext1)", - fontSize: "0.8rem", + fontSize: "0.75rem", + fontWeight: 500, padding: "0.2rem 0.4rem", + borderRadius: "0.375rem", }; diff --git a/web/src/components/items/ImportItemsPane.tsx b/web/src/components/items/ImportItemsPane.tsx index 057a429..b55a42b 100644 --- a/web/src/components/items/ImportItemsPane.tsx +++ b/web/src/components/items/ImportItemsPane.tsx @@ -185,9 +185,10 @@ export function ImportItemsPane({ disabled={!file || importing} style={{ padding: "0.4rem 0.75rem", - fontSize: "0.85rem", + fontSize: "0.75rem", + fontWeight: 500, border: "none", - borderRadius: "0.3rem", + borderRadius: "0.375rem", backgroundColor: "var(--ctp-yellow)", color: "var(--ctp-crust)", cursor: "pointer", @@ -202,9 +203,10 @@ export function ImportItemsPane({ disabled={importing || (result?.error_count ?? 0) > 0} style={{ padding: "0.4rem 0.75rem", - fontSize: "0.85rem", + fontSize: "0.75rem", + fontWeight: 500, border: "none", - borderRadius: "0.3rem", + borderRadius: "0.375rem", backgroundColor: "var(--ctp-green)", color: "var(--ctp-crust)", cursor: "pointer", @@ -289,6 +291,8 @@ const headerBtnStyle: React.CSSProperties = { border: "none", cursor: "pointer", color: "var(--ctp-subtext1)", - fontSize: "0.8rem", + fontSize: "0.75rem", + fontWeight: 500, padding: "0.2rem 0.4rem", + borderRadius: "0.375rem", }; diff --git a/web/src/components/items/ItemTable.tsx b/web/src/components/items/ItemTable.tsx index a8941a4..9b3e44a 100644 --- a/web/src/components/items/ItemTable.tsx +++ b/web/src/components/items/ItemTable.tsx @@ -385,7 +385,8 @@ const actionBtnStyle: React.CSSProperties = { border: "none", color: "var(--ctp-subtext1)", cursor: "pointer", - fontSize: "0.8rem", + fontSize: "0.75rem", + fontWeight: 500, padding: "0.15rem 0.4rem", - borderRadius: "0.25rem", + borderRadius: "0.375rem", }; diff --git a/web/src/components/items/ItemsToolbar.tsx b/web/src/components/items/ItemsToolbar.tsx index d385339..fdfd238 100644 --- a/web/src/components/items/ItemsToolbar.tsx +++ b/web/src/components/items/ItemsToolbar.tsx @@ -37,9 +37,10 @@ export function ItemsToolbar({ onClick={() => onFilterChange({ searchScope: scope })} style={{ padding: "var(--d-input-py) var(--d-input-px)", - fontSize: "var(--d-input-font)", + fontSize: "0.75rem", + fontWeight: 500, border: "none", - borderRadius: "0.3rem", + borderRadius: "0.375rem", cursor: "pointer", backgroundColor: filters.searchScope === scope @@ -173,8 +174,9 @@ const toolBtnStyle: React.CSSProperties = { padding: "var(--d-input-py) var(--d-input-px)", backgroundColor: "var(--ctp-surface1)", border: "none", - borderRadius: "0.4rem", + borderRadius: "0.375rem", color: "var(--ctp-text)", - fontSize: "var(--d-input-font)", + fontSize: "0.75rem", + fontWeight: 500, cursor: "pointer", }; diff --git a/web/src/pages/LoginPage.tsx b/web/src/pages/LoginPage.tsx index 1974b55..4e10359 100644 --- a/web/src/pages/LoginPage.tsx +++ b/web/src/pages/LoginPage.tsx @@ -162,9 +162,9 @@ const btnPrimaryStyle: React.CSSProperties = { display: "block", width: "100%", padding: "0.75rem 1.5rem", - borderRadius: "0.5rem", - fontWeight: 600, - fontSize: "1rem", + borderRadius: "0.375rem", + fontWeight: 500, + fontSize: "0.75rem", cursor: "pointer", border: "none", backgroundColor: "var(--ctp-mauve)", @@ -187,9 +187,9 @@ const btnOidcStyle: React.CSSProperties = { display: "block", width: "100%", padding: "0.75rem 1.5rem", - borderRadius: "0.5rem", - fontWeight: 600, - fontSize: "1rem", + borderRadius: "0.375rem", + fontWeight: 500, + fontSize: "0.75rem", cursor: "pointer", border: "none", backgroundColor: "var(--ctp-blue)", diff --git a/web/src/pages/ProjectsPage.tsx b/web/src/pages/ProjectsPage.tsx index 80ce67f..e07069e 100644 --- a/web/src/pages/ProjectsPage.tsx +++ b/web/src/pages/ProjectsPage.tsx @@ -443,43 +443,45 @@ export function ProjectsPage() { // Styles const btnPrimaryStyle: React.CSSProperties = { padding: "0.5rem 1rem", - borderRadius: "0.4rem", + borderRadius: "0.375rem", border: "none", backgroundColor: "var(--ctp-mauve)", color: "var(--ctp-crust)", - fontWeight: 600, - fontSize: "0.85rem", + fontWeight: 500, + fontSize: "0.75rem", cursor: "pointer", }; const btnSecondaryStyle: React.CSSProperties = { padding: "0.5rem 1rem", - borderRadius: "0.4rem", + borderRadius: "0.375rem", border: "none", backgroundColor: "var(--ctp-surface1)", color: "var(--ctp-text)", - fontSize: "0.85rem", + fontWeight: 500, + fontSize: "0.75rem", cursor: "pointer", }; const btnDangerStyle: React.CSSProperties = { padding: "0.5rem 1rem", - borderRadius: "0.4rem", + borderRadius: "0.375rem", border: "none", backgroundColor: "var(--ctp-red)", color: "var(--ctp-crust)", - fontWeight: 600, - fontSize: "0.85rem", + fontWeight: 500, + fontSize: "0.75rem", cursor: "pointer", }; const btnSmallStyle: React.CSSProperties = { padding: "0.3rem 0.6rem", - borderRadius: "0.3rem", + borderRadius: "0.375rem", border: "none", backgroundColor: "var(--ctp-surface1)", color: "var(--ctp-text)", - fontSize: "0.8rem", + fontWeight: 500, + fontSize: "0.75rem", cursor: "pointer", }; @@ -504,8 +506,9 @@ const formCloseStyle: React.CSSProperties = { border: "none", color: "inherit", cursor: "pointer", - fontSize: "0.85rem", - fontWeight: 600, + fontSize: "0.75rem", + fontWeight: 500, + borderRadius: "0.375rem", }; const errorBannerStyle: React.CSSProperties = { diff --git a/web/src/pages/SchemasPage.tsx b/web/src/pages/SchemasPage.tsx index 0c8d6d1..07e0b55 100644 --- a/web/src/pages/SchemasPage.tsx +++ b/web/src/pages/SchemasPage.tsx @@ -706,22 +706,23 @@ const tdStyle: React.CSSProperties = { const btnTinyStyle: React.CSSProperties = { padding: "0.2rem 0.5rem", - borderRadius: "0.25rem", + borderRadius: "0.375rem", border: "none", backgroundColor: "var(--ctp-surface1)", color: "var(--ctp-text)", fontSize: "0.75rem", + fontWeight: 500, cursor: "pointer", }; const btnTinyPrimaryStyle: React.CSSProperties = { padding: "0.2rem 0.5rem", - borderRadius: "0.25rem", + borderRadius: "0.375rem", border: "none", backgroundColor: "var(--ctp-mauve)", color: "var(--ctp-crust)", fontSize: "0.75rem", - fontWeight: 600, + fontWeight: 500, cursor: "pointer", }; diff --git a/web/src/pages/SettingsPage.tsx b/web/src/pages/SettingsPage.tsx index 7d429c0..811e4b6 100644 --- a/web/src/pages/SettingsPage.tsx +++ b/web/src/pages/SettingsPage.tsx @@ -404,12 +404,12 @@ const inputStyle: React.CSSProperties = { const btnPrimaryStyle: React.CSSProperties = { padding: "0.5rem 1rem", - borderRadius: "0.4rem", + borderRadius: "0.375rem", border: "none", backgroundColor: "var(--ctp-mauve)", color: "var(--ctp-crust)", - fontWeight: 600, - fontSize: "0.85rem", + fontWeight: 500, + fontSize: "0.75rem", cursor: "pointer", whiteSpace: "nowrap", }; @@ -418,19 +418,22 @@ const btnCopyStyle: React.CSSProperties = { padding: "0.4rem 0.75rem", background: "var(--ctp-surface1)", border: "none", - borderRadius: "0.4rem", + borderRadius: "0.375rem", color: "var(--ctp-text)", cursor: "pointer", - fontSize: "0.85rem", + fontSize: "0.75rem", + fontWeight: 500, }; const btnDismissStyle: React.CSSProperties = { padding: "0.4rem 0.75rem", background: "none", border: "none", + borderRadius: "0.375rem", color: "var(--ctp-subtext0)", cursor: "pointer", - fontSize: "0.85rem", + fontSize: "0.75rem", + fontWeight: 500, }; const btnDangerStyle: React.CSSProperties = { @@ -438,9 +441,10 @@ const btnDangerStyle: React.CSSProperties = { color: "var(--ctp-red)", border: "none", padding: "0.3rem 0.6rem", - borderRadius: "0.3rem", + borderRadius: "0.375rem", cursor: "pointer", - fontSize: "0.8rem", + fontSize: "0.75rem", + fontWeight: 500, }; const btnRevokeConfirmStyle: React.CSSProperties = { @@ -448,19 +452,20 @@ const btnRevokeConfirmStyle: React.CSSProperties = { color: "var(--ctp-crust)", border: "none", padding: "0.2rem 0.5rem", - borderRadius: "0.25rem", + borderRadius: "0.375rem", cursor: "pointer", fontSize: "0.75rem", - fontWeight: 600, + fontWeight: 500, }; const btnTinyStyle: React.CSSProperties = { padding: "0.2rem 0.5rem", - borderRadius: "0.25rem", + borderRadius: "0.375rem", border: "none", backgroundColor: "var(--ctp-surface1)", color: "var(--ctp-text)", fontSize: "0.75rem", + fontWeight: 500, cursor: "pointer", }; From 289d48846997b92955c0f632b959c94672879454 Mon Sep 17 00:00:00 2001 From: Forbes Date: Fri, 13 Feb 2026 13:22:30 -0600 Subject: [PATCH 06/43] fix(web): table header color overlay1 + selected row mauve tint (#69) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - All thStyle objects: color subtext1/subtext0 → overlay1 - Selected row bg: surface1 → rgba(mauve, 0.08) Files: ItemTable, BOMTab, ProjectsPage, SchemasPage, SettingsPage, AuditTable Closes #69 --- web/src/components/audit/AuditTable.tsx | 4 ++-- web/src/components/items/BOMTab.tsx | 2 +- web/src/components/items/ItemTable.tsx | 4 ++-- web/src/pages/ProjectsPage.tsx | 2 +- web/src/pages/SchemasPage.tsx | 2 +- web/src/pages/SettingsPage.tsx | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/web/src/components/audit/AuditTable.tsx b/web/src/components/audit/AuditTable.tsx index c471d9a..4e2d089 100644 --- a/web/src/components/audit/AuditTable.tsx +++ b/web/src/components/audit/AuditTable.tsx @@ -85,7 +85,7 @@ export function AuditTable({ style={{ cursor: "pointer", backgroundColor: isSelected - ? "var(--ctp-surface1)" + ? "rgba(203, 166, 247, 0.08)" : "transparent", transition: "background-color 0.15s", }} @@ -154,7 +154,7 @@ const thStyle: React.CSSProperties = { padding: "var(--d-th-py) var(--d-th-px)", fontSize: "var(--d-th-font)", borderBottom: "1px solid var(--ctp-surface1)", - color: "var(--ctp-subtext0)", + color: "var(--ctp-overlay1)", fontWeight: 500, position: "sticky", top: 0, diff --git a/web/src/components/items/BOMTab.tsx b/web/src/components/items/BOMTab.tsx index f6a5b73..0d1e64a 100644 --- a/web/src/components/items/BOMTab.tsx +++ b/web/src/components/items/BOMTab.tsx @@ -406,7 +406,7 @@ const thStyle: React.CSSProperties = { padding: "0.3rem 0.5rem", textAlign: "left", borderBottom: "1px solid var(--ctp-surface1)", - color: "var(--ctp-subtext1)", + color: "var(--ctp-overlay1)", fontWeight: 600, fontSize: "0.7rem", textTransform: "uppercase", diff --git a/web/src/components/items/ItemTable.tsx b/web/src/components/items/ItemTable.tsx index 9b3e44a..32b82fd 100644 --- a/web/src/components/items/ItemTable.tsx +++ b/web/src/components/items/ItemTable.tsx @@ -150,7 +150,7 @@ export function ItemTable({ padding: "var(--d-th-py) var(--d-th-px)", textAlign: "left", borderBottom: "1px solid var(--ctp-surface1)", - color: "var(--ctp-subtext1)", + color: "var(--ctp-overlay1)", fontWeight: 600, fontSize: "var(--d-th-font)", textTransform: "uppercase", @@ -203,7 +203,7 @@ export function ItemTable({ {sortedItems.map((item, idx) => { const isSelected = item.part_number === selectedPN; const rowBg = isSelected - ? "var(--ctp-surface1)" + ? "rgba(203, 166, 247, 0.08)" : idx % 2 === 0 ? "var(--ctp-base)" : "var(--ctp-surface0)"; diff --git a/web/src/pages/ProjectsPage.tsx b/web/src/pages/ProjectsPage.tsx index e07069e..baf36a4 100644 --- a/web/src/pages/ProjectsPage.tsx +++ b/web/src/pages/ProjectsPage.tsx @@ -555,7 +555,7 @@ const thStyle: React.CSSProperties = { padding: "0.5rem 0.75rem", textAlign: "left", borderBottom: "1px solid var(--ctp-surface1)", - color: "var(--ctp-subtext1)", + color: "var(--ctp-overlay1)", fontWeight: 600, fontSize: "0.8rem", textTransform: "uppercase", diff --git a/web/src/pages/SchemasPage.tsx b/web/src/pages/SchemasPage.tsx index 07e0b55..abb0eeb 100644 --- a/web/src/pages/SchemasPage.tsx +++ b/web/src/pages/SchemasPage.tsx @@ -691,7 +691,7 @@ const thStyle: React.CSSProperties = { padding: "0.4rem 0.75rem", textAlign: "left", borderBottom: "1px solid var(--ctp-surface1)", - color: "var(--ctp-subtext1)", + color: "var(--ctp-overlay1)", fontWeight: 600, fontSize: "0.8rem", textTransform: "uppercase", diff --git a/web/src/pages/SettingsPage.tsx b/web/src/pages/SettingsPage.tsx index 811e4b6..1b4d99c 100644 --- a/web/src/pages/SettingsPage.tsx +++ b/web/src/pages/SettingsPage.tsx @@ -479,7 +479,7 @@ const thStyle: React.CSSProperties = { padding: "0.5rem 0.75rem", textAlign: "left", borderBottom: "1px solid var(--ctp-surface1)", - color: "var(--ctp-subtext1)", + color: "var(--ctp-overlay1)", fontWeight: 600, fontSize: "0.8rem", textTransform: "uppercase", From a9614e704e5ad237ef9094d2402fc437e60e7278 Mon Sep 17 00:00:00 2001 From: Forbes Date: Fri, 13 Feb 2026 13:23:08 -0600 Subject: [PATCH 07/43] fix(web): standardize transition durations to 0.15s ease (#73) All inline transition properties now use 'all 0.15s ease'. Files: AppShell, CategoryPicker, AuditDetailPanel, AuditSummaryBar, AuditTable, FileDropZone Closes #73 --- web/src/components/AppShell.tsx | 2 +- web/src/components/audit/AuditDetailPanel.tsx | 2 +- web/src/components/audit/AuditSummaryBar.tsx | 10 +++------- web/src/components/audit/AuditTable.tsx | 2 +- web/src/components/items/CategoryPicker.tsx | 4 ++-- web/src/components/items/FileDropZone.tsx | 16 +++++++++------- 6 files changed, 17 insertions(+), 19 deletions(-) diff --git a/web/src/components/AppShell.tsx b/web/src/components/AppShell.tsx index 41b21fd..92d291b 100644 --- a/web/src/components/AppShell.tsx +++ b/web/src/components/AppShell.tsx @@ -73,7 +73,7 @@ export function AppShell() { padding: "var(--d-nav-py) var(--d-nav-px)", borderRadius: "var(--d-nav-radius)", textDecoration: "none", - transition: "all 0.2s", + transition: "all 0.15s ease", })} > {link.label} diff --git a/web/src/components/audit/AuditDetailPanel.tsx b/web/src/components/audit/AuditDetailPanel.tsx index dc83757..ba5819a 100644 --- a/web/src/components/audit/AuditDetailPanel.tsx +++ b/web/src/components/audit/AuditDetailPanel.tsx @@ -252,7 +252,7 @@ export function AuditDetailPanel({ height: "100%", width: `${Math.min(audit.score * 100, 100)}%`, backgroundColor: color, - transition: "width 0.3s, background-color 0.3s", + transition: "all 0.15s ease", borderRadius: "0 3px 3px 0", }} /> diff --git a/web/src/components/audit/AuditSummaryBar.tsx b/web/src/components/audit/AuditSummaryBar.tsx index 93021d6..503037d 100644 --- a/web/src/components/audit/AuditSummaryBar.tsx +++ b/web/src/components/audit/AuditSummaryBar.tsx @@ -54,7 +54,7 @@ export function AuditSummaryBar({ fontSize: "0.7rem", fontWeight: 600, color: "var(--ctp-crust)", - transition: "opacity 0.2s", + transition: "all 0.15s ease", outline: isActive ? "2px solid var(--ctp-text)" : "none", outlineOffset: -2, }} @@ -75,12 +75,8 @@ export function AuditSummaryBar({ color: "var(--ctp-subtext0)", }} > - - {summary.total_items} items - - - Avg score: {(summary.avg_score * 100).toFixed(1)}% - + {summary.total_items} items + Avg score: {(summary.avg_score * 100).toFixed(1)}% {summary.manufactured_without_bom > 0 && ( {summary.manufactured_without_bom} manufactured without BOM diff --git a/web/src/components/audit/AuditTable.tsx b/web/src/components/audit/AuditTable.tsx index 4e2d089..c71e095 100644 --- a/web/src/components/audit/AuditTable.tsx +++ b/web/src/components/audit/AuditTable.tsx @@ -87,7 +87,7 @@ export function AuditTable({ backgroundColor: isSelected ? "rgba(203, 166, 247, 0.08)" : "transparent", - transition: "background-color 0.15s", + transition: "all 0.15s ease", }} onMouseEnter={(e) => { if (!isSelected) diff --git a/web/src/components/items/CategoryPicker.tsx b/web/src/components/items/CategoryPicker.tsx index 48858c7..4b64592 100644 --- a/web/src/components/items/CategoryPicker.tsx +++ b/web/src/components/items/CategoryPicker.tsx @@ -107,7 +107,7 @@ export function CategoryPicker({ color: isActive ? "var(--ctp-mauve)" : "var(--ctp-subtext0)", - transition: "background-color 0.1s", + transition: "all 0.15s ease", }} > @@ -188,7 +188,7 @@ export function CategoryPicker({ : "transparent", color: isSelected ? "var(--ctp-mauve)" : "var(--ctp-text)", fontWeight: isSelected ? 600 : 400, - transition: "background-color 0.1s", + transition: "all 0.15s ease", }} onMouseEnter={(e) => { if (!isSelected) diff --git a/web/src/components/items/FileDropZone.tsx b/web/src/components/items/FileDropZone.tsx index 93455a8..c6585a1 100644 --- a/web/src/components/items/FileDropZone.tsx +++ b/web/src/components/items/FileDropZone.tsx @@ -72,10 +72,8 @@ export function FileDropZone({ padding: "1.25rem", textAlign: "center", cursor: "pointer", - backgroundColor: dragOver - ? "rgba(203,166,247,0.05)" - : "transparent", - transition: "border-color 0.15s, background-color 0.15s", + backgroundColor: dragOver ? "rgba(203,166,247,0.05)" : "transparent", + transition: "all 0.15s ease", }} >
@@ -113,7 +111,11 @@ export function FileDropZone({ {files.length > 0 && (
{files.map((att, i) => ( - onFileRemoved(i)} /> + onFileRemoved(i)} + /> ))}
)} @@ -202,7 +204,7 @@ function FileRow({ width: `${attachment.uploadProgress}%`, backgroundColor: "var(--ctp-mauve)", borderRadius: 1, - transition: "width 0.15s", + transition: "all 0.15s ease", }} />
@@ -235,7 +237,7 @@ function FileRow({ color: hovered ? "var(--ctp-red)" : "var(--ctp-overlay0)", padding: "0 0.2rem", flexShrink: 0, - transition: "color 0.15s", + transition: "all 0.15s ease", }} title="Remove" > From f4a1c8004bf3c2f3f31423fe56d340d72afb3d6d Mon Sep 17 00:00:00 2001 From: Forbes Date: Fri, 13 Feb 2026 13:24:39 -0600 Subject: [PATCH 08/43] feat(web): add input focus states via silo-base.css (#72) Create silo-base.css with .silo-input hover/focus pseudo-classes: - hover: border-color overlay0 - focus: border-color mauve + 0.2rem mauve box-shadow Applied className='silo-input' to form inputs in: CreateItemPane, EditItemPane, ProjectsPage, SchemasPage, SettingsPage, LoginPage Closes #72 --- web/src/components/items/CreateItemPane.tsx | 6 ++++++ web/src/components/items/EditItemPane.tsx | 5 +++++ web/src/pages/LoginPage.tsx | 2 ++ web/src/pages/ProjectsPage.tsx | 3 +++ web/src/pages/SchemasPage.tsx | 3 +++ web/src/pages/SettingsPage.tsx | 1 + web/src/styles/global.css | 1 + web/src/styles/silo-base.css | 14 ++++++++++++++ 8 files changed, 35 insertions(+) create mode 100644 web/src/styles/silo-base.css diff --git a/web/src/components/items/CreateItemPane.tsx b/web/src/components/items/CreateItemPane.tsx index 800a8ac..cac706f 100644 --- a/web/src/components/items/CreateItemPane.tsx +++ b/web/src/components/items/CreateItemPane.tsx @@ -453,6 +453,7 @@ function renderField(