Add Core Hub staging deployment profile

This commit is contained in:
2026-06-27 21:11:46 +02:00
parent f280f9b0f8
commit b895d1f772
12 changed files with 519 additions and 2 deletions

View File

@@ -0,0 +1,153 @@
# Core Hub Staging Deployment Profile
Status: service-repo profile for `CORE-WP-0008-T04`.
This profile turns the Core Hub replacement work into a repeatable staging
shape that can run the deployed API smoke (`CORE-WP-0008-T02`), the
activity-core evidence sink proof (`CORE-WP-0008-T03`), and the staging import
for `CORE-WP-0005-T02` without reconstructing shell state from memory.
## Ownership Boundary
Core Hub owns the application image, runtime environment contract, migrations,
smokes, and API behavior. Railiance application deployment ownership should
move to `railiance-apps` once the permanent Helm/chart path is created. Until
then, `k8s/railiance-staging/` is the checked-in service-repo staging profile.
## Runtime Configuration
The staging API runs as `core-hub-api` in namespace `core-hub-staging` on port
`8010`.
Non-secret runtime config lives in `core-hub-staging-runtime`:
| Variable | Staging value | Notes |
| --- | --- | --- |
| `CORE_HUB_ENV` | `staging` | Appears in process config only. |
| `CORE_HUB_AUTO_CREATE_TABLES` | `0` | Alembic is the only staging schema path. |
Secret runtime config is referenced through `core-hub-staging-env`; it is not
committed:
| Secret key | Owner / custody path | Notes |
| --- | --- | --- |
| `CORE_HUB_DATABASE_URL` | OpenBao / railiance-platform database custody | Async SQLAlchemy URL for the staging Postgres database. |
| `CORE_HUB_API_TOKEN` | OpenBao / railiance-platform app-secret custody | Operator token for protected API smokes and bootstrap operations. |
The runtime Secret may later also provide an activity-core runtime token or
widget mapping if the operator chooses to run activity-core from the cluster
against this staging API. Keep those in the consuming service's Secret, not in
Core Hub manifests, unless Core Hub itself needs them.
## Database And Migrations
Use a dedicated staging database, for example database `core_hub_staging` and
least-privilege app user `core_hub_staging`. The actual password and URL are
operator-owned secrets.
Local validation before deploy:
```bash
PYTHONPATH=src uv run --extra dev alembic upgrade head
```
Cluster migration path:
```bash
kubectl -n core-hub-staging delete job core-hub-staging-migrate --ignore-not-found
kubectl apply -f k8s/railiance-staging/20-runtime.yaml
kubectl -n core-hub-staging set image job/core-hub-staging-migrate \
migrate=gitea.coulomb.social/coulomb/core-hub:<tag>
kubectl -n core-hub-staging wait --for=condition=complete \
job/core-hub-staging-migrate --timeout=180s
```
Do not set `CORE_HUB_AUTO_CREATE_TABLES=1` in staging. That flag is for local
smoke/test bootstraps only.
## Build And Release Commands
Near-term service-repo image build:
```bash
IMAGE_REPOSITORY=gitea.coulomb.social/coulomb/core-hub \
IMAGE_TAG=$(git rev-parse --short HEAD) \
make container-build
docker push gitea.coulomb.social/coulomb/core-hub:$(git rev-parse --short HEAD)
```
Railiance-style deploy skeleton:
```bash
kubectl apply -f k8s/railiance-staging/00-namespace.yaml
kubectl -n core-hub-staging get secret core-hub-staging-env
kubectl apply -f k8s/railiance-staging/20-runtime.yaml
kubectl -n core-hub-staging set image deploy/core-hub-api \
api=gitea.coulomb.social/coulomb/core-hub:<tag>
kubectl -n core-hub-staging rollout status deploy/core-hub-api --timeout=180s
```
Longer term, promote this into `railiance-apps` with explicit targets analogous
to `inter-hub-dry-run`, `inter-hub-server-dry-run`, `inter-hub-deploy`, and
`inter-hub-status`. Production or shared staging deploys must use explicit image
tags, not mutable `latest`.
## Health, Readiness, And Smokes
Cluster-local checks:
```bash
kubectl -n core-hub-staging exec deploy/core-hub-api -- \
python -c "import urllib.request; print(urllib.request.urlopen('http://localhost:8010/healthz').read().decode())"
kubectl -n core-hub-staging exec deploy/core-hub-api -- \
python -c "import urllib.request; print(urllib.request.urlopen('http://localhost:8010/readyz').read().decode())"
```
Operator smoke after routing or port-forward is available:
```bash
CORE_HUB_BASE_URL=https://core-hub-staging.example.invalid \
CORE_HUB_OPERATOR_TOKEN_FILE=/secure/operator/path/core-hub-staging-operator-token \
CORE_HUB_SMOKE_OUTPUT=.local/smoke/core-hub-staging.json \
make deployed-smoke
```
activity-core can use the direct sink from `ACTIVITY-WP-0017` once it has:
- `CORE_HUB_BASE_URL` for staging;
- `CORE_HUB_RUNTIME_TOKEN_FILE` or a named token environment variable;
- `CORE_HUB_WIDGET_ID` or `CORE_HUB_WIDGET_MAPPING` for the target widget.
## Staging Import Relationship
`CORE-WP-0005-T02` starts only after this profile is deployed, migrations have
completed, and the target staging database is known. Import sequence:
```bash
PYTHONPATH=src uv run --extra dev python scripts/core_hub_migrate.py validate \
/secure/operator/path/interhub-export.bundle.json
CORE_HUB_DATABASE_URL=postgresql+asyncpg://... \
PYTHONPATH=src uv run --extra dev python scripts/core_hub_migrate.py import \
/secure/operator/path/interhub-export.bundle.json --dry-run
CORE_HUB_DATABASE_URL=postgresql+asyncpg://... \
PYTHONPATH=src uv run --extra dev python scripts/core_hub_migrate.py import \
/secure/operator/path/interhub-export.bundle.json
```
Record the generated row counts and diagnostics as non-secret evidence. The
bundle path and database URL shown above are placeholders; use approved operator
paths and secret references.
## Rollback Notes
- Keep Haskell Inter-Hub live as compatibility and rollback until Core Hub
staging import, deployed smokes, dual-run, and operator approval complete.
- For staging-only failures, scale the API to zero or roll the Deployment image
back to the last known good tag.
- For migration failures, snapshot/reset the staging database and replay the
same approved bundle after fixing mapper/schema defects.
- Never rotate or delete legacy Inter-Hub keys during staging rollback.

View File

@@ -49,6 +49,15 @@ harness creates a runtime key for the smoke API consumer, set
value into the approved custody system immediately. Do not commit `.local/`
reports or runtime token files.
## Staging Deployment Profile
The staging deployment profile lives in `docs/deployment/staging-profile.md`
and `k8s/railiance-staging/`. Validate it with `make
staging-profile-check`. The profile defines the non-secret Kubernetes
runtime shape, secret references, Alembic migration job, image build
command, health/readiness checks, rollback notes, and the handoff to
`CORE-WP-0005-T02` staging import.
## Release Gates
A Core Hub release cannot replace Inter-Hub until: