Skip to content

Commit 710b3dc

Browse files
Merge pull request #115 from makeitfutureDev/release/0.6.0
Release 0.6.0
2 parents 7115d3e + 20f2425 commit 710b3dc

214 files changed

Lines changed: 16641 additions & 1475 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎AGENTS.md‎

Lines changed: 90 additions & 28 deletions
Large diffs are not rendered by default.

‎CHANGELOG.md‎

Lines changed: 136 additions & 0 deletions
Large diffs are not rendered by default.

‎FEATURES.md‎

Lines changed: 461 additions & 80 deletions
Large diffs are not rendered by default.

‎INSTALL.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ see [README.md](./README.md).
2020
claude login # or set ANTHROPIC_API_KEY
2121
claude --version # must work
2222
```
23-
- **(Optional) OpenAI Codex CLI** — only if you'll use the Codex engine. Its host sign-in file is
24-
bind-mounted into the channel containers (sessions stay per channel; the sign-in is shared):
23+
- **(Optional) OpenAI Codex CLI** — only if you'll use the Codex engine. Its host sign-in is
24+
relayed into the channel containers through the egress proxy — each container gets an access-only
25+
stand-in, never the host's login file (sessions stay per channel):
2526
```bash
2627
npm install -g @openai/codex
2728
codex login # or set OPENAI_API_KEY

‎README.md‎

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -284,14 +284,19 @@ background and scheduled engine run uses the same runtime boundary.
284284
work/runtime mounts. Other channel workspaces and the operator's home are excluded by default.
285285
An explicit, off-by-default Full-access home-sharing option exposes the operator's whole home
286286
to admitted authors in those channels; choose shared work folders and this option deliberately.
287-
2. **Network access is not an egress firewall.** Containers use bridge networking. The
288-
*Allow network* switch communicates policy to the engines; there is no domain filtering or
289-
container-level egress cut-off in this release.
290-
3. **Usable credentials have runtime exposure.** Claude's host credentials file is never copied
291-
or mounted; runs receive a relay of its access token or a configured credential. Codex's host
292-
sign-in file is shared with its containers while sessions stay per channel. Protected transient
293-
MCP artifacts can contain credentials. Channel environment secrets have no reveal endpoint,
294-
but an agent using them can access their runtime values; masking and redaction are not a vault.
287+
2. **Egress goes through a per-channel proxy.** Containers run with no network of their own; the
288+
daemon's egress proxy is their only way out. It enforces the *Allow network* switch on every
289+
request (off: engine endpoints and selected connectors only), always refuses private, loopback
290+
and cloud-metadata addresses, and has no per-domain allow-list when the switch is on. The
291+
legacy open-bridge mode and a channel's raw-socket escape make the switch advisory again.
292+
3. **Usable credentials have runtime exposure, reduced by placeholders.** Claude's host credentials
293+
file is never copied or mounted; containers receive a placeholder for the relayed access token,
294+
swapped in by the egress proxy on the Anthropic API only. Secrets with an egress rule (built in
295+
for GitHub, Vercel, Supabase, Make and Composio tokens, or declared "used on hosts") are
296+
placeholders too; any other secret is injected raw and flagged unprotected. Codex's host sign-in
297+
file is still shared with its containers while sessions stay per channel. Channel environment
298+
secrets have no reveal endpoint, but an agent can use whatever it is given; masking and
299+
redaction are not a vault.
295300
4. **Authorization is checked before a run.** Channel use/manage policies and guest grants are
296301
enforced; unknown users without a guest grant are denied, and DMs require approval or admin status. Admin bypass needs an admin author and Admin mode. API callers cannot
297302
claim personal connector identities or widen a channel's durable tool permissions.

‎TEST-PLAN.md‎

Lines changed: 1082 additions & 51 deletions
Large diffs are not rendered by default.

‎containers/Containerfile‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ ENV DEBIAN_FRONTEND=noninteractive
5252
# this layer.
5353
RUN apt-get update \
5454
&& apt-get install -y --no-install-recommends \
55-
ca-certificates curl ffmpeg git jq less openssh-client openssh-server pipx postgresql-client procps python3 python3-pip python3-venv ripgrep tini unzip \
55+
bubblewrap ca-certificates curl ffmpeg git jq less openssh-client openssh-server pipx postgresql-client procps python3 python3-pip python3-venv ripgrep tini unzip \
5656
&& rm -f /etc/ssh/ssh_host_*_key /etc/ssh/ssh_host_*_key.pub \
5757
&& curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg -o /usr/share/keyrings/githubcli-archive-keyring.gpg \
5858
&& chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \

‎containers/bin/cg-egress-connect‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/sh
2+
# cg-egress-connect — an SSH ProxyCommand through the gateway's egress proxy (docs/SSH-ACCESS.md).
3+
# A `--network none` channel container has no route of its own; this speaks `CONNECT host:port` to
4+
# the in-container forwarder (127.0.0.1:3128) and pipes stdio through the raw tunnel the proxy
5+
# allows (github.com:22, plus the channel's declared raw hosts, with Allow network on). An SSH
6+
# session's GIT_SSH_COMMAND already uses it; for your own ssh:
7+
# ssh -o ProxyCommand='/opt/channelgate/bin/cg-egress-connect %h %p' user@host
8+
# The implementation is bin/cg-egress-connect.mjs, staged verbatim from src/mcp/egress-connect.js.
9+
exec node /opt/channelgate/bin/cg-egress-connect.mjs "$@"

‎containers/bin/cg-init‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,28 @@ if [ -d "$VSCODE_SHARED" ] && [ ! -e "$VSCODE_HOME/.cg-no-shared-server" ]; then
4545
done
4646
fi
4747

48+
# The egress forwarder (container-secrets P2). A proxy-mode container is created with
49+
# `--network none`: its only way out is 127.0.0.1:3128 (HTTPS_PROXY), which cg-egress pipes to the
50+
# daemon's per-channel egress socket. Started in the background on EVERY start (a stop kills it with
51+
# everything else), only when the daemon created this container with CG_EGRESS=proxy. It never
52+
# exits on an error, and a second copy just finds the port taken. Its failure lines (at most one
53+
# per category a minute) go to /run/cg/egress.log on the /run tmpfs: readable with `podman exec`,
54+
# gone at the next start.
55+
if [ "${CG_EGRESS:-}" = "proxy" ] && [ -f /opt/channelgate/bin/cg-egress.mjs ]; then
56+
node /opt/channelgate/bin/cg-egress.mjs </dev/null >/dev/null 2>>/run/cg/egress.log &
57+
fi
58+
59+
# Codex behind the egress proxy (container-secrets P4) is RELAYED: before each Codex run the daemon
60+
# writes an ACCESS-ONLY auth.json here (a placeholder token, an EMPTY refresh token). So under the
61+
# proxy a Codex login file in this volume that carries a refresh token is never the daemon's — it is
62+
# a leftover from before the relay (an old copy of a real login) — and is removed on every start.
63+
# A mounted file (the shared-file mode an API-key login keeps) is never touched.
64+
CODEX_AUTH=/home/agent/.codex/auth.json
65+
if [ "${CG_EGRESS:-}" = "proxy" ] && [ -f "$CODEX_AUTH" ] && ! grep -q " $CODEX_AUTH " /proc/self/mountinfo 2>/dev/null \
66+
&& grep -q '"refresh_token"[[:space:]]*:[[:space:]]*"[^"]' "$CODEX_AUTH" 2>/dev/null; then
67+
rm -f "$CODEX_AUTH"
68+
fi
69+
4870
# Claude credentials are NEVER copied in here: the daemon hands the engine a `claude setup-token`
4971
# value through the exec environment (CLAUDE_CODE_OAUTH_TOKEN). A copy of the gateway's own login
5072
# would refresh, rotate the refresh token and log the gateway itself out (2026-09-02 incident).

‎containers/versions.json‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
2-
"imageSpecVersion": "1.5.1",
2+
"imageSpecVersion": "1.6.1",
33
"comment": "Pinned toolchain for the channel image. Keep `claude` and `codex` at the versions the gateway host runs, so a channel behaves identically on either runtime backend; bump deliberately, rebuild, and let the image-id fingerprint recreate the containers. `imageSpecVersion` is the image CONTRACT (paths, PATH, baked-in packages), not the pins: bump it when the image gains or moves something the daemon relies on, keep it equal to IMAGE_SPEC_VERSION in src/runtimes/container/image-paths.js (a test pins them together), and the daemon will tell an operator at boot when the built image is older.",
44
"base": "node:22-bookworm-slim",
55
"npm": {
66
"@anthropic-ai/claude-code": "2.1.281",
77
"@openai/codex": "0.156.1",
8-
"mcp-remote": "0.8.3",
8+
"mcp-remote": "0.14.3",
99
"vercel": "59.11.1",
1010
"supabase": "2.116.0",
1111
"playwright": "1.63.0",

0 commit comments

Comments
 (0)