-- ops-hub bootstrap fallback for Inter-Hub.
--
-- Use only when authenticated UI bootstrap is not practical and a
-- deployment-side migration/bootstrap is acceptable.
--
-- This creates:
-- - Hub row
-- - Active HubCapabilityManifest
-- - Owned type registry entries
-- - ApiConsumer row
-- - Seed widgets
-- - Initial widget versions for the seed widgets
-- - First Gitea registry readiness event
--
-- It intentionally does not create an ApiKey. Generate the key through the
-- authenticated Inter-Hub UI so the full static key can be shown once and
-- stored in the operator secret store.

BEGIN;

INSERT INTO hubs (slug, name, domain, hub_kind)
VALUES ('ops-hub', 'Ops Hub', 'ops.coulomb.social', 'domain')
ON CONFLICT (slug) DO UPDATE
SET name = EXCLUDED.name,
    domain = EXCLUDED.domain,
    hub_kind = EXCLUDED.hub_kind;

-- Newer inter-hub schemas have first-class VSM metadata columns. Keep this
-- block conditional so the bootstrap still works against an older deployment
-- where the metadata is only carried by the manifest description.
DO $$
BEGIN
    IF EXISTS (
        SELECT 1
        FROM information_schema.columns
        WHERE table_name = 'hubs'
          AND column_name = 'hub_family'
    ) THEN
        UPDATE hubs
        SET hub_family = 'vsm',
            vsm_function = 'OPS',
            vsm_system = '1'
        WHERE slug = 'ops-hub';
    END IF;
END $$;

WITH hub AS (
    SELECT id FROM hubs WHERE slug = 'ops-hub'
)
INSERT INTO hub_capability_manifests (
    hub_id,
    manifest_version,
    declared_widget_types,
    declared_event_types,
    declared_annotation_categories,
    declared_policy_scopes,
    capability_description,
    contact,
    status,
    activated_at
)
SELECT
    hub.id,
    '1.0',
    '[
      "ops-environment",
      "ops-host",
      "ops-cluster",
      "ops-service",
      "ops-service-catalog",
      "ops-endpoint",
      "ops-release",
      "ops-backup-set",
      "ops-secret-set",
      "ops-runbook",
      "ops-incident",
      "ops-readiness-gate",
      "ops-migration-wave",
      "ops-risk"
    ]'::jsonb,
    '[
      "ops-inventory-registered",
      "ops-inventory-updated",
      "ops-service-discovered",
      "ops-health-checked",
      "ops-release-observed",
      "ops-endpoint-verified",
      "ops-backup-verified",
      "ops-restore-tested",
      "ops-runbook-executed",
      "ops-drift-detected",
      "ops-risk-raised",
      "ops-risk-accepted",
      "ops-readiness-gate-updated",
      "ops-migration-gate-passed",
      "ops-migration-gate-failed"
    ]'::jsonb,
    '[
      "ops-drift",
      "ops-service-catalog-gap",
      "ops-backup-gap",
      "ops-security-gap",
      "ops-routing-gap",
      "ops-secret-gap",
      "ops-readiness-blocker",
      "ops-migration-risk",
      "ops-observability-gap",
      "ops-recovery-gap"
    ]'::jsonb,
    '[
      "ops-local",
      "ops-transitional-prod",
      "ops-production",
      "ops-threephoenix",
      "ops-registry",
      "ops-secrets",
      "ops-backup-retention"
    ]'::jsonb,
    'VSM Operations / System 1 hub for operational truth and evidence. Metadata: hub_family=vsm; vsm_function=OPS; vsm_system=S1; scope=operational truth, service catalog, readiness, incidents, runbooks, migration waves, and evidence events.',
    'operator',
    'active',
    NOW()
FROM hub
ON CONFLICT (hub_id) DO UPDATE
SET manifest_version = EXCLUDED.manifest_version,
    declared_widget_types = EXCLUDED.declared_widget_types,
    declared_event_types = EXCLUDED.declared_event_types,
    declared_annotation_categories = EXCLUDED.declared_annotation_categories,
    declared_policy_scopes = EXCLUDED.declared_policy_scopes,
    capability_description = EXCLUDED.capability_description,
    contact = EXCLUDED.contact,
    status = EXCLUDED.status,
    activated_at = COALESCE(hub_capability_manifests.activated_at, NOW()),
    updated_at = NOW();

WITH hub AS (
    SELECT id FROM hubs WHERE slug = 'ops-hub'
), names(name) AS (
    VALUES
      ('ops-environment'),
      ('ops-host'),
      ('ops-cluster'),
      ('ops-service'),
      ('ops-service-catalog'),
      ('ops-endpoint'),
      ('ops-release'),
      ('ops-backup-set'),
      ('ops-secret-set'),
      ('ops-runbook'),
      ('ops-incident'),
      ('ops-readiness-gate'),
      ('ops-migration-wave'),
      ('ops-risk')
)
INSERT INTO widget_type_registry (name, label, owner_hub_id, status)
SELECT names.name, names.name, hub.id, 'active'
FROM names CROSS JOIN hub
ON CONFLICT (name) DO NOTHING;

WITH hub AS (
    SELECT id FROM hubs WHERE slug = 'ops-hub'
), names(name) AS (
    VALUES
      ('ops-inventory-registered'),
      ('ops-inventory-updated'),
      ('ops-service-discovered'),
      ('ops-health-checked'),
      ('ops-release-observed'),
      ('ops-endpoint-verified'),
      ('ops-backup-verified'),
      ('ops-restore-tested'),
      ('ops-runbook-executed'),
      ('ops-drift-detected'),
      ('ops-risk-raised'),
      ('ops-risk-accepted'),
      ('ops-readiness-gate-updated'),
      ('ops-migration-gate-passed'),
      ('ops-migration-gate-failed')
)
INSERT INTO event_type_registry (name, label, owner_hub_id, status)
SELECT names.name, names.name, hub.id, 'active'
FROM names CROSS JOIN hub
ON CONFLICT (name) DO NOTHING;

WITH hub AS (
    SELECT id FROM hubs WHERE slug = 'ops-hub'
), names(name) AS (
    VALUES
      ('ops-drift'),
      ('ops-service-catalog-gap'),
      ('ops-backup-gap'),
      ('ops-security-gap'),
      ('ops-routing-gap'),
      ('ops-secret-gap'),
      ('ops-readiness-blocker'),
      ('ops-migration-risk'),
      ('ops-observability-gap'),
      ('ops-recovery-gap')
)
INSERT INTO annotation_category_registry (name, label, owner_hub_id, status)
SELECT names.name, names.name, hub.id, 'active'
FROM names CROSS JOIN hub
ON CONFLICT (name) DO NOTHING;

WITH hub AS (
    SELECT id FROM hubs WHERE slug = 'ops-hub'
), names(name) AS (
    VALUES
      ('ops-local'),
      ('ops-transitional-prod'),
      ('ops-production'),
      ('ops-threephoenix'),
      ('ops-registry'),
      ('ops-secrets'),
      ('ops-backup-retention')
)
INSERT INTO policy_scope_registry (name, label, owner_hub_id, status)
SELECT names.name, names.name, hub.id, 'active'
FROM names CROSS JOIN hub
ON CONFLICT (name) DO NOTHING;

WITH manifest AS (
    SELECT id FROM hub_capability_manifests
    WHERE hub_id = (SELECT id FROM hubs WHERE slug = 'ops-hub')
)
INSERT INTO api_consumers (
    name,
    description,
    hub_capability_manifest_id,
    rate_limit_per_minute,
    quota_per_day,
    is_active
)
SELECT
    'ops-hub',
    'API consumer for the VSM Operations hub',
    manifest.id,
    60,
    10000,
    TRUE
FROM manifest
WHERE NOT EXISTS (
    SELECT 1 FROM api_consumers WHERE name = 'ops-hub'
);

WITH hub AS (
    SELECT id FROM hubs WHERE slug = 'ops-hub'
), seed(name, widget_type, capability_ref, view_context, policy_scope) AS (
    VALUES
      ('Local Environment', 'ops-environment', 'ops:environment:local', 'ops-hub/environments/local', 'ops-local'),
      ('CoulombCore Environment', 'ops-environment', 'ops:environment:coulombcore', 'ops-hub/environments/coulombcore', 'ops-transitional-prod'),
      ('Railiance01 Environment', 'ops-environment', 'ops:environment:railiance01', 'ops-hub/environments/railiance01', 'ops-threephoenix'),
      ('ThreePhoenix Production Environment', 'ops-environment', 'ops:environment:threephoenix-prod', 'ops-hub/environments/threephoenix-prod', 'ops-production'),
      ('CoulombCore Host', 'ops-host', 'ops:host:coulombcore', 'ops-hub/hosts/coulombcore', 'ops-transitional-prod'),
      ('Railiance01 Host', 'ops-host', 'ops:host:railiance01', 'ops-hub/hosts/railiance01', 'ops-threephoenix'),
      ('Operations Service Catalog', 'ops-service-catalog', 'ops:service-catalog', 'ops-hub/service-catalog', 'ops-production'),
      ('Gitea Service', 'ops-service', 'ops:service:gitea', 'ops-hub/services/gitea', 'ops-transitional-prod'),
      ('State Hub Service', 'ops-service', 'ops:service:state-hub', 'ops-hub/services/state-hub', 'ops-local'),
      ('Inter-Hub Service', 'ops-service', 'ops:service:inter-hub', 'ops-hub/services/inter-hub', 'ops-production'),
      ('Gitea Registry Endpoint', 'ops-endpoint', 'ops:endpoint:gitea-registry', 'ops-hub/endpoints/gitea-registry', 'ops-registry'),
      ('Gitea Registry Readiness', 'ops-readiness-gate', 'ops:readiness:gitea-registry', 'ops-hub/readiness/gitea-registry', 'ops-registry'),
      ('State Hub Cluster Deploy Readiness', 'ops-readiness-gate', 'ops:readiness:state-hub-cluster-deploy', 'ops-hub/readiness/state-hub-cluster-deploy', 'ops-production'),
      ('CoulombCore to ThreePhoenix Migration', 'ops-migration-wave', 'ops:migration:coulombcore-to-threephoenix', 'ops-hub/migrations/coulombcore-to-threephoenix', 'ops-threephoenix')
)
INSERT INTO widgets (
    hub_id,
    name,
    widget_type,
    capability_ref,
    view_context,
    policy_scope,
    status
)
SELECT
    hub.id,
    seed.name,
    seed.widget_type,
    seed.capability_ref,
    seed.view_context,
    seed.policy_scope,
    'active'
FROM seed CROSS JOIN hub
WHERE NOT EXISTS (
    SELECT 1 FROM widgets
    WHERE hub_id = hub.id
      AND capability_ref = seed.capability_ref
);

WITH hub AS (
    SELECT id FROM hubs WHERE slug = 'ops-hub'
), seeded_widgets AS (
    SELECT
        w.id,
        w.name,
        w.widget_type,
        w.hub_id,
        w.capability_ref,
        w.view_context,
        w.policy_scope,
        w.status,
        w.version
    FROM widgets w
    JOIN hub ON hub.id = w.hub_id
    WHERE w.capability_ref IN (
      'ops:environment:local',
      'ops:environment:coulombcore',
      'ops:environment:railiance01',
      'ops:environment:threephoenix-prod',
      'ops:host:coulombcore',
      'ops:host:railiance01',
      'ops:service-catalog',
      'ops:service:gitea',
      'ops:service:state-hub',
      'ops:service:inter-hub',
      'ops:endpoint:gitea-registry',
      'ops:readiness:gitea-registry',
      'ops:readiness:state-hub-cluster-deploy',
      'ops:migration:coulombcore-to-threephoenix'
    )
)
INSERT INTO widget_versions (
    widget_id,
    version,
    schema_snapshot
)
SELECT
    seeded_widgets.id,
    1,
    jsonb_build_object(
        'name', seeded_widgets.name,
        'widget_type', seeded_widgets.widget_type,
        'hub_id', seeded_widgets.hub_id,
        'capability_ref', seeded_widgets.capability_ref,
        'view_context', seeded_widgets.view_context,
        'policy_scope', seeded_widgets.policy_scope,
        'status', seeded_widgets.status,
        'version', seeded_widgets.version
    )
FROM seeded_widgets
WHERE NOT EXISTS (
    SELECT 1
    FROM widget_versions
    WHERE widget_id = seeded_widgets.id
      AND version = 1
);

WITH readiness_widget AS (
    SELECT id
    FROM widgets
    WHERE capability_ref = 'ops:readiness:gitea-registry'
      AND hub_id = (SELECT id FROM hubs WHERE slug = 'ops-hub')
)
INSERT INTO interaction_events (
    widget_id,
    event_type,
    actor_type,
    view_context_ref,
    metadata
)
SELECT
    readiness_widget.id,
    'ops-endpoint-verified',
    'api',
    'railiance-apps/workplans/RAIL-AP-WP-0001',
    jsonb_build_object(
        'vsmFunction', 'OPS',
        'vsmSystem', 'S1',
        'endpoint', 'https://gitea.coulomb.social/v2/',
        'expectedStatus', 401,
        'observedHeader', 'Docker-Distribution-Api-Version: registry/2.0',
        'recordedBy', 'helix-forge/wiki/ops-hub-bootstrap.sql'
    )
FROM readiness_widget
WHERE NOT EXISTS (
    SELECT 1
    FROM interaction_events
    WHERE widget_id = readiness_widget.id
      AND event_type = 'ops-endpoint-verified'
      AND view_context_ref = 'railiance-apps/workplans/RAIL-AP-WP-0001'
);

COMMIT;
