Skip to content

chore(agents): go-grpc 0.1.72, so a process receives each configuration variable once - #1287

Merged
antoinetoussaint-byte merged 6 commits into
mainfrom
chore/agents-go-grpc-0.1.72
Oct 31, 2026
Merged

antoinetoussaint-byte merged 6 commits into
mainfrom
chore/agents-go-grpc-0.1.72

Conversation

@antoinetoussaint-byte

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

Copy link
Copy Markdown
Contributor

Why

platform-core's gate refused to start saas/accounts natively because its environment was 992,926 bytes, with each key counted twice (service-go-grpc#220). I could not find the accounts log line itself on any issue. The same refusal from a sibling agent is quoted verbatim in service-go#162:

NativeProc.start: cannot prepare the process environment: process environment exceeds its limit: Codefly environment is 569730 bytes, above 524288; largest: …

(The list of keys is cut: the same key appears twice in it.)

The cause is go-grpc 0.1.58: CreateRunnerEnvironment put the service's whole environment on the runner environment, and Start handed the same set to the process again.

The agent fix

go-grpc 0.1.72 carries service-go-grpc#220 ("hand the service its environment once"). The runner environment no longer carries the service environment, so Start delivers each variable once. It still builds with Go 1.27.3 (GoVersion = "1.27.3"), so the AGENTS.md toolchain line only changes its version.

What moved / regenerated

  • codefly update workspace (CLI v0.1.233, checksum checked): accounts and auth-gateway go from 0.1.58 to 0.1.72. The command also moved nextjs (0.0.167 to 0.0.171) and postgres (0.0.146 to 0.0.147). I reverted those two so this PR stays on one objective; they can move in their own PR.

  • Runtime image change, disclosed. Agent 0.1.70+ (service-go-grpc#214) builds a static service's final image FROM scratch when it has neither CGO nor runtime-packages (templates/builder/Dockerfile.tmpl: if and (not .WithCGO) (not .RuntimePackages)).

    • auth-gateway declares no runtime-packages, so its runtime image moves from alpine to scratch. Review found no os/exec, time.LoadLocation or temp-dir use in the gateway's code, and its liveness probe is TCP, so nothing needs a shell, tzdata or /tmp.
    • accounts declares runtime-packages: [git], so it stays on alpine:3.23.7.
  • codefly sync service failed on accounts under 0.1.72, for two reasons:

    1. plugins/plugins.yaml used import:, and the agent reads package:.
    2. With that corrected, the agent refused: "plugins/plugins.yaml lists 1 plugin(s), but the plugin registry is not rendered: no proto file under proto/ declares service AccountsService". Accounts declares 48 proto services across 40 files.

    Without the plugin listed, 0.1.72's main-only refresh would rewrite code/main.go as follows:

    • It drops the module authority listener. The rendered main resolves one listener per API (grpc / rest / connect). The authority gRPC endpoint declared in service.codefly.yaml never reaches Configuration.EndpointAuthorityPort, so that listener is never bound.
    • It reorders startup. It calls server.Start before work(ctx), so handlers are served while the business service is still nil, and a port probe races readiness. Accounts deliberately finishes wiring, plugin registration and fixture seeding before any listener opens.
    • It turns an unresolved Connect address into a panic, where accounts treated it as optional.

    0.1.58 never synced either file, so both have been maintained by hand under a DO NOT EDIT marker. Stopgap, not a fix: main.go drops the generated-code marker, so sync leaves it alone. registry_gen.go becomes a hand-written plugins/registry.go, and plugins.yaml is deleted. Both files carry a STOPGAP (codefly-dev/service-go-grpc#223) header. Sync cannot keep a multi-service, custom-adapter service's entrypoint and plugin registry generated service-go-grpc#223 asks for the shape accounts needs: a plugin registry without a single scaffold service, every declared endpoint (or a documented Configure seam) in the generated main, and a stated ordering seam. Once it lands, accounts restores the marker and adopts the generated main. Sync is now clean for both services. The CUSTOM hooks in connect_gen.go are untouched.

  • codefly generate runnables: the three accounts runnable packages record the agent version, so they and their digests change. generate contracts --check and check-generated-libraries.sh are clean with CI's CLI 0.1.221. Under 0.1.233 only the generated-by provenance changed, so I did not commit that.

  • scripts/ci/build-images.json: go-grpc 0.1.72 builds on golang:1.27.3-alpine3.23@sha256:8a504649… and runs on alpine:3.23.7@sha256:ff7f0c72… (the agent's build_images.go / AlpineDigest; 3.23.7 carries OpenSSL 3.5.9 and musl 1.2.5-r24). The build-evidence gate refused accounts and auth-gateway until the image contract moved with the agent, as RELEASE_GATES.md requires. build-images.test.mjs passes.

  • Frontend advisories (the supply-chain red), fixed in the frontend's own manifests:

  • Authority libraries. In accounts' go.mod, authority-core, authority-client and conformance move from d0210535 (Generate exact bootstrap network policies (#61) #62) to authority main dea37afa (Generate ambient authorization for internal topology edges #65). At the old pin, the conformance case "a standing one-second delegation does not issue … parent session expired" raced the parent session's whole-second expiry and turned the pinned conformance job red. Generate ambient authorization for internal topology edges #65 fixes it.

Tests

  • accounts go build ./... && go test ./...: passed twice on the agent move. At dea37afa: full suite including conformance passes, and conformance passes 3× more with -count=3. One pkg/business failure in the full run was the test store's Postgres port collision (could not bind 127.0.0.1:49740: Address already in use); it passed when re-run alone.

  • auth-gateway build + tests: pass

  • module/tools and root go test: pass

  • check-boundaries.sh, naming gate (tests and records), agent-docs links: pass

  • Frontend: CI's exact npm audit --omit=dev --audit-level=high passes on frontend and marketing; npm run typecheck passes; test:pure passes (357 files / 5064 tests); module-verify.mjs install graph in sync

  • Composed boot on 0.1.72. I ran codefly run service from auth-gateway (CLI 0.1.233, workspace local env, --fixture dev-admin, --naming-scope pr1287).

    • store, cache, vault, object-storage, accounts (Running on :7243) and auth-gateway (Running in 25.4s) all reached Running. No "exceeds its limit" refusal appeared.
    • The live accounts process carries 122 CODEFLY__ keys, each exactly once.
    • Gateway REST: GET /health, /healthz and /ready return 200 {"status":"ok"}. GET /v1/auth/.well-known/jwks.json returns 200 with an Ed25519 key. The sign-in route POST /v1/auth/authenticate with an empty body returns accounts' 400 validation error through the gateway.
    • I stopped the run with SIGINT and cleaned the scope. The run left two object-storage containers and their network behind (…-object-storage-pr1287-{gateway,minio}), which I removed by hand.

Not verified: a container (--runtime-context container) or cluster boot, so the gateway's new scratch image has not been booted.

🤖 Generated with Claude Code

antoinetoussaint-byte and others added 4 commits October 30, 2026 20:09
…on variable once

go-grpc 0.1.58 put a native service's environment on the runner environment
and handed it to the process again, so every configuration variable arrived
twice; platform-core's gate refused saas/accounts with a 992,926-byte
environment. go-grpc 0.1.72 (service-go-grpc#220) delivers it once.

`codefly update workspace` moved accounts and auth-gateway to 0.1.72. It also
moved nextjs and postgres; those moves are left for their own change.

0.1.72's Sync keeps a custom-adapter service's marked main.go current and
renders plugins/registry_gen.go from plugins/plugins.yaml only with the full
scaffold. Accounts has no single AccountsService, so 0.1.58 never touched
either file, and both are hand-maintained (main serves the module authority
listener and finishes work wiring before any listener opens). Say so: main.go
drops the generated-code marker, the registry becomes plugins/registry.go, and
the plugins.yaml no agent ever read (it used `import:`) is deleted. Sync is now
clean for both services.

Runnables regenerated: the three accounts runnable packages record the agent
version, so their digests move. Contracts and generated libraries unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
go-grpc 0.1.72 builds on golang:1.27.3-alpine3.23@sha256:8a504649 and runs
on alpine:3.23.7@sha256:ff7f0c72 (its build_images.go and AlpineDigest; 3.23.7
carries the OpenSSL 3.5.9 and musl 1.2.5-r24 fixes 3.23.5 lacked). The
build-evidence gate refused accounts and auth-gateway on the old expectation,
so the image contract moves with the agent, as RELEASE_GATES.md requires.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… advisories

The supply-chain job's `npm audit --omit=dev --audit-level=high` on the
frontend failed on follow-redirects 1.16.1 (GHSA-mrwp-f3q8-3g9p, high; fixed in
1.16.2) and reported fast-uri 3.1.8 (GHSA-w74x-v6f9-j3xg, GHSA-wjr9-j795-jxcr,
GHSA-xhq7-xmqj-769h, GHSA-333x-w4r6-6crp; fixed in 3.1.9).

follow-redirects moves in the lockfile only, inside axios's ^1.16.0. fast-uri
moves through the override that already pinned it, now `<3.1.9 -> 3.1.9`.
Nothing else in the lockfile changed.

deepmerge 4.3.1 (GHSA-gcqx-w48m-w2h4, low, via swagger-client) has no patched
release; it stays, below the job's high threshold.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…try as stopgaps

The accounts main.go and plugins/registry.go should be go-grpc's generated
output. They stay hand-maintained only because the agent cannot generate them
for a multi-service, custom-adapter service: its main-only refresh drops the
module authority listener and starts the server before work's wiring, and it
renders no registry without a single AccountsService. Both files now say so
and name codefly-dev/service-go-grpc#223, the request for that shape.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@antoinetoussaint-byte

Copy link
Copy Markdown
Contributor Author

module-saas-starter#1287 review, head 4ce393e (bug-hunter + security)

No blockers found.

Ran locally: GOWORK=off auth-gateway go build ./... && go test -count=1 ./... passed. accounts go build ./... passed, and go test -count=1 . ./plugins ./pkg/permissionsplugin ./pkg/adapters passed. All 21 CI checks pass and 4 are skipped.

Follow-ups, ranked

  1. Startup on 0.1.72 is still unproven, and one image change is not disclosed. Nobody ran a composed codefly run, so the PR's purpose (accounts starts natively) is not proven. The body says so, as deployment/AGENTS.md:27-32 requires. The body does not say that agent 0.1.70 ([security] Pass-1 security fixes landed (H2-code, H3, H4, M6) — needs PR + integration verify #214) builds a static service's final image FROM scratch (templates/builder/Dockerfile.tmpl if and (not .WithCGO) (not .RuntimePackages)). auth-gateway declares no runtime-packages, so its runtime image moves from alpine to scratch. accounts keeps alpine 3.23.7 because it needs git. I found no exec, LoadLocation or temp-dir use in gateway code, and liveness is a tcpSocket probe, so the risk is low. Say it in the body and boot both services before release.

  2. The accounts adapters still claim to be agent output. pkg/adapters/{connect,grpc,rest,server,cors}_gen.go:5 say "generated by the agent. Do not edit". No agent version renders them: both 0.1.58 and 0.1.72 require a single AccountsService (builder.go generatedScaffoldTargets). This is the same false marker the PR removes from main.go. As a result, for question 1:

    • Neither service's listener code changed.
    • The CUSTOM delivery-routes mount at connect_gen.go:95 is intact.
    • The authority listener and the listener-after-work ordering are unchanged.
    • None of the Connect read, header or idle timeouts or MaxMessageBytes from 0.1.65+ reach accounts or the gateway, so long install RPCs get no new limit.

    feat: enforce an OIDC audience binding (#207) #223 should also name these files and the wildcard ":%d" binds (grpc_gen.go:251,263, connect_gen.go:143). Those binds ignore 0.1.69's native-host rule, which predates this PR.

  3. Agent 0.1.72 is built on an untagged Core. It pins Core v0.19.18-0.20261029150419-9d2348c460ae, and no tag in my mirror contains that commit. My mirror fetch failed, so it may be stale. This is the agent's issue, not this PR's.

  4. Nit: plugins/registry.go:19 still says "registry_gen.go has no dependency".

Verified clean

  • main.go: header-only hunk; body byte-identical. 0.1.58 never synced it, so the old marker was already false. The header is honest; feat: enforce an OIDC audience binding (#207) #223 is actionable (three asks, exit plan). registry.go and plugin.go: comments only.
  • build-images.json: digests equal agent v0.1.72 build_images.go/AlpineDigest.
  • npm: two lockfile entries; integrity matches the registry; no dependencies; inside ^1.16.0/^3.0.1.
  • Runnables: all three pass Core PreparePackage digest checks; index.json matches.
  • Tests: none changed; no gate reads the removed marker or plugins.yaml.

VERDICT: merge

antoinetoussaint-byte and others added 2 commits October 30, 2026 21:18
…not registry_gen.go

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Move authority-core, authority-client and the conformance suite from
d0210535 (#62) to authority main dea37afa (#65). The suite at the old pin
raced a one-second delegation against its parent session's whole-second
expiry ("a standing one-second delegation does not issue ... parent session
expired") and reddened the pinned conformance job; #65 fixes that case, and
the authority-main job already ran it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@antoinetoussaint-byte
antoinetoussaint-byte added this pull request to the merge queue Oct 31, 2026
Merged via the queue into main with commit 2c2aa81 Oct 31, 2026
25 of 26 checks passed
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