Files
inter-hub/Application/Schema.sql
Bernd Worsch 74bab5f6f2 fix(WP-0014/A2): continued type-correctness fixes and Tailwind CSS output
- Schema.sql: add FK constraints for phases 6–12 so IHP generates Id X
  instead of UUID for FK columns (widget_adapter_specs, friction_scores,
  hub_routing_rules, agent_proposals, hub_capability_manifests, etc.)
- HubHealth, ModelRouter, ApiInteractionEvents: remove toUUID() wrappers
  now that FK columns carry proper Id types
- FederatedGovernance/Dashboard, HubRoutingRules/Index: same Id comparison fix
- AgentProposals/Index, DecisionRecords/Index, ApiConsumers/Edit: Id type fixes
- BottleneckDetector: add Data.Coerce import; CrossHubPropagation: add guard
- ApiKeys: qualify cryptohash-sha256 import to resolve package ambiguity
- WebhookDeliveryJob: use LBS.fromStrict; remove duplicate diffUTCTime
- Sessions/New: use renderFlashMessages (IHP built-in)
- ArchiveRecords/LineageInspector: simplify renderChainStep signature
- static/app.css: Tailwind CSS output (2011 lines) — A3 confirmed
- workplans/IHUB-WP-0015-local-deployment-intro-ui.md: add workplan

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 01:49:41 +00:00

1146 lines
50 KiB
PL/PgSQL

-- IHF Phase 1 + Phase 2 Schema
-- Hub, Widget, WidgetVersion, InteractionEvent, Annotation
-- Phase 2: AnnotationThread, RequirementCandidate, TriageState, ReviewerAssignment
-- See workplans/IHUB-WP-0001-ihf-phase1-minimal-interaction-core.md
-- See workplans/IHUB-WP-0002-ihf-phase2-structured-feedback-and-triage.md
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- Users (T10 — authentication)
CREATE TABLE users (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
email TEXT NOT NULL UNIQUE,
password_hash TEXT NOT NULL,
name TEXT NOT NULL,
locked_at TIMESTAMP WITH TIME ZONE DEFAULT NULL,
failed_login_attempts INT NOT NULL DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
);
-- Hubs — bounded domains of responsibility
CREATE TABLE hubs (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
slug TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
domain TEXT 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,
name TEXT NOT NULL,
widget_type TEXT NOT NULL,
capability_ref TEXT,
view_context TEXT,
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,
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,
version INT NOT NULL,
schema_snapshot JSONB NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
UNIQUE (widget_id, version)
);
-- Interaction events — append-only capture
CREATE TABLE interaction_events (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
widget_id UUID NOT NULL,
event_type TEXT NOT NULL,
actor_id UUID,
actor_type TEXT NOT NULL DEFAULT 'user',
view_context_ref TEXT,
metadata JSONB DEFAULT '{}' NOT NULL,
occurred_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
);
CREATE INDEX interaction_events_widget_id_idx ON interaction_events (widget_id);
CREATE INDEX interaction_events_occurred_at_idx ON interaction_events (occurred_at DESC);
-- Enforce append-only on interaction_events
CREATE OR REPLACE FUNCTION prevent_interaction_event_mutation()
RETURNS TRIGGER AS $$
BEGIN
RAISE EXCEPTION 'interaction_events is append-only: UPDATE and DELETE are not permitted';
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER interaction_events_no_update
BEFORE UPDATE ON interaction_events
FOR EACH ROW EXECUTE FUNCTION prevent_interaction_event_mutation();
CREATE TRIGGER interaction_events_no_delete
BEFORE DELETE ON interaction_events
FOR EACH ROW EXECUTE FUNCTION prevent_interaction_event_mutation();
-- 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,
title TEXT NOT NULL,
description TEXT,
created_by UUID,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
);
-- Annotations — structured commentary, also append-only by convention
-- Phase 2 additions: severity, thread_id
CREATE TABLE annotations (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
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,
actor_id UUID,
actor_type TEXT NOT NULL DEFAULT 'user',
widget_state_ref TEXT,
retracted_at TIMESTAMP WITH TIME ZONE DEFAULT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
);
CREATE INDEX annotations_widget_id_idx ON annotations (widget_id);
-- Requirement candidates — escalated from annotations/threads (Phase 2)
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,
source_thread_id UUID,
source_annotation_id UUID,
category TEXT NOT NULL DEFAULT 'friction',
status TEXT NOT NULL DEFAULT 'open',
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);
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,
status TEXT NOT NULL,
notes TEXT,
changed_by UUID,
changed_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
);
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,
user_id UUID NOT NULL,
assigned_by UUID,
assigned_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
UNIQUE (candidate_id)
);
-- Requirements — promoted from accepted RequirementCandidates (Phase 3)
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,
status TEXT NOT NULL DEFAULT 'active',
created_by UUID,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
);
CREATE INDEX requirements_source_candidate_id_idx ON requirements (source_candidate_id);
-- Decision records — governance decisions acting on requirements/candidates (Phase 3)
CREATE TABLE decision_records (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
title TEXT NOT NULL,
rationale TEXT NOT NULL,
outcome TEXT NOT NULL,
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,
outcome_summary JSONB
);
CREATE INDEX decision_records_outcome_idx ON decision_records (outcome);
CREATE INDEX decision_records_requirement_id_idx ON decision_records (requirement_id);
-- 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,
policy_scope TEXT NOT NULL,
constraint_note TEXT,
created_by UUID,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
);
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,
work_item_ref TEXT NOT NULL,
system TEXT NOT NULL DEFAULT 'github',
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)
-- 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,
decision_id UUID NOT NULL,
version_ref TEXT NOT NULL,
deployed_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
deployed_by UUID,
notes TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
);
CREATE INDEX deployment_records_decision_id_idx ON deployment_records (decision_id);
CREATE INDEX deployment_records_deployed_at_idx ON deployment_records (deployed_at DESC);
-- 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,
deployment_id UUID NOT NULL,
signal_type TEXT NOT NULL,
value NUMERIC,
observed_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
);
CREATE INDEX outcome_signals_widget_id_idx ON outcome_signals (widget_id);
CREATE INDEX outcome_signals_deployment_id_idx ON outcome_signals (deployment_id);
CREATE INDEX outcome_signals_observed_at_idx ON outcome_signals (observed_at DESC);
CREATE OR REPLACE FUNCTION prevent_outcome_signal_mutation()
RETURNS TRIGGER AS $$
BEGIN
RAISE EXCEPTION 'outcome_signals is append-only: UPDATE and DELETE are not permitted';
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER outcome_signals_no_update
BEFORE UPDATE ON outcome_signals
FOR EACH ROW EXECUTE FUNCTION prevent_outcome_signal_mutation();
CREATE TRIGGER outcome_signals_no_delete
BEFORE DELETE ON outcome_signals
FOR EACH ROW EXECUTE FUNCTION prevent_outcome_signal_mutation();
-- 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,
decision_id UUID,
score SMALLINT NOT NULL,
rationale TEXT NOT NULL,
evaluated_by UUID,
evaluated_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
UNIQUE (deployment_id)
);
CREATE INDEX change_evaluations_deployment_id_idx ON change_evaluations (deployment_id);
-- Agent proposals — AI-generated outputs awaiting human review (Phase 5)
CREATE TABLE agent_proposals (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
proposal_type TEXT NOT 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,
status TEXT NOT NULL DEFAULT 'pending',
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);
CREATE INDEX agent_proposals_status_idx ON agent_proposals (status);
CREATE INDEX agent_proposals_source_widget_id_idx ON agent_proposals (source_widget_id);
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,
reviewer_id UUID,
decision TEXT NOT NULL,
notes TEXT,
reviewed_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
UNIQUE (proposal_id)
);
CREATE INDEX agent_review_records_proposal_id_idx ON agent_review_records (proposal_id);
-- 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,
dimension TEXT NOT NULL,
score NUMERIC NOT NULL,
explanation TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
);
CREATE INDEX confidence_annotations_proposal_id_idx ON confidence_annotations (proposal_id);
-- ============================================================
-- Phase 6 — Cross-Framework UI Adaptation Layer
-- ============================================================
-- Formalises the rules for widget envelope emission: which data-* attributes
-- 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,
required_attributes JSONB NOT NULL,
optional_attributes JSONB NOT NULL DEFAULT '[]',
validation_rules JSONB NOT NULL DEFAULT '{}',
description TEXT,
status TEXT NOT NULL DEFAULT 'active',
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);
-- Standardised REST interface contract for external event and annotation
-- 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,
endpoint_path TEXT NOT NULL,
accepted_event_types JSONB NOT NULL,
required_fields JSONB NOT NULL,
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,
maturity TEXT NOT NULL DEFAULT 'stable'
);
CREATE INDEX interaction_reporting_contracts_status_idx ON interaction_reporting_contracts (status);
-- 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,
framework TEXT NOT NULL,
version TEXT NOT NULL,
envelope_contract_id UUID,
reporting_contract_id UUID,
status TEXT NOT NULL DEFAULT 'draft',
notes TEXT,
created_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).
-- 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.
-- 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,
score INTEGER NOT NULL DEFAULT 0,
annotation_count INTEGER NOT NULL DEFAULT 0,
error_event_count INTEGER NOT NULL DEFAULT 0,
regression_flag BOOLEAN NOT NULL DEFAULT FALSE,
stale_candidate_count INTEGER NOT NULL DEFAULT 0,
last_computed_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
UNIQUE (widget_id)
);
CREATE INDEX friction_scores_widget_id_idx ON friction_scores (widget_id);
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,
stage TEXT NOT NULL,
subject_type TEXT NOT NULL,
subject_id UUID NOT NULL,
stalled_since TIMESTAMP WITH TIME ZONE NOT NULL,
severity TEXT NOT NULL DEFAULT 'medium',
resolved_at TIMESTAMP WITH TIME ZONE,
notes TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
);
CREATE INDEX bottleneck_records_hub_id_idx ON bottleneck_records (hub_id);
CREATE INDEX bottleneck_records_stage_idx ON bottleneck_records (stage);
CREATE INDEX bottleneck_records_resolved_idx ON bottleneck_records (resolved_at)
WHERE resolved_at IS NULL;
-- 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,
health_score INTEGER NOT NULL,
open_candidates INTEGER NOT NULL DEFAULT 0,
regressed_widgets INTEGER NOT NULL DEFAULT 0,
stale_decisions INTEGER NOT NULL DEFAULT 0,
active_bottlenecks INTEGER NOT NULL DEFAULT 0,
computed_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
);
CREATE INDEX hub_health_snapshots_hub_id_idx ON hub_health_snapshots (hub_id);
CREATE INDEX hub_health_snapshots_computed_at_idx
ON hub_health_snapshots (hub_id, computed_at DESC);
-- Patterns detected across multiple hubs.
CREATE TABLE cross_hub_propagations (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
pattern_type TEXT NOT NULL,
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,
status TEXT NOT NULL DEFAULT 'open',
notes TEXT
);
CREATE INDEX cross_hub_propagations_status_idx ON cross_hub_propagations (status);
CREATE INDEX cross_hub_propagations_pattern_idx ON cross_hub_propagations (pattern_type);
-- Phase 8: Federated Hub Maturity
-- 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,
owner_hub_id UUID NOT NULL,
steward_hub_id UUID,
ownership_type TEXT NOT NULL DEFAULT 'local',
effective_from TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
effective_until TIMESTAMP WITH TIME ZONE,
notes TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
);
CREATE INDEX widget_ownerships_widget_id_idx ON widget_ownerships (widget_id);
CREATE INDEX widget_ownerships_owner_hub_idx ON widget_ownerships (owner_hub_id);
CREATE INDEX widget_ownerships_steward_hub_idx ON widget_ownerships (steward_hub_id);
-- 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,
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',
notes TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
);
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.
-- 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)
WHERE routed_to_hub_id IS NOT NULL;
-- Org-wide policy overlay applied across selected hubs.
CREATE TABLE federated_policy_overlays (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
title TEXT NOT NULL,
policy_text TEXT NOT NULL,
applies_to_hubs JSONB NOT NULL DEFAULT '[]',
enforced_from TIMESTAMP WITH TIME ZONE,
status TEXT NOT NULL DEFAULT 'draft',
notes TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
);
CREATE INDEX federated_policy_overlays_status_idx ON federated_policy_overlays (status);
-- 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,
role_name TEXT NOT NULL,
assigned_to TEXT NOT NULL,
granted_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
revoked_at TIMESTAMP WITH TIME ZONE,
notes TEXT
);
CREATE INDEX stewardship_roles_hub_id_idx ON stewardship_roles (hub_id);
CREATE INDEX stewardship_roles_active_idx ON stewardship_roles (revoked_at)
WHERE revoked_at IS NULL;
-- Long-term archival entry for any IHF artifact.
CREATE TABLE archive_records (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
subject_type TEXT NOT NULL,
subject_id UUID NOT NULL,
archived_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
reason TEXT NOT NULL,
archived_by TEXT NOT NULL,
lineage_ref TEXT
);
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.
-- 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;
-- ============================================================
-- GAAF Compliance Foundation (IHUB-WP-0009)
-- T02: hub_kind | T03: type registries + seed | T04: maturity columns | T05: manifests
-- ============================================================
-- T02 — Hub kind classification
-- 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);
CREATE UNIQUE INDEX hubs_one_framework_idx ON hubs (hub_kind)
WHERE hub_kind = 'framework';
-- T03 — Type registries
CREATE TABLE widget_type_registry (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
name TEXT NOT NULL UNIQUE,
label TEXT NOT NULL,
description TEXT,
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
);
CREATE INDEX widget_type_registry_status_idx ON widget_type_registry (status);
CREATE INDEX widget_type_registry_owner_hub_idx ON widget_type_registry (owner_hub_id);
CREATE TABLE event_type_registry (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
name TEXT NOT NULL UNIQUE,
label TEXT NOT NULL,
description TEXT,
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
);
CREATE INDEX event_type_registry_status_idx ON event_type_registry (status);
CREATE INDEX event_type_registry_owner_hub_idx ON event_type_registry (owner_hub_id);
CREATE TABLE annotation_category_registry (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
name TEXT NOT NULL UNIQUE,
label TEXT NOT NULL,
description TEXT,
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
);
CREATE INDEX annotation_category_registry_status_idx ON annotation_category_registry (status);
CREATE INDEX annotation_category_registry_owner_hub_idx ON annotation_category_registry (owner_hub_id);
CREATE TABLE policy_scope_registry (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
name TEXT NOT NULL UNIQUE,
label TEXT NOT NULL,
description TEXT,
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
);
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 — Type registry seed data moved to Migration/1744502400-seed-type-registries.sql
-- T04 — Maturity columns on existing contract tables
-- 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,
manifest_version TEXT NOT NULL DEFAULT '1.0',
declared_widget_types JSONB NOT NULL DEFAULT '[]',
declared_event_types JSONB NOT NULL DEFAULT '[]',
declared_annotation_categories JSONB NOT NULL DEFAULT '[]',
declared_policy_scopes JSONB NOT NULL DEFAULT '[]',
capability_description TEXT,
contact TEXT,
status TEXT NOT NULL DEFAULT 'draft',
activated_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
);
CREATE INDEX hub_capability_manifests_hub_id_idx ON hub_capability_manifests (hub_id);
CREATE INDEX hub_capability_manifests_status_idx ON hub_capability_manifests (status);
-- GAAF: type registries enforced from here (IHUB-WP-0009)
-- All new type discriminator columns (widget_type, event_type, category,
-- policy_scope) must reference a registry table or carry a CHECK constraint.
-- IHF Phase 9 — External API Surface and Consumer SDKs (IHUB-WP-0010)
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,
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 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
);
CREATE INDEX api_consumers_manifest_idx ON api_consumers (hub_capability_manifest_id);
CREATE TABLE api_keys (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
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',
expires_at TIMESTAMP WITH TIME ZONE,
revoked_at TIMESTAMP WITH TIME ZONE,
last_used_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
);
CREATE UNIQUE INDEX api_keys_prefix_idx ON api_keys (key_prefix);
CREATE INDEX api_keys_consumer_idx ON api_keys (api_consumer_id);
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,
event_type TEXT NOT NULL,
target_url TEXT NOT NULL,
secret TEXT NOT NULL,
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
);
CREATE INDEX webhook_subs_consumer_idx ON webhook_subscriptions (api_consumer_id);
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,
payload JSONB NOT NULL,
attempted_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
status TEXT NOT NULL,
response_code INTEGER,
latency_ms INTEGER,
error_message TEXT
);
CREATE INDEX webhook_deliveries_sub_idx
ON webhook_deliveries (webhook_subscription_id, attempted_at DESC);
CREATE TABLE api_request_log (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
api_consumer_id UUID,
endpoint TEXT NOT NULL,
method TEXT NOT NULL,
status_code INTEGER NOT NULL,
latency_ms INTEGER,
requested_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
);
CREATE INDEX api_request_log_consumer_time_idx
ON api_request_log (api_consumer_id, requested_at DESC);
-- IHF Phase 10 — Hub Registry and Widget Marketplace (IHUB-WP-0011)
-- No HubRegistry table — hub registry is a view over existing tables
-- (hub_capability_manifests + hub_health_snapshots + hubs)
-- widget_patterns: reusable widget definitions tied to registered types
-- 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,
name TEXT NOT NULL,
description TEXT,
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,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
);
CREATE INDEX widget_patterns_hub_id_idx ON widget_patterns (hub_id);
CREATE INDEX widget_patterns_widget_type_idx ON widget_patterns (widget_type);
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,
version_number INTEGER NOT NULL,
definition JSONB NOT NULL,
changelog TEXT,
published_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
UNIQUE (widget_pattern_id, version_number)
);
CREATE INDEX widget_pattern_versions_pattern_idx ON widget_pattern_versions (widget_pattern_id);
-- 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,
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,
UNIQUE (widget_pattern_id, adopting_hub_id)
);
CREATE INDEX pattern_adoptions_pattern_idx ON pattern_adoptions (widget_pattern_id);
CREATE INDEX pattern_adoptions_hub_idx ON pattern_adoptions (adopting_hub_id);
-- governance_templates: requirement distillation and decision templates
-- categories is JSONB array of annotation_category_registry names;
-- 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,
name TEXT NOT NULL,
description TEXT,
categories JSONB NOT NULL DEFAULT '[]',
template_body JSONB NOT NULL,
is_published BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
);
CREATE INDEX governance_templates_hub_id_idx ON governance_templates (hub_id);
CREATE INDEX governance_templates_is_published_idx ON governance_templates (is_published);
-- 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,
cloning_hub_id UUID NOT NULL,
cloned_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
UNIQUE (governance_template_id, cloning_hub_id)
);
CREATE INDEX governance_template_clones_template_idx ON governance_template_clones (governance_template_id);
CREATE INDEX governance_template_clones_hub_idx ON governance_template_clones (cloning_hub_id);
-- IHF Phase 11 — Advanced AI Federation (IHUB-WP-0012)
-- agent_registrations: named, versioned AI agents backed by llm-connect providers
-- 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,
name TEXT NOT NULL,
slug TEXT NOT NULL UNIQUE,
description TEXT,
provider TEXT NOT NULL,
model_name TEXT NOT NULL,
trust_level TEXT NOT NULL DEFAULT 'advisory',
capabilities JSONB NOT NULL DEFAULT '[]',
system_prompt TEXT,
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
);
CREATE INDEX agent_registrations_hub_id_idx ON agent_registrations (hub_id);
CREATE INDEX agent_registrations_slug_idx ON agent_registrations (slug);
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,
task_type TEXT NOT NULL,
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,
UNIQUE (hub_id, task_type, priority)
);
CREATE INDEX model_routing_policies_hub_task_idx ON model_routing_policies (hub_id, task_type);
-- agent_delegations: auditable inter-agent subtask delegation records
-- GAAF: status CHECK constraint
CREATE TABLE agent_delegations (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
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
);
CREATE INDEX agent_delegations_delegating_idx ON agent_delegations (delegating_agent_id);
CREATE INDEX agent_delegations_receiving_idx ON agent_delegations (receiving_agent_id);
CREATE INDEX agent_delegations_parent_proposal_idx ON agent_delegations (parent_proposal_id);
-- collective_proposals: multi-agent proposals with attribution
-- GAAF: consensus_status CHECK constraint
CREATE TABLE collective_proposals (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
title TEXT NOT NULL,
summary TEXT,
task_type TEXT NOT NULL,
consensus_status TEXT NOT NULL DEFAULT 'pending',
final_content JSONB,
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
);
CREATE INDEX collective_proposals_task_type_idx ON collective_proposals (task_type);
CREATE INDEX collective_proposals_consensus_status_idx ON collective_proposals (consensus_status);
-- 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,
agent_registration_id UUID NOT NULL,
content JSONB NOT NULL,
tokens_in INTEGER,
tokens_out INTEGER,
model_used TEXT,
contributed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
);
CREATE INDEX collective_proposal_contributions_proposal_idx ON collective_proposal_contributions (collective_proposal_id);
CREATE INDEX collective_proposal_contributions_agent_idx ON collective_proposal_contributions (agent_registration_id);
-- ai_governance_policies: per-hub rules controlling agent scope
-- allowed_actions is JSONB array; elements validated at controller layer
-- (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,
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,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
);
CREATE INDEX ai_governance_policies_hub_agent_idx ON ai_governance_policies (hub_id, agent_registration_id);
CREATE INDEX ai_governance_policies_is_active_idx ON ai_governance_policies (is_active);
-- 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,
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,
proposals_accepted INTEGER NOT NULL DEFAULT 0,
proposals_rejected INTEGER NOT NULL DEFAULT 0,
proposals_revised INTEGER NOT NULL DEFAULT 0,
mean_confidence DOUBLE PRECISION,
calibration_score DOUBLE PRECISION,
computed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
);
CREATE INDEX agent_performance_records_agent_idx ON agent_performance_records (agent_registration_id);
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)
-- 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);
-- ============================================================
-- Phase 12 — Platform Memory and Continuous Learning
-- ============================================================
-- outcome_correlations: links annotation signals to downstream outcome quality
-- GAAF: correlation_type CHECK constraint
CREATE TABLE outcome_correlations (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
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
);
CREATE INDEX outcome_correlations_hub_idx ON outcome_correlations (hub_id);
CREATE INDEX outcome_correlations_score_idx ON outcome_correlations (correlation_score DESC);
-- 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,
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,
mean_outcome_value DOUBLE PRECISION,
outcome_rank INTEGER,
calibrated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
UNIQUE (widget_pattern_id, hub_id)
);
CREATE INDEX pattern_performance_pattern_idx ON pattern_performance_records (widget_pattern_id);
CREATE INDEX pattern_performance_rank_idx ON pattern_performance_records (hub_id, outcome_rank);
-- 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 UNIQUE,
weight_overrides JSONB NOT NULL DEFAULT '{}',
bottleneck_threshold_override DOUBLE PRECISION,
calibration_date TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
notes TEXT
);
CREATE INDEX adaptive_threshold_hub_idx ON adaptive_threshold_configs (hub_id);
-- institutional_knowledge_entries: distilled decision summaries
-- 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,
decision_record_id UUID,
summary TEXT NOT NULL,
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
);
CREATE INDEX institutional_knowledge_hub_idx ON institutional_knowledge_entries (hub_id);
CREATE INDEX institutional_knowledge_fts_idx ON institutional_knowledge_entries USING GIN (summary_tsv);
-- learning_insights: platform-level insights with evidence links
-- GAAF: insight_type CHECK constraint
CREATE TABLE learning_insights (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
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
);
CREATE INDEX learning_insights_hub_idx ON learning_insights (hub_id);
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
-- 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;
-- 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);
-- Additional FK constraints for IHP type generation (Id vs UUID)
-- Phase 6 — widget_adapter_specs
ALTER TABLE widget_adapter_specs ADD FOREIGN KEY (envelope_contract_id) REFERENCES envelope_emission_contracts(id);
ALTER TABLE widget_adapter_specs ADD FOREIGN KEY (reporting_contract_id) REFERENCES interaction_reporting_contracts(id);
ALTER TABLE widgets ADD FOREIGN KEY (adapter_spec_id) REFERENCES widget_adapter_specs(id);
-- Phase 7 — friction_scores, bottleneck_records, hub_health_snapshots
ALTER TABLE friction_scores ADD FOREIGN KEY (widget_id) REFERENCES widgets(id);
ALTER TABLE bottleneck_records ADD FOREIGN KEY (hub_id) REFERENCES hubs(id);
ALTER TABLE hub_health_snapshots ADD FOREIGN KEY (hub_id) REFERENCES hubs(id);
ALTER TABLE cross_hub_propagations ADD FOREIGN KEY (source_hub_id) REFERENCES hubs(id);
-- Phase 8 — widget_ownerships, hub_routing_rules, stewardship_roles
ALTER TABLE widget_ownerships ADD FOREIGN KEY (widget_id) REFERENCES widgets(id);
ALTER TABLE widget_ownerships ADD FOREIGN KEY (owner_hub_id) REFERENCES hubs(id);
ALTER TABLE widget_ownerships ADD FOREIGN KEY (steward_hub_id) REFERENCES hubs(id);
ALTER TABLE hub_routing_rules ADD FOREIGN KEY (source_hub_id) REFERENCES hubs(id);
ALTER TABLE hub_routing_rules ADD FOREIGN KEY (target_hub_id) REFERENCES hubs(id);
ALTER TABLE stewardship_roles ADD FOREIGN KEY (hub_id) REFERENCES hubs(id);
ALTER TABLE requirement_candidates ADD FOREIGN KEY (routed_to_hub_id) REFERENCES hubs(id);
-- User actor references (nullable)
ALTER TABLE annotation_threads ADD FOREIGN KEY (created_by) REFERENCES users(id);
ALTER TABLE requirement_candidates ADD FOREIGN KEY (created_by) REFERENCES users(id);
ALTER TABLE triage_states ADD FOREIGN KEY (changed_by) REFERENCES users(id);
ALTER TABLE requirements ADD FOREIGN KEY (created_by) REFERENCES users(id);
ALTER TABLE decision_records ADD FOREIGN KEY (decided_by) REFERENCES users(id);
ALTER TABLE policy_references ADD FOREIGN KEY (created_by) REFERENCES users(id);
ALTER TABLE implementation_change_references ADD FOREIGN KEY (linked_by) REFERENCES users(id);
ALTER TABLE deployment_records ADD FOREIGN KEY (deployed_by) REFERENCES users(id);
ALTER TABLE agent_review_records ADD FOREIGN KEY (reviewer_id) REFERENCES users(id);
-- change_evaluations
ALTER TABLE change_evaluations ADD FOREIGN KEY (deployment_id) REFERENCES deployment_records(id);
ALTER TABLE change_evaluations ADD FOREIGN KEY (decision_id) REFERENCES decision_records(id);
ALTER TABLE change_evaluations ADD FOREIGN KEY (evaluated_by) REFERENCES users(id);
-- agent_proposals source refs
ALTER TABLE agent_proposals ADD FOREIGN KEY (source_widget_id) REFERENCES widgets(id);
ALTER TABLE agent_proposals ADD FOREIGN KEY (source_candidate_id) REFERENCES requirement_candidates(id);
ALTER TABLE agent_proposals ADD FOREIGN KEY (source_thread_id) REFERENCES annotation_threads(id);
ALTER TABLE agent_proposals ADD FOREIGN KEY (source_decision_id) REFERENCES decision_records(id);
ALTER TABLE agent_proposals ADD FOREIGN KEY (agent_registration_id) REFERENCES agent_registrations(id);
-- GAAF type registry owner refs (nullable)
ALTER TABLE widget_type_registry ADD FOREIGN KEY (owner_hub_id) REFERENCES hubs(id);
ALTER TABLE event_type_registry ADD FOREIGN KEY (owner_hub_id) REFERENCES hubs(id);
ALTER TABLE annotation_category_registry ADD FOREIGN KEY (owner_hub_id) REFERENCES hubs(id);
ALTER TABLE policy_scope_registry ADD FOREIGN KEY (owner_hub_id) REFERENCES hubs(id);
-- hub_capability_manifests
ALTER TABLE hub_capability_manifests ADD FOREIGN KEY (hub_id) REFERENCES hubs(id);
-- Phase 9 — api_consumers, webhook_deliveries, api_request_log
ALTER TABLE api_consumers ADD FOREIGN KEY (hub_capability_manifest_id) REFERENCES hub_capability_manifests(id);
ALTER TABLE webhook_deliveries ADD FOREIGN KEY (webhook_subscription_id) REFERENCES webhook_subscriptions(id);
ALTER TABLE api_request_log ADD FOREIGN KEY (api_consumer_id) REFERENCES api_consumers(id);
-- Phase 10 — widget_patterns, pattern_adoptions, governance_templates
ALTER TABLE widget_patterns ADD FOREIGN KEY (hub_id) REFERENCES hubs(id);
ALTER TABLE widget_pattern_versions ADD FOREIGN KEY (widget_pattern_id) REFERENCES widget_patterns(id);
ALTER TABLE pattern_adoptions ADD FOREIGN KEY (adopting_hub_id) REFERENCES hubs(id);
ALTER TABLE pattern_adoptions ADD FOREIGN KEY (pinned_version_id) REFERENCES widget_pattern_versions(id);
ALTER TABLE governance_templates ADD FOREIGN KEY (hub_id) REFERENCES hubs(id);
ALTER TABLE governance_template_clones ADD FOREIGN KEY (governance_template_id) REFERENCES governance_templates(id);
ALTER TABLE governance_template_clones ADD FOREIGN KEY (cloning_hub_id) REFERENCES hubs(id);
-- Phase 11 — agent_registrations, model_routing_policies, agent_delegations, collective_proposals
ALTER TABLE agent_registrations ADD FOREIGN KEY (hub_id) REFERENCES hubs(id);
ALTER TABLE model_routing_policies ADD FOREIGN KEY (hub_id) REFERENCES hubs(id);
ALTER TABLE model_routing_policies ADD FOREIGN KEY (agent_registration_id) REFERENCES agent_registrations(id);
ALTER TABLE agent_delegations ADD FOREIGN KEY (delegating_agent_id) REFERENCES agent_registrations(id);
ALTER TABLE agent_delegations ADD FOREIGN KEY (receiving_agent_id) REFERENCES agent_registrations(id);
ALTER TABLE agent_delegations ADD FOREIGN KEY (parent_proposal_id) REFERENCES agent_proposals(id);
ALTER TABLE collective_proposals ADD FOREIGN KEY (source_widget_id) REFERENCES widgets(id);
ALTER TABLE collective_proposals ADD FOREIGN KEY (source_candidate_id) REFERENCES requirement_candidates(id);
ALTER TABLE collective_proposal_contributions ADD FOREIGN KEY (collective_proposal_id) REFERENCES collective_proposals(id);
ALTER TABLE collective_proposal_contributions ADD FOREIGN KEY (agent_registration_id) REFERENCES agent_registrations(id);
ALTER TABLE ai_governance_policies ADD FOREIGN KEY (hub_id) REFERENCES hubs(id);
ALTER TABLE ai_governance_policies ADD FOREIGN KEY (agent_registration_id) REFERENCES agent_registrations(id);
ALTER TABLE agent_performance_records ADD FOREIGN KEY (agent_registration_id) REFERENCES agent_registrations(id);
ALTER TABLE agent_performance_records ADD FOREIGN KEY (hub_id) REFERENCES hubs(id);
-- Phase 12 — outcome_correlations, pattern_performance_records, adaptive_threshold_configs, learning_insights
ALTER TABLE outcome_correlations ADD FOREIGN KEY (hub_id) REFERENCES hubs(id);
ALTER TABLE pattern_performance_records ADD FOREIGN KEY (widget_pattern_id) REFERENCES widget_patterns(id);
ALTER TABLE pattern_performance_records ADD FOREIGN KEY (hub_id) REFERENCES hubs(id);
ALTER TABLE adaptive_threshold_configs ADD FOREIGN KEY (hub_id) REFERENCES hubs(id);
ALTER TABLE learning_insights ADD FOREIGN KEY (hub_id) REFERENCES hubs(id);