Commit Graph
6 Commits
Author SHA1 Message Date
Omar SobhandClaude Opus 5 869c3adcb7 fix(missions): egress from a subnet of their own, so the host can police it
deploy / test (push) Successful in 5m39s
deploy / build (push) Successful in 7m28s
docs/MISSION-EGRESS.md measured that a mission container reaches the entire
tailnet and SSH on its own host, and left the remediation unapplied. Applying
it on 2026-09-18 found why five iptables lines were never going to be enough:
missions egressed from clawmates_edge, the SERVER's network, and the server
needs the tailnet — Beszel on architect, Ollama for the local backend, the
node daemons for exec-test and node-placed terminals. A tailnet drop scoped to
172.23/16 cut the server off from architect:8090 inside a minute.

Missions now egress from clawmates_missions, 172.25.0.0/16, pinned so the
firewall can name it and declared in both compose files with the same shape
edge has. Compose v1 does not create a network no service uses, so on gw-04
it was created by hand with compose's own labels; the server's attach failure
message now says to check for it. core is unchanged: the door and API are
still reached over 172.20.

The policy itself (/usr/local/sbin/clawmates-egress.sh on gw-04, systemd unit
+ drop-ins on docker and tailscaled) lives in mangle/PREROUTING with
--ctstate NEW. Two earlier placements failed measurably: filter/FORWARD loses
to tailscaled re-inserting ts-forward above it on every restart, and
raw/PREROUTING runs before conntrack, so it dropped the server's replies to
tailnet clients and took the API off 100.102.112.85:8088. Verified from the
mission subnet (tailnet, host ssh, link-local blocked; public and core open),
from edge (tailnet open, ssh blocked), and inbound from tank; and proved to
survive restarting both daemons.

Also: deploy/compose/docker-compose.override.yml is tracked now. It holds the
fixes for the five local bring-up gaps and every credential in it is a
${VAR:?} reference, and it had lived on one laptop that lost a volume this
week.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01WZb5A2kfVfjpdwSochkuHz
2026-09-18 11:06:03 -05:00
Omar SobhandClaude Opus 5 b1bf50160a ci: build and deploy to production from a push to main
deploy / test (push) Failing after 42s
deploy / build (push) Skipped
Closes the one manual step left in the pipeline. gw-04 has run
clawmates-deploy.timer every minute since July, pulling :latest and rolling on
drift — the CD half already worked. What was missing was anything that moved
:latest, since the old build host (tank) is packed for the move.

The runner lives on gw-04 because it is the only reachable x86_64 host and prod
images must be linux/amd64: web-01 is aarch64 and the fleet build boxes are
offline. Host executor, capacity 1, so builds serialize rather than competing
with production traffic.

Three details that are not obvious:
- `docker push :latest` does NOT move the tag on this registry once the manifest
  exists under another tag. The PUT-the-manifest step is what actually moves it,
  and its absence is how a "successful" deploy could leave prod on a stale image.
- The final step verifies the image prod is RUNNING, not the one we pushed. A
  green edge on the old image is the failure this pipeline exists to prevent.
- broker is built here too. It had no :latest tag at all, so gw-04's deploy loop
  logged a pull failure every single cycle since 2026-08-11.

Also ignore the local env backups: `.env` was ignored but `.env.bak.*` was not,
and those copies hold real credentials.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-13 10:03:35 -07:00
Omar SobhandClaude Opus 4.8 417d858bdd Fleet: host the node installer + daemon binaries (fix install.sh 404)
ci / rust (push) Has been skipped
ci / sandbox-k8s (push) Has been skipped
ci / frontend (push) Has been skipped
ci / e2e (push) Has been skipped
ci / gates (push) Failing after 5s
The connect-host curl one-liner 404'd because install.sh was never served. Serve
it from the frontend's public/ (Next serves it at /install.sh), and host the
daemon binaries at /dl/clawmates-node-<os>-<arch>:
- frontend/public/install.sh: detects OS/ARCH, downloads the matching binary,
  runs it (or prints from-source instructions if no prebuilt exists).
- Binaries (linux-amd64 built on tank, darwin-arm64 built locally) are baked into
  the frontend image at public/dl/ (gitignored, not committed).

Now `curl -fsSL https://clawmates.work/install.sh | bash -s -- --server … --token …`
works on linux + macOS nodes.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-24 16:06:19 -07:00
Omar SobhandClaude Opus 4.8 fbe783e278 Runtime: drive topology turns on the Claude subscription via claude_cli
ci / gates (push) Has been cancelled
ci / rust (push) Has been cancelled
ci / sandbox-k8s (push) Has been cancelled
ci / frontend (push) Has been cancelled
ci / e2e (push) Has been cancelled
Switch the per-tenant runtime to ZeroClaw's new native `claude_cli` model
provider (added in the zeroclaw repo): every agent turn spawns `claude -p`
headless, authed by CLAUDE_CODE_OAUTH_TOKEN — i.e. the Claude subscription, no
per-minute API TPM ceiling (the groq free tier 429'd multi-turn pipelines).

- Dockerfile: install the Claude Code CLI (@anthropic-ai/claude-code) into the
  runtime image.
- agent.config.example.toml: role-cast on model_provider = "claude_cli.default".
  NOTE: set the model via env (ZEROCLAW_providers__models__claude_cli__default__model)
  not the TOML sub-table, else resolve_default_model() reads empty -> NEEDS_ONBOARDING.
- .gitignore: token.key (local Claude OAuth token, never committed).

Validated live on gw-04: a 2-node researcher->writer pipeline ran via the
deployed POST /api/topologies/run -> claude_cli -> real claude turns; 2-step
RunRecord, cost_usd 0.0 (subscription), no rate limiting.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-16 15:46:27 -07:00
Omar SobhandClaude Fable 5 889c65685e e2e harness: refuse to run when port 8080 is already serving
The Playwright backend harness now aborts if something else (e.g. the
compose stack) is already on :8080, instead of letting reuseExistingServer
silently point every journey at the wrong backend with the wrong seed —
the failure mode that surfaced mid-restyle. Also gitignore the local
data/ blob-store artifacts.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-10 20:32:29 -05:00
Omar SobhandClaude Fable 5 0afb359183 P0: workspace scaffold, CI gates, tc-domain, tc-config, tc-db vs real Postgres
- Cargo workspace with 1250-line and no-placeholder CI gates wired first
- tc-domain: id newtypes, SessionKey codec (proptest round-trip), Role,
  GatedCategory (spec §15), AccessPolicy, core entities
- tc-config: figment TOML+env config, DeployTarget/provider/auth selection
  with semantic validation
- migrations/0001: full spec §14 schema incl. DB-enforced append-only audit_log
- tc-db: compile-time-checked sqlx repos (workspaces, users, agents+policies,
  credits, audit) with committed .sqlx offline metadata
- tc-testkit: per-test real-Postgres databases (testcontainers or
  TC_TEST_DATABASE_URL), embedded migrations

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-09 22:25:47 -05:00