generated from coulomb/repo-seed
Record ops-hub bootstrap progress and add API bootstrap helper
Document the 2026-06-15 attended Inter-Hub bootstrap: hub row, active manifest, widget seeding, and runtime API key creation. Add scripts/ops-hub-bootstrap-api.py, extend the SQL fallback for widget versions and the first Gitea event, refresh OpsHubBootstrapRunbook, and inline credential-routing guidance for agents.
This commit is contained in:
@@ -8,8 +8,9 @@ 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.
|
||||
is available. The current public v2 API now exposes the supported bootstrap
|
||||
surface; creation and mutation calls require an Inter-Hub operator/admin API
|
||||
key.
|
||||
|
||||
As of 2026-06-06, implementation work for `ops-hub` belongs in the dedicated
|
||||
repo at `/home/worsch/ops-hub` with remote `gitea-remote:coulomb/ops-hub.git`.
|
||||
@@ -25,31 +26,23 @@ implementation repo ports or supersedes it.
|
||||
|
||||
## Current Bootstrap Decision
|
||||
|
||||
Prefer the supported Inter-Hub bootstrap API once production exposes the
|
||||
current API surface. Do not proceed with manual DB seeding unless the operator
|
||||
explicitly chooses that fallback. Until the production API gate passes, the
|
||||
authenticated Inter-Hub admin UI and SQL migration remain fallback paths for
|
||||
attended operator use only.
|
||||
Prefer the supported Inter-Hub bootstrap API for hub, manifest, API consumer,
|
||||
and runtime key creation. Use the idempotent SQL fallback for seed widgets and
|
||||
initial evidence only when the live API hits a known server-side bootstrap bug
|
||||
and the operator explicitly approves that fallback.
|
||||
|
||||
Production API gate:
|
||||
Latest check, 2026-06-14 after Inter-Hub deployment:
|
||||
|
||||
- `https://hub.coulomb.social/api/v2/hubs` returns `401` unauthenticated, not
|
||||
`404`.
|
||||
- `https://hub.coulomb.social/api/v2/hubs` returns `200` with a public,
|
||||
paginated hub list.
|
||||
- OpenAPI lists `/hubs`, `/hub-capability-manifests`, `/api-consumers`, and
|
||||
`/policy-scopes`.
|
||||
- After the gate passes, run the supported bootstrap/smoke path from the
|
||||
relevant `inter-hub` or `ops-hub` tooling with `IHUB_BASE` and an operator
|
||||
key.
|
||||
|
||||
Latest check, 2026-06-14:
|
||||
|
||||
- `ops-hub/scripts/interhub-gate-probe.py` still reports the production gate
|
||||
closed.
|
||||
- `GET /api/v2/hubs` returns `404`.
|
||||
- Live OpenAPI still omits `/hubs`, `/hub-capability-manifests`,
|
||||
`/api-consumers`, and `/policy-scopes`.
|
||||
- Do not run the preferred API bootstrap path until the current Inter-Hub API
|
||||
is deployed, unless the operator explicitly chooses the SQL fallback.
|
||||
- Hub and policy-scope list reads are public. Hub creation, manifest
|
||||
creation/activation, API consumer/key creation, widget creation, and event
|
||||
submission require `Authorization: Bearer <key>`.
|
||||
- The old `ops-hub/scripts/interhub-gate-probe.py` expectation that
|
||||
unauthenticated `GET /api/v2/hubs` must return `401` is stale. The deployed
|
||||
contract is public-read/authenticated-write.
|
||||
|
||||
VSM classification is stored in the manifest capability description for now:
|
||||
|
||||
@@ -61,6 +54,120 @@ Newer Inter-Hub schemas have first-class hub metadata columns for these values.
|
||||
The SQL fallback sets those columns when present and still carries the same
|
||||
classification in the manifest description for older deployments.
|
||||
|
||||
Latest bootstrap result, 2026-06-15:
|
||||
|
||||
- `scripts/ops-hub-bootstrap-api.py` created/reused the `ops-hub` hub row,
|
||||
active manifest, runtime API consumer, and display-once runtime API key.
|
||||
- `POST /api/v2/widgets` failed with an Inter-Hub `COUNT(*)` decode error in
|
||||
type-registry validation.
|
||||
- The operator-approved SQL fallback seeded 14 widgets, 14 initial widget
|
||||
versions, and the first Gitea registry readiness event.
|
||||
- The runtime key can be exchanged through `POST /api/v2/token`, can read all
|
||||
14 widgets through `GET /api/v2/widgets`, and can read the first event
|
||||
through `GET /api/v2/interaction-events`.
|
||||
- `GET /api/v2/hub-registry` currently returns HTTP 500 because Inter-Hub
|
||||
decodes `COUNT(*)` from `api_request_log` as `Int` while PostgreSQL returns
|
||||
`bigint`.
|
||||
|
||||
## Inter-Hub Operator Key
|
||||
|
||||
`IHUB_OPERATOR_KEY` is an existing Inter-Hub API key or short-lived access
|
||||
token accepted by v2 endpoints as:
|
||||
|
||||
```text
|
||||
Authorization: Bearer <key>
|
||||
```
|
||||
|
||||
It is needed only for privileged bootstrap writes:
|
||||
|
||||
- creating or reusing the `ops-hub` hub row;
|
||||
- creating and activating the capability manifest;
|
||||
- creating the `ops-hub` runtime `ApiConsumer`;
|
||||
- minting the display-once runtime API key;
|
||||
- creating widgets and submitting the first event.
|
||||
|
||||
The operator key is not the long-term `ops-hub` runtime credential. It should
|
||||
be used for the attended bootstrap only, then normal `ops-hub` traffic should
|
||||
use the narrower runtime key created during bootstrap.
|
||||
|
||||
Allowed sources:
|
||||
|
||||
1. Retrieve an existing Inter-Hub operator/admin key from the approved secret
|
||||
store, if one has already been created. After `HF-WP-0002` is deployed,
|
||||
the intended browser path is `https://bao.coulomb.social` with KeyCape auth
|
||||
path `netkingdom` and role `platform-admin`. The older `keycape` auth path
|
||||
may remain available as a compatibility alias.
|
||||
2. If no such key exists, log in to the Inter-Hub admin UI and create an
|
||||
operator/bootstrap `ApiConsumer` and API key. The full key is display-once;
|
||||
store it immediately in the approved secret store.
|
||||
3. NetKingdom/OpenBao may provide the key only as the secret-custody path once
|
||||
the key exists and an appropriate policy/path is defined. The
|
||||
`net-kingdom` Git repository must not contain the key.
|
||||
|
||||
`net-kingdom-pg-1` is only the PostgreSQL pod used by the SQL fallback. It is
|
||||
not by itself the source of an Inter-Hub operator key.
|
||||
|
||||
When using the OpenBao browser UI, inspect metadata/path presence first, for
|
||||
example under:
|
||||
|
||||
```text
|
||||
platform/operators/
|
||||
platform/operators/inter-hub/
|
||||
```
|
||||
|
||||
Do not copy secret values into Git, State Hub, chat, shell history, or this
|
||||
runbook. Store display-once Inter-Hub and `ops-hub` runtime keys directly in
|
||||
the approved secret path.
|
||||
|
||||
For an attended local run, enter the key in a trusted shell without echoing it:
|
||||
|
||||
```bash
|
||||
export IHUB_BASE="https://hub.coulomb.social"
|
||||
read -rsp "Inter-Hub operator key: " IHUB_OPERATOR_KEY
|
||||
echo
|
||||
export IHUB_OPERATOR_KEY
|
||||
```
|
||||
|
||||
The preferred HelixForge helper uses the prepared manifest and widget seed
|
||||
artifacts instead of the smaller one-widget smoke fixture:
|
||||
|
||||
```bash
|
||||
umask 077
|
||||
IHUB_KEY_FILE=$(mktemp)
|
||||
# Paste the OpenBao value into this file without printing it to the terminal.
|
||||
read -rsp "Inter-Hub operator key: " IHUB_OPERATOR_KEY
|
||||
printf '%s' "$IHUB_OPERATOR_KEY" > "$IHUB_KEY_FILE"
|
||||
unset IHUB_OPERATOR_KEY
|
||||
echo
|
||||
|
||||
IHUB_BASE="https://hub.coulomb.social" \
|
||||
IHUB_OPERATOR_KEY_FILE="$IHUB_KEY_FILE" \
|
||||
python3 scripts/ops-hub-bootstrap-api.py
|
||||
```
|
||||
|
||||
The helper creates/reuses the `ops-hub` hub row, activates the full
|
||||
HelixForge manifest, creates the `ops-hub` API consumer, creates the runtime
|
||||
API key if needed, creates any missing seed widgets, and submits the first
|
||||
Gitea registry readiness event. If it creates a new `ops-hub` runtime API key,
|
||||
it writes the full key to a 0600 temp file and prints only the path and key
|
||||
prefix. Store that runtime key immediately in OpenBao, for example:
|
||||
|
||||
```text
|
||||
platform/operators/ops-hub/runtime
|
||||
field: OPS_HUB_KEY
|
||||
```
|
||||
|
||||
After storing both keys in OpenBao, remove local temp files:
|
||||
|
||||
```bash
|
||||
rm -f "$IHUB_KEY_FILE" "<runtime-key-file-printed-by-helper>"
|
||||
unset IHUB_KEY_FILE
|
||||
```
|
||||
|
||||
`/home/worsch/inter-hub/scripts/ops-hub-bootstrap-smoke.py` remains useful as
|
||||
a narrow source-side smoke proof, but it creates a one-widget fixture rather
|
||||
than the full HF-WP-0001 Operations vocabulary.
|
||||
|
||||
As of the 2026-05-19 access check, the workstation kubeconfig only points at
|
||||
CoulombCore (`92.205.130.254`) and does not include the Railiance01
|
||||
(`92.205.62.239`) cluster where `hub.coulomb.social` resolves. SSH key access
|
||||
@@ -118,9 +225,10 @@ kubectl exec -i -n databases net-kingdom-pg-1 -- \
|
||||
```
|
||||
|
||||
The SQL fallback creates the hub, active manifest, registry entries, API
|
||||
consumer row, and seed widgets. It does not create the one-time visible static
|
||||
API key; generate that in the authenticated Inter-Hub UI and store it outside
|
||||
Git.
|
||||
consumer row, seed widgets, initial widget version rows, and the first Gitea
|
||||
registry readiness event. It does not create the one-time visible static API
|
||||
key; generate that through the authenticated Inter-Hub API/UI helper and store
|
||||
it outside Git.
|
||||
|
||||
## Validation
|
||||
|
||||
@@ -150,20 +258,24 @@ Expected: a short-lived access token is returned.
|
||||
After widget seeding:
|
||||
|
||||
```bash
|
||||
curl -s https://hub.coulomb.social/api/v2/hub-registry
|
||||
curl -s https://hub.coulomb.social/api/v2/widgets
|
||||
curl -s https://hub.coulomb.social/api/v2/interaction-events
|
||||
```
|
||||
|
||||
Expected: `ops-hub` is visible, and the operator can see the seeded widgets in
|
||||
the authenticated UI.
|
||||
Expected: the 14 seeded `ops-hub` widgets are readable, and the Gitea registry
|
||||
readiness event is visible. `GET /api/v2/hub-registry` is the desired final
|
||||
registry validation, but it currently returns HTTP 500 on production because
|
||||
of the `api_request_log` `COUNT(*)` decode issue.
|
||||
|
||||
## 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.
|
||||
- `POST /api/v2/widgets` currently fails on production because Inter-Hub
|
||||
decodes `COUNT(*)` from `widget_type_registry` as `Int` while PostgreSQL
|
||||
returns `bigint`.
|
||||
- `GET /api/v2/hub-registry` currently fails on production for the same bug
|
||||
class in the `api_request_log` rate-limit query.
|
||||
- The generated `ops-hub` runtime key must be moved from the local temp file
|
||||
into OpenBao at `platform/operators/ops-hub/runtime`, field `OPS_HUB_KEY`,
|
||||
then the temp file must be removed.
|
||||
|
||||
These are tracked by HF-WP-0001 T10 for Inter-Hub hardening.
|
||||
|
||||
Reference in New Issue
Block a user