From c7d49d3102e7cd6ab33f7c8c966a717cd27679d6 Mon Sep 17 00:00:00 2001 From: tegwick Date: Mon, 15 Jun 2026 22:07:03 +0200 Subject: [PATCH] Handle app deployment guardrail suggestions --- AGENTS.md | 8 +- Makefile | 89 +++++++++++--- charts/inter-hub/templates/_helpers.tpl | 4 +- charts/inter-hub/templates/deployment.yaml | 2 +- docs/inter-hub-on-railiance01.md | 110 ++++++++++++++++++ docs/operator-setup.md | 39 +++++++ docs/reuse-surface-on-railiance01.md | 28 ++--- helm/inter-hub-values.yaml | 2 +- tools/check-tools.sh | 1 + tools/k8s-server-dry-run.sh | 6 + workplans/ADHOC-2026-06-15.md | 51 ++++++++ ...P-0007-reuse-surface-hub-on-railiance01.md | 6 +- 12 files changed, 303 insertions(+), 43 deletions(-) create mode 100644 docs/inter-hub-on-railiance01.md create mode 100644 workplans/ADHOC-2026-06-15.md diff --git a/AGENTS.md b/AGENTS.md index 803c9bb..111d0f4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -63,8 +63,8 @@ Omit `workstream_id` / `task_id` when not applicable. ```bash curl -s -X PATCH "http://127.0.0.1:8000/tasks/" \ -H "Content-Type: application/json" \ - -d '{"status": "in_progress"}' -# values: todo | in_progress | done | blocked + -d '{"status": "progress"}' +# values: wait | todo | progress | done | cancel ``` ### Flag a task for human review @@ -146,7 +146,7 @@ derived health labels, not frontmatter statuses. ` ` `task id: RAILIANCE-WP-NNNN-T01 -status: todo | in_progress | done | blocked +status: wait | todo | progress | done | cancel priority: high | medium | low state_hub_task_id: "" # written by fix-consistency — do not edit ` ` ` @@ -154,7 +154,7 @@ state_hub_task_id: "" # written by fix-consistency — do not edit Task description text. ``` -Status progression: `todo` → `in_progress` → `done` (or `blocked`) +Status progression: `wait` → `todo` → `progress` → `done` (or `cancel`) To create a new workplan: 1. Write the file following the format above diff --git a/Makefile b/Makefile index c47e5f7..aaea0fd 100644 --- a/Makefile +++ b/Makefile @@ -18,11 +18,20 @@ INTER_HUB_RELEASE ?= inter-hub INTER_HUB_NAMESPACE ?= inter-hub INTER_HUB_CHART ?= charts/inter-hub INTER_HUB_VALUES ?= helm/inter-hub-values.yaml +INTER_HUB_IMAGE_TAG ?= +INTER_HUB_BASE_URL ?= https://hub.coulomb.social REUSE_RELEASE ?= reuse REUSE_NAMESPACE ?= reuse REUSE_CHART ?= charts/reuse-surface REUSE_VALUES ?= helm/reuse-surface-values.yaml +REUSE_URL ?= https://reuse.coulomb.social +REUSE_CERTIFICATE ?= reuse-surface-tls + +RAILIANCE01_KUBECONFIG ?= $(HOME)/.kube/config-hosteurope +INTER_HUB_KUBECONFIG ?= $(RAILIANCE01_KUBECONFIG) +REUSE_KUBECONFIG ?= $(RAILIANCE01_KUBECONFIG) +INTER_HUB_IMAGE_SET_ARG = $(if $(strip $(INTER_HUB_IMAGE_TAG)),--set image.tag=$(INTER_HUB_IMAGE_TAG),) SOPS_SENTINEL ?= DRY_RUN_CREATE_NAMESPACES ?= false @@ -47,6 +56,21 @@ apps-pg-status: ## Check the shared apps-pg cnpg cluster kubectl get pods -n databases -l cnpg.io/cluster=apps-pg; \ fi +check-railiance01-kubeconfig: ## Verify Railiance01 production kubeconfig exists + @test -r "$(RAILIANCE01_KUBECONFIG)" || { \ + echo "Missing Railiance01 kubeconfig: $(RAILIANCE01_KUBECONFIG)" >&2; \ + echo "Restore it with:" >&2; \ + echo " ssh tegwick@92.205.62.239 'sudo cat /etc/rancher/k3s/k3s.yaml' | sed 's|127.0.0.1|92.205.62.239|' > $(RAILIANCE01_KUBECONFIG)" >&2; \ + exit 1; \ + } + +check-inter-hub-image-tag: ## Require an explicit inter-hub image tag for production deploys + @test -n "$(INTER_HUB_IMAGE_TAG)" || { \ + echo "Set INTER_HUB_IMAGE_TAG= for inter-hub production deploys." >&2; \ + echo "Example: INTER_HUB_IMAGE_TAG=91037a4 make inter-hub-deploy" >&2; \ + exit 1; \ + } + ##@ Vergabe Teilnahme vergabe-dry-run: ## helm template render (no apply) for inspection @@ -89,39 +113,66 @@ vergabe-db-url-secret: ## Rebuild DATABASE_URL with a URL-encoded cnpg password ##@ Inter-Hub -inter-hub-dry-run: ## helm template render (no apply) for inter-hub - helm template $(INTER_HUB_RELEASE) $(INTER_HUB_CHART) \ +inter-hub-dry-run: check-railiance01-kubeconfig ## helm template render (no apply) for inter-hub + KUBECONFIG="$(INTER_HUB_KUBECONFIG)" helm template $(INTER_HUB_RELEASE) $(INTER_HUB_CHART) \ --namespace $(INTER_HUB_NAMESPACE) \ - -f $(INTER_HUB_VALUES) + -f $(INTER_HUB_VALUES) $(INTER_HUB_IMAGE_SET_ARG) -inter-hub-deploy: ## Deploy / upgrade inter-hub Helm release - helm upgrade --install $(INTER_HUB_RELEASE) $(INTER_HUB_CHART) \ +inter-hub-deploy: check-railiance01-kubeconfig check-inter-hub-image-tag ## Deploy / upgrade inter-hub Helm release on Railiance01 + KUBECONFIG="$(INTER_HUB_KUBECONFIG)" helm upgrade --install $(INTER_HUB_RELEASE) $(INTER_HUB_CHART) \ --namespace $(INTER_HUB_NAMESPACE) --create-namespace \ - -f $(INTER_HUB_VALUES) --wait --timeout 5m + -f $(INTER_HUB_VALUES) $(INTER_HUB_IMAGE_SET_ARG) --wait --timeout 5m -inter-hub-status: ## Show inter-hub pod / svc / ingress / cert state - kubectl get pods,svc,ingress,certificate -n $(INTER_HUB_NAMESPACE) -l app.kubernetes.io/instance=$(INTER_HUB_RELEASE) --ignore-not-found +inter-hub-status: check-railiance01-kubeconfig ## Show inter-hub pod / svc / ingress / cert state on Railiance01 + KUBECONFIG="$(INTER_HUB_KUBECONFIG)" kubectl get pods,svc,ingress,certificate -n $(INTER_HUB_NAMESPACE) -l app=$(INTER_HUB_RELEASE) --ignore-not-found -inter-hub-logs: ## Tail inter-hub app logs - kubectl logs -n $(INTER_HUB_NAMESPACE) -l app.kubernetes.io/instance=$(INTER_HUB_RELEASE) -f --tail=50 +inter-hub-release-info: check-railiance01-kubeconfig ## Show inter-hub Helm history, values, deployment, and pods + KUBECONFIG="$(INTER_HUB_KUBECONFIG)" helm history $(INTER_HUB_RELEASE) -n $(INTER_HUB_NAMESPACE) + KUBECONFIG="$(INTER_HUB_KUBECONFIG)" helm get values $(INTER_HUB_RELEASE) -n $(INTER_HUB_NAMESPACE) + KUBECONFIG="$(INTER_HUB_KUBECONFIG)" kubectl describe deploy/$(INTER_HUB_RELEASE) -n $(INTER_HUB_NAMESPACE) + KUBECONFIG="$(INTER_HUB_KUBECONFIG)" kubectl get pods -n $(INTER_HUB_NAMESPACE) -o wide + +inter-hub-smoke: ## Verify public inter-hub v2 route and OpenAPI surface after rollout + @status="$$(curl -sS -o /tmp/inter-hub-api-v2-hubs.body -w "%{http_code}" "$(INTER_HUB_BASE_URL)/api/v2/hubs")"; \ + if [ "$$status" != "401" ]; then \ + echo "expected $(INTER_HUB_BASE_URL)/api/v2/hubs to return 401, got $$status" >&2; \ + cat /tmp/inter-hub-api-v2-hubs.body >&2; \ + exit 1; \ + fi; \ + echo "ok: /api/v2/hubs returned 401" + @tmp="$$(mktemp)"; \ + trap 'rm -f "$$tmp"' EXIT; \ + curl -fsS "$(INTER_HUB_BASE_URL)/openapi.json" > "$$tmp"; \ + for route in /hubs /hub-capability-manifests /api-consumers /policy-scopes; do \ + grep -q "$$route" "$$tmp" || { echo "missing OpenAPI route: $$route" >&2; exit 1; }; \ + done; \ + echo "ok: OpenAPI lists expected v2 resources" + +inter-hub-logs: check-railiance01-kubeconfig ## Tail inter-hub app logs from Railiance01 + KUBECONFIG="$(INTER_HUB_KUBECONFIG)" kubectl logs -n $(INTER_HUB_NAMESPACE) -l app=$(INTER_HUB_RELEASE) -f --tail=50 ##@ reuse-surface (reuse.coulomb.social) -reuse-dry-run: ## helm template render (no apply) for reuse-surface - helm template $(REUSE_RELEASE) $(REUSE_CHART) \ +reuse-dry-run: check-railiance01-kubeconfig ## helm template render (no apply) for reuse-surface + KUBECONFIG="$(REUSE_KUBECONFIG)" helm template $(REUSE_RELEASE) $(REUSE_CHART) \ --namespace $(REUSE_NAMESPACE) \ -f $(REUSE_VALUES) -reuse-deploy: ## Deploy / upgrade reuse-surface Helm release - helm upgrade --install $(REUSE_RELEASE) $(REUSE_CHART) \ +reuse-deploy: check-railiance01-kubeconfig ## Deploy / upgrade reuse-surface Helm release on Railiance01 + KUBECONFIG="$(REUSE_KUBECONFIG)" helm upgrade --install $(REUSE_RELEASE) $(REUSE_CHART) \ --namespace $(REUSE_NAMESPACE) --create-namespace \ -f $(REUSE_VALUES) --wait --timeout 5m -reuse-status: ## Show reuse-surface pod / svc / ingress / cert state - kubectl get pods,svc,ingress,pvc,certificate -n $(REUSE_NAMESPACE) -l app.kubernetes.io/instance=$(REUSE_RELEASE) --ignore-not-found +reuse-status: check-railiance01-kubeconfig ## Show reuse-surface pod / svc / ingress / cert state on Railiance01 + KUBECONFIG="$(REUSE_KUBECONFIG)" kubectl get pods,svc,ingress,pvc,certificate -n $(REUSE_NAMESPACE) -l app.kubernetes.io/instance=$(REUSE_RELEASE) --ignore-not-found -reuse-logs: ## Tail reuse-surface service logs - kubectl logs -n $(REUSE_NAMESPACE) -l app.kubernetes.io/instance=$(REUSE_RELEASE) -f --tail=50 +reuse-smoke: check-railiance01-kubeconfig ## Verify reuse public health, repo list, and TLS certificate readiness + curl -fsS "$(REUSE_URL)/health" + curl -fsS "$(REUSE_URL)/v1/repos" + KUBECONFIG="$(REUSE_KUBECONFIG)" kubectl wait -n $(REUSE_NAMESPACE) --for=condition=Ready certificate/$(REUSE_CERTIFICATE) --timeout=30s + +reuse-logs: check-railiance01-kubeconfig ## Tail reuse-surface service logs from Railiance01 + KUBECONFIG="$(REUSE_KUBECONFIG)" kubectl logs -n $(REUSE_NAMESPACE) -l app.kubernetes.io/instance=$(REUSE_RELEASE) -f --tail=50 ##@ Help @@ -130,4 +181,4 @@ help: ## Show this help /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } \ /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) }' $(MAKEFILE_LIST) -.PHONY: check-tools check-sops k8s-server-dry-run apps-pg-status vergabe-dry-run vergabe-deploy vergabe-ingress-deploy vergabe-status vergabe-migrate vergabe-seed vergabe-superuser vergabe-logs vergabe-db-url-secret inter-hub-dry-run inter-hub-deploy inter-hub-status inter-hub-logs reuse-dry-run reuse-deploy reuse-status reuse-logs help +.PHONY: check-tools check-sops k8s-server-dry-run apps-pg-status check-railiance01-kubeconfig check-inter-hub-image-tag vergabe-dry-run vergabe-deploy vergabe-ingress-deploy vergabe-status vergabe-migrate vergabe-seed vergabe-superuser vergabe-logs vergabe-db-url-secret inter-hub-dry-run inter-hub-deploy inter-hub-status inter-hub-release-info inter-hub-smoke inter-hub-logs reuse-dry-run reuse-deploy reuse-status reuse-smoke reuse-logs help diff --git a/charts/inter-hub/templates/_helpers.tpl b/charts/inter-hub/templates/_helpers.tpl index 6bcae89..f7fa4f1 100644 --- a/charts/inter-hub/templates/_helpers.tpl +++ b/charts/inter-hub/templates/_helpers.tpl @@ -7,6 +7,7 @@ Chart name + release name produce a unique resource name. {{- end -}} {{- define "interhub.labels" -}} +app: {{ include "interhub.fullname" . }} app.kubernetes.io/name: {{ include "interhub.fullname" . }} app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} @@ -16,8 +17,7 @@ helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" }} {{- end -}} {{- define "interhub.selectorLabels" -}} -app.kubernetes.io/name: {{ include "interhub.fullname" . }} -app.kubernetes.io/instance: {{ .Release.Name }} +app: {{ include "interhub.fullname" . }} {{- end -}} {{- define "interhub.image" -}} diff --git a/charts/inter-hub/templates/deployment.yaml b/charts/inter-hub/templates/deployment.yaml index fad6062..0646509 100644 --- a/charts/inter-hub/templates/deployment.yaml +++ b/charts/inter-hub/templates/deployment.yaml @@ -14,7 +14,7 @@ spec: maxUnavailable: 0 template: metadata: - labels: {{- include "interhub.selectorLabels" . | nindent 8 }} + labels: {{- include "interhub.labels" . | nindent 8 }} spec: securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} containers: diff --git a/docs/inter-hub-on-railiance01.md b/docs/inter-hub-on-railiance01.md new file mode 100644 index 0000000..59763a2 --- /dev/null +++ b/docs/inter-hub-on-railiance01.md @@ -0,0 +1,110 @@ +# inter-hub on railiance01 + +Interaction Hub deployment for **`https://hub.coulomb.social`**. + +Companion source repo: `coulomb/inter-hub`. This repo owns the Railiance app +Helm surface and operator targets, not the runtime application code. + +## Hosts and release surface + +| Server | IP | Role | +|---|---|---| +| Railiance01 | `92.205.62.239` | Production k3s; deploy S5 apps here | +| CoulombCore | `92.205.130.254` | Bootstrap / prerelease only | + +| Item | Value | +|---|---| +| Namespace | `inter-hub` | +| Helm release | `inter-hub` | +| Chart | `charts/inter-hub` | +| Values | `helm/inter-hub-values.yaml` | +| Image | `gitea.coulomb.social/coulomb/inter-hub:` | +| Secret | `inter-hub-env` | +| Production kubeconfig | `~/.kube/config-hosteurope` | + +## Current evidence + +Read-only checks on 2026-06-15 showed: + +- Helm release `inter-hub` revision 2 is deployed in namespace `inter-hub`. +- `helm get values` reports `image.tag: 11ff61c`, + `image.pullPolicy: Always`, and `runMigrations: false`. +- The live Deployment image is + `92.205.130.254:32166/coulomb/inter-hub:790b5e5`, so production image state + has drifted from Helm values and from this repo's desired Gitea registry + target. +- The pod is Running and `certificate/inter-hub-tls` is Ready on Railiance01. +- `GET https://hub.coulomb.social/api/v2/hubs` returned `200` unauthenticated, + proving the route is present but not satisfying the expected `401` auth gate. +- `/openapi.json`, `/api/openapi.json`, `/swagger.json`, and + `/api/swagger.json` returned `404`; the public OpenAPI route still needs to + be confirmed by the upstream inter-hub owner. + +## Deploy + +Use the Railiance01 kubeconfig. The Makefile defaults to +`~/.kube/config-hosteurope` and fails fast when it is missing. + +```bash +make inter-hub-dry-run +INTER_HUB_IMAGE_TAG=91037a4 make inter-hub-deploy +make inter-hub-status +``` + +Deploy automation should pass the image tag without rewriting +`helm/inter-hub-values.yaml`. The production deploy target requires this +explicit tag: + +```bash +INTER_HUB_IMAGE_TAG=91037a4 make inter-hub-deploy +``` + +Use a tag at or after the commit that contains the required v2 bootstrap API +routes. The upstream inter-hub workplan names `91037a4` as the first expected +tag for the IHUB-WP-0019 route surface; verify the actual registry tag before +announcing rollout. + +## Release verification + +```bash +make inter-hub-release-info +``` + +This wraps the required non-secret inspection commands: + +```bash +helm history inter-hub -n inter-hub +helm get values inter-hub -n inter-hub +kubectl describe deploy/inter-hub -n inter-hub +kubectl get pods -n inter-hub -o wide +``` + +Confirm the rendered deployment uses the intended immutable image tag and does +not rely on a stale `latest` image. + +The chart intentionally keeps the legacy Deployment and Service selector +`app=inter-hub` because the live Helm release was created with that selector. +Kubernetes treats Deployment selectors as immutable; do not change this +selector during a normal in-place production upgrade. + +## Migration boundary + +The Railiance app chart currently does **not** run inter-hub database +migrations. Treat migration execution as an upstream inter-hub operator step +and record the evidence before closing a production rollout. Do not describe +migrations as automatic unless the chart grows an explicit init job/container +or another committed migration mechanism. + +## Smoke checks + +After rollout, the unauthenticated v2 API gate should be present: + +```bash +make inter-hub-smoke +``` + +Expected results: + +- `GET https://hub.coulomb.social/api/v2/hubs` returns `401`, not `404`. +- OpenAPI lists `/hubs`, `/hub-capability-manifests`, `/api-consumers`, and + `/policy-scopes`. diff --git a/docs/operator-setup.md b/docs/operator-setup.md index 7ab9537..5596735 100644 --- a/docs/operator-setup.md +++ b/docs/operator-setup.md @@ -19,6 +19,7 @@ SOPS_SENTINEL= make check-sops - `helm` - `sops` - `python3` +- `curl` Install the CNPG plugin for better database diagnostics: @@ -31,6 +32,44 @@ kubectl krew install cnpg plain Kubernetes resources, but the plugin output is the preferred view for primary/replica health and backup state. +## Production Cluster Kubeconfig + +S5 production app releases belong on **Railiance01**. CoulombCore may still +host bootstrap or prerelease services, so do not rely on the workstation's +ambient `kubectl` context for production app deploys. + +| Name | IP | Role | +|---|---|---| +| Railiance01 | `92.205.62.239` | Production k3s; deploy S5 apps here | +| CoulombCore | `92.205.130.254` | Bootstrap / prerelease only | + +| Hostname | Production DNS A | Notes | +|---|---|---| +| `reuse.coulomb.social` | `92.205.62.239` | Production reuse-surface hub | +| `hub.coulomb.social` | `92.205.62.239` | Target production inter-hub host; bootstrap may still point at CoulombCore until cutover | + +The production Makefile targets default to: + +```text +~/.kube/config-hosteurope +``` + +Restore it from Railiance01 when missing: + +```bash +ssh tegwick@92.205.62.239 'sudo cat /etc/rancher/k3s/k3s.yaml' \ + | sed 's|127.0.0.1|92.205.62.239|' > ~/.kube/config-hosteurope +chmod 600 ~/.kube/config-hosteurope +export KUBECONFIG=~/.kube/config-hosteurope +``` + +The app-specific targets also accept explicit overrides: + +```bash +REUSE_KUBECONFIG=~/.kube/config-hosteurope make reuse-status +INTER_HUB_KUBECONFIG=~/.kube/config-hosteurope make inter-hub-status +``` + ## SOPS Age Key Bootstrap SOPS-encrypted values used by app release work expect an age identity at: diff --git a/docs/reuse-surface-on-railiance01.md b/docs/reuse-surface-on-railiance01.md index a0b6d6c..670492c 100644 --- a/docs/reuse-surface-on-railiance01.md +++ b/docs/reuse-surface-on-railiance01.md @@ -18,14 +18,15 @@ Companion workplans: **RAILIANCE-WP-0007** (Helm release), **REUSE-WP-0011** | `hub.coulomb.social` A | `92.205.62.239` (future) | `92.205.130.254` (CoulombCore bootstrap OK for now) | Let's Encrypt HTTP-01 on Railiance01 requires the public A record to reach -**`92.205.62.239`**. Service is live on the production cluster; TLS waits on DNS. +**`92.205.62.239`**. Service and TLS are live on the production cluster. ```bash dig +short reuse.coulomb.social A KUBECONFIG=~/.kube/config-hosteurope kubectl get certificate -n reuse ``` -Until DNS propagates and `certificate/reuse-surface-tls` is Ready: +If DNS is being changed in the future, use an explicit resolve only during +propagation: ```bash curl -k --resolve reuse.coulomb.social:443:92.205.62.239 https://reuse.coulomb.social/health @@ -63,8 +64,8 @@ links to `/health`, `/v1/federated`, and this operator runbook. It must not include `REUSE_SURFACE_TOKEN` or any other runtime secret. Rollback: set `landing.enabled: false` in `helm/reuse-surface-values.yaml` and -run `KUBECONFIG=~/.kube/config-hosteurope make reuse-deploy`; the ingress will -return to routing all `/` traffic to the API service. +run `make reuse-deploy`; the ingress will return to routing all `/` traffic to +the API service. ## Deploy @@ -77,9 +78,9 @@ kubectl create secret generic reuse-surface-env \ --from-literal=REUSE_SURFACE_TOKEN='' \ --dry-run=client -o yaml | kubectl apply -f - -# Production (Railiance01) -KUBECONFIG=~/.kube/config-hosteurope make reuse-deploy -KUBECONFIG=~/.kube/config-hosteurope make reuse-status +# Production (Railiance01, defaults to ~/.kube/config-hosteurope) +make reuse-deploy +make reuse-status # Restore kubeconfig from the node if missing: # ssh tegwick@92.205.62.239 'sudo cat /etc/rancher/k3s/k3s.yaml' \ @@ -89,14 +90,15 @@ KUBECONFIG=~/.kube/config-hosteurope make reuse-status ## Smoke checks ```bash +make reuse-smoke curl -I http://reuse.coulomb.social/ -curl -k --resolve reuse.coulomb.social:443:92.205.62.239 https://reuse.coulomb.social/ -curl -k --resolve reuse.coulomb.social:443:92.205.62.239 https://reuse.coulomb.social/health -curl -k --resolve reuse.coulomb.social:443:92.205.62.239 https://reuse.coulomb.social/v1/federated +curl -fsS https://reuse.coulomb.social/ +curl -fsS https://reuse.coulomb.social/health +curl -fsS https://reuse.coulomb.social/v1/federated -export REUSE_SURFACE_TOKEN=$(KUBECONFIG=~/.kube/config-hosteurope kubectl get secret reuse-surface-env -n reuse \ +export REUSE_SURFACE_TOKEN=$(kubectl --kubeconfig ~/.kube/config-hosteurope get secret reuse-surface-env -n reuse \ -o jsonpath='{.data.REUSE_SURFACE_TOKEN}' | base64 -d) -export REUSE_SURFACE_URL=https://reuse.coulomb.social # after DNS + TLS Ready +export REUSE_SURFACE_URL=https://reuse.coulomb.social reuse-surface hub status reuse-surface hub list curl -fsS "$REUSE_SURFACE_URL/v1/federated" | jq '.capabilities | length' @@ -116,7 +118,7 @@ Image promotion: build from `coulomb/reuse-surface`, push to Gitea OCI, update `helm/reuse-surface-values.yaml` `image.tag`, then: ```bash -KUBECONFIG=~/.kube/config-hosteurope make reuse-deploy +make reuse-deploy ``` Bootstrap copy on CoulombCore (`92.205.130.254`) was removed 2026-06-15 — use diff --git a/helm/inter-hub-values.yaml b/helm/inter-hub-values.yaml index 7034e02..160f6af 100644 --- a/helm/inter-hub-values.yaml +++ b/helm/inter-hub-values.yaml @@ -3,4 +3,4 @@ # Secret 'inter-hub-env' in the inter-hub namespace. image: - tag: "fde5525" # Current verified deployment (gitea.coulomb.social/coulomb/inter-hub) + tag: "fde5525" # Render baseline only; production deploy requires INTER_HUB_IMAGE_TAG=. diff --git a/tools/check-tools.sh b/tools/check-tools.sh index e1335b8..c75123b 100755 --- a/tools/check-tools.sh +++ b/tools/check-tools.sh @@ -17,6 +17,7 @@ check_required kubectl check_required helm check_required sops check_required python3 +check_required curl if command -v kubectl >/dev/null 2>&1; then if kubectl cnpg --help >/dev/null 2>&1; then diff --git a/tools/k8s-server-dry-run.sh b/tools/k8s-server-dry-run.sh index bbe54ed..1b228a2 100755 --- a/tools/k8s-server-dry-run.sh +++ b/tools/k8s-server-dry-run.sh @@ -12,6 +12,7 @@ INTER_HUB_RELEASE="${INTER_HUB_RELEASE:-inter-hub}" INTER_HUB_NAMESPACE="${INTER_HUB_NAMESPACE:-inter-hub}" INTER_HUB_CHART="${INTER_HUB_CHART:-charts/inter-hub}" INTER_HUB_VALUES="${INTER_HUB_VALUES:-helm/inter-hub-values.yaml}" +INTER_HUB_IMAGE_TAG="${INTER_HUB_IMAGE_TAG:-}" DRY_RUN_CREATE_NAMESPACES="${DRY_RUN_CREATE_NAMESPACES:-false}" for cmd in kubectl helm; do @@ -38,6 +39,10 @@ fi tmpdir="$(mktemp -d)" trap 'rm -rf "$tmpdir"' EXIT +inter_hub_image_args=() +if [[ -n "$INTER_HUB_IMAGE_TAG" ]]; then + inter_hub_image_args=(--set "image.tag=$INTER_HUB_IMAGE_TAG") +fi helm template "$VERGABE_RELEASE" "$VERGABE_CHART" \ --namespace "$VERGABE_NAMESPACE" \ @@ -47,6 +52,7 @@ helm template "$VERGABE_RELEASE" "$VERGABE_CHART" \ helm template "$INTER_HUB_RELEASE" "$INTER_HUB_CHART" \ --namespace "$INTER_HUB_NAMESPACE" \ -f "$INTER_HUB_VALUES" \ + "${inter_hub_image_args[@]}" \ > "$tmpdir/inter-hub.yaml" echo "server dry-run: committed manifests" diff --git a/workplans/ADHOC-2026-06-15.md b/workplans/ADHOC-2026-06-15.md new file mode 100644 index 0000000..556e28d --- /dev/null +++ b/workplans/ADHOC-2026-06-15.md @@ -0,0 +1,51 @@ +--- +id: ADHOC-2026-06-15 +type: workplan +title: "Ad hoc Railiance app inbox suggestions" +domain: railiance +repo: railiance-apps +status: finished +owner: codex +topic_slug: railiance +created: "2026-06-15" +updated: "2026-06-15" +--- + +# ADHOC-2026-06-15 - Ad hoc Railiance app inbox suggestions + +## Apply reuse-surface production guardrails + +```task +id: ADHOC-2026-06-15-T01 +status: done +priority: high +``` + +Added Railiance01 kubeconfig guardrails to the reuse-surface Makefile targets, +documented the production kubeconfig restore path, added `make reuse-smoke`, +and corrected stale `RAILIANCE-WP-0007` host/TLS notes to `92.205.62.239`. + +## Document inter-hub rollout verification + +```task +id: ADHOC-2026-06-15-T02 +status: done +priority: high +``` + +Added Makefile support for `INTER_HUB_IMAGE_TAG=` deploy overrides, aligned +server dry-run handling, and documented the release inspection, migration +boundary, immutable legacy selector guardrail, and v2 API smoke gate in +`docs/inter-hub-on-railiance01.md`. The production deploy target now requires an +explicit image tag to avoid silently deploying a stale checked-in value. + +## Adopt State Hub task status canon + +```task +id: ADHOC-2026-06-15-T03 +status: done +priority: medium +``` + +Updated `AGENTS.md` task status examples from the legacy aliases to the +canonical `wait`, `todo`, `progress`, `done`, and `cancel` values. diff --git a/workplans/RAILIANCE-WP-0007-reuse-surface-hub-on-railiance01.md b/workplans/RAILIANCE-WP-0007-reuse-surface-hub-on-railiance01.md index 8539dff..b88ca77 100644 --- a/workplans/RAILIANCE-WP-0007-reuse-surface-hub-on-railiance01.md +++ b/workplans/RAILIANCE-WP-0007-reuse-surface-hub-on-railiance01.md @@ -16,7 +16,7 @@ state_hub_workstream_id: "7da18dd8-76b9-4a70-b9d7-de541afc65c0" Companion to **`reuse-surface` REUSE-WP-0011**. Own the S5 Helm release, ingress, and operator targets for the federation service on production cluster -node `railiance01` (`92.205.130.254`). +node `railiance01` (`92.205.62.239`). ## Goal @@ -109,7 +109,7 @@ state_hub_task_id: "14049fd1-3319-4a76-8b48-c4228a7939f7" ``` Helm revision 3 (image `cb7a6e4`). Pod Running; `/health` and `/v1/federated` -verified. TLS pending DNS A → `92.205.130.254`. +verified. TLS Ready after DNS A → `92.205.62.239`. ## Post-Deploy Verification And Runbook @@ -122,4 +122,4 @@ state_hub_task_id: "30b08789-4eb7-4182-87d1-8e464fc968d1" Runbook `docs/reuse-surface-on-railiance01.md` updated with deploy evidence, token retrieval, and TLS/DNS operator note. Smoke checks pass via ingress -resolve; public TLS awaits DNS A → `92.205.130.254`. +and public TLS on DNS A → `92.205.62.239`.