Repository navigation
feat: compose the gateway as a codefly service agent, with its image and SBOM evidence (#12) - #13
Conversation
…efly-dev#12) A gateway a Codefly workspace composes is reachable by whatever shares its network, so it has to ask each caller for the deployment's token. This adds the mechanism service-object-storage already uses (internal/auth) and the Codefly host uses for agent plugins: a shared secret in the x-codefly-token metadata header, compared in constant time, on unary and streaming calls, with the standard gRPC health service exempt because a readiness probe carries no token. It is a copy rather than an import: codefly-dev/core exports only the header name, from the package that links the whole agent runtime, and keeps its interceptors unexported, and codefly-dev/sdk-go has none. The package says so, so a fix to one is made in the other. This is authentication only. Which caller may run which statement stays settled before the request arrives; nothing here knows a caller. Not wired into the server yet; the next commit does that. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…er's token (codefly-dev#12) The server runs SQL against the database it is bound to and its listen address says nothing about who can reach it, so config resolution now refuses to start without SWH_AUTH_TOKEN unless the operator states SWH_ALLOW_ANONYMOUS=true for a listener confined elsewhere (network policy, mesh mTLS). Both together is refused as a contradiction, a malformed opt-out is an error rather than a silent false, and the token is trimmed because a secret delivered through a file or block scalar carries a trailing newline no client would send. newGRPCServer, which run() now uses, installs the auth interceptors from that token and registers the gRPC health service they exempt. The health service reports the process as serving, not that a warehouse is reachable: this server does not probe its backend. The tests enumerate the methods the server registers instead of a list kept beside it, so an RPC added to the proto is covered by the refusal test the day it exists. Mutating the wiring (no interceptors, no stream interceptor, no health exemption) turns the matching tests red. Behaviour change: a bare SWH_BACKEND=mem no longer starts. README and AGENTS.md now give the command with SWH_ALLOW_ANONYMOUS=true. Not verified: no codefly host was involved, so token delivery through the configuration the host provides is untested here; this repository has no agent yet to receive it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ence (codefly-dev#12) Composing this gateway as a codefly service means shipping it as an image, and an image owes image-scope SBOM evidence under codefly-dev/core's docs/sbom.md: one CycloneDX inventory per shipped platform, bound to the digest scanned. This is the part of that evidence that refers to no image yet, so it lands first. internal/imageevidence holds the one list of shipped platforms and the subjects derived from it, so the agent's Builder.SBOM, the release command and the drift tests read the same description. For a pushed image the subjects come from core's sbom.ExpectedFromImageReference, which also refuses a reference that is not digest-pinned; for an image only the local daemon holds, the subject carries the daemon's image ID, the identity such a scan binds to. cmd/image-sbom scans each subject with core's sbom.Image and writes the documents and an index, failing the whole run when any platform fails rather than publishing partial coverage. The service identity it records defaults to the agent's publisher/name in agent.codefly.yaml, so no name is typed in a workflow. Reuse: the scanner, the subject derivation, the source selector and the CycloneDX encoder are imported from core. Core exports no helper that writes a scanned image's documents to disk or resolves a locally built image's ID, so Collect, WriteIndex and localImageID are adapted from codefly-dev/service-object-storage's internal/imageevidence (the same three functions), and the package comment says so. go.mod now requires codefly-dev/core v0.16.0, the release the later workflow pins resolve to; core requires grpc v1.83.2, so that moves with it. Verified: the command ran against service-object-storage's published multi-architecture image and wrote a CycloneDX document for each of linux/amd64 and linux/arm64, bound to the child manifest digests. Not verified: -local mode, which needs syft on PATH. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…mage and SBOM evidence (codefly-dev#12) A workspace can now compose this gateway the way it composes codefly-dev/service-object-storage: the repo-root main package is a codefly service agent (Service, Runtime, Builder on codefly-dev/core's agents package), declared by agent.codefly.yaml at 0.0.1 and released by a tag workflow as a GitHub release asset a consumer pins by version. This closes codefly-dev#12. The agent - Runtime starts the gateway container with a fresh x-codefly-token secret per run (an operator may pin one), publishes the port, and waits until the gateway's health service reports serving and Capabilities accepts the token. That attests the process and the credential, not the warehouse: the gateway probes no backend. A rejected token fails at once instead of burning the budget. - Consumers receive the "warehouse" configuration group: connection, endpoint and a secret-marked token. - Builder renders a Deployment, Service and a dedicated ServiceAccount (so a cloud warehouse can grant exactly this workload), gRPC health probes on the overall service, SWH_ALLOW_ANONYMOUS=true as service-object-storage does for its deployed profile. It refuses what it cannot deliver (SWH_AUTH_TOKEN, SWH_CREDENTIALS_FILE) and any value the manifest cannot carry. - The agent links no backend, so no cgo driver reaches its CGO_ENABLED=0 release build; a test holds that. The image and its evidence (the same commit, so the gate never reads no-image) - Dockerfile builds cmd/service-warehouse with cgo on a Debian 13 builder onto distroless/cc, not static: the embedded DuckDB engine is a cgo driver. - gateway-image.json pins the image by digest; the registry comes from core (resources.ImageRegistry), the repository name from the workflows' own github.repository. It records no digest until the first image is published, and the agent, Deploy, the audit and the release all refuse an empty one rather than run :latest. - publish-gateway-image.yml pushes the image by digest before the tag exists; release.yml tags only after the tag matches agent.codefly.yaml, the recorded digest was built for that version, and evidence for every platform was written. - Builder.SBOM serves image scope through core's SBOMImages and is checked against sbom.ValidateCoverage. ValidationCapabilities.image_sbom is served and deliberately not advertised (core docs/sbom.md rollout gate); a test pins it. - distribution_test.go no longer claims "no image". It lists every image- producing path, fails on one that is not accounted for or no longer produces its signal, and fails if the tests holding the evidence are gone. README and AGENTS.md state the new distribution, the agent and the release order. Reuse: core's resources.PublishedImage/ImageRegistry, sbom.Image, sbom.ExpectedFromImageReference, sbom.ValidateCoverage, agents.AuthMetadataKey (held equal to internal/auth's copy by a test), dockerrun, the kustomize conformance helper and the agent registration are imported. Copied from service-object-storage: the four generic deployment templates (namespace and kustomization base, kustomization and secret overlay), and the agent, workflow and test structure, adapted, without MinIO. Core's endpoint model no longer has the "external" visibility service-object-storage declares; the endpoint here is "internal", its replacement for cross-module reach. Classification: feature; nothing here works around a missing fix elsewhere. Release workflows pin codefly-dev/core's reusable workflows at the v0.16.0 commit that go.mod requires. Verified: build, vet, race tests under go1.27.0; the image builds for linux/arm64 and linux/amd64 and starts under both; the agent Runtime run against the built image (e2e tag) starts it, refuses a missing or wrong token, hands out the secret token and removes the container on Destroy; the release's lock check and tag guard were run against the real files; each guard was seen to fail when its property was broken. Not verified: the image-scope SBOM against a real warehouse image (needs syft on PATH, absent here), the multi-platform publish and the release workflows (never run; GH_PAT is needed), codefly agent ci past its source stage (the installed CLI's packager carries Go 1.26.4, so its build stage fails as documented in agent-ci.yml), and the image with the DuckDB driver linked (not on this branch). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
lazybox has finished working on this. Build, vet, race tests and all three PR CI jobs (https://github.com/codefly-dev/service-warehouse/actions/ Full conformance still fails before lint because the published gateway digest is absent. The coordinator owns the documented nine-step v0.0.2 release sequence and conformance rerun after the lock lands. No merge, dispatch, publish or release tag was performed. Worked for 20m 13s • 10:17 AM › Ask Codex to do anything GPT-6-Astra xhigh · ~/.lazybox/v2/github-codefly-dev-service-warehouse/PR-13-feat-compose-the-gateway-as-a-codefly-se… ? for shortcuts⚠ 3 warnings · f2 to view › The independent review of PR #13 head 2bc9e68 is posted: https://github.com/codefly-dev/service-warehouse/pull/13#pu… Build, vet, race tests and all three PR CI jobs (https://github.com/codefly-dev/service-warehouse/actions/ Full conformance still fails before lint because the published gateway digest is absent. The coordinator owns the documented nine-step v0.0.2 release sequence and conformance rerun after the lock lands. No merge, dispatch, publish or release tag was performed. Worked for 20m 13s • 10:17 AM › Ask Codex to do anything GPT-6-Astra · xhigh) held it from 2026-10-11 12:45 UTC until 2026-10-11 18:20 UTC. The claim detail |
|
Core v0.18.1 adoption is pushed at The copied auth, image-lock parsing and image-evidence implementations are replaced by core's exports, and the publisher calls core's immutable v0.18.1 workflow. The PR body records the behavior changes, removes the copied-implementation qualification, and credits the coordinator's worker for the adoption. README and AGENTS describe the resulting ownership and behavior. Local build, vet and race tests pass. The local ARM64 gateway also passed runtime and SBOM end-to-end tests; its scan found 9 Go modules and 14 OS packages, and the thin evidence command wrote its document and index. One release prerequisite remains explicit: |
antoinetoussaint-byte
left a comment
There was a problem hiding this comment.
Deep review (fresh context, Opus) of head 2bc9e68
Base b1191e8 (merge-base with main), head 2bc9e68. I read the whole diff, issue #12, the repo AGENTS.md and README, core v0.18.1 (callertoken, resources/image_lock.go, agents/services/sbom and the docs, publish-service-image.yml, go-service-release.yml), and the CLI v0.1.181 code for codefly publish and codefly agent ci. I ran the checks listed under Verification below.
Verdict: 0 merge blockers. 4 major findings, 5 minor. I'd merge on fix-forward terms, but two findings block the first release: F9 stops codefly publish today, and F1 lets that same gate approve a generated service that cannot start.
Will break
F1 (major, blocks the release, not the merge): a newly generated service crashes on first run, and conformance still passes
builder.go:254-263:Createreturnss.SettingswithBackend: "", so the generatedservice.codefly.yamlnames no backend.runtime.go:186-200: an empty backend is not passed, so the gateway falls back to its own default,duckdb(internal/config/config.go:58).cmd/service-warehouse/main.go:50:backend.Openfails. I reproduced it at this head:SWH_AUTH_TOKEN=x ./service-warehouseexits 1 withduckdb.Open: Unsupported: duckdb backend not yet implemented.- Effect on
codefly run:WaitForReadyspends its 60 s budget on connection-refused and reports a readiness timeout. - Why the release gate misses it:
- The agent advertises no
Validation(main.go:109-129). The CLI therefore takes the legacyTEST_DEPENDENCY_MODE_NONEpath (cli pkg/orchestration/test_execution.go:38-44), which runs Load, then Init, then Test, with no Start (runtime_test_policy.go:79-81). - Init only creates and starts the container (
core runners/dockerrun/docker_runner.go:201-255). Nothing checks that it stays up. Runtime.Testreturns an empty response (runtime.go:342-344).
- The agent advertises no
- Result: once a digest is recorded,
codefly agent ciconformance will pass while the generated gateway has already exited. This is the "green about a name" pattern: the gate checks that the agent responds, not that the gateway serves. Issue #12's first ask was "so a workspace can compose this". The default composition does not serve, andtemplates/factory/GETTING_STARTED.md.tmplsays nothing aboutbackend: mem. The README discloses it (lines 142-145), but disclosure does not fix it. - Fix, both halves:
- Have the factory default the local backend to
mem, for example by settings.Settings.Backend = "mem"inCreatebeforeCreateResponse. That is a setting the user can change, not a hardcode. - Make readiness part of what conformance observes, for example by having
Runtime.TestcallWaitForReady. A gateway that dies on startup must then failcodefly ci run. - Test: generate a service through
Create, run Init then Test against the e2e image, and assert failure when the backend isduckdband success when it ismem.
- Have the factory default the local backend to
F2 (major, security): in a deployment, any pod in the cluster can run SQL with the gateway's warehouse identity
templates/deployment/kustomize/base/deployment.yaml.tmpl:65-75hardcodesSWH_ALLOW_ANONYMOUS=true. The comment and README.md:152-158 say caller identity is "enforced by the cluster (NetworkPolicy and service-mesh mTLS)". The agent renders no NetworkPolicy, and nothing checks that a mesh exists.builder.go:250-252deliberately gives the pod its own workload identity on the warehouse.- Concrete failure: any workload in any namespace that can resolve
<name>.<ns>.svccan callQuerywith arbitrary SQL, with no token, and act with that identity against the bound database. That includes a compromised sidecar or a job in an unrelated namespace. service-object-storageships the same pattern, so this is fleet precedent, not a new invention. But this gateway exposes a whole database, not a bucket. Under the maximum-security posture the strongest option comes first:- Render a NetworkPolicy that admits only the declared consumers (or at least only the same namespace).
- Or deliver the token to consumers through the environment's secret configuration, so the deployed gateway is authenticated like the local one.
- At minimum, the README must not claim an enforcement the agent does not render.
F3 (major, tracking): Closes #12 closes the issue on merge, but two of its three asks are not done
Issue #12 asked for (1) a manifest, (2) a release tag a consumer can pin, and (3) an answer on per-row refusal in InsertRows, which it names as the one input that could flip handbook#253. Merging closes #12 with no tag (the tag only exists after the release sequence below) and no answer.
The answer is already in the proto, and it is not a clean yes:
RowError(proto/codefly/warehouse/v0/warehouse.proto:314-318) carriesrow_indexbut only a free-formstring error. There is no permanent-versus-transient code.- AGENTS.md rule 3 says clients branch on codes, never on strings. So a consumer cannot tell "the backend permanently refused this row" from "retry this row" without parsing a string.
Fix: change the PR body to Part of #12 (or Refs #12), close #12 when vX.Y.Z is tagged, and post that answer on #12 so handbook#253 has its input.
F9 (major, can block the release): whether the agent's CI audit passes depends on the releasing host's Docker cache, and the released binaries are built with Go 1.27.0
- I ran
codefly agent ci(CLI 0.1.181) at 2bc9e68. Manifest, source and build passed. audit failed:8 high/critical vulnerability(ies) with available upstream fixes in warehouse:0.0.1. All eight are in stdlib v1.27.1 and fixed in v1.27.2 (GO-2026-6603, -6605, -6607, -6608, -6610, -6611, -6613, -6617). Conformance and drift were skipped. codefly publishruns release-gradecodefly agent ciinBeforeCommit(cli cmd/publish/release.go,agent_release.gorunReleaseAgentCI), so the release aborts here.- The PR comment reports the audit passing. That is consistent with a host whose cached image was newer, which is the problem.
- Causes:
agent.codefly.yaml:7pinssource.agent: codefly.dev/go:0.0.56, which builds on the floatinggolang:1.27-alpinetag.- On my host that tag was cached at go1.27.1, so the audit failed. A fresh host may pull 1.27.2 and pass. The verdict therefore depends on the Docker cache, which is the defect.
codefly.dev/gov0.0.69 pinsgolang:1.27.2-alpine3.23, andservice-object-storageis on 0.0.69.- The release binaries are built by
go-service-release.ymlwithgo-version-file: go.mod, andgo.mod:3saysgo 1.27.0with notoolchainline.ci.ymlpins1.27.0too. If setup-go resolves that to go1.27.0, which I did not run, the agent binariesv0.0.2ships would carry all eight stdlib advisories regardless of the local audit.
- Fix:
- Bump
source.agenttocodefly.dev/go:0.0.69. - Raise
go.modtogo 1.27.2(AGENTS.md: bumpgo.modandci.ymltogether) so the goreleaser build cannot pick an older toolchain. - Re-run
codefly agent ci.
- Bump
Worth reconsidering
F4 (minor): the first release is v0.0.2, not 0.0.1, and a wrong version is only caught after the tag is pushed
agent.codefly.yaml:4seedsversion: 0.0.1.codefly publishalways bumps (cli cmd/publish/release.go,Release: no tags, manifest 0.0.1, patch), so it tags v0.0.2. The PR body and brief call this "0.0.1".- The image's version label is checked against the tag only in
release.yml:85-111, which runs aftercodefly publishhas already pushed the tag. - Concrete failure: dispatch the publisher with
version=0.0.1, commit the lock, and every pre-tag gate passes (CI, agent CI conformance). Thencodefly publishpushes v0.0.2,release.ymlfails on the label, and v0.0.2 is left stranded. Recovery means deleting the tag or re-publishing the image. - Fix: say "the first release is v0.0.2" in README §Releasing, or seed
0.0.0, or add a pre-tag check that the lock's label equals the bumped version.
F5 (minor): releasing depends on two never-run core workflows and an unstated registry-visibility step
- No other repo in the fleet mirrors pins
ea49e7a. No caller ofpublish-service-image.ymlexists anywhere. So this repo's first release is the first execution of both core's publisher and thisgo-service-release.yml. - The
ghcr.io/codefly-dev/service-warehousepackage does not exist yet (anonymous token: DENIED).service-object-storage's package is public. - The CI step "inventory the published multi-architecture image" (
ci.yml:73-81) does no registry login, and consumers'codefly runpulls anonymously. If the first push creates a private package, the lock PR goes red and consumers cannot pull. - Fix: add "make the package public and verify anonymous pull" between README §Releasing steps 2 and 3, and confirm the
GH_PATrepository or org secret exists before step 4.
F6 (minor): release SBOM evidence expires
release.yml:124-128uploadssbom/only as a workflow artifact, which disappears at the repository's retention limit (90 days by default).- The README text this PR replaced required evidence "retrievable with the image". The agent can rescan on demand, so no capability is lost, but the release-time evidence for the bytes that were tagged is.
- Fix: attach
sbom/to the GitHub release, or push it as an OCI referrer of the digest.
F7 (minor): cgo is enabled for a driver that does not exist yet, and the SBOM test would not notice the gap it creates later
- Today the cgo link is dynamic glibc only, and syft inventories
libc6andlibstdc++6from distroless/cc's dpkg status (CI: 14 OS packages, 9 Go modules). So the cgo libraries are covered now. - When go-duckdb lands, libduckdb is statically linked into the Go binary. It will then appear only as a Go module, with nothing recording the C++ engine.
sbom_e2e_test.go:66-77only asserts "some deb package". It does not assert that the library the binary actually links is present.- Fix: assert
pkg:deb/debian/libc6today. When the driver lands, require the engine to appear as its own component.
F8 (minor): one reader still treats an empty lock as a pass
- Every other reader fails closed: agent Runtime, Deploy, Audit, SBOM at both scopes, and
release.yml. Core'sParseImageLockreturnsErrImageUnpublishedfor"", a missing key, ornull. ci.yml:73-81passes with a notice instead, and does so permanently. After the first release, a PR that blanks the digest (a bad merge, a mis-resolved conflict) merges green.- Fix: make that pass conditional on no
v*tag existing.
Sprawl against #12
None material. The token requirement is a breaking change to the standalone gateway, but it is justified: the agent publishes on all interfaces. The SBOM and image work was required by the pre-PR README's own contract. The copied implementations really are gone: internal/auth and internal/imageevidence are deleted, and no hand-rolled ConstantTimeCompare, lock decoding or syft execution remains. The token interceptors and the health exemption match core's: only Check and Watch are exempt, List requires the token, the Kubernetes gRPC probes hit Check, and anonymous mode installs no interceptor. The manifest declares release.owner: workflow / workflow: release.yml, which CLI v0.1.181 accepts. The service-warehouse_<ver>_<os>_<arch>.tar.gz archive name matches the loader name.
The first-release sequence
The design makes the first release possible without hand edits beyond the reviewed lock commit, provided F1 is fixed (or knowingly accepted) first:
- Merge #13 to
main.mainis unprotected.ci.ymlpasses on the empty lock through the notice path. - On a clean
mainthat is in sync with origin, runcodefly publish --dry-run. Expectwould bump 0.0.1 → 0.0.2 and tag v0.0.2. That version is the one to use below. - Run
gh workflow run publish-gateway-image.yml --repo codefly-dev/service-warehouse --ref main -f version=0.0.2. The default-branch guard passes because the commit is onmain. - Make the new ghcr package public and confirm anonymous pull (F5).
- Commit the run's
gateway-image.json(step summary, or artifactgateway-image.json-0.0.2) in a reviewed PR. Its CI now inventories both platforms from the registry for the first time. Merge it. - Optionally dispatch
agent-ci.ymlonmainfor the first full conformance run, then switch that workflow topull_requestas its comment says. - Fix F9 first (packager and toolchain bump), or
codefly publishaborts at the audit. Then, withGH_PATconfirmed, runcodefly publishfrom a clean, syncedmainon a host with Docker. It runs release-gradecodefly agent cion the bumped tree, commitsrelease: v0.0.2and pushes the tag.release.ymlthen runs the tests, checks the tag against the manifest and the image label against 0.0.2, collects the SBOM, creates:0.0.2/:latest, and goreleaser builds the agent. The CLI then verifies the loader archives. - Close #12 and answer its question (F3).
Verification
GOWORK=off go build ./... && go vet ./... && go test -race ./...passes at 2bc9e68 (darwin/arm64, go1.27.2). An enclosinggo.workin my scratch area had to be disabled first; it is not part of the repo.- CI run 38141866866 at this head shows
--- PASS: TestRuntimeEndToEnd(with theno_credentialsandwrong_tokensubtests) and--- PASS: TestImageSBOMInventoriesTheGatewayImage(9 Go modules, 14 OS packages). The published-image step took the empty-digest notice path. - I reproduced F1's gateway exit locally.
codefly agent ci --dir .(CLI 0.1.181, local Docker, cachedgolang:1.27-alpine= go1.27.1): manifest, source and build passed; audit failed (F9); conformance and drift were skipped. I could not reach conformance at all: it would stop atErrImageUnpublishedanyway, as the PR comment says.
What I did not examine
- I did not execute
publish-service-image.ymlorgo-service-release.yml. Nothing can, before merge, because of the default-branch guard. Their first run is the residual risk. - I could not read whether
GH_PATexists or what the org's default package visibility is (403 on both). - I did not build or scan the multi-arch image under QEMU.
service-object-storagepublishes the same non-$BUILDPLATFORMpattern successfully, and no cgo code compiles today. - I did not review the
gen/orprotocontract beyondRowError, because the diff does not touch them.
Highest risk to keep watching: F1. If it is not fixed, the release gate certifies an agent whose default composition cannot serve, and the first consumer finds out.
antoinetoussaint-byte
left a comment
There was a problem hiding this comment.
Follow-up to review r23 of 2bc9e68: the nine findings are addressed in fd2dab805d0c4fb3df7604ade6f06c750eb128e3.
- F1: Create writes
backend: mem; Runtime.Test probes health and authenticated Capabilities without requiring Start. Docker tests cover a generated service's Init → Test with no backend override, and a gateway stopped after Init that Test must reject. Both actually PASS in PR CI. - F2: Deployment requires
SWH_AUTH_TOKENvia Kubernetes secret reference for both output profiles. Missing references, literal tokens and anonymous deployment configuration fail. README documents binding the same key to consumers'warehouse.token. The rendered NetworkPolicy permits only same-namespace ingress to the gateway port. Limits are explicit: a policy-capable CNI is required, this is not an individual-consumer allowlist, no mesh is installed, and the environment provisions/rotates the secret and configures both bindings. Local direct gateway execution retains the explicit anonymous opt-in. - F3: Body now uses
Refs #12; the tracking issue remains open through release verification. README and the body state the actual contract:RowErrorhasrow_indexand free-formstring error, with no permanent/retryable code. #14's separate API work is not duplicated or claimed here. - F4: The first-release procedure says seed 0.0.1 → v0.0.2, with publisher input 0.0.2.
- F5: The procedure requires public GHCR package visibility and an anonymous digest pull using a fresh Docker configuration.
- F6: The release workflow now waits for GoReleaser, downloads this run's image evidence, and attaches all CycloneDX documents plus
index.txtto the GitHub release. The attachment job must complete before release verification is complete. - F7: The real-image SBOM test requires Debian
libc6by purl. It passes locally and in PR CI alongside the Go and OS package checks. - F8: The initial empty-lock exception requires complete history, no
v*tags, and no prior nonempty lock on fetched history. It rejects clearing a lock even before the first tag; disposable Git fixtures verify each boundary. - F9: Packager is 0.0.69; go.mod and CI select Go 1.27.2. The gateway's toolchain image is pinned by index digest, with exact
GOTOOLCHAIN=go1.27.2.GOTOOLCHAIN=go1.27.2 codefly agent cipasses its source, native/Linux build and binary vulnerability audit with default HIGH/CRITICAL enforcement; no audit skip or suppression.
PR CI is green: build/vet/race, runtime e2e, and image SBOM. Local build/vet/race, Docker e2e, actionlint and tidy checks also pass.
Full agent conformance is still not green: its generated workspace's codefly ci run stops before lint because the image lock has no published digest; later phases and drift are skipped. The nine-step coordinator release sequence is in the PR body and README and includes rerunning that gate after the reviewed lock lands. Cloud backends, live cluster policy enforcement, the published multi-platform image and release asset upload were not exercised. No merge, dispatch, publish or release tag was performed.
|
Pushed all nine review fixes in Local With packager 0.0.69 and Go 1.27.2, The body now references #12, documents the current per-row error limitation, and contains the nine-step first-release sequence for v0.0.2, including public GHCR access and durable release SBOMs. The coordinator owns merge, dispatch, the reviewed digest-lock PR, the full conformance rerun, and publication. None of those release actions was performed here; #12 remains open until release verification. |
|
Added the publisher follow-up in
The workflow, README, AGENTS.md and PR body explicitly label this a stopgap pending core#770, the core 0.18.2 composite action. The core Go adoption remains at v0.18.1. Build, vet, race tests and actionlint pass. New tests execute the actual ancestry guard against disposable Git history and validate the emitted lock through core's parser. The fresh No merge, publisher dispatch, image publication or release tag was performed; live GHCR write authorization remains to be verified by the coordinator. After the reviewed merge, the first image dispatch is version=0.0.2 and returns gateway-image-lock-0.0.2. The existing nine-step release sequence remains in the body. |
antoinetoussaint-byte
left a comment
There was a problem hiding this comment.
Fix verification (fresh context, Opus) of head fc6a6ea against r23
Plain clone, GOWORK=off, released CLI 0.1.185, local Docker. Each line gives the probe and what I observed. Result: 6 fixed, 3 partially fixed (F1, F2, F3), 0 regressed. One of the three partial fixes, F1, still blocks the first release.
-
F1, partially fixed (release-blocking). The generated defaults and the probe are fixed.
SWH_GATEWAY_IMAGE=<local build> go test -tags e2e -run 'TestRuntimeEndToEnd' .passes: Create → Load → Init → Test with no override usesbackend=mem, and Test passes. TestRuntimeEndToEndRejectsDeadGateway passes too. I ran two mutations, and both turned the tests red:- Removing the
memdefault inCreatemade Test fail with "not ready after 1m", and the gateway loggedduckdb backend not yet implemented. - Making
Runtime.Testa no-op turned the dead-gateway test red.
The conformance run itself still does not pass. With the image override,
codefly agent ci --dir . --skip-audit --native-onlygets past runtime-init. It then fails the test phase:tests for app/subject returned no run-level outcome: the runtime agent reported "UNKNOWN". The cause is thatruntime.go:346returnsTestResponseWithResults(...)with noTestRunResult, and CLI 0.1.185 refuses that as a verdict. I patched only that line to setResult{State: PASSED}. Conformance then passed its test phase and stopped at the audit phase on the unpublished lock, which is expected. So once a digest is committed,codefly agent ciconformance, and with itcodefly publish's BeforeCommit gate, will still fail. The author's run never got this far because it stopped earlier on the empty digest. - Removing the
-
F9, fixed.
codefly agent ci --dir .(0.1.185) reports manifest, source, build and audit passed. The only advisories left are 2 docker/docker items with no upstream fix. Conformance then stops on the empty digest, as the author said. The pins are in place:source.agent: codefly.dev/go:0.0.69,go 1.27.2in go.mod, ci.ymlGOTOOLCHAIN=go1.27.2andgo-version: 1.27.2, and the Dockerfile buildergolang:1.27.2-trixie@sha256:…. release.yml usesgo-version-file: go.mod, which is now 1.27.2. -
F2, partially fixed. The default is authenticated. Deploy refuses a missing
SWH_AUTH_TOKENsecret ref, a literal token, andSWH_ALLOW_ANONYMOUSset totrue,1,TRUEoryes, in both profiles. The NetworkPolicy (same namespace, gateway port) is rendered in both profiles. Mutations confirmed the tests catch both: removing the anonymous refusal failed TestDeployRefusesWhatItHasNoWayToDeliver/anonymous_deployment, and dropping networkpolicy.yaml from the kustomization failed TestDeployRequiresAuthentication….Residual gap: I added a secret reference keyed
SWH_ALLOW_ANONYMOUS(probe test). Deploy returns SUCCESS in both profiles and renders a secondSWH_ALLOW_ANONYMOUSenv entry fromsecretKeyRefafter the literal"false", through therange .Deployment.SecretReferencesat deployment.yaml.tmpl:67. Kubernetes takes the later duplicate, so this is an anonymous deployment that the stated refusal does not catch. I did not apply it to a cluster. The fix is to refuse any secret ref other thanSWH_AUTH_TOKEN, or at leastSWH_ALLOW_ANONYMOUS. The PR body states the remaining NetworkPolicy limits precisely: it needs a policy-capable CNI, does not tell consumers in the same namespace apart, and installs no mesh. -
F3, partially fixed. The PR body says "Refs #12", and
closingIssuesReferencesis empty. But commit 632feea's message contains "This closes #12." The repo allows merge commits, rebase merges, and squash merges withsquash_merge_commit_message=COMMIT_MESSAGES. Every merge method therefore puts that keyword on main and closes #12 at merge, unless the squash message is edited by hand. This is not a manual merge-time step: the PR body says there is no rebase or force-push, so 632feea stays as written. -
F4, fixed. README §Releasing and AGENTS.md say the first release is v0.0.2 and the image publisher receives
version=0.0.2, with artifactgateway-image-lock-0.0.2. The publish input description says the same. -
F5, fixed. README step 4 says to make
ghcr.io/codefly-dev/service-warehousepublic and verify an anonymous pull by the digest. -
F6, fixed in the workflow; not executed, since no tag can be run before merge.
attach-image-evidence(needs gateway-image and release,contents: write) downloadsgateway-image-sbom-*and runsgh release upload … --clobber. I checked thatgo run ./cmd/image-sbom -local -out dwrites flat files (*.cdx.jsonplusindex.txt), sosbom/*will upload. Not verified: whether GoReleaser leaves the release mutable at that point. If the org enables immutable releases, a post-create upload is refused. -
F7, fixed. TestImageSBOMInventoriesTheGatewayImage passes against the local build. As a mutation I rebuilt the final stage on
distroless/static-debian13, and the test failed with "inventory must contain Debian libc6". -
F8, fixed. I ran
.github/scripts/allow-unpublished-image.shagainst disposable repos:- Pre-release empty lock with no tag: exit 0.
- A
v*tag present: exit 1. - A nonempty lock earlier in history, then blanked: exit 1.
- Shallow clone: exit 1.
ci.yml keeps
fetch-depth: 0. -
In-repo publish job (stopgap), correct. The workflow, README and AGENTS.md label it a stopgap pending core#770.
- Permissions: top-level
contents: read; the job adds onlypackages: write. Checkout usespersist-credentials: false, and.dockerignoreexcludes.git. - Default-branch refusal: I extracted the guard script and ran it against a disposable bare origin:
- Unmerged feature commit: exit 1, with "not reachable from refs/remotes/origin/main".
- Main: exit 0.
- Main commit dispatched from another branch: exit 0.
- Origin HEAD unreadable: exit 1.
- Push and lock: the build uses
push-by-digest=true,name-canonical=truewith no tags. The lock step requires^sha256:[0-9a-f]{64}$and writes{name,digest}to thegateway-image-lock-<v>artifact and the step summary. Core v0.18.1's evidence collector skips buildxunknown/unknownattestation children, so the default provenance does not break evidence. Actions are SHA-pinned, and inputs reachrun:only through env. actionlint is clean. - One deviation from "token only at login": the guard also uses
github.tokenforls-remoteandfetch, throughgit -c http…extraheader=. That is not persisted, but it puts the base64 token in that git process's argv. The repo is public, so those reads need no authentication; dropping the token there would leave login as its only use. This is minor and does not block.
- Permissions: top-level
-
Build/vet/test:
GOWORK=off go build ./... && go vet ./... && go test -race -count=1 ./...all pass.
Not done: no live GHCR push, no tag run of release.yml, no cluster apply. Nothing was pushed, approved or merged.
…cking Refs codefly-dev#12. Return explicit readiness PASSED/FAILED results for CLI 0.1.185, reject the reserved anonymous-mode key across deployment configuration sources, and use anonymous Git reads in the public repository's publisher guard. The coordinator must supply an explicit squash body containing the reference above. The historical closing directive in commit 632feea must be omitted from that squash message so the issue stays open until the release is verified.
antoinetoussaint-byte
left a comment
There was a problem hiding this comment.
Follow-up to verification r26, fixed in 784ec02cdd54d7ef8c70d6cc3e99994ed978b466:
- F1: Runtime.Test now returns
TestRunResult_PASSEDwhen readiness succeeds andFAILEDwhen it fails, with consistent structured and legacy counters and the failure diagnostic. Unit tests and both Docker e2e cases assert the run-level result. I reran fullcodefly agent ci --dir .using the supplied released CLI 0.1.185,GOWORK=off, Go 1.27.2 and the local gateway image override, with no audit or packaging skips. Manifest, source, native/Linux packaging and agent-binary audit pass. The generated consumer's lint, compile andtest:default:app/subjectpass. The only remaining failure isaudit:app/subject: the published image lock records no digest. The UNKNOWN test failure is gone.agent-ci.ymlnow pins CLI 0.1.185 too. - F2: The anonymous-mode key is refused by presence, regardless of value or source. This covers Kubernetes secret references (including a nil reference), own/dependency configuration, secret and templated values, raw ConfigMap data, environment overrides and configuration carriers. Empty and false values are also refused. Tests exercise both output profiles and require refusal before any files are rendered. Core v0.18.1 exposes no native ConfigMap-reference field, so such a reference cannot enter its deployment renderer; its supported raw ConfigMap/environment-data path is covered by the key guard. The template remains the sole owner of the literal false entry.
- F3: The fixup commit explicitly says Refs #12. The PR body, README and AGENTS.md require the coordinator to supply an explicit squash body containing that reference, omitting the historical closing directive in
632feea. They warn that the squash message must not contain the closing keywordclosesfollowed by issue#12. The original commit is unchanged; no rebase or force-push was used. The coordinator's explicit squash body is still required to keep the issue open through release verification. - Publisher token note: Removed GH_TOKEN from the guard and removed the authenticated Git wrapper and
http.extraheaderargument. The publicgit ls-remoteandgit fetchcalls are anonymous. The guard still refuses unmerged commits before registry login; its regression test checks that no token environment or authentication header is supplied.
Build, vet, race tests, actionlint, formatting and tidy checks pass. All three final-head PR CI jobs are green, including real runtime and image-SBOM tests. No merge, workflow dispatch, image publication or release tag was performed. First image dispatch remains version 0.0.2 under the coordinator's release sequence.
|
Pushed the r26 fixes in Runtime.Test now returns explicit PASSED/FAILED results. The anonymous-mode key is rejected across every supported deployment configuration source, including references and empty/false values. The publisher's public Git reads no longer receive credentials. The fixup commit says Refs #12, and the body/docs record the explicit squash-message requirement. Build, vet, race tests, actionlint and Docker runtime tests pass. Using the supplied released CLI 0.1.185 with the local image override, full agent CI passes manifest, source, native/Linux packaging and binary vulnerability audit; generated-service lint, compile and test pass. The only failure is now the expected service-image audit error: the published image lock has no digest. No audit skip or suppression was used. Coordinator handoff: use an explicit squash body containing Refs #12, omitting the historical closing directive from |
antoinetoussaint-byte
left a comment
There was a problem hiding this comment.
Fix verification 2 (fresh context, Opus) of head 784ec02 against r26
Plain clone + pull/13/head, GOWORK=off GOTOOLCHAIN=go1.27.2, released CLI 0.1.185, gateway image built locally from this head and passed as SWH_GATEWAY_IMAGE. Every claim below was probed, not read.
- F1 — FIXED.
codefly agent ciat head: manifest/source/build/audit stages pass; conformance's generated-service gate reportslint,compileandtest:default:app/subjectpassed, and the only failure isaudit:app/subject— "image lock records no digest: the image has not been published". Mutation: reverting theruntime.gohunk of 784ec02 makes the new unit testTestRuntimeTestReportsRunLevelOutcome/servingfail at the source stage; also reverting that test lets conformance reach the test phase, which then fails with "tests for app/subject returned no run-level outcome: the runtime agent reported "UNKNOWN"". (WithoutSWH_GATEWAY_IMAGE, conformance stops earlier atlinton the same unpublished-digest refusal — still the only failure, as README now documents.) - F2 — FIXED.
TestDeployRejectsAnonymousKeyFromEveryConfigurationSourcepasses 30/30 subtests (15 sources × both profiles, including secret ref, nil secret ref, raw ConfigMap data, env override, carrier key, dependency config, and literal true/false/empty). An independent probe rendered the deploy withSWH_ALLOW_ANONYMOUSas a secret reference, as raw ConfigMap data and as a plain value in both profiles: all three refused with "the key is reserved in deployments", nothing written; a clean deploy renders exactly one entry,value: "false". Mutation: removing the guard call fails all 30 subtests, and the secret-reference render emits a secondSWH_ALLOW_ANONYMOUSentry fromsecretKeyRef {name: attacker, key: flag}after the literal — the r26 hole, now closed. Core v0.18.1'sKubernetesDeploymentproto has no ConfigMap-reference field (onlysecret_references), so a "ConfigMap ref" input cannot be expressed; ConfigMap data is covered by the raw-configuration path. - F3 — FIXED BY PROCEDURE (needs the explicit squash body). PR body says
Refs #12andclosingIssuesReferencesis empty; the only closing directive in branch history is 632feea ("This closes #12"). The repo'ssquash_merge_commit_messageisCOMMIT_MESSAGES, so a default squash would close #12, and so would a merge commit or a rebase merge (both land 632feea's message on main). Squash only, with this body:
Refs #12.
Compose the warehouse gateway as the codefly service agent codefly.dev/warehouse, with its pinned image lock and image SBOM evidence. Adopts core v0.18.1's caller-token, image-lock and SBOM primitives; deployments require an SWH_AUTH_TOKEN secret reference and reserve SWH_ALLOW_ANONYMOUS; Runtime.Test returns an explicit run-level PASSED/FAILED verdict; the gateway image is published from this repository (stopgap pending core#770).
Issue #12 stays open until release v0.0.2 is verified.
- Token note — FIXED. The
default-branchstep has noenv:, and the workflow's only token use isdocker/login-action'spassword: secrets.GITHUB_TOKEN; git reads are plaingit ls-remote/git fetch.TestPublisherRefusesCommitOutsideDefaultBranchexecutes the step against disposable history with no token in the environment and passes; mutation re-addingenv: GH_TOKENfails it ("public git reads must receive no token"). - Build/vet/test -race — PASS.
go build ./...,go vet ./...,go test -race -count=1 ./...all green, 0 skips; tree restored clean after mutations. PR CI (build-test, agent-runtime-e2e, image-sbom) is green at this head. Not run here: thee2e-tagged Docker tests locally (covered by CI's agent-runtime-e2e).
Unfixed items: 0.
Refs #12.
What changes
A workspace can compose the warehouse gateway as
codefly.dev/warehouse. The agent starts the gateway, distributes its local caller token, renders authenticated Kubernetes deployments, and serves image SBOM evidence. It remains bound to one database and authorizes nothing.The coordinator's worker did the core v0.18.1 adoption (core PR #759).
codefly agent deps --pin v0.18.1updated the dependency. The release and agent-CI reusable workflows use that tag's immutable commit,ea49e7a968ef5f2fd325b1c41f823a47eb20141c.origin/mainis merged into this branch; there was no rebase or force-push.internal/authandinternal/imageevidenceand the copied lock parser. Core'scallertoken,resources.ParseImageLock, andagents/services/sbomnow own those behaviors.internal/gatewayimagedeclares only this service's platforms and role.cmd/image-sbomis a thin main usingCollectImageEvidenceandWriteImageEvidenceIndex. The image publisher now defines its job in this repository, using the job's ownGITHUB_TOKEN; it does not call core's reusable publisher (see the labelled stopgap below).linux/amd64,linux/arm64). The publisher usespersist-credentials: falseand refuses commits outside the default branch's history.nameanddigest, the expected registry/name, and lowercase SHA-256 digests. The current empty digest records an unpublished image and is refused by runtime, deployment, audit and release.Classification: fixes at the owning layer for the core Go adoption and r23 findings: core owns the shared Go primitives; this repository owns its generated defaults, readiness integration, deployment template, distribution gates and release procedure. Hack/stopgap: the local publishing steps below temporarily duplicate the shared publisher pending the owning fix in core#770.
Publisher stopgap pending core#770
Object-storage's first live image publication was denied with
installation not allowed to Write organization package: GHCR checks the workflow's defining repository, which was core. The owning fix is core#770, a composite publisher for core 0.18.2.As requested,
publish-gateway-image.ymlnow defines its publish job in this service repository, withpackages: writeand login using its ownGITHUB_TOKEN. Checkout haspersist-credentials: false. The default-branch ancestry refusal runs before registry login. Git remote reads are anonymous because this repository is public; the guard receives no token and uses no credential-bearing command-line arguments. The build pushes an untagged image index by digest forlinux/amd64,linux/arm64, with the version and source labels, and records a strictgateway-image.jsonin the artifact and run summary. QEMU supports the cgo build on the non-native platform.This is an explicitly labelled stopgap pending core#770 in the workflow, README and AGENTS.md. Once the core 0.18.2 composite action is available and adopted, replace the local publishing steps while keeping the job in this repository. The rest of core stays at v0.18.1. First dispatch remains version=0.0.2, with artifact gateway-image-lock-0.0.2.
The tests execute the workflow's actual default-branch guard against disposable Git history (reviewed, unmerged and unreadable-default cases), verify that it receives no token or authentication header, and check the writer's output with core's strict lock parser. The image-distribution and SBOM platform gates now inspect the in-repository build step. No live push has been attempted here; first registry authorization remains a coordinator release check.
r26 verification follow-up
Verification r26 identified three partial fixes and the publisher-token note. Fixup commit
784ec02adds explicit Test PASSED/FAILED results, rejects the anonymous-mode key across every supported deployment input, recordsRefs #12and the explicit squash-body requirement, and removes token handling from the public Git reads. Both successful and failed readiness outcomes, both deployment profiles, the reserved key's empty/false/reference cases, and the anonymous branch guard are regression-tested. README and AGENTS.md describe the corrected behavior.Independent review F1–F9
Addresses the review of 2bc9e68 in
fd2dab8.backend: mem. Runtime.Test waits for health and authenticated Capabilities even when Start was never called, then returns explicit run-level PASSED/FAILED verdicts and matching structured/legacy counts. CLI 0.1.185 now passes the generated-service test phase. The Docker regression generates a service and exercises Init → Test without a backend override; a second case stops the gateway after Init and requires Test to fail.SWH_AUTH_TOKENKubernetes secret reference in both output profiles. Missing auth references and literal tokens are refused. TheSWH_ALLOW_ANONYMOUSkey is reserved: caller-supplied secret references, plain/secret/templated values, dependency values and raw environment/ConfigMap data are rejected by key even when empty or false. Core v0.18.1 has no ConfigMap-reference input; that source cannot be rendered through its deployment API. Consumers bind the same secret key to theirwarehouse.tokensecret configuration; README specifies both bindings. A NetworkPolicy restricts ingress to the gateway port from the same namespace. It requires a policy-capable CNI, does not distinguish individual consumers in that namespace, and installs no mesh/mTLS. Secret provisioning/rotation and consumer bindings belong to the environment; this agent does not automatically copy references between services. Anonymous access is an explicit local gateway opt-in only.RowErrorcontainsrow_indexand free-formstring error, with no permanent/retryable code. feat: add the bigquery backend, with portable per-row refusal reasons #14 owns the separate API work. Keep No plugin manifest and no release: the server works but no workspace can compose it #12 open until the release is verified and record that answer with its release URL. Historical commit632feeastill contains a closing directive; the coordinator must squash with an explicit body containingRefs #12, not the default concatenation of commit messages. The squash message must not contain the closing keywordclosesfollowed by issue#12. Fixup commit784ec02records this requirement without rewriting history.attach-image-evidencedownloads this run's image artifact and uploads every CycloneDX document andindex.txtas durable GitHub release assets. Workflow artifacts alone are no longer the retention plan.pkg:deb/debian/libc6@…, alongside Go modules and OS packages.v*tag or any prior nonempty image lock, including a lock reverted before the first tag. Disposable Git fixtures cover initial, prior-lock, release-tag and shallow-history states.codefly.dev/go:0.0.69; its recipes pin images by digest.go.modand CI use Go 1.27.2. The gateway build pinsgolang:1.27.2-trixieto its image-index digest and setsGOTOOLCHAIN=go1.27.2; CI sets the same toolchain. The new agent-binary audit passes with default HIGH/CRITICAL enforcement, without skips or suppressions.Behavior and procedure docs updated in the same PR:
README.md,AGENTS.md,templates/agent/README.md.tmpl, and the factory getting-started and local-secret guidance.Validation
go build ./...,go vet ./...,go test -race ./...,actionlint, formatting andgo mod tidy -diff.784ec02: local build/vet/race, actionlint, formatting, tidy and Docker runtime tests pass. All three final-head PR CI jobs are green: build/vet/race, runtime e2e and real-image SBOM.codefly agent ci --dir .was rerun with the coordinator-supplied released CLI 0.1.185,GOWORK=off,GOTOOLCHAIN=go1.27.2andSWH_GATEWAY_IMAGE=service-warehouse:pr13-e2e, without audit or packaging skips.agent-ci.ymlnow pins the same CLI.codefly ci run, lint, compile andtest:default:app/subjectpass with the explicit run-level verdict.audit:app/subjectrefusesgateway-image.jsonwith no digest. Runtime's local-image override does not bypass the published-image audit. Subsequent SBOM/build phases and drift are skipped; full conformance is not claimed green.Not exercised: cloud backends, live cluster NetworkPolicy enforcement, published two-platform scan, public registry pull or release asset upload. No merge, workflow dispatch,
codefly publishor release tag was performed.Coordinator's nine-step first release
Refs #12. Omit the historical closing directive from632feea; do not use the default concatenated commit messages. The squash message must not containclosesfollowed by#12.codefly publish --dry-run; confirm 0.0.1 → 0.0.2.publish-gateway-imagejob on main with version=0.0.2; downloadgateway-image.jsonfrom gateway-image-lock-0.0.2.codefly agent cion synced main, including audit and generated-servicecodefly ci run. After a green full run, enable the PR trigger inagent-ci.yml.codefly publish. Verify the manifest/tag version, image version labels and locked digest, image tags, agent archives, and the completed release SBOM attachment job.