Files
silo/migrations/018_kc_metadata.sql
Forbes 8d777e83bb feat(db): .kc metadata database migration (#140)
Add migration 018_kc_metadata.sql with all tables needed for .kc
server-side metadata indexing:

- item_metadata: indexed manifest + metadata fields from silo/
  directory (tags, lifecycle_state, fields JSONB, manifest info)
- item_dependencies: CAD-extracted assembly dependencies
  (complements existing relationships table)
- item_approvals + approval_signatures: ECO workflow state
- item_macros: registered macros from silo/macros/

Also adds docs/KC_SERVER.md specification document.

Closes #140
2026-02-18 15:04:03 -06:00

111 lines
4.4 KiB
PL/PgSQL

-- Migration 018: .kc Server-Side Metadata Tables
--
-- Adds tables for indexing the silo/ directory contents from .kc files.
-- See docs/KC_SERVER.md for the full specification.
--
-- Tables:
-- item_metadata - indexed manifest + metadata fields (Section 3.1)
-- item_dependencies - CAD-extracted assembly dependencies (Section 3.2)
-- item_approvals - ECO workflow state (Section 3.3)
-- approval_signatures - individual approval/rejection records (Section 3.3)
-- item_macros - registered macros from silo/macros/ (Section 3.4)
BEGIN;
--------------------------------------------------------------------------------
-- item_metadata: indexed silo/manifest.json + silo/metadata.json
--------------------------------------------------------------------------------
CREATE TABLE item_metadata (
item_id UUID PRIMARY KEY REFERENCES items(id) ON DELETE CASCADE,
schema_name TEXT,
tags TEXT[] NOT NULL DEFAULT '{}',
lifecycle_state TEXT NOT NULL DEFAULT 'draft',
fields JSONB NOT NULL DEFAULT '{}',
kc_version TEXT,
manifest_uuid UUID,
silo_instance TEXT,
revision_hash TEXT,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_by TEXT
);
CREATE INDEX idx_item_metadata_tags ON item_metadata USING GIN (tags);
CREATE INDEX idx_item_metadata_lifecycle ON item_metadata (lifecycle_state);
CREATE INDEX idx_item_metadata_fields ON item_metadata USING GIN (fields);
--------------------------------------------------------------------------------
-- item_dependencies: indexed silo/dependencies.json
--
-- Complements the existing `relationships` table.
-- relationships = server-authoritative BOM (web UI / API editable)
-- item_dependencies = CAD-authoritative record (extracted from .kc)
-- BOM merge reconciles the two (see docs/BOM_MERGE.md).
--------------------------------------------------------------------------------
CREATE TABLE item_dependencies (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
parent_item_id UUID NOT NULL REFERENCES items(id) ON DELETE CASCADE,
child_uuid UUID NOT NULL,
child_part_number TEXT,
child_revision INTEGER,
quantity DECIMAL,
label TEXT,
relationship TEXT NOT NULL DEFAULT 'component',
revision_number INTEGER NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_item_deps_parent ON item_dependencies (parent_item_id);
CREATE INDEX idx_item_deps_child ON item_dependencies (child_uuid);
--------------------------------------------------------------------------------
-- item_approvals + approval_signatures: ECO workflow
--
-- Server-authoritative. The .kc silo/approvals.json is a read cache
-- packed on checkout for offline display in Create.
--------------------------------------------------------------------------------
CREATE TABLE item_approvals (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
item_id UUID NOT NULL REFERENCES items(id) ON DELETE CASCADE,
eco_number TEXT,
state TEXT NOT NULL DEFAULT 'draft',
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_by TEXT
);
CREATE INDEX idx_item_approvals_item ON item_approvals (item_id);
CREATE INDEX idx_item_approvals_state ON item_approvals (state);
CREATE TABLE approval_signatures (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
approval_id UUID NOT NULL REFERENCES item_approvals(id) ON DELETE CASCADE,
username TEXT NOT NULL,
role TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'pending',
signed_at TIMESTAMPTZ,
comment TEXT
);
CREATE INDEX idx_approval_sigs_approval ON approval_signatures (approval_id);
--------------------------------------------------------------------------------
-- item_macros: registered macros from silo/macros/
--------------------------------------------------------------------------------
CREATE TABLE item_macros (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
item_id UUID NOT NULL REFERENCES items(id) ON DELETE CASCADE,
filename TEXT NOT NULL,
trigger TEXT NOT NULL DEFAULT 'manual',
content TEXT NOT NULL,
revision_number INTEGER NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
UNIQUE(item_id, filename)
);
CREATE INDEX idx_item_macros_item ON item_macros (item_id);
COMMIT;