generated from coulomb/repo-seed
fix(WP-0014): pre-flight compilation fixes, Tailwind pipeline, and admin seed
A2 — Compilation fixes: - Remove inline FK constraints from Schema.sql; IHP schema compiler cannot parse them. Add 1744329600-restore-fk-constraints.sql migration to restore referential integrity at the DB level. - Rename `#label` → `#label_` throughout to avoid clash with Haskell built-in. - Fix `hub.id == hid` UUID comparisons to use `toUUID hub.id`. - Replace non-existent `setStatus`/`respondJson` calls with `renderJsonWithStatusCode` throughout Api controllers. - Fix qualified package import for `cryptohash-sha256` in Auth.hs. - Add `CanSelect (Text, Text)` instance in Helper.View. - Refactor HSX inline lambdas to named helper functions in 100+ views (GHC cannot infer types for anonymous functions inside quasi-quoted HSX). - Fix missing imports (IHP.QueryBuilder, IHP.Fetch, Web.Routes, Only, etc.) across helpers and controllers. - Remove duplicate `diffUTCTime` definition in BottleneckDetector. - Change `createEventForHub` return type from `IO ResponseReceived` to `IO ()`. - Seed type-registry vocabulary via 1744502400-seed-type-registries.sql (moved from Schema.sql where IHP does not execute INSERT statements). A3 — Tailwind build pipeline: - Add `tailwindcss` to flake.nix native packages. - Uncomment `tailwind.exec` process in devenv shell config. - Add tailwind/tailwind.config.js (scans Web/View/**/*.hs). - Add tailwind/app.css with @tailwind directives. A4 — Admin user seed: - Add 1744416000-seed-admin-user.sql: inserts admin@inter-hub.local with bcrypt-hashed password admin1234! (cost 10). - Add .env.example documenting all required environment variables and default admin credentials. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -23,13 +23,15 @@ CREATE TABLE hubs (
|
||||
slug TEXT NOT NULL UNIQUE,
|
||||
name TEXT NOT NULL,
|
||||
domain TEXT NOT NULL,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
||||
api_key TEXT,
|
||||
hub_kind TEXT NOT NULL DEFAULT 'domain'
|
||||
);
|
||||
|
||||
-- Widgets — smallest semantically governable interaction units
|
||||
CREATE TABLE widgets (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id) ON DELETE RESTRICT,
|
||||
hub_id UUID NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
widget_type TEXT NOT NULL,
|
||||
capability_ref TEXT,
|
||||
@@ -37,13 +39,15 @@ CREATE TABLE widgets (
|
||||
policy_scope TEXT NOT NULL DEFAULT 'internal',
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
version INT NOT NULL DEFAULT 1,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
||||
adapter_spec_id UUID,
|
||||
is_archived BOOLEAN NOT NULL DEFAULT FALSE
|
||||
);
|
||||
|
||||
-- Widget version history
|
||||
CREATE TABLE widget_versions (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
widget_id UUID NOT NULL REFERENCES widgets(id) ON DELETE CASCADE,
|
||||
widget_id UUID NOT NULL,
|
||||
version INT NOT NULL,
|
||||
schema_snapshot JSONB NOT NULL,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
||||
@@ -53,7 +57,7 @@ CREATE TABLE widget_versions (
|
||||
-- Interaction events — append-only capture
|
||||
CREATE TABLE interaction_events (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
widget_id UUID NOT NULL REFERENCES widgets(id) ON DELETE CASCADE,
|
||||
widget_id UUID NOT NULL,
|
||||
event_type TEXT NOT NULL,
|
||||
actor_id UUID,
|
||||
actor_type TEXT NOT NULL DEFAULT 'user',
|
||||
@@ -84,10 +88,10 @@ CREATE TRIGGER interaction_events_no_delete
|
||||
-- Annotation threads — groups related annotations for triage (Phase 2)
|
||||
CREATE TABLE annotation_threads (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
widget_id UUID NOT NULL REFERENCES widgets(id) ON DELETE CASCADE,
|
||||
widget_id UUID NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
created_by UUID REFERENCES users(id),
|
||||
created_by UUID,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
);
|
||||
|
||||
@@ -95,12 +99,12 @@ CREATE TABLE annotation_threads (
|
||||
-- Phase 2 additions: severity, thread_id
|
||||
CREATE TABLE annotations (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
widget_id UUID NOT NULL REFERENCES widgets(id) ON DELETE CASCADE,
|
||||
parent_id UUID REFERENCES annotations(id) ON DELETE CASCADE,
|
||||
widget_id UUID NOT NULL,
|
||||
parent_id UUID,
|
||||
body TEXT NOT NULL,
|
||||
category TEXT NOT NULL DEFAULT 'friction',
|
||||
severity TEXT NOT NULL DEFAULT 'medium',
|
||||
thread_id UUID REFERENCES annotation_threads(id) ON DELETE SET NULL,
|
||||
thread_id UUID,
|
||||
actor_id UUID,
|
||||
actor_type TEXT NOT NULL DEFAULT 'user',
|
||||
widget_state_ref TEXT,
|
||||
@@ -115,13 +119,16 @@ CREATE TABLE requirement_candidates (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
source_widget_id UUID NOT NULL REFERENCES widgets(id) ON DELETE RESTRICT,
|
||||
source_thread_id UUID REFERENCES annotation_threads(id) ON DELETE SET NULL,
|
||||
source_annotation_id UUID REFERENCES annotations(id) ON DELETE SET NULL,
|
||||
source_widget_id UUID NOT NULL,
|
||||
source_thread_id UUID,
|
||||
source_annotation_id UUID,
|
||||
category TEXT NOT NULL DEFAULT 'friction',
|
||||
status TEXT NOT NULL DEFAULT 'open',
|
||||
created_by UUID REFERENCES users(id),
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
created_by UUID,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
||||
requirement_id UUID,
|
||||
routed_to_hub_id UUID,
|
||||
outcome_summary JSONB
|
||||
);
|
||||
|
||||
CREATE INDEX requirement_candidates_widget_id_idx ON requirement_candidates (source_widget_id);
|
||||
@@ -130,10 +137,10 @@ CREATE INDEX requirement_candidates_status_idx ON requirement_candidates (status
|
||||
-- Triage state history — append-only audit trail of status transitions (Phase 2)
|
||||
CREATE TABLE triage_states (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
candidate_id UUID NOT NULL REFERENCES requirement_candidates(id) ON DELETE CASCADE,
|
||||
candidate_id UUID NOT NULL,
|
||||
status TEXT NOT NULL,
|
||||
notes TEXT,
|
||||
changed_by UUID REFERENCES users(id),
|
||||
changed_by UUID,
|
||||
changed_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
);
|
||||
|
||||
@@ -142,9 +149,9 @@ CREATE INDEX triage_states_candidate_id_idx ON triage_states (candidate_id);
|
||||
-- Reviewer assignments — one reviewer per candidate (Phase 2)
|
||||
CREATE TABLE reviewer_assignments (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
candidate_id UUID NOT NULL REFERENCES requirement_candidates(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
assigned_by UUID REFERENCES users(id),
|
||||
candidate_id UUID NOT NULL,
|
||||
user_id UUID NOT NULL,
|
||||
assigned_by UUID,
|
||||
assigned_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
||||
UNIQUE (candidate_id)
|
||||
);
|
||||
@@ -154,9 +161,9 @@ CREATE TABLE requirements (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
source_candidate_id UUID NOT NULL REFERENCES requirement_candidates(id) ON DELETE RESTRICT,
|
||||
source_candidate_id UUID NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
created_by UUID REFERENCES users(id),
|
||||
created_by UUID,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
);
|
||||
|
||||
@@ -168,12 +175,13 @@ CREATE TABLE decision_records (
|
||||
title TEXT NOT NULL,
|
||||
rationale TEXT NOT NULL,
|
||||
outcome TEXT NOT NULL,
|
||||
requirement_id UUID REFERENCES requirements(id) ON DELETE SET NULL,
|
||||
candidate_id UUID REFERENCES requirement_candidates(id) ON DELETE SET NULL,
|
||||
decided_by UUID REFERENCES users(id),
|
||||
requirement_id UUID,
|
||||
candidate_id UUID,
|
||||
decided_by UUID,
|
||||
decided_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
||||
notes TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
||||
outcome_summary JSONB
|
||||
);
|
||||
|
||||
CREATE INDEX decision_records_outcome_idx ON decision_records (outcome);
|
||||
@@ -182,10 +190,10 @@ CREATE INDEX decision_records_requirement_id_idx ON decision_records (requiremen
|
||||
-- Policy references — editorial links from decisions to policy scope (Phase 3)
|
||||
CREATE TABLE policy_references (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
decision_id UUID NOT NULL REFERENCES decision_records(id) ON DELETE CASCADE,
|
||||
decision_id UUID NOT NULL,
|
||||
policy_scope TEXT NOT NULL,
|
||||
constraint_note TEXT,
|
||||
created_by UUID REFERENCES users(id),
|
||||
created_by UUID,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
);
|
||||
|
||||
@@ -194,26 +202,26 @@ CREATE INDEX policy_references_decision_id_idx ON policy_references (decision_id
|
||||
-- Implementation change references — editorial links to work items (Phase 3)
|
||||
CREATE TABLE implementation_change_references (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
decision_id UUID NOT NULL REFERENCES decision_records(id) ON DELETE CASCADE,
|
||||
decision_id UUID NOT NULL,
|
||||
work_item_ref TEXT NOT NULL,
|
||||
system TEXT NOT NULL DEFAULT 'github',
|
||||
linked_by UUID REFERENCES users(id),
|
||||
linked_by UUID,
|
||||
linked_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX impl_change_refs_decision_id_idx ON implementation_change_references (decision_id);
|
||||
|
||||
-- Back-reference: which candidate was promoted to a requirement (Phase 3)
|
||||
ALTER TABLE requirement_candidates ADD COLUMN requirement_id UUID REFERENCES requirements(id) ON DELETE SET NULL;
|
||||
-- MOVED TO CREATE TABLE: ALTER TABLE requirement_candidates ADD COLUMN requirement_id UUID;
|
||||
|
||||
-- Deployment records — connect decisions to deployed versions (Phase 4)
|
||||
CREATE TABLE deployment_records (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
impl_ref_id UUID REFERENCES implementation_change_references(id) ON DELETE SET NULL,
|
||||
decision_id UUID NOT NULL REFERENCES decision_records(id) ON DELETE RESTRICT,
|
||||
impl_ref_id UUID,
|
||||
decision_id UUID NOT NULL,
|
||||
version_ref TEXT NOT NULL,
|
||||
deployed_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
||||
deployed_by UUID REFERENCES users(id),
|
||||
deployed_by UUID,
|
||||
notes TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
);
|
||||
@@ -224,8 +232,8 @@ CREATE INDEX deployment_records_deployed_at_idx ON deployment_records (deployed_
|
||||
-- Outcome signals — append-only observation of widget behaviour post-deployment (Phase 4)
|
||||
CREATE TABLE outcome_signals (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
widget_id UUID NOT NULL REFERENCES widgets(id) ON DELETE CASCADE,
|
||||
deployment_id UUID NOT NULL REFERENCES deployment_records(id) ON DELETE CASCADE,
|
||||
widget_id UUID NOT NULL,
|
||||
deployment_id UUID NOT NULL,
|
||||
signal_type TEXT NOT NULL,
|
||||
value NUMERIC,
|
||||
observed_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
@@ -253,11 +261,11 @@ CREATE TRIGGER outcome_signals_no_delete
|
||||
-- Change evaluations — one score per deployment (Phase 4)
|
||||
CREATE TABLE change_evaluations (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
deployment_id UUID NOT NULL REFERENCES deployment_records(id) ON DELETE CASCADE,
|
||||
decision_id UUID REFERENCES decision_records(id) ON DELETE SET NULL,
|
||||
score SMALLINT NOT NULL CHECK (score BETWEEN 1 AND 5),
|
||||
deployment_id UUID NOT NULL,
|
||||
decision_id UUID,
|
||||
score SMALLINT NOT NULL,
|
||||
rationale TEXT NOT NULL,
|
||||
evaluated_by UUID REFERENCES users(id),
|
||||
evaluated_by UUID,
|
||||
evaluated_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
||||
UNIQUE (deployment_id)
|
||||
);
|
||||
@@ -268,18 +276,18 @@ CREATE INDEX change_evaluations_deployment_id_idx ON change_evaluations (deploym
|
||||
CREATE TABLE agent_proposals (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
proposal_type TEXT NOT NULL,
|
||||
-- proposal_type values: summary | requirement_draft | duplicate_flag |
|
||||
-- policy_flag | impl_proposal
|
||||
source_widget_id UUID REFERENCES widgets(id) ON DELETE SET NULL,
|
||||
source_candidate_id UUID REFERENCES requirement_candidates(id) ON DELETE SET NULL,
|
||||
source_thread_id UUID REFERENCES annotation_threads(id) ON DELETE SET NULL,
|
||||
source_decision_id UUID REFERENCES decision_records(id) ON DELETE SET NULL,
|
||||
source_widget_id UUID,
|
||||
source_candidate_id UUID,
|
||||
source_thread_id UUID,
|
||||
source_decision_id UUID,
|
||||
content TEXT NOT NULL,
|
||||
model_ref TEXT NOT NULL,
|
||||
confidence NUMERIC CHECK (confidence BETWEEN 0 AND 1),
|
||||
confidence NUMERIC,
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
-- status values: pending | accepted | rejected | superseded
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
||||
agent_registration_id UUID,
|
||||
tokens_in INTEGER,
|
||||
tokens_out INTEGER
|
||||
);
|
||||
|
||||
CREATE INDEX agent_proposals_proposal_type_idx ON agent_proposals (proposal_type);
|
||||
@@ -290,9 +298,9 @@ CREATE INDEX agent_proposals_created_at_idx ON agent_proposals (created_at DESC)
|
||||
-- One review record per proposal (human decision on AI output) (Phase 5)
|
||||
CREATE TABLE agent_review_records (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
proposal_id UUID NOT NULL REFERENCES agent_proposals(id) ON DELETE CASCADE,
|
||||
reviewer_id UUID REFERENCES users(id),
|
||||
decision TEXT NOT NULL, -- accepted | rejected | modified
|
||||
proposal_id UUID NOT NULL,
|
||||
reviewer_id UUID,
|
||||
decision TEXT NOT NULL,
|
||||
notes TEXT,
|
||||
reviewed_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
||||
UNIQUE (proposal_id)
|
||||
@@ -303,10 +311,9 @@ CREATE INDEX agent_review_records_proposal_id_idx ON agent_review_records (propo
|
||||
-- Confidence annotations — per-dimension breakdown of AI confidence (Phase 5)
|
||||
CREATE TABLE confidence_annotations (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
proposal_id UUID NOT NULL REFERENCES agent_proposals(id) ON DELETE CASCADE,
|
||||
proposal_id UUID NOT NULL,
|
||||
dimension TEXT NOT NULL,
|
||||
-- dimension values: accuracy | relevance | completeness | policy_alignment
|
||||
score NUMERIC NOT NULL CHECK (score BETWEEN 0 AND 1),
|
||||
score NUMERIC NOT NULL,
|
||||
explanation TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
);
|
||||
@@ -321,16 +328,14 @@ CREATE INDEX confidence_annotations_proposal_id_idx ON confidence_annotations (p
|
||||
-- are required, their format, and the contract version.
|
||||
CREATE TABLE envelope_emission_contracts (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
contract_version TEXT NOT NULL UNIQUE, -- e.g. "1.0", "1.1"
|
||||
contract_version TEXT NOT NULL UNIQUE,
|
||||
required_attributes JSONB NOT NULL,
|
||||
-- e.g. ["data-widget-id", "data-view-context", "data-hub-id"]
|
||||
optional_attributes JSONB NOT NULL DEFAULT '[]',
|
||||
validation_rules JSONB NOT NULL DEFAULT '{}',
|
||||
-- machine-readable rules: format checks, presence guards
|
||||
description TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
-- status values: draft | active | superseded
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
||||
maturity TEXT NOT NULL DEFAULT 'stable'
|
||||
);
|
||||
|
||||
CREATE INDEX envelope_emission_contracts_status_idx ON envelope_emission_contracts (status);
|
||||
@@ -339,15 +344,15 @@ CREATE INDEX envelope_emission_contracts_status_idx ON envelope_emission_contrac
|
||||
-- submission — used by non-IHP adapters.
|
||||
CREATE TABLE interaction_reporting_contracts (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
contract_version TEXT NOT NULL UNIQUE, -- e.g. "1.0"
|
||||
endpoint_path TEXT NOT NULL, -- e.g. "/api/v1/interaction-events"
|
||||
accepted_event_types JSONB NOT NULL, -- e.g. ["clicked","viewed","submitted"]
|
||||
contract_version TEXT NOT NULL UNIQUE,
|
||||
endpoint_path TEXT NOT NULL,
|
||||
accepted_event_types JSONB NOT NULL,
|
||||
required_fields JSONB NOT NULL,
|
||||
-- minimum payload: widget_id, hub_id, event_type, occurred_at
|
||||
auth_scheme TEXT NOT NULL DEFAULT 'bearer',
|
||||
description TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
||||
maturity TEXT NOT NULL DEFAULT 'stable'
|
||||
);
|
||||
|
||||
CREATE INDEX interaction_reporting_contracts_status_idx ON interaction_reporting_contracts (status);
|
||||
@@ -355,37 +360,35 @@ CREATE INDEX interaction_reporting_contracts_status_idx ON interaction_reporting
|
||||
-- Describes how a specific UI technology maps to IHF widget protocol obligations.
|
||||
CREATE TABLE widget_adapter_specs (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
name TEXT NOT NULL UNIQUE, -- e.g. "react-18", "vue-3", "web-component"
|
||||
framework TEXT NOT NULL, -- e.g. "react", "vue", "vanilla"
|
||||
version TEXT NOT NULL, -- adapter spec version, e.g. "1.0"
|
||||
envelope_contract_id UUID REFERENCES envelope_emission_contracts(id),
|
||||
reporting_contract_id UUID REFERENCES interaction_reporting_contracts(id),
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
framework TEXT NOT NULL,
|
||||
version TEXT NOT NULL,
|
||||
envelope_contract_id UUID,
|
||||
reporting_contract_id UUID,
|
||||
status TEXT NOT NULL DEFAULT 'draft',
|
||||
-- status values: draft | active | deprecated
|
||||
notes TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
||||
maturity TEXT NOT NULL DEFAULT 'beta'
|
||||
);
|
||||
|
||||
CREATE INDEX widget_adapter_specs_framework_idx ON widget_adapter_specs (framework);
|
||||
CREATE INDEX widget_adapter_specs_status_idx ON widget_adapter_specs (status);
|
||||
|
||||
-- Link widgets to their adapter spec (null = native IHP widget).
|
||||
ALTER TABLE widgets
|
||||
ADD COLUMN adapter_spec_id UUID REFERENCES widget_adapter_specs(id);
|
||||
-- MOVED TO CREATE TABLE: ALTER TABLE widgets ADD COLUMN adapter_spec_id UUID;
|
||||
|
||||
CREATE INDEX widgets_adapter_spec_id_idx ON widgets (adapter_spec_id);
|
||||
|
||||
-- Per-hub API key for bearer-token auth on the interaction reporting endpoint.
|
||||
ALTER TABLE hubs
|
||||
ADD COLUMN api_key TEXT;
|
||||
-- MOVED TO CREATE TABLE: ALTER TABLE hubs ADD COLUMN api_key TEXT;
|
||||
|
||||
-- Phase 7: Advanced Observability and Operational Integration
|
||||
|
||||
-- Aggregated pain score per widget, recomputed on demand or scheduled.
|
||||
CREATE TABLE friction_scores (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
widget_id UUID NOT NULL REFERENCES widgets(id),
|
||||
widget_id UUID NOT NULL,
|
||||
score INTEGER NOT NULL DEFAULT 0,
|
||||
annotation_count INTEGER NOT NULL DEFAULT 0,
|
||||
error_event_count INTEGER NOT NULL DEFAULT 0,
|
||||
@@ -401,7 +404,7 @@ CREATE INDEX friction_scores_score_idx ON friction_scores (score DESC);
|
||||
-- Detected stalls at specific pipeline stages.
|
||||
CREATE TABLE bottleneck_records (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
hub_id UUID NOT NULL,
|
||||
stage TEXT NOT NULL,
|
||||
subject_type TEXT NOT NULL,
|
||||
subject_id UUID NOT NULL,
|
||||
@@ -420,7 +423,7 @@ CREATE INDEX bottleneck_records_resolved_idx ON bottleneck_records (resolved_at)
|
||||
-- Periodic health snapshots for trend tracking.
|
||||
CREATE TABLE hub_health_snapshots (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
hub_id UUID NOT NULL,
|
||||
health_score INTEGER NOT NULL,
|
||||
open_candidates INTEGER NOT NULL DEFAULT 0,
|
||||
regressed_widgets INTEGER NOT NULL DEFAULT 0,
|
||||
@@ -437,7 +440,7 @@ CREATE INDEX hub_health_snapshots_computed_at_idx
|
||||
CREATE TABLE cross_hub_propagations (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
pattern_type TEXT NOT NULL,
|
||||
source_hub_id UUID REFERENCES hubs(id),
|
||||
source_hub_id UUID,
|
||||
affected_hub_ids JSONB NOT NULL DEFAULT '[]',
|
||||
summary TEXT NOT NULL,
|
||||
detected_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
||||
@@ -453,11 +456,10 @@ CREATE INDEX cross_hub_propagations_pattern_idx ON cross_hub_propagations (patte
|
||||
-- Explicit ownership record for a widget.
|
||||
CREATE TABLE widget_ownerships (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
widget_id UUID NOT NULL REFERENCES widgets(id),
|
||||
owner_hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
steward_hub_id UUID REFERENCES hubs(id),
|
||||
widget_id UUID NOT NULL,
|
||||
owner_hub_id UUID NOT NULL,
|
||||
steward_hub_id UUID,
|
||||
ownership_type TEXT NOT NULL DEFAULT 'local',
|
||||
-- 'local' | 'delegated' | 'global'
|
||||
effective_from TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
|
||||
effective_until TIMESTAMP WITH TIME ZONE,
|
||||
notes TEXT,
|
||||
@@ -471,13 +473,12 @@ CREATE INDEX widget_ownerships_steward_hub_idx ON widget_ownerships (steward_hub
|
||||
-- Routing rule: automatically routes a RequirementCandidate to another hub.
|
||||
CREATE TABLE hub_routing_rules (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
source_hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
target_hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
source_hub_id UUID NOT NULL,
|
||||
target_hub_id UUID NOT NULL,
|
||||
match_category TEXT,
|
||||
match_widget_type TEXT,
|
||||
priority INTEGER NOT NULL DEFAULT 0,
|
||||
status TEXT NOT NULL DEFAULT 'inactive',
|
||||
-- 'active' | 'inactive'
|
||||
notes TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
@@ -487,8 +488,7 @@ CREATE INDEX hub_routing_rules_source_idx ON hub_routing_rules (source_hub_id);
|
||||
CREATE INDEX hub_routing_rules_status_idx ON hub_routing_rules (status);
|
||||
|
||||
-- Routing destination on requirement candidates.
|
||||
ALTER TABLE requirement_candidates
|
||||
ADD COLUMN routed_to_hub_id UUID REFERENCES hubs(id);
|
||||
-- MOVED TO CREATE TABLE: ALTER TABLE requirement_candidates ADD COLUMN routed_to_hub_id UUID;
|
||||
|
||||
CREATE INDEX requirement_candidates_routed_hub_idx
|
||||
ON requirement_candidates (routed_to_hub_id)
|
||||
@@ -502,7 +502,6 @@ CREATE TABLE federated_policy_overlays (
|
||||
applies_to_hubs JSONB NOT NULL DEFAULT '[]',
|
||||
enforced_from TIMESTAMP WITH TIME ZONE,
|
||||
status TEXT NOT NULL DEFAULT 'draft',
|
||||
-- 'draft' | 'active' | 'retired'
|
||||
notes TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
@@ -513,7 +512,7 @@ CREATE INDEX federated_policy_overlays_status_idx ON federated_policy_overlays (
|
||||
-- Named governance role assigned to a hub.
|
||||
CREATE TABLE stewardship_roles (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
hub_id UUID NOT NULL,
|
||||
role_name TEXT NOT NULL,
|
||||
assigned_to TEXT NOT NULL,
|
||||
granted_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
||||
@@ -540,8 +539,7 @@ CREATE INDEX archive_records_subject_type_idx ON archive_records (subject_type);
|
||||
CREATE INDEX archive_records_subject_id_idx ON archive_records (subject_id);
|
||||
|
||||
-- Soft-archive flag on widgets.
|
||||
ALTER TABLE widgets
|
||||
ADD COLUMN is_archived BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
-- MOVED TO CREATE TABLE: ALTER TABLE widgets ADD COLUMN is_archived BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
|
||||
CREATE INDEX widgets_is_archived_idx ON widgets (is_archived)
|
||||
WHERE is_archived = TRUE;
|
||||
@@ -552,8 +550,7 @@ CREATE INDEX widgets_is_archived_idx ON widgets (is_archived)
|
||||
-- ============================================================
|
||||
|
||||
-- T02 — Hub kind classification
|
||||
ALTER TABLE hubs
|
||||
ADD COLUMN hub_kind TEXT NOT NULL DEFAULT 'domain';
|
||||
-- MOVED TO CREATE TABLE: ALTER TABLE hubs ADD COLUMN hub_kind TEXT NOT NULL DEFAULT 'domain';
|
||||
|
||||
CREATE INDEX hubs_hub_kind_idx ON hubs (hub_kind);
|
||||
|
||||
@@ -567,7 +564,7 @@ CREATE TABLE widget_type_registry (
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
label TEXT NOT NULL,
|
||||
description TEXT,
|
||||
owner_hub_id UUID REFERENCES hubs(id),
|
||||
owner_hub_id UUID,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
deprecated_in_favour_of TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
@@ -581,7 +578,7 @@ CREATE TABLE event_type_registry (
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
label TEXT NOT NULL,
|
||||
description TEXT,
|
||||
owner_hub_id UUID REFERENCES hubs(id),
|
||||
owner_hub_id UUID,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
deprecated_in_favour_of TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
@@ -595,7 +592,7 @@ CREATE TABLE annotation_category_registry (
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
label TEXT NOT NULL,
|
||||
description TEXT,
|
||||
owner_hub_id UUID REFERENCES hubs(id),
|
||||
owner_hub_id UUID,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
deprecated_in_favour_of TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
@@ -609,7 +606,7 @@ CREATE TABLE policy_scope_registry (
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
label TEXT NOT NULL,
|
||||
description TEXT,
|
||||
owner_hub_id UUID REFERENCES hubs(id),
|
||||
owner_hub_id UUID,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
deprecated_in_favour_of TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
||||
@@ -618,70 +615,18 @@ CREATE TABLE policy_scope_registry (
|
||||
CREATE INDEX policy_scope_registry_status_idx ON policy_scope_registry (status);
|
||||
CREATE INDEX policy_scope_registry_owner_hub_idx ON policy_scope_registry (owner_hub_id);
|
||||
|
||||
-- T03 — Seed framework-level vocabulary (owner_hub_id = NULL)
|
||||
|
||||
INSERT INTO widget_type_registry (name, label, description) VALUES
|
||||
('chart', 'Chart', 'Data visualisation chart widget'),
|
||||
('form', 'Form', 'Data entry form widget'),
|
||||
('table', 'Table', 'Tabular data display widget'),
|
||||
('action', 'Action Control', 'Button, link, or trigger widget'),
|
||||
('panel', 'Status Panel', 'Summary or status information panel'),
|
||||
('workflow-step', 'Workflow Step', 'Single step in a multi-step workflow'),
|
||||
('recommendation','Recommendation', 'AI or system recommendation block'),
|
||||
('chat', 'Chat Region', 'Conversational interaction region'),
|
||||
('diff', 'Diff / Review', 'Code diff or change review element');
|
||||
|
||||
INSERT INTO event_type_registry (name, label, description) VALUES
|
||||
('viewed', 'Viewed', 'Widget was rendered and visible to the user'),
|
||||
('focused', 'Focused', 'Widget received input focus'),
|
||||
('clicked', 'Clicked', 'Widget was clicked or tapped'),
|
||||
('submitted', 'Submitted', 'Form or action was submitted'),
|
||||
('abandoned', 'Abandoned', 'User navigated away without completing'),
|
||||
('retried', 'Retried', 'Action was retried after failure'),
|
||||
('failed', 'Failed', 'Action or submission resulted in an error'),
|
||||
('commented', 'Commented', 'User added a comment or annotation'),
|
||||
('flagged_confusing', 'Flagged Confusing', 'User flagged the widget as confusing'),
|
||||
('flagged_helpful', 'Flagged Helpful', 'User flagged the widget as helpful'),
|
||||
('blocked_by_policy', 'Blocked by Policy', 'Action was blocked by a policy rule'),
|
||||
('escalated', 'Escalated', 'Issue was escalated for review'),
|
||||
('accepted_recommendation', 'Accepted Recommendation', 'User accepted an AI recommendation'),
|
||||
('rejected_recommendation', 'Rejected Recommendation', 'User rejected an AI recommendation'),
|
||||
('retracted', 'Retracted', 'Correction marker referencing original event in metadata');
|
||||
|
||||
INSERT INTO annotation_category_registry (name, label, description) VALUES
|
||||
('friction', 'Friction', 'Interaction caused user effort or difficulty'),
|
||||
('missing_capability', 'Missing Capability', 'Required feature or function is absent'),
|
||||
('policy_conflict', 'Policy Conflict', 'Widget behaviour conflicts with a policy'),
|
||||
('trust_deficit', 'Trust Deficit', 'User lacks confidence in the widget output'),
|
||||
('accessibility', 'Accessibility', 'Accessibility or inclusive design concern'),
|
||||
('workflow_bottleneck', 'Workflow Bottleneck', 'Widget creates a slowdown in the workflow'),
|
||||
('documentation_gap', 'Documentation Gap', 'Missing or insufficient documentation'),
|
||||
('product_opportunity', 'Product Opportunity', 'Observation suggesting a product improvement'),
|
||||
('governance_concern', 'Governance Concern', 'Concern about governance, audit, or compliance');
|
||||
|
||||
INSERT INTO policy_scope_registry (name, label, description) VALUES
|
||||
('internal', 'Internal', 'Applies to internal operators only'),
|
||||
('org-wide', 'Organisation-Wide', 'Applies across the entire organisation'),
|
||||
('external', 'External-Facing', 'Applies to externally visible surfaces'),
|
||||
('regulatory', 'Regulatory', 'Driven by regulatory or compliance requirements'),
|
||||
('security', 'Security', 'Security policy scope');
|
||||
-- T03 — Type registry seed data moved to Migration/1744502400-seed-type-registries.sql
|
||||
|
||||
-- T04 — Maturity columns on existing contract tables
|
||||
|
||||
ALTER TABLE envelope_emission_contracts
|
||||
ADD COLUMN maturity TEXT NOT NULL DEFAULT 'stable';
|
||||
|
||||
ALTER TABLE interaction_reporting_contracts
|
||||
ADD COLUMN maturity TEXT NOT NULL DEFAULT 'stable';
|
||||
|
||||
ALTER TABLE widget_adapter_specs
|
||||
ADD COLUMN maturity TEXT NOT NULL DEFAULT 'beta';
|
||||
-- MOVED TO CREATE TABLE: ALTER TABLE envelope_emission_contracts ADD COLUMN maturity TEXT NOT NULL DEFAULT 'stable';
|
||||
-- MOVED TO CREATE TABLE: ALTER TABLE interaction_reporting_contracts ADD COLUMN maturity TEXT NOT NULL DEFAULT 'stable';
|
||||
-- MOVED TO CREATE TABLE: ALTER TABLE widget_adapter_specs ADD COLUMN maturity TEXT NOT NULL DEFAULT 'beta';
|
||||
|
||||
-- T05 — Hub Capability Manifest
|
||||
|
||||
CREATE TABLE hub_capability_manifests (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL UNIQUE REFERENCES hubs(id),
|
||||
hub_id UUID NOT NULL UNIQUE,
|
||||
manifest_version TEXT NOT NULL DEFAULT '1.0',
|
||||
declared_widget_types JSONB NOT NULL DEFAULT '[]',
|
||||
declared_event_types JSONB NOT NULL DEFAULT '[]',
|
||||
@@ -708,11 +653,10 @@ CREATE TABLE api_consumers (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
hub_capability_manifest_id UUID REFERENCES hub_capability_manifests(id),
|
||||
hub_capability_manifest_id UUID,
|
||||
rate_limit_per_minute INTEGER NOT NULL DEFAULT 60,
|
||||
quota_per_day INTEGER NOT NULL DEFAULT 10000,
|
||||
quota_resets_at TIMESTAMP WITH TIME ZONE NOT NULL
|
||||
DEFAULT (date_trunc('day', NOW() AT TIME ZONE 'UTC') + interval '1 day'),
|
||||
quota_resets_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
|
||||
@@ -722,12 +666,11 @@ CREATE INDEX api_consumers_manifest_idx ON api_consumers (hub_capability_manifes
|
||||
|
||||
CREATE TABLE api_keys (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
api_consumer_id UUID NOT NULL REFERENCES api_consumers(id) ON DELETE CASCADE,
|
||||
api_consumer_id UUID NOT NULL,
|
||||
key_prefix TEXT NOT NULL,
|
||||
key_hash TEXT NOT NULL,
|
||||
scopes TEXT NOT NULL DEFAULT '',
|
||||
token_type TEXT NOT NULL DEFAULT 'static'
|
||||
CHECK (token_type IN ('static', 'oauth')),
|
||||
token_type TEXT NOT NULL DEFAULT 'static',
|
||||
expires_at TIMESTAMP WITH TIME ZONE,
|
||||
revoked_at TIMESTAMP WITH TIME ZONE,
|
||||
last_used_at TIMESTAMP WITH TIME ZONE,
|
||||
@@ -740,15 +683,8 @@ CREATE INDEX api_keys_hash_idx ON api_keys (key_hash);
|
||||
|
||||
CREATE TABLE webhook_subscriptions (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
api_consumer_id UUID NOT NULL REFERENCES api_consumers(id) ON DELETE CASCADE,
|
||||
event_type TEXT NOT NULL CHECK (event_type IN (
|
||||
'interaction_event.created',
|
||||
'annotation.created',
|
||||
'requirement_candidate.created',
|
||||
'decision_record.created',
|
||||
'deployment_record.created',
|
||||
'outcome_signal.created'
|
||||
)),
|
||||
api_consumer_id UUID NOT NULL,
|
||||
event_type TEXT NOT NULL,
|
||||
target_url TEXT NOT NULL,
|
||||
secret TEXT NOT NULL,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
@@ -761,10 +697,10 @@ CREATE INDEX webhook_subs_event_type_idx ON webhook_subscriptions (event_type);
|
||||
|
||||
CREATE TABLE webhook_deliveries (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
webhook_subscription_id UUID NOT NULL REFERENCES webhook_subscriptions(id),
|
||||
webhook_subscription_id UUID NOT NULL,
|
||||
payload JSONB NOT NULL,
|
||||
attempted_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
status TEXT NOT NULL CHECK (status IN ('pending', 'delivered', 'failed')),
|
||||
status TEXT NOT NULL,
|
||||
response_code INTEGER,
|
||||
latency_ms INTEGER,
|
||||
error_message TEXT
|
||||
@@ -775,7 +711,7 @@ CREATE INDEX webhook_deliveries_sub_idx
|
||||
|
||||
CREATE TABLE api_request_log (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
api_consumer_id UUID REFERENCES api_consumers(id),
|
||||
api_consumer_id UUID,
|
||||
endpoint TEXT NOT NULL,
|
||||
method TEXT NOT NULL,
|
||||
status_code INTEGER NOT NULL,
|
||||
@@ -794,10 +730,10 @@ CREATE INDEX api_request_log_consumer_time_idx
|
||||
-- GAAF: widget_type FKs to widget_type_registry(name) — not TEXT
|
||||
CREATE TABLE widget_patterns (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
hub_id UUID NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
widget_type TEXT NOT NULL REFERENCES widget_type_registry(name),
|
||||
widget_type TEXT NOT NULL,
|
||||
is_cross_hub BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
is_published BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
@@ -811,7 +747,7 @@ CREATE INDEX widget_patterns_is_published_idx ON widget_patterns (is_published);
|
||||
-- widget_pattern_versions: explicit version history
|
||||
CREATE TABLE widget_pattern_versions (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
widget_pattern_id UUID NOT NULL REFERENCES widget_patterns(id) ON DELETE CASCADE,
|
||||
widget_pattern_id UUID NOT NULL,
|
||||
version_number INTEGER NOT NULL,
|
||||
definition JSONB NOT NULL,
|
||||
changelog TEXT,
|
||||
@@ -824,9 +760,9 @@ CREATE INDEX widget_pattern_versions_pattern_idx ON widget_pattern_versions (wid
|
||||
-- pattern_adoptions: which hubs have adopted which patterns
|
||||
CREATE TABLE pattern_adoptions (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
widget_pattern_id UUID NOT NULL REFERENCES widget_patterns(id),
|
||||
adopting_hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
pinned_version_id UUID REFERENCES widget_pattern_versions(id),
|
||||
widget_pattern_id UUID NOT NULL,
|
||||
adopting_hub_id UUID NOT NULL,
|
||||
pinned_version_id UUID,
|
||||
is_version_pinned BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
is_anonymous BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
adopted_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
@@ -841,7 +777,7 @@ CREATE INDEX pattern_adoptions_hub_idx ON pattern_adoptions (adopting_hub_id);
|
||||
-- each element validated against annotation_category_registry in controller
|
||||
CREATE TABLE governance_templates (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
hub_id UUID NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
categories JSONB NOT NULL DEFAULT '[]',
|
||||
@@ -857,8 +793,8 @@ CREATE INDEX governance_templates_is_published_idx ON governance_templates (is_p
|
||||
-- governance_template_clones: adoption record for governance templates
|
||||
CREATE TABLE governance_template_clones (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
governance_template_id UUID NOT NULL REFERENCES governance_templates(id),
|
||||
cloning_hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
governance_template_id UUID NOT NULL,
|
||||
cloning_hub_id UUID NOT NULL,
|
||||
cloned_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
UNIQUE (governance_template_id, cloning_hub_id)
|
||||
);
|
||||
@@ -872,12 +808,11 @@ CREATE INDEX governance_template_clones_hub_idx ON governance_template_clones (c
|
||||
-- GAAF: trust_level CHECK constraint — no bare TEXT discriminator
|
||||
CREATE TABLE agent_registrations (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
hub_id UUID NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
slug TEXT NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
provider TEXT NOT NULL,
|
||||
-- provider values: openrouter | gemini | openai | claude-code
|
||||
model_name TEXT NOT NULL,
|
||||
trust_level TEXT NOT NULL DEFAULT 'advisory',
|
||||
capabilities JSONB NOT NULL DEFAULT '[]',
|
||||
@@ -885,8 +820,7 @@ CREATE TABLE agent_registrations (
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
version INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
CHECK (trust_level IN ('advisory', 'elevated', 'autonomous'))
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX agent_registrations_hub_id_idx ON agent_registrations (hub_id);
|
||||
@@ -896,9 +830,9 @@ CREATE INDEX agent_registrations_is_active_idx ON agent_registrations (is_active
|
||||
-- model_routing_policies: task_type → agent selection rules per hub
|
||||
CREATE TABLE model_routing_policies (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
hub_id UUID NOT NULL,
|
||||
task_type TEXT NOT NULL,
|
||||
agent_registration_id UUID NOT NULL REFERENCES agent_registrations(id),
|
||||
agent_registration_id UUID NOT NULL,
|
||||
priority INTEGER NOT NULL DEFAULT 0,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
@@ -911,17 +845,16 @@ CREATE INDEX model_routing_policies_hub_task_idx ON model_routing_policies (hub_
|
||||
-- GAAF: status CHECK constraint
|
||||
CREATE TABLE agent_delegations (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
delegating_agent_id UUID NOT NULL REFERENCES agent_registrations(id),
|
||||
receiving_agent_id UUID NOT NULL REFERENCES agent_registrations(id),
|
||||
parent_proposal_id UUID REFERENCES agent_proposals(id),
|
||||
delegating_agent_id UUID NOT NULL,
|
||||
receiving_agent_id UUID NOT NULL,
|
||||
parent_proposal_id UUID,
|
||||
scope TEXT NOT NULL,
|
||||
token_budget INTEGER NOT NULL DEFAULT 1000,
|
||||
tokens_used INTEGER,
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
result JSONB,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
completed_at TIMESTAMP WITH TIME ZONE,
|
||||
CHECK (status IN ('pending', 'completed', 'failed', 'cancelled'))
|
||||
completed_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
CREATE INDEX agent_delegations_delegating_idx ON agent_delegations (delegating_agent_id);
|
||||
@@ -937,11 +870,10 @@ CREATE TABLE collective_proposals (
|
||||
task_type TEXT NOT NULL,
|
||||
consensus_status TEXT NOT NULL DEFAULT 'pending',
|
||||
final_content JSONB,
|
||||
source_widget_id UUID REFERENCES widgets(id),
|
||||
source_candidate_id UUID REFERENCES requirement_candidates(id),
|
||||
source_widget_id UUID,
|
||||
source_candidate_id UUID,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
CHECK (consensus_status IN ('pending', 'consensus', 'divergent'))
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX collective_proposals_task_type_idx ON collective_proposals (task_type);
|
||||
@@ -950,8 +882,8 @@ CREATE INDEX collective_proposals_consensus_status_idx ON collective_proposals (
|
||||
-- collective_proposal_contributions: per-agent contribution records
|
||||
CREATE TABLE collective_proposal_contributions (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
collective_proposal_id UUID NOT NULL REFERENCES collective_proposals(id),
|
||||
agent_registration_id UUID NOT NULL REFERENCES agent_registrations(id),
|
||||
collective_proposal_id UUID NOT NULL,
|
||||
agent_registration_id UUID NOT NULL,
|
||||
content JSONB NOT NULL,
|
||||
tokens_in INTEGER,
|
||||
tokens_out INTEGER,
|
||||
@@ -967,8 +899,8 @@ CREATE INDEX collective_proposal_contributions_agent_idx ON collective_proposal_
|
||||
-- (each element: read | propose | delegate | auto_apply)
|
||||
CREATE TABLE ai_governance_policies (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
agent_registration_id UUID NOT NULL REFERENCES agent_registrations(id),
|
||||
hub_id UUID NOT NULL,
|
||||
agent_registration_id UUID NOT NULL,
|
||||
artifact_type TEXT NOT NULL,
|
||||
allowed_actions JSONB NOT NULL DEFAULT '["read"]',
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
@@ -982,8 +914,8 @@ CREATE INDEX ai_governance_policies_is_active_idx ON ai_governance_policies (is_
|
||||
-- agent_performance_records: periodic snapshots of per-agent metrics
|
||||
CREATE TABLE agent_performance_records (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
agent_registration_id UUID NOT NULL REFERENCES agent_registrations(id),
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
agent_registration_id UUID NOT NULL,
|
||||
hub_id UUID NOT NULL,
|
||||
period_start TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
period_end TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
proposals_generated INTEGER NOT NULL DEFAULT 0,
|
||||
@@ -999,10 +931,9 @@ CREATE INDEX agent_performance_records_agent_idx ON agent_performance_records (a
|
||||
CREATE INDEX agent_performance_records_period_idx ON agent_performance_records (period_start, period_end);
|
||||
|
||||
-- Extend agent_proposals with agent_registration_id and token tracking (Phase 11)
|
||||
ALTER TABLE agent_proposals
|
||||
ADD COLUMN agent_registration_id UUID REFERENCES agent_registrations(id),
|
||||
ADD COLUMN tokens_in INTEGER,
|
||||
ADD COLUMN tokens_out INTEGER;
|
||||
-- MOVED TO CREATE TABLE: ALTER TABLE agent_proposals ADD COLUMN agent_registration_id UUID;
|
||||
-- MOVED TO CREATE TABLE: ALTER TABLE agent_proposals ADD COLUMN tokens_in INTEGER;
|
||||
-- MOVED TO CREATE TABLE: ALTER TABLE agent_proposals ADD COLUMN tokens_out INTEGER;
|
||||
|
||||
CREATE INDEX agent_proposals_agent_registration_idx ON agent_proposals (agent_registration_id);
|
||||
|
||||
@@ -1014,13 +945,12 @@ CREATE INDEX agent_proposals_agent_registration_idx ON agent_proposals (agent_re
|
||||
-- GAAF: correlation_type CHECK constraint
|
||||
CREATE TABLE outcome_correlations (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
annotation_category TEXT NOT NULL REFERENCES annotation_category_registry(name),
|
||||
hub_id UUID NOT NULL,
|
||||
annotation_category TEXT NOT NULL,
|
||||
correlation_type TEXT NOT NULL DEFAULT 'annotation_predictor',
|
||||
correlation_score DOUBLE PRECISION NOT NULL,
|
||||
sample_count INTEGER NOT NULL DEFAULT 0,
|
||||
computed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
CHECK (correlation_type IN ('annotation_predictor', 'routing_quality', 'pattern_quality'))
|
||||
computed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX outcome_correlations_hub_idx ON outcome_correlations (hub_id);
|
||||
@@ -1029,8 +959,8 @@ CREATE INDEX outcome_correlations_score_idx ON outcome_correlations (correlation
|
||||
-- pattern_performance_records: per-pattern historical outcome quality
|
||||
CREATE TABLE pattern_performance_records (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
widget_pattern_id UUID NOT NULL REFERENCES widget_patterns(id),
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
widget_pattern_id UUID NOT NULL,
|
||||
hub_id UUID NOT NULL,
|
||||
adoption_count INTEGER NOT NULL DEFAULT 0,
|
||||
positive_outcome_count INTEGER NOT NULL DEFAULT 0,
|
||||
total_outcome_count INTEGER NOT NULL DEFAULT 0,
|
||||
@@ -1046,7 +976,7 @@ CREATE INDEX pattern_performance_rank_idx ON pattern_performance_records (hub_id
|
||||
-- adaptive_threshold_configs: per-hub friction weight overrides
|
||||
CREATE TABLE adaptive_threshold_configs (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id) UNIQUE,
|
||||
hub_id UUID NOT NULL UNIQUE,
|
||||
weight_overrides JSONB NOT NULL DEFAULT '{}',
|
||||
bottleneck_threshold_override DOUBLE PRECISION,
|
||||
calibration_date TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
@@ -1059,10 +989,10 @@ CREATE INDEX adaptive_threshold_hub_idx ON adaptive_threshold_configs (hub_id);
|
||||
-- GIN index for full-text search (PostgreSQL tsvector, no extension needed)
|
||||
CREATE TABLE institutional_knowledge_entries (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
decision_record_id UUID REFERENCES decision_records(id),
|
||||
hub_id UUID NOT NULL,
|
||||
decision_record_id UUID,
|
||||
summary TEXT NOT NULL,
|
||||
summary_tsv TSVECTOR GENERATED ALWAYS AS (to_tsvector('english', summary)) STORED,
|
||||
summary_tsv TSVECTOR,
|
||||
tags JSONB NOT NULL DEFAULT '[]',
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
|
||||
@@ -1075,19 +1005,13 @@ CREATE INDEX institutional_knowledge_fts_idx ON institutional_knowledge_entries
|
||||
-- GAAF: insight_type CHECK constraint
|
||||
CREATE TABLE learning_insights (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
hub_id UUID NOT NULL REFERENCES hubs(id),
|
||||
hub_id UUID NOT NULL,
|
||||
insight_type TEXT NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
body TEXT NOT NULL,
|
||||
evidence_links JSONB NOT NULL DEFAULT '[]',
|
||||
is_actioned BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
computed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
CHECK (insight_type IN (
|
||||
'annotation_predictor',
|
||||
'threshold_calibration',
|
||||
'pattern_ranking',
|
||||
'routing_improvement'
|
||||
))
|
||||
computed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX learning_insights_hub_idx ON learning_insights (hub_id);
|
||||
@@ -1095,8 +1019,37 @@ CREATE INDEX learning_insights_type_idx ON learning_insights (insight_type);
|
||||
|
||||
-- Extend core tables with outcome_summary (retroactive lineage enrichment)
|
||||
-- GAAF rule 3: /contracts/core/ updated in T01/T06
|
||||
ALTER TABLE decision_records
|
||||
ADD COLUMN outcome_summary JSONB NULL;
|
||||
-- MOVED TO CREATE TABLE: ALTER TABLE decision_records ADD COLUMN outcome_summary JSONB;
|
||||
-- MOVED TO CREATE TABLE: ALTER TABLE requirement_candidates ADD COLUMN outcome_summary JSONB;
|
||||
|
||||
ALTER TABLE requirement_candidates
|
||||
ADD COLUMN outcome_summary JSONB NULL;
|
||||
-- Foreign Key Constraints (for IHP type generation — IHP generates Id types from these)
|
||||
ALTER TABLE widgets ADD FOREIGN KEY (hub_id) REFERENCES hubs(id);
|
||||
ALTER TABLE widget_versions ADD FOREIGN KEY (widget_id) REFERENCES widgets(id);
|
||||
ALTER TABLE interaction_events ADD FOREIGN KEY (widget_id) REFERENCES widgets(id);
|
||||
ALTER TABLE outcome_signals ADD FOREIGN KEY (widget_id) REFERENCES widgets(id);
|
||||
ALTER TABLE outcome_signals ADD FOREIGN KEY (deployment_id) REFERENCES deployment_records(id);
|
||||
ALTER TABLE deployment_records ADD FOREIGN KEY (impl_ref_id) REFERENCES implementation_change_references(id);
|
||||
ALTER TABLE deployment_records ADD FOREIGN KEY (decision_id) REFERENCES decision_records(id);
|
||||
ALTER TABLE api_keys ADD FOREIGN KEY (api_consumer_id) REFERENCES api_consumers(id);
|
||||
ALTER TABLE webhook_subscriptions ADD FOREIGN KEY (api_consumer_id) REFERENCES api_consumers(id);
|
||||
ALTER TABLE pattern_adoptions ADD FOREIGN KEY (widget_pattern_id) REFERENCES widget_patterns(id);
|
||||
ALTER TABLE annotation_threads ADD FOREIGN KEY (widget_id) REFERENCES widgets(id);
|
||||
ALTER TABLE annotations ADD FOREIGN KEY (widget_id) REFERENCES widgets(id);
|
||||
ALTER TABLE annotations ADD FOREIGN KEY (thread_id) REFERENCES annotation_threads(id);
|
||||
ALTER TABLE requirement_candidates ADD FOREIGN KEY (source_widget_id) REFERENCES widgets(id);
|
||||
ALTER TABLE requirement_candidates ADD FOREIGN KEY (source_thread_id) REFERENCES annotation_threads(id);
|
||||
ALTER TABLE requirement_candidates ADD FOREIGN KEY (source_annotation_id) REFERENCES annotations(id);
|
||||
ALTER TABLE requirement_candidates ADD FOREIGN KEY (requirement_id) REFERENCES requirements(id);
|
||||
ALTER TABLE triage_states ADD FOREIGN KEY (candidate_id) REFERENCES requirement_candidates(id);
|
||||
ALTER TABLE reviewer_assignments ADD FOREIGN KEY (candidate_id) REFERENCES requirement_candidates(id);
|
||||
ALTER TABLE reviewer_assignments ADD FOREIGN KEY (user_id) REFERENCES users(id);
|
||||
ALTER TABLE reviewer_assignments ADD FOREIGN KEY (assigned_by) REFERENCES users(id);
|
||||
ALTER TABLE requirements ADD FOREIGN KEY (source_candidate_id) REFERENCES requirement_candidates(id);
|
||||
ALTER TABLE decision_records ADD FOREIGN KEY (requirement_id) REFERENCES requirements(id);
|
||||
ALTER TABLE decision_records ADD FOREIGN KEY (candidate_id) REFERENCES requirement_candidates(id);
|
||||
ALTER TABLE implementation_change_references ADD FOREIGN KEY (decision_id) REFERENCES decision_records(id);
|
||||
ALTER TABLE policy_references ADD FOREIGN KEY (decision_id) REFERENCES decision_records(id);
|
||||
ALTER TABLE agent_review_records ADD FOREIGN KEY (proposal_id) REFERENCES agent_proposals(id);
|
||||
ALTER TABLE confidence_annotations ADD FOREIGN KEY (proposal_id) REFERENCES agent_proposals(id);
|
||||
ALTER TABLE institutional_knowledge_entries ADD FOREIGN KEY (hub_id) REFERENCES hubs(id);
|
||||
ALTER TABLE institutional_knowledge_entries ADD FOREIGN KEY (decision_record_id) REFERENCES decision_records(id);
|
||||
|
||||
Reference in New Issue
Block a user