Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
137 commits
Select commit Hold shift + click to select a range
c48b641
docs(plans): add NetBird dynamic WireGuard implementation plan
Jun 15, 2026
1c3a385
docs(plans): revise netbird plan — manager/consumer split, no caps on…
Jun 15, 2026
0c3b740
feat(netbird): install netbird binary in wg-client image
Jun 15, 2026
2ef59bc
feat(netbird): add netbird daemon startup and supervision to wg-clien…
Jun 16, 2026
1386e87
feat(netbird): add enable_netbird compose helper with idempotency
Jun 16, 2026
9b76c45
test(netbird): add compose contract tests enforcing single NET_ADMIN …
Jun 16, 2026
9538b3e
feat(netbird): add netbird management API helpers with unit tests
Jun 16, 2026
730917c
feat(netbird): add sandcat netbird subcommand dispatcher
Jun 16, 2026
a6a23f4
feat(init): add --netbird flag and enrollment key seeding
Jun 16, 2026
485409e
docs(cli): document --netbird flag and sandcat netbird subcommand
Jun 16, 2026
fe90b1b
feat(netbird): pin netbird binary with per-arch sha256 checksums
Jun 16, 2026
90abce8
feat(netbird): resolve API and enrollment tokens from sandcat settings
Jun 16, 2026
1fcfba5
feat(netbird): add management server selection and template provisioning
Jun 18, 2026
feea415
this is kind of working
Jun 20, 2026
286b11d
working before cleanup
Jun 20, 2026
15ce9dd
feat(netbird): add server lifecycle commands and harden API client
Jun 22, 2026
7db49a5
feat(capability-runtime): add project scaffold and v1 types
Jun 22, 2026
780035f
feat(capability-runtime): add typed error taxonomy (spec §3.3)
Jun 22, 2026
11d418b
feat(capability-runtime): add observability collector with replay
Jun 22, 2026
42f9194
feat(capability-runtime): add capability catalog and lifecycle states
Jun 22, 2026
5f96b25
feat(capability-runtime): add LeaseManager for grant and quota tracking
Jun 22, 2026
ba52973
feat(capability-runtime): add revocation and discovery
Jun 22, 2026
f83a310
Implement CapabilityRuntime with all protocol surfaces
Jun 22, 2026
cdc228b
feat(capability-runtime): add AgentExecutionLoop harness
Jun 22, 2026
5648527
feat(capability-runtime): add mock MCP tool adapter for PoC 2
Jun 22, 2026
58d677e
feat(capability-runtime): add PoC 1 create_pr runnable demo
Jun 22, 2026
f629cea
feat(capability-runtime): add network capability types and physical b…
Jun 22, 2026
9ee6274
feat(capability-runtime): add NetBird client with mock and REST imple…
Jun 22, 2026
a440e11
feat(capability-runtime): add NetBirdRevocationBackend for physical n…
Jun 22, 2026
3b30612
Add network capability catalog and bundle assembly
Jun 22, 2026
5d14c15
Wire logical revoke to physical NetBird backend
Jun 22, 2026
60db8c7
feat: implement RouteDisappearanceWatcher for physical-to-logical rev…
Jun 22, 2026
11e3343
feat(capability-runtime): add PoC 3 network route demo
Jun 22, 2026
e1f259e
docs(capability-runtime): document Phase 3 NetBird networking scope
Jun 22, 2026
b590052
feat(capability-runtime): extract lease policy and add security bound…
Jun 23, 2026
e280034
chore(tests): fix failing tests
Jun 23, 2026
33cfab9
feat(capability-runtime): enforce caller identity and operator-only r…
Jun 29, 2026
544fb90
feat(capability-runtime): load NetBird credentials from sandcat setti…
Jun 29, 2026
b7d87df
feat(capability-runtime): add JSON-RPC dispatcher with agent and admi…
Jun 29, 2026
b4e48ae
feat(capability-runtime): add sidecar daemon with dual Unix socket RPC
Jun 29, 2026
bd251ea
feat(capability-runtime): add MCP stdio bridge to agent RPC socket
Jun 29, 2026
c6927dc
feat(cli): add capability-runtime sidecar compose integration
Jun 29, 2026
6ada509
feat(cli): add sandcat capability operator subcommand
Jun 29, 2026
e865645
docs: document Phase 3b capability sidecar and MCP bridge
Jun 29, 2026
eeadf0d
fix(cli): mount capability socket outside read-only wg-runtime path
Jun 29, 2026
2ee2aa6
feat(capability-runtime): add NetworkBinding sync_mode and grant prot…
Jun 30, 2026
10a8e0b
feat(capability-runtime): add NetBirdClient enable/disable binding
Jun 30, 2026
a791f6a
feat(capability-runtime): wire grant path to NetBird enable_binding
Jun 30, 2026
109ce26
feat(capability-runtime): prefer disable_binding on revoke
Jun 30, 2026
60cc941
feat(cli): catalog sync_mode and capability watch physical sync events
Jun 30, 2026
8491d22
docs: Phase 3c NetBird policy sync grant/revoke
Jun 30, 2026
636e6a2
fix(cli): fix capability sidecar startup and agent MCP connectivity
Jul 2, 2026
95ab2d6
fix(capability-runtime): disable NetBird binding on revoke by lease ID
Jul 3, 2026
558c1ce
test(cli): use yq -e for capability compose existence checks
Jul 3, 2026
ef7a7fb
fix(capability-runtime): allow re-lease after revoke or expiry
Jul 3, 2026
4edbca5
fix(capability-runtime): mark leases revoked on ref-based revoke
Jul 3, 2026
2876774
feat(capability-runtime): reconcile route disappearance in watcher
Jul 3, 2026
4139ace
fix(capability-runtime): tolerate NetBird errors during TTL expiry
Jul 3, 2026
587bf05
docs: add Phase 3c engineering gate script and live smoke steps
Jul 3, 2026
f598631
ix(capability-runtime): tolerate NetBird errors on operator revoke
Jul 3, 2026
b49b3a2
fixes
Jul 8, 2026
2006c66
feat(cli): add proxy-peer hello HTTP server for mesh smoke
Jul 8, 2026
086aebc
test(cli): harden proxy-peer hello bats harness
Jul 8, 2026
ad59676
feat(cli): add proxy-peer NetBird enrollment init script
Jul 8, 2026
492f3dc
feat(cli): add proxy-peer Docker image and compose stack
Jul 8, 2026
3a79ef1
feat(cli): add sandcat init --proxy-peer template wiring
Jul 8, 2026
75624bd
docs(cli): add Layer 1 mitmproxy profile for proxy-peer gateway
Jul 8, 2026
123a6d9
feat(capability-runtime): catalog lease_policy for network capabilities
Jul 8, 2026
dc3da7d
feat(capability-runtime): admin capability.l7.record for flow quota
Jul 8, 2026
da6e98e
feat(mitmproxy): post-hoc l7 flow record to capability sidecar
Jul 8, 2026
1ce0eda
docs: add Phase 3e proxy-peer engineering gate
Jul 8, 2026
7bd6ca5
fix(phase3e): address code review findings for L7 quota loop
Jul 9, 2026
c04b46c
chore: drop accidental cli/.version from commit
Jul 9, 2026
fd46105
fix(capability-runtime): fail closed on revoke and schedule TTL expiry
Jul 9, 2026
e764e19
test(cli): harden proxy-peer hello bats against port flakes
Jul 9, 2026
fff385e
docs(spec): add proxy-peer NetBird DNS targeting design
Jul 22, 2026
cf0df20
feat(capability-runtime): resolve network binding from NetBird dns_label
Jul 22, 2026
6e815d3
feat(wg-client): forward NetBird DNS domain via dnsmasq
Jul 22, 2026
a23c724
docs(cli): proxy-peer Layer 1 and gate prefer NetBird FQDN
Jul 22, 2026
1488309
docs: wire NetBird DNS targeting into CONTEXT and Phase 3e
Jul 22, 2026
f24ce35
fix(netbird-dns): address three review findings
Jul 22, 2026
b56b5bc
fix(l7-record): match FQDN host against dns_label for quota tracking
Jul 22, 2026
6dd2cf0
feat(mitmproxy): honor network rule enabled flag
Aug 6, 2026
9d5d71a
feat(capability-runtime): add revocation close policy to network bind…
Aug 6, 2026
a3059be
feat(mitmproxy): apply L7 revoke host deny and close policies
Aug 6, 2026
3280952
fix(mitmproxy): complete L7 revocation close policy implementation
Aug 6, 2026
7f90553
fix(mitmproxy): run drain kill after response hooks
Aug 6, 2026
5bb2714
feat(mitmproxy): expose Mitmproxy Revocation Socket for revoke_flows
Aug 6, 2026
6e1c176
fix(mitmproxy): address Task 4 review findings for revoke RPC
Aug 6, 2026
2eefb32
feat(capability-runtime): add best-effort L7 revocation push client
Aug 6, 2026
0df5f10
feat(capability-runtime): push L7 revoke on network logical revocation
Aug 6, 2026
08af6ac
feat(cli): add --close-policy override for capability revoke
Aug 6, 2026
df9d058
feat(compose): wire Mitmproxy Revocation Socket into capability-runtime
Aug 6, 2026
19617ce
fix(mitmproxy): make L7 revoke server optional and track live flows
Aug 6, 2026
9c8b1f6
fix(capability-runtime): make L7 push additive and add a restore path
Aug 6, 2026
d8465b7
fix(compose): mount l7_revoke_rpc and declare mitmproxy-config uncond…
Aug 6, 2026
f05a745
fix(compose): isolate the L7 revoke socket on its own volume
Aug 6, 2026
4a9861c
fix(mitmproxy): scope L7 restore to its capability and harden flow kills
Aug 6, 2026
bc93dfe
feat(cli): run NetBird on mitmproxy and bridge mesh DNS to the agent
Aug 12, 2026
3b28683
feat(netbird): add project-scoped peer name settings helpers
Aug 13, 2026
8dd82f3
test(netbird): cover empty-string peer name refill
Aug 13, 2026
caf6c8b
feat(netbird): rewrite catalog and Layer 1 example from peer names
Aug 13, 2026
78a6227
feat(composefile): inject NetBird peer name, token, and state volume
Aug 13, 2026
27f0f1c
feat(composefile): project-scope proxy-peer NetBird hostname and state
Aug 13, 2026
c9b4195
feat(init): seed and apply project-scoped NetBird peer names
Aug 13, 2026
b8a0962
test(init): assert NetBird peer name override propagation
Aug 13, 2026
2e24c88
feat(netbird): share peer reconnect and replacement lifecycle
Aug 13, 2026
6838f1c
fix(netbird): make peer replacement deterministic
Aug 13, 2026
92dc130
fix(netbird): restore delete peer by name helper
Aug 13, 2026
4564e39
feat(netbird): wire peer lifecycle into proxy enrollment
Aug 13, 2026
082945b
docs(netbird): retire peer-proxy spelling in Phase A operator surfaces
Aug 13, 2026
83fdd56
fix revoking in capability-runtime
Aug 26, 2026
158ec58
refactor(cli): configure NetBird instead of provisioning it
Aug 27, 2026
9c16468
cleanup POC leftovers
Aug 29, 2026
4e41e87
feat: bind-mount project catalog into capability-runtime
Aug 30, 2026
981c0c6
feat: add sandcat edit capability-catalog
Aug 30, 2026
fd33d5b
feat: restart capability-runtime from catalog edit with --restart
Aug 30, 2026
3d05ffb
fix: warn when catalog is not bind-mounted into capability-runtime
Aug 30, 2026
f19f983
docs: edit capability-catalog instead of hand-restarting a baked file
Aug 30, 2026
983b394
fix: catalog-edit warning, mounted no-restart test, and remount docs
Aug 30, 2026
7019c6c
fix(cli): reject --capability so init no longer wires the sidecar
Aug 31, 2026
5a191cb
refactor(cli): remove capability-runtime sidecar and operator commands
Aug 31, 2026
29d0f0b
fix(mitmproxy): drop L7 revoke and record paths
Aug 31, 2026
b70b0be
refactor(cli): remove sandcat netbird host REST commands
Aug 31, 2026
d211000
feat(netbird): flatten settings objects into NB_* compose env
Aug 31, 2026
490ec1e
feat(netbird): resolve op:// and pass:// enroll creds in the container
Aug 31, 2026
a5ac03e
fix(netbird): let prepare flatten enrollment key from settings.json
Aug 31, 2026
f6fde9f
fix(examples): drive proxy-peer from env files without committed secrets
Aug 31, 2026
a1f7b13
docs: thin NetBird PoC runbooks to compose, ACL, and mitmproxy enroll
Sep 1, 2026
a24f3aa
docs: drop Layer 2 route wording from proxy-peer settings comment
Sep 1, 2026
e088ebd
fix(netbird): bound secret CLI timeouts and flatten API token resolve
Sep 1, 2026
d7514e8
fix(netbird): pin clients to 0.72.4 so Docker peers can use the embed…
Sep 2, 2026
b903d90
fix(netbird): skip replace without a PAT and keep one lifecycle script
Sep 3, 2026
31e600e
fix(cli): heal post-rebase compose include and test fallout
Sep 10, 2026
cad4315
fix(netbird): keep mitmproxy healthy and stop mesh/repo credential leaks
Sep 10, 2026
7af3302
perf(cli): cut yq process overhead during sandcat init
Sep 10, 2026
a667f1d
fix(cli): heal post-rebase compose include and test fallout
Sep 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ __pycache__/
.pytest_cache/
.sandcat/settings.local.json
.devcontainer
.orca
.orca
.worktrees/
docs/examples/proxy-peer/.env
docs/examples/netbird-server/config.local.yaml
128 changes: 128 additions & 0 deletions cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ Options:
- `--stacks` - Comma-separated development stacks to install: `node`, `python`, `java`, `rust`, `go`, `scala`, `ruby`, `dotnet`, `zig` (skips prompt)
- `--proxy` - Proxy UI mode: `web` (default, mitmweb browser UI) or `tui` (mitmproxy console, use with `sandcat proxy` to attach)
- `--secret-provider` / `--sp` - Secret backend: `none` (default), `1password`, `protonpass` (skips prompt when set)
- `--netbird` - Enable dynamic WireGuard control via NetBird. The NetBird client
daemon runs inside the **mitmproxy** container and manages `wt0` — a second
WireGuard interface for the NetBird overlay mesh. Agent egress always flows
`wg0 (wg-client) → mitmproxy L7 inspect → internet or wt0 mesh`, so all
traffic — including mesh traffic — is subject to mitmproxy network rules and
secret substitution. Seeds `netbird_enrollment_key` and `netbird_api_token`
in `~/.config/sandcat/settings.json`.
- `--netbird-management-url` - Existing NetBird management server URL (requires
`--netbird`). Omit to use NetBird Cloud (`https://api.netbird.io`). Sandcat
does not create or start a management server; see
[`docs/examples/netbird-server/`](../docs/examples/netbird-server/).
- `--1password` - Deprecated alias for `--secret-provider 1password`
- `--features` - Comma-separated optional non-provider features: `tui` (proxy console mode; prefer `--proxy tui`), `no-gitignore` (skip appending the `# Sandcat` block to the project's `.gitignore`; equivalent to `SANDCAT_GITIGNORE=false`), `no-rtk` (skip RTK installation; equivalent to `SANDCAT_RTK=false`), `strict-network` (project settings get network presets for the selected stacks instead of the allow-all-GET wildcard; equivalent to `SANDCAT_STRICT_NETWORK=true`)
- `--name` - Project name for Docker Compose (default: derived from directory name)
Expand All @@ -43,6 +54,13 @@ sandcat init --agent claude --ide vscode --secret-provider 1password --name mypr

# With Proton Pass integration
sandcat init --agent claude --ide vscode --secret-provider protonpass --name myproject

# With NetBird dynamic WireGuard
sandcat init --agent claude --ide vscode --netbird --name myproject

# Point at an existing self-hosted management server
sandcat init --agent cursor --ide vscode --netbird \
--netbird-management-url https://netbird.example.com --name myproject
```

#### Proton Pass setup (scoped Personal Access Token)
Expand Down Expand Up @@ -213,6 +231,116 @@ shell, `sandcat run npm install` runs npm inside the container.
Options:
- `--build` — Rebuild images before running (e.g. after editing `Dockerfile.app`)

## Dynamic networking (NetBird)

When initialized with `--netbird`, sandcat enrolls **mitmproxy** as a NetBird peer.
The NetBird client daemon runs inside the mitmproxy container and manages `wt0` — a
second WireGuard interface for the overlay mesh. Agent traffic always flows:

```
agent → wg0 (wg-client kill switch) → mitmproxy (L7 inspect + secrets) → internet
↘ wt0 (NetBird mesh)
```

This design eliminates the routing collision that occurred when NetBird ran on `wg-client`
alongside `wg0` (WireGuard-in-WireGuard). wg-client is now a pure tunnel shim with no
NetBird involvement.

The NetBird client binary is pinned by version and per-arch sha256 in
[`templates/devcontainer/sandcat/netbird.env`](templates/devcontainer/sandcat/netbird.env).
`sandcat init --netbird` injects these as compose build args for `Dockerfile.mitmproxy`
automatically. NetBird is downloaded and checksum-verified in a throwaway builder stage,
then copied into a final image built `FROM $BASE_IMAGE`.

`BASE_IMAGE` defaults to `mitmproxy/mitmproxy:latest`. When a secret provider is also
selected, `sandcat init` sets it to that provider's variant
(`ghcr.io/virtuslab/sandcat-mitmproxy-pass` or `-op`), so the proxy ends up with **both**
NetBird and the provider CLI. Combining `--netbird` with `--secret-provider` therefore
keeps `pass://` and `op://` references resolvable.

To build the image manually:

```bash
cd cli/templates/devcontainer/sandcat
set -a; . netbird.env; set +a
docker build -f Dockerfile.mitmproxy \
--build-arg NETBIRD_VERSION \
--build-arg NETBIRD_SHA256_AMD64 \
--build-arg NETBIRD_SHA256_ARM64 \
--build-arg BASE_IMAGE=ghcr.io/virtuslab/sandcat-mitmproxy-pass:latest \
-t mitmproxy-netbird-test .
```

### Setup

NetBird uses **two separate credentials**. Both go in `~/.config/sandcat/settings.json`
(created by `sandcat init`; edit with `sandcat edit user-settings`):

| Setting key | Used for | Where to get it |
|-------------|----------|-----------------|
| `netbird_enrollment_key` | Enrolling mitmproxy as a mesh peer (`NB_SETUP_KEY`); may be a literal or `op://` / `pass://` (resolved in the container) | NetBird dashboard → **Setup Keys** |
| `netbird_api_token` | Used by mitmproxy for same-name replace and dns_label; may be a literal or `op://` / `pass://` (resolved in the container) | NetBird dashboard → **API Keys** (Personal Access Token) |
| `netbird_management_url` | Management API and dashboard | Empty = cloud; otherwise your server URL |
| `netbird_enrollment_management_url` | mitmproxy enrollment URL (container cannot use `localhost`) | Docker host LAN IP for a local server; see [docs/examples/netbird-server](../docs/examples/netbird-server/) |

Complete steps 1–4 below before enrollment. Container enrollment
(`netbird_enrollment_key`) is separate from same-name replace and dns_label
(`netbird_api_token`) — you need the API token even if the setup key is already
in settings.

1. Create a NetBird account at <https://app.netbird.io> or self-host the server.
2. In the dashboard, create a **Setup Key** (for peer enrollment).
3. In the dashboard, create an **API Key** / personal access token (for mitmproxy same-name replace and dns_label).
4. Add both values to user settings:

```json
{
"netbird_enrollment_key": "your-setup-key-here",
"netbird_api_token": "your-api-token-here"
}
```

Or edit interactively:

```bash
sandcat edit user-settings
```

`sandcat compose` and `sandcat run` read `netbird_enrollment_key` and
`netbird_api_token` from **user** settings (`~/.config/sandcat/settings.json`)
only — not from project `.sandcat/` files, which are bind-mounted into the
agent. Environment variables `NB_SETUP_KEY` and `NB_API_TOKEN` override
user settings when set. The agent mount is a filtered copy with those two
keys stripped.

### Management server

Sandcat configures connection details; it does not create or lifecycle a
NetBird management server.

- **Cloud** — omit `--netbird-management-url` (defaults to `https://api.netbird.io`).
- **Existing self-hosted** — pass `--netbird-management-url <http(s)://url>`.
- **Run a local server yourself** — follow
[`docs/examples/netbird-server/`](../docs/examples/netbird-server/), then
point sandcat at it.

```bash
# Cloud
sandcat init --agent claude --ide vscode --netbird --name myproject

# Existing self-hosted management server
sandcat init --agent claude --ide vscode --netbird \
--netbird-management-url https://netbird.example.com --name myproject
```

Interactive `sandcat init --netbird` (when other options are also prompted)
offers cloud vs “I have a server running”.

## Optional mesh gateway (proxy-peer)

Sandcat does not create a proxy-peer container. See
[`docs/examples/proxy-peer/`](../docs/examples/proxy-peer/).

## Directory Structure

Each module is contained in its own directory under `cli/libexec/`.
Expand Down
Loading
Loading