Skip to content

the first-Init port guard excuses every container this service's agent kept - #1201

Merged
antoinetoussaint-byte merged 5 commits into
mainfrom
fix/adopt-agent-container-ports
Oct 27, 2026
Merged

antoinetoussaint-byte merged 5 commits into
mainfrom
fix/adopt-agent-container-ports

Conversation

@antoinetoussaint-byte

@antoinetoussaint-byte antoinetoussaint-byte commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

A repeated service flow can find its deterministic port still published by an agent-owned sidecar. The old prefix exception also accepted a different service such as web/gateway-admin for web/gateway, and did not require the logical name to equal an actual Docker name.

This fixes the CLI-owned first-Init guard using Core's exact ContainerServiceIdentity API. A present parent must equal the loaded module/service; its logical name must match an actual Docker name. Existing owner, recovery scope, namespace, lifecycle and per-address-family publication checks remain. An absent parent preserves only the pre-existing exact bare-name compatibility path; it never establishes suffixed ownership. Malformed or conflicting parents always refuse. The CLI adds no suffix roster, agent-specific logic, relabeling or cleanup policy.

Core owns attribution and reuse validation; object-storage #117 binds both constructors. The current dependency is reviewed Core candidate 6eadd92; final release pin remains pending the owner release. docs/orchestration.md documents the producer obligation, bounded legacy exception and retained-state limitations. This is an owner fix using the shared parser.

Validation: full orchestration package passed (50.014s). Fresh independent architecture/elegance review found no material CLI defect and independently reproduced all five unsafe acceptances by restoring the old predicate. Selected merged #1200 fixture-composition and recovery acknowledgement regressions pass. In an isolated real CLI composition, the updated local object-storage source started twice under the same scope: both retained containers survived graceful stop, were replaced on the next flow for changed runtime configuration, and original gRPC object bytes plus complete Stat metadata survived. Both containers carried exact parent labels.

Limits: the real proof used a development agent built from object-storage 1037aeb source before that commit was recorded, with dirty build metadata; it is local integration evidence, not a released artifact claim. The owner separately supplies a clean build and real custody/Put-Get tests. Released-agent SaaS lint/compile qualification and the final Core/object-storage release pins remain required before declaring the original delivery blocker closed. Existing bare-name legacy compatibility remains lossy; no claim of full parent proof for unlabelled objects or future agent reuse is made. No cloud deployment was performed.

…ice's agent kept, not just one named after the service

An agent may run SEVERAL containers for one service and names each after
itself: service-object-storage publishes the service's own grpc port from
`<unique>-gateway` and keeps `<unique>-minio` and `<unique>-network` beside it.
The guard added in #1180 excused only a container named exactly
`ContainerName(<unique>)`, so it excused none of them — and `adoptableContainer`
could therefore never match a keep-running agent that suffixes its container
names, which is the fleet's actual convention.

What that cost: the first flow of a job starts the service fine and leaves its
gateway container up, publishing the service's deterministic port. A later flow
in the same job builds a fresh Runner, so `everStarted` is false and the guard
runs, finds the port bound by Docker's forwarder, fails to attribute it to this
service's own container, and refuses. Deterministically, in every phase, which
is what saas#1265 hit on both of its runs — the first run of that graph on a
release carrying #1180.

A container is now this service's when its logical name label and its Docker
name are the service's name or that name with a suffix. Every other guard is
unchanged: the codefly owner label, this flow's exact recovery scope, the
namespace rule, running, non-ephemeral, and the container must publish the
proposed port on that address's own loopback family. A sibling service is still
not this one, and a squatter is still refused on either family.

Diagnosed by reproduction rather than inference, with the RELEASED 0.1.219 in a
repo unrelated to saas: `codefly run service documents/object-storage
--init-only` twice in one workspace and scope leaves
`…-object-storage-osproof-gateway` publishing 0.0.0.0:47103 and then refuses
`port 47103 (grpc) held by pid … (OrbStack Helper)` — the Docker forwarder, so
the holder is the kept container and neither a leaked process nor a port
derivation. The same second flow passes with this fix. Restoring the old
comparison makes the two new unit cases fail with that same refusal.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@antoinetoussaint-byte
antoinetoussaint-byte added this pull request to the merge queue Oct 27, 2026
@antoinetoussaint-byte
antoinetoussaint-byte added this pull request to the merge queue Oct 27, 2026
Merged via the queue into main with commit afa66a6 Oct 27, 2026
24 of 25 checks passed
crisfiorini-oss pushed a commit to crisfiorini-oss/cli that referenced this pull request Oct 28, 2026
…t kept (codefly-dev#1201)

* fix(run): the first-Init port guard excuses every container this service's agent kept, not just one named after the service

An agent may run SEVERAL containers for one service and names each after
itself: service-object-storage publishes the service's own grpc port from
`<unique>-gateway` and keeps `<unique>-minio` and `<unique>-network` beside it.
The guard added in codefly-dev#1180 excused only a container named exactly
`ContainerName(<unique>)`, so it excused none of them — and `adoptableContainer`
could therefore never match a keep-running agent that suffixes its container
names, which is the fleet's actual convention.

What that cost: the first flow of a job starts the service fine and leaves its
gateway container up, publishing the service's deterministic port. A later flow
in the same job builds a fresh Runner, so `everStarted` is false and the guard
runs, finds the port bound by Docker's forwarder, fails to attribute it to this
service's own container, and refuses. Deterministically, in every phase, which
is what saas#1265 hit on both of its runs — the first run of that graph on a
release carrying codefly-dev#1180.

A container is now this service's when its logical name label and its Docker
name are the service's name or that name with a suffix. Every other guard is
unchanged: the codefly owner label, this flow's exact recovery scope, the
namespace rule, running, non-ephemeral, and the container must publish the
proposed port on that address's own loopback family. A sibling service is still
not this one, and a squatter is still refused on either family.

Diagnosed by reproduction rather than inference, with the RELEASED 0.1.219 in a
repo unrelated to saas: `codefly run service documents/object-storage
--init-only` twice in one workspace and scope leaves
`…-object-storage-osproof-gateway` publishing 0.0.0.0:47103 and then refuses
`port 47103 (grpc) held by pid … (OrbStack Helper)` — the Docker forwarder, so
the holder is the kept container and neither a leaked process nor a port
derivation. The same second flow passes with this fix. Restoring the old
comparison makes the two new unit cases fail with that same refusal.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(orchestration): require exact parent attribution for sidecars

* docs(orchestration): bound container attribution claims

* fix(conformance): track the selected Core release line

---------

Co-authored-by: Antoine Toussaint <312536060+antoinetoussaint-byte@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant