Skip to content

v1.2.0

Choose a tag to compare

@pacepace pacepace released this 05 Sep 22:08
· 108 commits to develop since this release
ace4ef5

A feature release: an aidc session can now reach a stack that is already running
elsewhere on the host.

Sessions can reach another stack's services

Until now a session's dev container sat alone on aidc-<session>-net, and
aidc proxy only went host → container. There was no way for a session to talk
to a database, queue, or cache belonging to another compose project — which is
exactly what you need when the thing you are debugging is that stack.

A session's dev container can now attach to named Docker bridge networks and
resolve that project's containers by name.

Declared — survives restart, upgrade, and recreate:

aidc create metallm --network metallm_default
# or in .aidc/config.yaml
networks:
  - metallm_default

Repeatable, and the CLI merges with config rather than overriding it (unlike
--dns) — every named network is something the session needs, so more sources
means more networks. Networks are validated immediately after config load,
before any image build, so a typo costs you a message rather than a full
dev-base rebuild.

Adhoc — attaches a session that is already running, no recreate:

aidc network metallm add metallm_default
aidc network metallm ls          # marks each attachment declared or adhoc
aidc network metallm rm metallm_default

Then, from inside the session: psql -h metallm-postgres-1 -U metallm.

aidc restart aidc upgrade aidc kill + create
declared survives survives survives
adhoc survives lost lost

Adhoc attachments survive a restart, unlike adhoc port forwards which
aidc restart sweeps. The difference is real rather than an inconsistency: a
port forward is a separate sidecar container pointed at a container that is
going away, while a network endpoint is part of the dev container's own config
and comes back with it. aidc upgrade now names the adhoc attachments it is
about to drop, with the commands to re-add them.

aidc status <name> gained an attached networks section, listed even when
empty.

The gateway pin

Every attachment pins gw_priority so aidc-<session>-net keeps the default
route. This is the load-bearing part of the change, and it is not what the
obvious implementation would have done. Measured on Docker 29.1.3:

default route ends up on
docker network connect ext dev ext — steals it immediately
Compose priority: 100 on the aidc net ext — steals it anyway
--gw-priority / Compose gw_priority the aidc net — correct

Compose's priority only orders the connect sequence; it does not choose the
gateway. Without the pin, attaching a network silently reroutes all of the
session's egress — squid-proxied traffic included — out through someone else's
bridge, with nothing in the audit trail to show for it. A unit test and a smoke
assertion both pin this, the latter by reading the container's own
/proc/net/route.

gw_priority needs Docker Compose 2.34+, so aidc create probes for it and
fails with that reason rather than rendering a file whose pin would be silently
dropped. Sessions with no attachment render a byte-identical compose file to
before
, so they neither change behaviour nor acquire a new Compose version
floor.

This widens the sandbox, on purpose

Everything on an attached network is reachable from the session on every
port
. That traffic does not pass through squid, so the blocklist does not
apply and taint detection cannot see it. The attachment is bidirectional.

Only the dev service is ever attached — squid, refresher, policy, and audit
stay isolated on the session's own network. host, none, and Docker's default
bridge are refused outright. The CLI help, the config template, aidc create's
output, and aidc status all say this at the point of use, and
docs/done/design-07-safety-model.md now sizes the residual risk honestly
instead of implying the proxy covers everything.

Attach the narrowest network that does the job, and treat anything on it as
being inside the blast radius.