feat: production release with React SPA, file attachments, and deploy tooling

Backend:
- Add file_handlers.go: presigned upload/download for item attachments
- Add item_files.go: item file and thumbnail DB operations
- Add migration 011: item_files table and thumbnail_key column
- Update items/projects/relationships DB with extended field support
- Update routes: React SPA serving from web/dist, file upload endpoints
- Update auth handlers and middleware for cookie + bearer token auth
- Remove Go HTML templates (replaced by React SPA)
- Update storage client for presigned URL generation

Frontend:
- Add TagInput component for tag/keyword entry
- Add SVG assets for Silo branding and UI icons
- Update API client and types for file uploads, auth, extended fields
- Update AuthContext for session-based auth flow
- Update LoginPage, ProjectsPage, SchemasPage, SettingsPage
- Fix tsconfig.node.json

Deployment:
- Update config.prod.yaml: single-binary SPA layout at /opt/silo
- Update silod.service: ReadOnlyPaths for /opt/silo
- Add scripts/deploy.sh: build, package, ship, migrate, start
- Update docker-compose.yaml and Dockerfile
- Add frontend-spec.md design document
This commit is contained in:
Forbes
2026-02-07 13:35:22 -06:00
parent d61f939d84
commit 50923cf56d
49 changed files with 4674 additions and 7915 deletions

View File

@@ -1,13 +1,22 @@
# Silo Production Configuration
# For deployment on dedicated VM using external PostgreSQL and MinIO
# Single-binary deployment: silod serves API + React SPA
#
# Credentials are provided via environment variables:
# Layout on silo.kindred.internal:
# /opt/silo/bin/silod - server binary
# /opt/silo/web/dist/ - built React frontend (served automatically)
# /opt/silo/schemas/ - part number schemas
# /etc/silo/config.yaml - this file
# /etc/silo/silod.env - secrets (env vars)
#
# Credentials via environment variables (set in /etc/silo/silod.env):
# SILO_DB_PASSWORD
# SILO_MINIO_ACCESS_KEY
# SILO_MINIO_SECRET_KEY
# SILO_SESSION_SECRET
# SILO_ADMIN_PASSWORD
server:
host: "127.0.0.1" # Listen only on localhost (nginx handles external traffic)
host: "0.0.0.0"
port: 8080
base_url: "https://silo.kindred.internal"
@@ -29,24 +38,19 @@ storage:
region: "us-east-1"
schemas:
directory: "/etc/silo/schemas"
directory: "/opt/silo/schemas"
default: "kindred-rd"
freecad:
uri_scheme: "silo"
executable: "/usr/bin/freecad"
# Authentication
# Set via SILO_SESSION_SECRET, SILO_OIDC_CLIENT_SECRET, SILO_LDAP_BIND_PASSWORD env vars
auth:
enabled: true
session_secret: "" # Set via SILO_SESSION_SECRET
local:
enabled: true
default_admin_username: "admin"
default_admin_password: "" # Set via SILO_ADMIN_PASSWORD
ldap:
enabled: true
url: "ldaps://ipa.kindred.internal"
@@ -65,18 +69,8 @@ auth:
viewer:
- "cn=silo-viewers,cn=groups,cn=accounts,dc=kindred,dc=internal"
tls_skip_verify: false
oidc:
enabled: false
issuer_url: "https://keycloak.kindred.internal/realms/silo"
client_id: "silo"
client_secret: "" # Set via SILO_OIDC_CLIENT_SECRET
redirect_url: "https://silo.kindred.internal/auth/callback"
scopes: ["openid", "profile", "email"]
admin_role: "silo-admin"
editor_role: "silo-editor"
default_role: "viewer"
cors:
allowed_origins:
- "https://silo.kindred.internal"