Archive closed workplans to workplans/archived/ (ADR-001)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-02 00:25:42 +02:00
parent effe568e07
commit acaef67f4d
5 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,134 @@
---
id: FORGE-WP-0001
type: workplan
title: "railiance-forge repository foundation"
domain: financials
repo: railiance-forge
status: finished
owner: codex
topic_slug: railiance
planning_priority: high
created: "2026-06-05"
updated: "2026-06-05"
state_hub_workstream_id: "4280f3d2-3d4c-4caf-946b-521fb8fb1494"
---
# railiance-forge repository foundation
## Context
`railiance-forge` is being created after the Railiance intent review identified
forge responsibilities as the main cross-layer smell. The current Gitea and
registry surface is still in `railiance-apps`; this workplan establishes the new
repo as the owner for forge runtime and artifact infrastructure before any live
deployment files move.
This workplan implements the opening tasks from
`railiance-apps/workplans/RAILIANCE-WP-0006-railiance-forge-extraction.md`.
## T01 - Define repository contract
```task
id: FORGE-WP-0001-T01
status: done
priority: high
state_hub_task_id: "8ebc1457-f681-4cad-9ca9-119246b0063c"
```
Create the initial repository contract:
- `INTENT.md`;
- `SCOPE.md`;
- `AGENTS.md`;
- `README.md`;
- repo-local workplan convention.
Done when the repo purpose, boundaries, State Hub integration, and workplan
prefix are explicit.
---
## T02 - Register with State Hub
```task
id: FORGE-WP-0001-T02
status: done
priority: high
state_hub_task_id: "cb2346cf-b4e5-47ad-a587-65d6e95e89c8"
```
Register the repo with State Hub and sync the first workplan.
Steps:
- register `railiance-forge` under domain `railiance`;
- register the local host path `/home/worsch/railiance-forge`;
- run `make fix-consistency REPO=railiance-forge`;
- verify State Hub created a workstream and task rows.
Done when State Hub can index this repo independently.
---
## T03 - Inventory current forge assets in `railiance-apps`
```task
id: FORGE-WP-0001-T03
status: done
priority: high
state_hub_task_id: "6957ebd3-321c-41e5-ad28-8d30b0bc1155"
```
Inventory all current Gitea, registry, package, and runner-related files and
operator commands in `railiance-apps`.
Done when each candidate file has a target disposition: move, copy with
compatibility pointer, leave in S5, or supersede.
---
## T04 - Draft first migration plan
```task
id: FORGE-WP-0001-T04
status: done
priority: high
state_hub_task_id: "6894dfb4-5641-45c1-8259-201801e6aede"
```
Draft the first migration plan for moving forge runtime ownership without
touching live service state.
The plan must preserve:
- secret boundaries;
- current Gitea deployment stability;
- operator discoverability during transition;
- future Forgejo cutover separation.
Done when `railiance-apps` and `railiance-forge` can agree on the first safe
file move.
---
## T05 - Define initial forge operating contracts
```task
id: FORGE-WP-0001-T05
status: done
priority: medium
state_hub_task_id: "a5924b97-ccf7-4da0-acea-4f6017fef278"
```
Create first draft contracts for:
- artifact retention and provenance;
- runner substrate ownership;
- backup and restore handoff with `railiance-platform`;
- secret custody boundaries;
- basic forge observability.
Done when follow-on implementation work can be split into focused workplans.
Completed in `docs/initial-operating-contracts.md`, with read-only operator
entry points in `Makefile` and follow-on migration tracked in `FORGE-WP-0002`.

View File

@@ -0,0 +1,122 @@
---
id: FORGE-WP-0002
type: workplan
title: "Canonical registry docs and read-only forge operations"
domain: financials
repo: railiance-forge
status: finished
owner: codex
topic_slug: railiance
planning_priority: high
created: "2026-06-05"
updated: "2026-06-05"
state_hub_workstream_id: "00c57adc-b8e6-46d6-a963-d6847646a6b0"
---
# Canonical registry docs and read-only forge operations
## Context
The `railiance-forge` remote now exists and the repository is synced with
State Hub. The first safe extraction step is to move registry operating
knowledge and read-only inspection targets before moving deploy-capable Gitea
configuration from `railiance-apps`.
## T01 - Adopt canonical Gitea registry docs
```task
id: FORGE-WP-0002-T01
status: done
priority: high
state_hub_task_id: "16fa09f4-f8fe-4d73-a9b1-7611bbf13dc9"
```
Move canonical container and Python package registry operation notes into
`railiance-forge/docs/`, leaving compatibility pointers in `railiance-apps`.
Done when operators can find registry endpoints, credential handling, package
publish/install recipes, and current storage notes in this repo.
---
## T02 - Add read-only operator targets
```task
id: FORGE-WP-0002-T02
status: done
priority: high
state_hub_task_id: "977af707-e455-4669-aeb5-62ccf31a8d55"
```
Add a forge-side `Makefile` with:
- `make registry-docs`;
- `make check-tools`;
- `make gitea-status`.
Done when the new repo can inspect current Gitea state without owning
deploy-capable Helm or Kubernetes apply commands.
---
## T03 - Prepare deploy-capable Gitea move review
```task
id: FORGE-WP-0002-T03
status: done
priority: high
state_hub_task_id: "58a8073d-4665-4cf6-a1f8-e4810c7d392d"
```
Review the next candidate move from `railiance-apps`:
- `helm/gitea-values.sops.yaml`;
- `helm/gitea-registry-values.yaml`;
- `manifests/gitea-ingress.yaml`;
- `releases/gitea/values.yaml`;
- `make gitea-deploy`;
- `make gitea-ingress-deploy`.
Done when the move plan is specific enough to preserve secret boundaries,
operator compatibility, and live Gitea stability.
Completed in `docs/deploy-capable-gitea-move-review.md`.
---
## T04 - Re-home parent workplan references
```task
id: FORGE-WP-0002-T04
status: done
priority: medium
state_hub_task_id: "bc0daafa-0b01-479b-9f46-79c6d8fe1c0e"
```
Update `railiance-apps` docs and workplans so registry operation points to
`railiance-forge`, while app release runbooks stay in S5.
Done when the old app-side registry docs are compatibility pointers instead of
competing canonical sources.
---
## T05 - Execute reviewed deploy-capable move
```task
id: FORGE-WP-0002-T05
status: done
priority: high
state_hub_task_id: "6f6fc3a4-a883-4803-84e7-2700629d397a"
```
After operator review, move deploy-capable Gitea files and commands into
`railiance-forge` with app-side compatibility targets.
Done when `railiance-forge` owns Gitea deploy/status/ingress commands and
`railiance-apps` no longer carries live forge deployment files as S5 scope.
Completed on 2026-06-05. The Gitea SOPS values, registry overlay, ingress
manifest, legacy release values, and deploy/status Makefile targets now live in
`railiance-forge`. `railiance-apps` keeps compatibility wrappers only. No live
deploy, SOPS decryption, or Kubernetes apply was run.

View File

@@ -0,0 +1,287 @@
---
id: FORGE-WP-0003
type: workplan
title: "Gitea Actions runner substrate for Railiance workloads"
domain: financials
repo: railiance-forge
status: finished
owner: codex
topic_slug: railiance
planning_priority: high
created: "2026-06-07"
updated: "2026-06-08"
state_hub_workstream_id: "149a0316-64d1-4664-96d0-274577c32e63"
---
# Gitea Actions runner substrate for Railiance workloads
## Context
Inter-Hub reported that its production deployment is blocked on a forge-owned
Actions runner substrate. The inter-hub workflow currently targets
`self-hosted` and `haskelseed`, but production remained on the older API surface
after deployment-trigger commits. The current forge migration notes explicitly
excluded an Actions runner deployment, while the forge operating contract says
`railiance-forge` owns runner deployment, registration, labels, credential
boundaries, and health evidence.
This workplan turns that ownership contract into an actionable runner substrate
without weakening repo or app boundaries. It should unblock inter-hub only after
the runner is registered, visible, and has passed a non-production sample job.
## T01 - Register blocker and dependency evidence
```task
id: FORGE-WP-0003-T01
status: done
priority: high
state_hub_task_id: "b5a42f74-7792-4fbc-8e1f-16c1082ea194"
```
Capture the immediate dependency chain:
- inter-hub `R7` waits on a self-hosted runner for labels currently written as
`self-hosted` and `haskelseed`;
- `hub.coulomb.social` still serves the older API surface after pushed
deployment-trigger commits;
- `docs/first-migration-plan.md` made runner deployment a non-goal for the first
forge migration;
- `docs/ci-runner-actions-gitops-ownership.md` assigns runner substrate
ownership to `railiance-forge`.
Done when this workplan is registered in State Hub and the unread forge inbox
messages that created the blocker are marked read.
---
## T02 - Inventory current Gitea Actions state
```task
id: FORGE-WP-0003-T02
status: done
priority: high
state_hub_task_id: "87181d63-049e-4a2b-a5e3-bf16763246d7"
```
Inspect the current Gitea Actions configuration without printing secrets.
Check:
- whether Actions are enabled for the current Gitea instance;
- whether any `act_runner` service is already registered and online;
- whether a haskelseed runner exists, and which labels it advertises;
- runner logs around the inter-hub Build and Deploy attempts;
- registry tags for the blocked inter-hub commits, including the commit tag and
`latest` where applicable.
Done when the actual current runner/registry state is recorded as non-secret
evidence in the repo and State Hub.
**2026-06-07:** Added `docs/gitea-actions-runner-evidence.md` and
`make runner-status` to capture non-secret inventory. Current session evidence:
public inter-hub `/api/v2/hubs` still returns `404`, the direct `haskelseed`
SSH alias timed out, and `skopeo` is unavailable for registry tag inspection.
After ops-bridge was updated, haskelseed is reachable at `root@192.168.178.135`
with `/home/worsch/.ssh/id_ops`. Haskelseed has `act_runner
v0.6.1-1-g8e6b3be9` and `/root/.runner` registered as `haskelseed` with labels
`haskelseed:host`, `linux:host`, and `x86_64:host`, but no OpenRC service or
live runner process was observed. This task still waits on Gitea runner admin
visibility and registry tag inspection.
**2026-06-07:** Activated the existing haskelseed runner registration through
ops-bridge. Backed up `/root/.runner` to
`/root/.runner.bak-20260607225905`, updated labels to include `self-hosted`,
`linux_amd64`, `container-build`, and `registry-publish`, installed the OpenRC
service from `runner/act-runner-haskelseed.openrc.example`, and started
`act_runner` as PID `5911`. The daemon log reports that runner `haskelseed`
declared successfully with labels `self-hosted`, `haskelseed`, `linux`,
`linux_amd64`, `x86_64`, `container-build`, and `registry-publish`.
**2026-06-08:** Completed current-state inventory. Gitea created
`forge-runner-smoke.yaml #1` for commit `19ee47fe82`, but the run remains
`Waiting` with duration `0s`. Haskelseed login shell has the deploy tools needed
by inter-hub (`skopeo`, `helm`, `kubectl`, `nix`, `git`, `curl`). Registry
inspection from haskelseed shows inter-hub tags `91037a4`, `ae9e497`,
`fa96fb8`, `7cc3173`, and `latest` are all `manifest unknown`, confirming the
blocked inter-hub workflow did not publish those images.
---
## T03 - Decide runner placement, labels, and capacity rules
```task
id: FORGE-WP-0003-T03
status: done
priority: high
state_hub_task_id: "eecde550-43a5-4d77-8e19-c991c5456b42"
```
Choose the first supported runner model.
Decisions:
- place the runner on haskelseed or on a separate approved runner host;
- publish semantic labels such as `linux`, `container-build`, and
`registry-publish`;
- decide whether to keep compatibility labels like `self-hosted` and
`haskelseed` during the first unblock;
- use concurrency `1` or an explicit build lock if haskelseed remains shared
infrastructure;
- treat cluster-deploy or cluster-access labels as separate approvals, not as
implicit side effects of the build runner.
Done when the label and placement contract is documented with any required
human approvals called out.
**2026-06-07:** Documented the first supported runner model in
`docs/gitea-actions-runner-substrate.md`: one haskelseed compatibility runner
named `railiance-haskelseed-build-01`, capacity `1`, compatibility labels
`self-hosted` and `haskelseed`, semantic labels `linux`, `linux_amd64`,
`container-build`, and `registry-publish`, and no implicit cluster-deploy label.
---
## T04 - Build the runner deployment and recovery runbook
```task
id: FORGE-WP-0003-T04
status: done
priority: high
state_hub_task_id: "a3d0adfb-d1f9-4a5f-8e05-c4a8fbb160b1"
```
Create the forge-owned runner operating surface.
Include:
- installation or service definition for the selected runner host;
- registration-token custody path, referenced by name only;
- start, stop, restart, drain, replacement, and token-rotation steps;
- log inspection commands that avoid secret output;
- health and label inspection commands;
- rollback or disable path for a bad runner registration.
Done when an operator can register and operate the runner from the forge repo
without committing decrypted secrets or machine-local assumptions.
**2026-06-07:** Added the attended install/recovery runbook, non-secret
`runner/` templates, systemd and OpenRC service examples, `make runner-docs`,
`make runner-status`, and `make check-runner-tools`. Registration tokens are
referenced by file path only and are never committed.
---
## T05 - Prove a non-production sample job
```task
id: FORGE-WP-0003-T05
status: done
priority: high
state_hub_task_id: "9ada5b3e-2ddb-4a55-b9f4-5a6e00fef8b2"
```
Run a tiny non-production workflow against the runner before using it for
inter-hub deployment.
The proof should show:
- job scheduling reaches the expected runner;
- labels match the published contract;
- build tooling required by the first supported workload is present;
- no cluster deployment authority is granted unless separately approved;
- logs and State Hub evidence identify the runner and commit without exposing
tokens.
Done when the sample job result is recorded and consumers can cite the runner
label as available.
**2026-06-07:** Added `.gitea/workflows/forge-runner-smoke.yaml`. It cannot pass
until an approved runner is registered and visible to Gitea.
**2026-06-07:** Haskelseed now has a running runner with matching labels. Smoke
execution is still pending until the workflow exists in the remote Gitea repo
and is dispatched or triggered.
**2026-06-08:** The workflow exists in Gitea and run `#1` was created from the
push, but it is still `Waiting`. This task now waits on authenticated Gitea
Actions inspection to approve, rerun, or diagnose runner assignment.
**2026-06-08:** Haskelseed was re-registered under the `coulomb` organization
runner scope using an attended Gitea UI token provided by the operator. Public
Gitea Actions no longer reports `No matching online runner with label:
self-hosted`, and `forge-runner-smoke.yaml #4` for commit `de6178764c` reports
`Success`. The runner substrate proof is complete.
---
## T06 - Unblock the inter-hub deployment path
```task
id: FORGE-WP-0003-T06
status: done
priority: high
state_hub_task_id: "53929202-40aa-4470-a249-9d0ee02d3213"
```
Coordinate the first real consumer unblock with inter-hub after T05 passes.
Steps:
- confirm the inter-hub workflow can target the approved runner labels;
- rerun or inspect the Build and Deploy workflow for the blocked commits;
- verify the expected inter-hub image tag exists in the registry;
- hand off runner evidence and any workflow adjustment recommendation to
inter-hub;
- avoid repeated production push probes until the runner is visible and ready.
Done when inter-hub has a clear deployment result or a narrower non-runner
blocker.
**2026-06-07:** Inter-hub unblock remains gated on T05. Do not rerun production
push probes until the forge smoke workflow passes.
**2026-06-08:** T05 passed. On runner reconnect, Gitea assigned haskelseed a
`coulomb/inter-hub` job, proving the inter-hub workflow can schedule on the
runner. The operator reported that the inter-hub job failed while the forge
smoke job succeeded, so the remaining work is to inspect the inter-hub job logs
and classify the workload-specific failure.
**2026-06-08:** Reproduced the non-secret inter-hub build step on haskelseed
from a committed-only `git archive` of inter-hub `84ee797`. `nix build
.#docker` fails before any registry push or Helm deployment with GHC-87543 in
`Web/Controller/Api/V2/Annotations.hs`: `createAnnotation` is ambiguous between
`Generated.Types.createAnnotation` and the local
`Web.Controller.Api.V2.Annotations.createAnnotation`. Registry tags `84ee797`,
`7cc3173`, `fa96fb8`, and `latest` remain `manifest unknown`. The forge runner
substrate is no longer the blocker; inter-hub now has a source build failure to
fix before deployment can proceed.
---
## T07 - Publish runner evidence and ongoing health checks
```task
id: FORGE-WP-0003-T07
status: done
priority: medium
state_hub_task_id: "c959a553-ec48-4e98-a752-168a2b067a81"
```
Update forge evidence docs and read-only operator targets so the runner is not a
one-off fix.
Include:
- runner inventory by label, placement, and trust level;
- last successful sample job and any publish job evidence;
- expected logs, dashboards, or status commands;
- documented alert or escalation condition for stuck jobs and offline runners;
- Forgejo migration notes so the same semantic labels can survive the future
Gitea-to-Forgejo cutover.
Done when forge can continuously explain whether the runner substrate is healthy
and what labels downstream workflows may depend on.
**2026-06-07:** Published runner evidence docs and Makefile probes. Current
health is explicitly `not proven`: no runner registration has been observed from
this session, and live host/Gitea inspection requires attended access.

View File

@@ -0,0 +1,116 @@
---
id: FORGE-WP-0004
type: workplan
title: "Standard public Gitea HTTPS root endpoint"
domain: financials
repo: railiance-forge
status: finished
owner: codex
topic_slug: railiance
planning_priority: high
created: "2026-06-13"
updated: "2026-06-13"
state_hub_workstream_id: "10a11cbb-9c2b-496b-af6a-dc934aeee68b"
---
# Standard public Gitea HTTPS root endpoint
## Context
Before this workplan, `https://gitea.coulomb.social/` returned `404` because
the forge-owned ingress only routed package and OCI registry paths. The Helm
overlay already declared `ROOT_URL: "https://gitea.coulomb.social/"`, so the
deployment standard now makes the public Gitea web route, Python package route,
and OCI registry route part of the same forge-owned endpoint contract.
## T01 - Set the public endpoint contract
```task
id: FORGE-WP-0004-T01
status: done
priority: high
state_hub_task_id: "f0125038-cf5b-4c8b-a90f-c3f3bedfc386"
```
Define the standard public Gitea endpoint as:
- `https://gitea.coulomb.social/` for the web UI and normal Gitea web/API
routes;
- `https://gitea.coulomb.social/api/packages/...` for package publication and
installation;
- `https://gitea.coulomb.social/v2/` for OCI registry clients.
This explicitly supersedes the temporary registry-only ingress posture.
## T02 - Update forge-owned deployment files
```task
id: FORGE-WP-0004-T02
status: done
priority: high
state_hub_task_id: "225707ce-10b5-41e3-809d-55f4b3a52c80"
```
Add a `/` catch-all path to `manifests/gitea-ingress.yaml`, keep the explicit
`/api/packages` and `/v2` paths visible for operator clarity, and reconcile the
ingress labels from the earlier `railiance-apps` extraction to
`railiance-forge` ownership.
Done when the manifest and operator docs describe the root web endpoint as the
standard deployment shape.
Completed on 2026-06-13. The ingress manifest now routes `/`, `/api/packages`,
and `/v2` to the Gitea service, and the ingress labels identify
`railiance-forge` ownership. Forge docs and operator target wording now describe
the public endpoint as web, package, and OCI registry surface rather than a
registry-only ingress.
## T03 - Apply and verify the live endpoint
```task
id: FORGE-WP-0004-T03
status: done
priority: high
state_hub_task_id: "9d1cd8e6-80da-4ded-9ae7-ddfeb64af0ae"
```
Apply the reviewed ingress and, if needed, reconcile the Gitea Helm release so
`ROOT_URL` remains the HTTPS host. Verify:
- root URL returns `200` or an expected redirect;
- `/api/v1/version` is reachable;
- `/v2/` still returns an OCI authentication challenge;
- the package-specific PyPI simple index for `issue-core` still returns `200`.
Completed on 2026-06-13. `kubectl apply -f manifests/gitea-ingress.yaml`
configured the public root path. A pinned Helm `--reuse-values` upgrade kept
chart `gitea-12.5.0` and app `1.25.4` while overriding only
`gitea.config.server.ROOT_URL=https://gitea.coulomb.social/`; Gitea rolled to
Helm revision 7.
Verification evidence:
- `https://gitea.coulomb.social/` returned `200`;
- `https://gitea.coulomb.social/api/v1/version` returned `200` with
`{"version":"1.25.4"}`;
- `https://gitea.coulomb.social/v2/` returned `401`, preserving the OCI auth
challenge;
- `https://gitea.coulomb.social/api/packages/coulomb/pypi/simple/issue-core/`
returned `200`;
- live `ROOT_URL` is `https://gitea.coulomb.social/`;
- the Gitea web UI bootstrap and `issue-core==0.2.0` package artifact links now
render HTTPS URLs.
## T04 - Sync State Hub and record evidence
```task
id: FORGE-WP-0004-T04
status: done
priority: medium
state_hub_task_id: "ad4b9574-89fd-4ced-8dde-3b0d5a9a555a"
```
Run State Hub consistency sync for `railiance-forge` and record a progress note
with non-secret verification evidence.
Completed on 2026-06-13 after the live endpoint verification.

View File

@@ -0,0 +1,97 @@
---
id: FORGE-WP-0005
type: workplan
title: "Remove public Gitea NodePort side door"
domain: financials
repo: railiance-forge
status: finished
owner: codex
topic_slug: railiance
planning_priority: high
created: "2026-06-14"
updated: "2026-06-14"
state_hub_workstream_id: "d6af707c-d9b1-463b-b24e-b384c5fb390d"
---
# Remove public Gitea NodePort side door
## Context
After `FORGE-WP-0004`, `https://gitea.coulomb.social/` is the canonical public
Gitea endpoint. The legacy `default/gitea` Service still exposed HTTP through
NodePort `32166`, which made `http://92.205.130.254:32166/` look like a second
Gitea entry point. It reached the same pod and database, but it bypassed the
canonical HTTPS host and created operator confusion.
## T01 - Make the HTTP Service internal-only
```task
id: FORGE-WP-0005-T01
status: done
priority: high
state_hub_task_id: "1ab4f7d0-0eef-4618-84d9-a84d72db9629"
```
Set the non-secret Gitea Helm overlay to `service.http.type: ClusterIP` so the
chart-supported `gitea-http` Service stays internal-only and the web/API surface
is only public through the forge-owned HTTPS ingress. Keep Git SSH exposure
separate and unchanged.
## T02 - Reconcile live Gitea and verify the side door is gone
```task
id: FORGE-WP-0005-T02
status: done
priority: high
state_hub_task_id: "34a9759e-10f1-4202-b8e9-443265495022"
```
Apply a pinned chart `--reuse-values` Helm reconciliation that keeps the
chart-supported HTTP service internal-only while preserving the existing Gitea
app version and HTTPS `ROOT_URL`. Move the ingress backend to `gitea-http`, then
delete the legacy `default/gitea` NodePort Service because it is no longer part
of the current chart's supported public endpoint model.
Verify:
- `default/gitea` is absent and `default/gitea-http` is internal-only;
- `http://92.205.130.254:32166/` is no longer reachable;
- `https://gitea.coulomb.social/` still returns `200`;
- `/api/v1/version` still returns the live Gitea version;
- `/v2/` still returns the OCI authentication challenge;
- the package-specific PyPI simple index for `issue-core` still returns `200`.
Completed on 2026-06-14. A pinned Helm `--reuse-values` reconciliation kept
chart `gitea-12.5.0`, app `1.25.4`, and
`gitea.config.server.ROOT_URL=https://gitea.coulomb.social/` while setting
`service.http.type=ClusterIP`. The forge ingress backend was moved from the
legacy `gitea` Service to the chart-supported internal `gitea-http` Service,
then the legacy `default/gitea` NodePort Service was deleted.
Verification evidence:
- `kubectl get svc -n default -l app.kubernetes.io/instance=gitea` lists
`gitea-http` as `ClusterIP`, `gitea-ssh` as `ClusterIP`, and
`gitea-ssh-nodeport` for Git SSH only; the legacy `gitea` Service is absent;
- `http://92.205.130.254:32166/` timed out;
- `https://gitea.coulomb.social/` returned `200`;
- `https://gitea.coulomb.social/api/v1/version` returned `200`;
- `https://gitea.coulomb.social/v2/` returned `401`, preserving the OCI auth
challenge;
- `https://gitea.coulomb.social/api/packages/coulomb/pypi/simple/issue-core/`
returned `200`.
## T03 - Sync State Hub and record closure evidence
```task
id: FORGE-WP-0005-T03
status: done
priority: medium
state_hub_task_id: "0f9f6b29-aeef-4558-a5f8-d1039a136224"
```
Run State Hub consistency sync for `railiance-forge`, record a progress note,
and keep the repo docs clear that raw HTTP NodePort access is not a supported
Gitea entry point.
Completed on 2026-06-14 after live verification.