generated from coulomb/repo-seed
docs: prepare ops-hub bootstrap handoff
This commit is contained in:
108
wiki/OpsHubBootstrapRunbook.md
Normal file
108
wiki/OpsHubBootstrapRunbook.md
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
# Ops Hub Bootstrap Runbook
|
||||||
|
|
||||||
|
Date: 2026-05-16
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
This runbook gives the operator-ready bootstrap path for `ops-hub`, the VSM
|
||||||
|
Operations / System 1 extension of Inter-Hub.
|
||||||
|
|
||||||
|
Use this when an authenticated Inter-Hub admin session or deployment migration
|
||||||
|
is available. The current public v2 API is not sufficient to create the hub,
|
||||||
|
manifest, API consumer, API key, or seed widgets by itself.
|
||||||
|
|
||||||
|
## Inputs
|
||||||
|
|
||||||
|
- Manifest draft: `wiki/ops-hub-manifest.draft.json`
|
||||||
|
- Widget seed: `wiki/ops-hub-widgets.seed.json`
|
||||||
|
- Migration fallback: `wiki/ops-hub-bootstrap.sql`
|
||||||
|
|
||||||
|
## Current Bootstrap Decision
|
||||||
|
|
||||||
|
Use the authenticated Inter-Hub admin UI first. Use the SQL migration fallback
|
||||||
|
only when a repeatable deployment-side bootstrap is needed before the v2 API is
|
||||||
|
hardened.
|
||||||
|
|
||||||
|
VSM classification is stored in the manifest capability description for now:
|
||||||
|
|
||||||
|
- `hub_family`: `vsm`
|
||||||
|
- `vsm_function`: `OPS`
|
||||||
|
- `vsm_system`: `S1`
|
||||||
|
|
||||||
|
Inter-Hub does not yet have first-class hub metadata columns for these values.
|
||||||
|
|
||||||
|
## UI Path
|
||||||
|
|
||||||
|
1. Log in to Inter-Hub at `https://hub.coulomb.social/NewSession`.
|
||||||
|
2. Open `/Hubs/new`.
|
||||||
|
3. Create the hub:
|
||||||
|
- Name: `Ops Hub`
|
||||||
|
- Slug: `ops-hub`
|
||||||
|
- Domain: `ops.coulomb.social`
|
||||||
|
- Kind: `domain`
|
||||||
|
4. Open `/HubCapabilityManifests/new?hubId=<ops-hub-id>`.
|
||||||
|
5. Create a draft manifest with:
|
||||||
|
- Version: `1.0`
|
||||||
|
- Capability description from `wiki/ops-hub-manifest.draft.json`
|
||||||
|
- Contact: operator/team contact
|
||||||
|
6. Edit the manifest and copy in:
|
||||||
|
- `declaredWidgetTypes`
|
||||||
|
- `declaredEventTypes`
|
||||||
|
- `declaredAnnotationCategories`
|
||||||
|
- `declaredPolicyScopes`
|
||||||
|
7. Activate the manifest.
|
||||||
|
8. Open `/ApiConsumers/new`.
|
||||||
|
9. Create an API consumer bound to the active ops manifest:
|
||||||
|
- Name: `ops-hub`
|
||||||
|
- Description: `API consumer for the VSM Operations hub`
|
||||||
|
- Scopes for the key: `framework:read hub:ops-hub:read hub:ops-hub:write`
|
||||||
|
10. Generate an API key and store it only in the operator secret store or local
|
||||||
|
environment. Do not commit it to Git.
|
||||||
|
11. Seed the widgets from `wiki/ops-hub-widgets.seed.json` through the UI or
|
||||||
|
migration fallback.
|
||||||
|
|
||||||
|
## Validation
|
||||||
|
|
||||||
|
After manifest activation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s https://hub.coulomb.social/api/v2/widget-types
|
||||||
|
curl -s https://hub.coulomb.social/api/v2/event-types
|
||||||
|
curl -s https://hub.coulomb.social/api/v2/annotation-categories
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: ops-owned vocabulary appears in the relevant registries.
|
||||||
|
|
||||||
|
After API key creation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s -X POST https://hub.coulomb.social/api/v2/token \
|
||||||
|
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||||
|
--data-urlencode "grant_type=client_credentials" \
|
||||||
|
--data-urlencode "client_id=<api-consumer-id>" \
|
||||||
|
--data-urlencode "client_secret=<static-api-key>" \
|
||||||
|
--data-urlencode "scope=framework:read hub:ops-hub:read hub:ops-hub:write"
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: a short-lived access token is returned.
|
||||||
|
|
||||||
|
After widget seeding:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s https://hub.coulomb.social/api/v2/hub-registry
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: `ops-hub` is visible, and the operator can see the seeded widgets in
|
||||||
|
the authenticated UI.
|
||||||
|
|
||||||
|
## Known Blockers
|
||||||
|
|
||||||
|
- The live public v2 API has no `POST /api/v2/hubs`.
|
||||||
|
- The live public v2 API has no `POST /api/v2/widgets`.
|
||||||
|
- There are no v2 endpoints for manifest creation/activation.
|
||||||
|
- There are no v2 endpoints for API consumer or key creation.
|
||||||
|
- There is no `/api/v2/policy-scopes`.
|
||||||
|
- Interaction event create currently does not persist submitted metadata.
|
||||||
|
- Webhook dispatch currently uses the hard-coded `"clicked"` event type.
|
||||||
|
|
||||||
|
These are tracked by HF-WP-0001 T10 for Inter-Hub hardening.
|
||||||
268
wiki/ops-hub-bootstrap.sql
Normal file
268
wiki/ops-hub-bootstrap.sql
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
-- 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
|
||||||
|
--
|
||||||
|
-- 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;
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
65
wiki/ops-hub-manifest.draft.json
Normal file
65
wiki/ops-hub-manifest.draft.json
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"hub": {
|
||||||
|
"name": "Ops Hub",
|
||||||
|
"slug": "ops-hub",
|
||||||
|
"domain": "ops.coulomb.social",
|
||||||
|
"hubKind": "domain"
|
||||||
|
},
|
||||||
|
"manifestVersion": "1.0",
|
||||||
|
"capabilityDescription": "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.",
|
||||||
|
"contact": "operator",
|
||||||
|
"declaredWidgetTypes": [
|
||||||
|
"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"
|
||||||
|
],
|
||||||
|
"declaredEventTypes": [
|
||||||
|
"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"
|
||||||
|
],
|
||||||
|
"declaredAnnotationCategories": [
|
||||||
|
"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"
|
||||||
|
],
|
||||||
|
"declaredPolicyScopes": [
|
||||||
|
"ops-local",
|
||||||
|
"ops-transitional-prod",
|
||||||
|
"ops-production",
|
||||||
|
"ops-threephoenix",
|
||||||
|
"ops-registry",
|
||||||
|
"ops-secrets",
|
||||||
|
"ops-backup-retention"
|
||||||
|
]
|
||||||
|
}
|
||||||
100
wiki/ops-hub-widgets.seed.json
Normal file
100
wiki/ops-hub-widgets.seed.json
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Local Environment",
|
||||||
|
"widgetType": "ops-environment",
|
||||||
|
"capabilityRef": "ops:environment:local",
|
||||||
|
"viewContext": "ops-hub/environments/local",
|
||||||
|
"policyScope": "ops-local"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CoulombCore Environment",
|
||||||
|
"widgetType": "ops-environment",
|
||||||
|
"capabilityRef": "ops:environment:coulombcore",
|
||||||
|
"viewContext": "ops-hub/environments/coulombcore",
|
||||||
|
"policyScope": "ops-transitional-prod"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Railiance01 Environment",
|
||||||
|
"widgetType": "ops-environment",
|
||||||
|
"capabilityRef": "ops:environment:railiance01",
|
||||||
|
"viewContext": "ops-hub/environments/railiance01",
|
||||||
|
"policyScope": "ops-threephoenix"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ThreePhoenix Production Environment",
|
||||||
|
"widgetType": "ops-environment",
|
||||||
|
"capabilityRef": "ops:environment:threephoenix-prod",
|
||||||
|
"viewContext": "ops-hub/environments/threephoenix-prod",
|
||||||
|
"policyScope": "ops-production"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CoulombCore Host",
|
||||||
|
"widgetType": "ops-host",
|
||||||
|
"capabilityRef": "ops:host:coulombcore",
|
||||||
|
"viewContext": "ops-hub/hosts/coulombcore",
|
||||||
|
"policyScope": "ops-transitional-prod"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Railiance01 Host",
|
||||||
|
"widgetType": "ops-host",
|
||||||
|
"capabilityRef": "ops:host:railiance01",
|
||||||
|
"viewContext": "ops-hub/hosts/railiance01",
|
||||||
|
"policyScope": "ops-threephoenix"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Operations Service Catalog",
|
||||||
|
"widgetType": "ops-service-catalog",
|
||||||
|
"capabilityRef": "ops:service-catalog",
|
||||||
|
"viewContext": "ops-hub/service-catalog",
|
||||||
|
"policyScope": "ops-production"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Gitea Service",
|
||||||
|
"widgetType": "ops-service",
|
||||||
|
"capabilityRef": "ops:service:gitea",
|
||||||
|
"viewContext": "ops-hub/services/gitea",
|
||||||
|
"policyScope": "ops-transitional-prod"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "State Hub Service",
|
||||||
|
"widgetType": "ops-service",
|
||||||
|
"capabilityRef": "ops:service:state-hub",
|
||||||
|
"viewContext": "ops-hub/services/state-hub",
|
||||||
|
"policyScope": "ops-local"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Inter-Hub Service",
|
||||||
|
"widgetType": "ops-service",
|
||||||
|
"capabilityRef": "ops:service:inter-hub",
|
||||||
|
"viewContext": "ops-hub/services/inter-hub",
|
||||||
|
"policyScope": "ops-production"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Gitea Registry Endpoint",
|
||||||
|
"widgetType": "ops-endpoint",
|
||||||
|
"capabilityRef": "ops:endpoint:gitea-registry",
|
||||||
|
"viewContext": "ops-hub/endpoints/gitea-registry",
|
||||||
|
"policyScope": "ops-registry"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Gitea Registry Readiness",
|
||||||
|
"widgetType": "ops-readiness-gate",
|
||||||
|
"capabilityRef": "ops:readiness:gitea-registry",
|
||||||
|
"viewContext": "ops-hub/readiness/gitea-registry",
|
||||||
|
"policyScope": "ops-registry"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "State Hub Cluster Deploy Readiness",
|
||||||
|
"widgetType": "ops-readiness-gate",
|
||||||
|
"capabilityRef": "ops:readiness:state-hub-cluster-deploy",
|
||||||
|
"viewContext": "ops-hub/readiness/state-hub-cluster-deploy",
|
||||||
|
"policyScope": "ops-production"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CoulombCore to ThreePhoenix Migration",
|
||||||
|
"widgetType": "ops-migration-wave",
|
||||||
|
"capabilityRef": "ops:migration:coulombcore-to-threephoenix",
|
||||||
|
"viewContext": "ops-hub/migrations/coulombcore-to-threephoenix",
|
||||||
|
"policyScope": "ops-threephoenix"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -365,7 +365,7 @@ Output: `Confirmed Bootstrap Path` section in this workplan.
|
|||||||
|
|
||||||
```task
|
```task
|
||||||
id: HF-WP-0001-T02
|
id: HF-WP-0001-T02
|
||||||
status: todo
|
status: blocked
|
||||||
priority: high
|
priority: high
|
||||||
state_hub_task_id: "8e9bd9b2-54fc-49a4-8bb8-11c8577be48d"
|
state_hub_task_id: "8e9bd9b2-54fc-49a4-8bb8-11c8577be48d"
|
||||||
```
|
```
|
||||||
@@ -388,13 +388,22 @@ fields as an Inter-Hub API/model gap.
|
|||||||
Done when: `ops-hub` appears in `/Hubs` and `/api/v2/hub-registry` after
|
Done when: `ops-hub` appears in `/Hubs` and `/api/v2/hub-registry` after
|
||||||
authentication, and a human can tell that it is the VSM Operations hub.
|
authentication, and a human can tell that it is the VSM Operations hub.
|
||||||
|
|
||||||
|
Blocked until: an authenticated Inter-Hub admin session or deployment-side
|
||||||
|
migration is available.
|
||||||
|
|
||||||
|
Prepared artifacts:
|
||||||
|
|
||||||
|
- `wiki/OpsHubBootstrapRunbook.md`
|
||||||
|
- `wiki/ops-hub-manifest.draft.json`
|
||||||
|
- `wiki/ops-hub-bootstrap.sql`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### T03 — Activate the ops-hub capability manifest
|
### T03 — Activate the ops-hub capability manifest
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: HF-WP-0001-T03
|
id: HF-WP-0001-T03
|
||||||
status: todo
|
status: blocked
|
||||||
priority: high
|
priority: high
|
||||||
state_hub_task_id: "55f5aeed-21c3-4a83-bc78-f90f92c7d597"
|
state_hub_task_id: "55f5aeed-21c3-4a83-bc78-f90f92c7d597"
|
||||||
```
|
```
|
||||||
@@ -421,13 +430,18 @@ Validation:
|
|||||||
|
|
||||||
Done when: the manifest status is `active` and no type conflicts remain.
|
Done when: the manifest status is `active` and no type conflicts remain.
|
||||||
|
|
||||||
|
Blocked until: the `ops-hub` row exists in Inter-Hub and an authenticated
|
||||||
|
operator or migration can create and activate the manifest.
|
||||||
|
|
||||||
|
Prepared artifact: `wiki/ops-hub-manifest.draft.json`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### T04 — Create ops-hub API consumer and key
|
### T04 — Create ops-hub API consumer and key
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: HF-WP-0001-T04
|
id: HF-WP-0001-T04
|
||||||
status: todo
|
status: blocked
|
||||||
priority: high
|
priority: high
|
||||||
state_hub_task_id: "ad08e729-8562-4a02-8bf6-dcdfebe430c8"
|
state_hub_task_id: "ad08e729-8562-4a02-8bf6-dcdfebe430c8"
|
||||||
```
|
```
|
||||||
@@ -444,13 +458,17 @@ Store the key only in the operator secret store or local env file, never in Git.
|
|||||||
Done when: `POST /api/v2/token` can exchange the static key for a short-lived
|
Done when: `POST /api/v2/token` can exchange the static key for a short-lived
|
||||||
access token and `GET /api/v2/hub-registry` works with that token.
|
access token and `GET /api/v2/hub-registry` works with that token.
|
||||||
|
|
||||||
|
Blocked until: an authenticated operator creates the API key and stores the
|
||||||
|
full static key outside Git. The SQL fallback intentionally creates only the
|
||||||
|
consumer row, not the one-time visible secret.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### T05 — Seed first governed ops widgets
|
### T05 — Seed first governed ops widgets
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: HF-WP-0001-T05
|
id: HF-WP-0001-T05
|
||||||
status: todo
|
status: blocked
|
||||||
priority: high
|
priority: high
|
||||||
state_hub_task_id: "d303884d-d1f6-4fd0-a4ec-97afe6162164"
|
state_hub_task_id: "d303884d-d1f6-4fd0-a4ec-97afe6162164"
|
||||||
```
|
```
|
||||||
@@ -478,6 +496,13 @@ migration and record that as an API gap.
|
|||||||
Done when: the widgets appear under `ops-hub` and can accept interaction events
|
Done when: the widgets appear under `ops-hub` and can accept interaction events
|
||||||
and annotations.
|
and annotations.
|
||||||
|
|
||||||
|
Blocked until: `ops-hub` and its active manifest exist in Inter-Hub.
|
||||||
|
|
||||||
|
Prepared artifacts:
|
||||||
|
|
||||||
|
- `wiki/ops-hub-widgets.seed.json`
|
||||||
|
- `wiki/ops-hub-bootstrap.sql`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### T06 — Build the first ops inventory artifact
|
### T06 — Build the first ops inventory artifact
|
||||||
@@ -517,7 +542,7 @@ Output: `wiki/OpsHubInventory.md`.
|
|||||||
|
|
||||||
```task
|
```task
|
||||||
id: HF-WP-0001-T07
|
id: HF-WP-0001-T07
|
||||||
status: todo
|
status: blocked
|
||||||
priority: medium
|
priority: medium
|
||||||
state_hub_task_id: "ed3e0396-b16d-40c2-9519-e755ad6241eb"
|
state_hub_task_id: "ed3e0396-b16d-40c2-9519-e755ad6241eb"
|
||||||
```
|
```
|
||||||
@@ -544,6 +569,10 @@ Suggested event:
|
|||||||
Done when: the Gitea registry readiness event is visible in Inter-Hub and
|
Done when: the Gitea registry readiness event is visible in Inter-Hub and
|
||||||
traceable back to the Railiance workplan.
|
traceable back to the Railiance workplan.
|
||||||
|
|
||||||
|
Blocked until: the `ops-endpoint-gitea-registry` widget exists, the
|
||||||
|
`ops-endpoint-verified` event type is active, and an ops-hub API key is
|
||||||
|
available to the operator.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### T08 — Define the ops-hub readiness gate model for ThreePhoenix migration
|
### T08 — Define the ops-hub readiness gate model for ThreePhoenix migration
|
||||||
@@ -604,7 +633,7 @@ needed.
|
|||||||
|
|
||||||
```task
|
```task
|
||||||
id: HF-WP-0001-T10
|
id: HF-WP-0001-T10
|
||||||
status: todo
|
status: in_progress
|
||||||
priority: high
|
priority: high
|
||||||
target_repo: inter-hub
|
target_repo: inter-hub
|
||||||
state_hub_task_id: "7fa54508-7add-4885-8913-12edaadc4d92"
|
state_hub_task_id: "7fa54508-7add-4885-8913-12edaadc4d92"
|
||||||
@@ -641,6 +670,9 @@ Recommended Inter-Hub improvements:
|
|||||||
Done when: the next VSM hub can be created from a script using documented API
|
Done when: the next VSM hub can be created from a script using documented API
|
||||||
calls and without direct DB access.
|
calls and without direct DB access.
|
||||||
|
|
||||||
|
Linked Inter-Hub workplan:
|
||||||
|
`inter-hub/workplans/IHUB-WP-0019-vsm-hub-bootstrap-api.md`.
|
||||||
|
|
||||||
## Initial Acceptance Criteria
|
## Initial Acceptance Criteria
|
||||||
|
|
||||||
This workplan is complete when:
|
This workplan is complete when:
|
||||||
|
|||||||
Reference in New Issue
Block a user