Add docs/cutover.md (shadow :8001, embedded NATS :4223, REQUIRE_BEARER host-token default, cutover/rollback; no JetStream for job-complete). Expand README Usage with env table and pkg/tsnats snippet; add examples/tsnats-bulk.
67 lines
3.2 KiB
Markdown
67 lines
3.2 KiB
Markdown
# Shadow deploy and cutover (Go MCP)
|
|
|
|
Python stays on `127.0.0.1:8000`. Go shadows on `127.0.0.1:8001` with embedded NATS on `127.0.0.1:4223`. Do **not** install or enable the Go unit on ns1 until an explicit publish/deploy order.
|
|
|
|
## Shadow layout
|
|
|
|
| Role | Bind | Notes |
|
|
| --- | --- | --- |
|
|
| Python MCP (live) | `127.0.0.1:8000` | Caddy → public `/mcp` |
|
|
| Go MCP (shadow) | `127.0.0.1:8001` | Internal smoke only until cutover |
|
|
| Go embedded NATS | `127.0.0.1:4223` | `pkg/tsnats` / bulk workers |
|
|
|
|
Install tree (when deploying): `/opt/verae/verae-mcp-timestamping-server-go/` (does not overwrite the Python venv). Unit file in-repo: `deploy/verae-mcp-timestamping-go.service`.
|
|
|
|
## Bearer / host-token (shadow default)
|
|
|
|
| `VERAE_MCP_REQUIRE_BEARER` | Behavior |
|
|
| --- | --- |
|
|
| `0` or unset (**default**) | Caller `Authorization: Bearer` wins when present. Otherwise the process keeps a host token from `~/.verae/auth.properties` (or `VERAE_AUTH_PROPERTIES` / `VERAE_GLOBAL_TOKEN`) and refreshes before expiry. |
|
|
| `1` | Caller bearer required for global VeraeTime paths; no host-token fallback. |
|
|
|
|
Shadow unit ships `VERAE_MCP_REQUIRE_BEARER=0` so operators can smoke without every client supplying a JWT.
|
|
|
|
## Embedded NATS / job-complete
|
|
|
|
- Listen: `VERAE_NATS_LISTEN=127.0.0.1:4223` (set empty to disable embed).
|
|
- Request/reply: `verae.ts.request`, `verae.ts.verify`, `verae.hash.report`.
|
|
- Job-complete / jobId notify: **core NATS only** on `verae.ts.completed` (and receipt notify if used). **No JetStream** (or other persistent stream) for job-complete. Publishers fire-and-forget; listeners subscribe.
|
|
|
|
## Env cheat sheet (shadow)
|
|
|
|
```sh
|
|
VERAE_MCP_TRANSPORT=streamable-http
|
|
VERAE_MCP_HOST=127.0.0.1
|
|
VERAE_MCP_PORT=8001
|
|
VERAE_NATS_LISTEN=127.0.0.1:4223
|
|
VERAE_MCP_REQUIRE_BEARER=0
|
|
# optional: VERAE_AUTH_PROPERTIES, VERAE_LEDGER_PATH, VERAE_GLOBAL_URL, VERAE_GLOBAL_TOKEN, VERAE_MCP_CORS
|
|
```
|
|
|
|
Service user on ns1 is `verae-mcp` with `HOME=/var/lib/verae-mcp` (share or isolate `auth.properties` vs Python as chosen for the soak).
|
|
|
|
## Local parity before soak
|
|
|
|
With Python on `:8000` and Go on `:8001`:
|
|
|
|
```sh
|
|
./scripts/parity_smoke.sh
|
|
```
|
|
|
|
Compares `tools/list` name sets. Optionally stamp/verify/hash_report the same digests against both ports during soak.
|
|
|
|
## Cutover checklist
|
|
|
|
1. Shadow green for the agreed soak (tools/list parity, global stamp/verify/hash_report, local ledger, NATS stamp + `verae.ts.completed` observe).
|
|
2. Stop Python unit **or** switch Caddy upstream away from `:8000` Python.
|
|
3. Point Go at public port: set `VERAE_MCP_PORT=8000` (or leave Go on `8001` and point Caddy at Go).
|
|
4. Confirm `https://mcp.verae.ai/mcp` `tools/list` and a known digest `hash_report`.
|
|
5. Keep the Python tree on disk for one release cycle.
|
|
6. Do not enable JetStream for job-complete as part of cutover.
|
|
|
|
## Rollback checklist
|
|
|
|
1. Restore Python `ExecStart` / Caddy upstream to `127.0.0.1:8000` Python.
|
|
2. Stop or disable `verae-mcp-timestamping-go.service` (or move Go back to `:8001` only).
|
|
3. Restart Python; confirm public `tools/list` and a known `hash_report`.
|
|
4. Leave Go binary under `/opt/verae/verae-mcp-timestamping-server-go/` for a later retry; do not delete until soak of the rollback is confirmed.
|