generated from coulomb/repo-seed
Add Core Hub staging deployment profile
This commit is contained in:
153
docs/deployment/staging-profile.md
Normal file
153
docs/deployment/staging-profile.md
Normal 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.
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user