generated from coulomb/repo-seed
Implements the final phase of the IHF v0.1 specification: - WidgetOwnership: delegated ownership registry (local/delegated/global), append-only audit artefacts, ownership badge on widget show page - HubRoutingRule + RoutingEngine: priority-ordered inter-hub routing engine; null-inclusive category/widget-type matching; RouteNowAction for manual re-evaluation; RoutedCandidates view per hub - FederatedPolicyOverlay: draft → active → retired lifecycle; activated overlays are immutable (same pattern as Phase 6 contracts); policy compliance dashboard with decision coverage metrics - StewardshipRole: named governance roles per hub; point-in-time revocation pattern; hub and ops-board integration - ArchiveRecord + is_archived: soft-delete on widgets; lineage inspector traces full traceability chain (Widget → Events → Annotations → Candidates → Requirements → Decisions → Deployments → Signals + ArchiveRecord) - FederatedGovernanceDashboard: 5-panel autoRefresh org-wide governance view (ownership coverage, routing activity, policy compliance, stewardship coverage, archive activity) Schema: widget_ownerships, hub_routing_rules, federated_policy_overlays, stewardship_roles, archive_records; ALTER widgets ADD is_archived; ALTER requirement_candidates ADD routed_to_hub_id Migration: 1743638400-ihf-phase8-federated-hub-maturity.sql Tests: Phase 8 integration tests appended to Test/Integration.hs Docs: docs/phase8-summary.md; SCOPE.md updated to Phase 8 complete Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
89 lines
3.3 KiB
SQL
89 lines
3.3 KiB
SQL
-- IHF Phase 8 — Federated Hub Maturity
|
|
-- Workplan: IHUB-WP-0008
|
|
|
|
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),
|
|
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);
|
|
|
|
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),
|
|
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);
|
|
|
|
ALTER TABLE requirement_candidates
|
|
ADD COLUMN routed_to_hub_id UUID REFERENCES hubs(id);
|
|
|
|
CREATE INDEX requirement_candidates_routed_hub_idx
|
|
ON requirement_candidates (routed_to_hub_id)
|
|
WHERE routed_to_hub_id IS NOT NULL;
|
|
|
|
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);
|
|
|
|
CREATE TABLE stewardship_roles (
|
|
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
|
hub_id UUID NOT NULL REFERENCES hubs(id),
|
|
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;
|
|
|
|
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);
|
|
|
|
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;
|