Add storage_backend columns to track which backend (minio or filesystem)
holds each file, enabling dual-running during migration.
Migration 017_file_storage_metadata.sql:
- item_files.storage_backend TEXT NOT NULL DEFAULT 'minio'
- revisions.file_storage_backend TEXT NOT NULL DEFAULT 'minio'
DB repository changes:
- Revision struct: add FileStorageBackend field
- ItemFile struct: add StorageBackend field
- All INSERT queries include the new columns
- All SELECT queries read them (COALESCE for pre-migration compat)
- CreateRevisionFromExisting copies the backend from source revision
- Default to 'minio' when field is empty (backward compat)
Existing rows default to 'minio'. New uploads will write 'filesystem'
when the filesystem backend is active.
Closes#128
Add useSSE hook that connects to /api/events with automatic reconnect
and exponential backoff. On settings.changed events:
- Refresh module state so sidebar nav items show/hide immediately
- Show dismissable toast when another admin updates settings
The backend already publishes settings.changed in HandleUpdateModuleSettings.
Closes#101
Relocate Edit and Delete buttons from the header row into the tab bar,
grouping them with tab navigation to reduce mouse travel. Adds Pencil
and Trash2 icons for quick visual recognition.
Header now only shows part number, type badge, and close button.
Closes#119
- Add kindred-logo.svg as site favicon (#115)
- Narrow settings page to 66% max-width, centered (#116)
- Add max-height and scroll to API token table (#118)
Closes#115, closes#116, closes#118
- Replace top header with left sidebar navigation
- Sidebar shows module-aware nav items filtered by /api/modules
- Collapsible: expanded shows icon+label, collapsed shows icon only
- Toggle with Ctrl+J or collapse button, state persisted in localStorage
- Keyboard navigable: Arrow Up/Down, Enter to navigate, Escape to collapse
- Bottom section: density toggle, user info with role badge, logout
- Add useModules hook for fetching module state
- Add sidebar density variables to theme.css
Closes#113, closes#114
Add LocationRepository with CRUD operations, hierarchy traversal
(children, subtree by path prefix), and inventory-safe deletion.
Endpoints:
GET /api/locations — list all or ?tree={path} for subtree
POST /api/locations — create (auto-resolves parent_id, depth)
GET /api/locations/{path..} — get by hierarchical path
PUT /api/locations/{path..} — update name, type, metadata
DELETE /api/locations/{path..} — delete (rejects if inventory exists)
Uses chi wildcard routes to support multi-segment paths like
/api/locations/lab/shelf-a/bin-3.
Includes 10 handler integration tests covering CRUD, nesting,
validation, duplicates, tree queries, and delete-not-found.
Closes#81
Add admin-only Module Configuration section to the Settings page.
Each module gets a collapsible card with enable/disable toggle,
status badge, module-specific config fields, save and test
connectivity buttons.
- AdminModules: fetches GET /api/modules + GET /api/admin/settings,
renders Infrastructure and Features groups, restart banner
- ModuleCard: collapsible card with toggle, status badge, field
layouts per module, save (PUT) and test (POST) actions
- TypeScript types for ModuleInfo, ModulesResponse, admin settings
API response shapes
Ref: #100
Add four admin-only endpoints under /api/admin/settings:
- GET / — full config (secrets redacted)
- GET /{module} — single module config
- PUT /{module} — toggle modules + persist config overrides
- POST /{module}/test — test external connectivity (database, storage)
PUT publishes a settings.changed SSE event. Config overrides are
persisted for future hot-reload support; changes to database/storage/
server/schemas namespaces return restart_required: true.
Wires SettingsRepository into Server struct.
Closes#99
Add HandleGetModules returning module state, metadata, and
public config (auth providers, Create URI scheme). No auth
required — clients call this pre-login.
Register at /api/modules before the auth middleware.
Ref #97
Add modules.Registry and config.Config fields to Server struct.
Create registry in main.go, load state from YAML+DB, log all
module states at startup.
Conditionally start job/runner sweeper goroutines only when the
jobs module is enabled.
Update all 5 test files to pass registry to NewServer.
Ref #95, #96
Add migration 016 with two tables for the module system:
- settings_overrides: dotted-path config overrides set via admin UI
- module_state: per-module enabled/disabled state
Update testutil.TruncateAll to include new tables.
Ref #94
Migration 014: dag_nodes, dag_edges, dag_cross_edges tables for the
feature-level dependency graph with validation state tracking.
Migration 015: runners, job_definitions, jobs, job_log tables for the
async compute job system with PostgreSQL-backed work queue.
Update TruncateAll in testutil to include new tables.
- Test ListItemFiles, DeleteItemFile with real DB
- Test cross-item file deletion guard (404)
- Test storage-unavailable paths: presign, upload, associate, thumbnail (503)
- Fix createItemDirect: StandardCost moved to revision properties