Prepare State Hub retirement baseline
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Multi-Context Image / build-and-push (push) Successful in 1m0s

This commit is contained in:
tegwick 2026-08-09 16:19:53 +02:00
parent 2217bdd9f5
commit 5927591be8
46 changed files with 32583 additions and 62 deletions

View file

@ -14,6 +14,7 @@ AUTHORIZE_SSH=0
ALLOW_PLAINTEXT_STORE=0
SKIP_GITEA=0
SKIP_MCP=0
SKIP_CODEX=0
SSH_KEY="${SSH_KEY:-$HOME/.ssh/id_ed25519}"
SSH_TARGETS=(
"tegwick@92.205.62.239"
@ -39,6 +40,7 @@ Options:
--gitea-token TOKEN Gitea token; otherwise prompted when interactive.
--skip-gitea Do not create or update ~/.railiance_gitea.conf.
--skip-mcp Do not run make register-mcp.
--skip-codex Do not configure Codex sandbox networking.
-h, --help Show this help.
USAGE
}
@ -118,6 +120,10 @@ while [ "$#" -gt 0 ]; do
SKIP_MCP=1
shift
;;
--skip-codex)
SKIP_CODEX=1
shift
;;
-h|--help)
usage
exit 0
@ -342,6 +348,19 @@ register_mcp() {
fi
}
configure_codex() {
step "Configuring Codex State Hub access"
if [ "$SKIP_CODEX" -eq 1 ]; then
warn "Skipping Codex configuration by request."
return
fi
local args=()
if [ "$DRY_RUN" -eq 1 ]; then
args+=(--dry-run)
fi
"$STATE_HUB_DIR/scripts/configure-codex.sh" "${args[@]}"
}
health_check() {
step "Checking State Hub reachability"
if curl -fsS --max-time 2 "http://127.0.0.1:8000/state/health" >/dev/null 2>&1; then
@ -362,6 +381,7 @@ main() {
setup_ssh_key
write_gitea_conf
register_mcp
configure_codex
health_check
ok "Bootstrap checks complete."
}

View file

@ -1,7 +1,9 @@
#!/usr/bin/env bash
set -euo pipefail
cd /home/worsch/state-hub
STATE_HUB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
STATE_HUB_PYTHON="${STATE_HUB_PYTHON:-$STATE_HUB_DIR/.venv/bin/python}"
cd "$STATE_HUB_DIR"
API_BASE="${API_BASE:-http://127.0.0.1:8000}"
HEALTH_URL="${API_BASE%/}/state/health"
@ -24,6 +26,12 @@ if ! api_healthy; then
exit 1
fi
if [ ! -x "$STATE_HUB_PYTHON" ]; then
echo "state-hub Python is not executable at $STATE_HUB_PYTHON" >&2
echo "install the repository environment before starting the Codex MCP server" >&2
exit 1
fi
export API_BASE
export MCP_TRANSPORT=stdio
exec uv run python mcp_server/server.py
exec "$STATE_HUB_PYTHON" mcp_server/codex_server.py

142
scripts/configure-codex.sh Executable file
View file

@ -0,0 +1,142 @@
#!/usr/bin/env bash
set -euo pipefail
CODEX_HOME_DIR="${CODEX_HOME:-$HOME/.codex}"
CONFIG_PATH="${CODEX_CONFIG_PATH:-$CODEX_HOME_DIR/config.toml}"
API_BASE="${API_BASE:-http://127.0.0.1:8000}"
DRY_RUN=0
SKIP_VERIFY=0
MCP_MODE="remove"
MCP_NAME="${STATE_HUB_MCP_NAME:-dev-hub}"
MCP_COMMAND="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/codex-state-hub-mcp.sh"
usage() {
cat <<'USAGE'
Usage: scripts/configure-codex.sh [options]
Enable direct network access for Codex workspace-write sandboxes and verify
that the sandbox can reach the local State Hub.
Options:
--codex-home DIR Codex home containing config.toml. Default: $CODEX_HOME or ~/.codex.
--api-base URL State Hub API base. Default: http://127.0.0.1:8000.
--dry-run Show the configuration change without writing it.
--skip-verify Do not run the sandboxed State Hub health check.
--with-mcp Opt in to the experimental slim State Hub MCP server.
--skip-mcp Do not add or remove a State Hub MCP registration.
-h, --help Show this help.
USAGE
}
while [ "$#" -gt 0 ]; do
case "$1" in
--codex-home)
test -n "${2:-}" || { echo "ERROR: --codex-home requires a directory" >&2; exit 2; }
CODEX_HOME_DIR="$2"
CONFIG_PATH="$CODEX_HOME_DIR/config.toml"
shift 2
;;
--api-base)
test -n "${2:-}" || { echo "ERROR: --api-base requires a URL" >&2; exit 2; }
API_BASE="$2"
shift 2
;;
--dry-run) DRY_RUN=1; shift ;;
--skip-verify) SKIP_VERIFY=1; shift ;;
--with-mcp) MCP_MODE="add"; shift ;;
--skip-mcp) MCP_MODE="skip"; shift ;;
-h|--help) usage; exit 0 ;;
*) echo "ERROR: unknown argument: $1" >&2; usage >&2; exit 2 ;;
esac
done
python3 - "$CONFIG_PATH" "$DRY_RUN" <<'PY'
import re
import sys
import tomllib
from pathlib import Path
path = Path(sys.argv[1])
dry_run = sys.argv[2] == "1"
original = path.read_text(encoding="utf-8") if path.exists() else ""
if original:
tomllib.loads(original)
header = "[sandbox_workspace_write]"
lines = original.splitlines()
start = next((i for i, line in enumerate(lines) if line.strip() == header), None)
if start is None:
if lines and lines[-1].strip():
lines.append("")
lines.extend([header, "network_access = true"])
else:
end = next(
(i for i in range(start + 1, len(lines)) if re.match(r"^\s*\[", lines[i])),
len(lines),
)
setting = next(
(i for i in range(start + 1, end) if re.match(r"^\s*network_access\s*=", lines[i])),
None,
)
if setting is None:
lines.insert(end, "network_access = true")
else:
lines[setting] = "network_access = true"
updated = "\n".join(lines).rstrip() + "\n"
tomllib.loads(updated)
if updated == original:
print(f"OK: {path} already enables sandbox workspace-write network access")
elif dry_run:
print(f"DRY-RUN: would enable sandbox_workspace_write.network_access in {path}")
else:
path.parent.mkdir(parents=True, exist_ok=True)
temporary = path.with_suffix(path.suffix + ".tmp")
temporary.write_text(updated, encoding="utf-8")
temporary.chmod(0o600)
temporary.replace(path)
print(f"OK: enabled sandbox_workspace_write.network_access in {path}")
PY
if [ "$MCP_MODE" = "add" ]; then
if [ "$DRY_RUN" -eq 1 ]; then
echo "DRY-RUN: would register Codex MCP server $MCP_NAME -> $MCP_COMMAND"
elif ! command -v codex >/dev/null 2>&1; then
echo "WARN: codex is not on PATH; State Hub MCP registration was skipped." >&2
elif CODEX_HOME="$CODEX_HOME_DIR" codex mcp get "$MCP_NAME" >/dev/null 2>&1; then
echo "OK: Codex MCP server $MCP_NAME is already registered"
else
CODEX_HOME="$CODEX_HOME_DIR" codex mcp add "$MCP_NAME" -- "$MCP_COMMAND"
echo "OK: registered Codex MCP server $MCP_NAME -> $MCP_COMMAND"
fi
elif [ "$MCP_MODE" = "remove" ]; then
if [ "$DRY_RUN" -eq 1 ]; then
echo "DRY-RUN: would remove Codex MCP server $MCP_NAME if registered"
elif command -v codex >/dev/null 2>&1 \
&& CODEX_HOME="$CODEX_HOME_DIR" codex mcp get "$MCP_NAME" >/dev/null 2>&1; then
CODEX_HOME="$CODEX_HOME_DIR" codex mcp remove "$MCP_NAME"
echo "OK: removed Codex MCP server $MCP_NAME; use REST/statehub CLI by default"
else
echo "OK: Codex MCP server $MCP_NAME is not registered"
fi
fi
if [ "$DRY_RUN" -eq 1 ] || [ "$SKIP_VERIFY" -eq 1 ]; then
exit 0
fi
if ! command -v codex >/dev/null 2>&1; then
echo "WARN: codex is not on PATH; configuration was written but not verified." >&2
exit 0
fi
HEALTH_URL="${API_BASE%/}/state/health"
if timeout 10 codex sandbox -- curl -fsS --max-time 3 "$HEALTH_URL" >/dev/null 2>&1; then
echo "OK: Codex sandbox can reach State Hub at $HEALTH_URL"
else
echo "WARN: Codex sandbox still cannot reach $HEALTH_URL." >&2
echo "WARN: A managed permission profile may enforce restricted networking/--unshare-net." >&2
echo "WARN: Retry State Hub REST/CLI commands with escalated execution or change the managed profile." >&2
fi

View file

@ -13,8 +13,10 @@
## State Hub Integration
The Custodian State Hub tracks work across all domains. Interact via HTTP REST —
there is no MCP server for Codex agents.
The Custodian State Hub tracks work across all domains. Codex uses HTTP REST and
the `statehub` CLI by default. MCP is opt-in because the current Codex MCP bridge
adds severe call latency; the full administrative MCP surface remains available
to clients that need it.
| Context | URL |
|---------|-----|
@ -27,6 +29,14 @@ Queueable writes return an explicit queued receipt if the central hub is
unreachable. Treat that as pending local evidence, then ask the operator to run
statehub outbox status/replay after connectivity returns.
Codex workspace-write sandboxes need network access enabled to reach the host's
loopback listener. Bootstrap this once with `make -C ~/state-hub configure-codex`
and restart Codex. The canonical REST health endpoint is `/state/health`, not
`/health`. If a sandboxed loopback probe fails, retry it with escalated execution
before declaring State Hub unavailable; a managed Codex permission profile may
still enforce isolated networking. Experimental MCP can be enabled explicitly
with `make -C ~/state-hub configure-codex WITH_MCP=1`.
### Orient at session start
```bash