Skip to content

feat: compose the gateway as a codefly service agent, with its image and SBOM evidence (#12) - #13

Merged
antoinetoussaint-byte merged 10 commits into
codefly-dev:mainfrom
crisfiorini-oss:feat/agent-manifest
Oct 11, 2026
Merged

antoinetoussaint-byte merged 10 commits into
codefly-dev:mainfrom
crisfiorini-oss:feat/agent-manifest

Conversation

@crisfiorini-oss

@crisfiorini-oss crisfiorini-oss commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

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.1 updated the dependency. The release and agent-CI reusable workflows use that tag's immutable commit, ea49e7a968ef5f2fd325b1c41f823a47eb20141c. origin/main is merged into this branch; there was no rebase or force-push.

  • Deleted internal/auth and internal/imageevidence and the copied lock parser. Core's callertoken, resources.ParseImageLock, and agents/services/sbom now own those behaviors. internal/gatewayimage declares only this service's platforms and role.
  • cmd/image-sbom is a thin main using CollectImageEvidence and WriteImageEvidenceIndex. The image publisher now defines its job in this repository, using the job's own GITHUB_TOKEN; it does not call core's reusable publisher (see the labelled stopgap below).
  • Health exemption is exact: Check/Watch only, not List. Empty server tokens fail closed. Generated tokens are 64 lowercase hex characters. Evidence has one subject per declared platform (linux/amd64, linux/arm64). The publisher uses persist-credentials: false and refuses commits outside the default branch's history.
  • Locks allow only name and digest, 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.yml now defines its publish job in this service repository, with packages: write and login using its own GITHUB_TOKEN. Checkout has persist-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 for linux/amd64,linux/arm64, with the version and source labels, and records a strict gateway-image.json in 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 784ec02 adds explicit Test PASSED/FAILED results, rejects the anonymous-mode key across every supported deployment input, records Refs #12 and 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.

  • F1: Create writes 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.
  • F2: Deployment requires an environment-managed SWH_AUTH_TOKEN Kubernetes secret reference in both output profiles. Missing auth references and literal tokens are refused. The SWH_ALLOW_ANONYMOUS key 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 their warehouse.token secret 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.
  • F3: This body says Refs No plugin manifest and no release: the server works but no workspace can compose it #12, not a closing keyword. At this revision RowError contains row_index and free-form string 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 commit 632feea still contains a closing directive; the coordinator must squash with an explicit body containing Refs #12, not the default concatenation of commit messages. The squash message must not contain the closing keyword closes followed by issue #12. Fixup commit 784ec02 records this requirement without rewriting history.
  • F4: The manifest seed remains 0.0.1; publish increments it, so the first release is v0.0.2 and the image workflow input is 0.0.2.
  • F5: README explicitly requires making the new GHCR package public and checking an anonymous digest pull.
  • F6: After GoReleaser creates the release, attach-image-evidence downloads this run's image artifact and uploads every CycloneDX document and index.txt as durable GitHub release assets. Workflow artifacts alone are no longer the retention plan.
  • F7: The real-image SBOM test now requires pkg:deb/debian/libc6@…, alongside Go modules and OS packages.
  • F8: CI uses complete fetched history. Its empty-digest exception fails after any 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.
  • F9: Source packager is codefly.dev/go:0.0.69; its recipes pin images by digest. go.mod and CI use Go 1.27.2. The gateway build pins golang:1.27.2-trixie to its image-index digest and sets GOTOOLCHAIN=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

  • Passed: go build ./..., go vet ./..., go test -race ./..., actionlint, formatting and go mod tidy -diff.
  • Passed locally on linux/arm64: Docker build; generated mem service Init → Test; authenticated/unauthenticated calls; stopped gateway rejected; real-image SBOM including libc6 (9 Go modules and 14 OS packages). Verbose tests show actual PASS, not skips.
  • r26 follow-up 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.
  • Full codefly agent ci --dir . was rerun with the coordinator-supplied released CLI 0.1.185, GOWORK=off, GOTOOLCHAIN=go1.27.2 and SWH_GATEWAY_IMAGE=service-warehouse:pr13-e2e, without audit or packaging skips. agent-ci.yml now pins the same CLI.
  • Manifest, source tests, native/Linux packaging and agent-binary vulnerability audit pass. In the generated consumer's codefly ci run, lint, compile and test:default:app/subject pass with the explicit run-level verdict.
  • The only remaining failure is the unpublished image: audit:app/subject refuses gateway-image.json with 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 publish or release tag was performed.

Coordinator's nine-step first release

  1. Squash the fixed, reviewed feat: compose the gateway as a codefly service agent, with its image and SBOM evidence (#12) #13 after PR CI is green, with an explicit squash body containing Refs #12. Omit the historical closing directive from 632feea; do not use the default concatenated commit messages. The squash message must not contain closes followed by #12.
  2. From clean, synced main, run codefly publish --dry-run; confirm 0.0.1 → 0.0.2.
  3. Dispatch the in-repository publish-gateway-image job on main with version=0.0.2; download gateway-image.json from gateway-image-lock-0.0.2.
  4. Make the new GHCR package public. Verify an anonymous pull by the returned digest using a fresh Docker configuration without a registry login.
  5. Commit the returned lock in a reviewed PR. CI must inventory both linux/amd64 and linux/arm64, then merge the lock PR.
  6. Run full codefly agent ci on synced main, including audit and generated-service codefly ci run. After a green full run, enable the PR trigger in agent-ci.yml.
  7. Confirm the repository's GH_PAT release secret and retain packager 0.0.69 / Go 1.27.2 prerequisites with passing audit.
  8. From clean, synced main with Docker available, run codefly publish. Verify the manifest/tag version, image version labels and locked digest, image tags, agent archives, and the completed release SBOM attachment job.
  9. Verify the release and production loader archive resolution. Only then mark issue No plugin manifest and no release: the server works but no workspace can compose it #12 complete, with the release URL and the accurate per-row answer: this revision has a row index and free-form error, no permanent/retryable code; account explicitly for any separately merged feat: add the bigquery backend, with portable per-row refusal reasons #14 API changes before claiming otherwise.

crisfiorini-oss and others added 4 commits October 8, 2026 16:03
…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>
@antoinetoussaint-byte

antoinetoussaint-byte commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

lazybox has finished working on this. codex (o1.27.2agentvulnerabilityauditpasses.Full conformance still fails before lint becase the published gateway digestisabsent.Thecoordinatorownsthedocumentednine-stepv0.0.2releasesequenceandconformancererunafterthelocklands.Nomerge,dispatch,publishor release tg wa performed. Worked for 20m 13s •› The independent review of PR #13 head 2bc9e68 is posted: https://github.com/codefly-dev/service-warehouse/pull/13#pu…
• Ran cat > /tmp/pr13-review-reply.md <<'EOF' …
└ (no output)
+ Show details
• Ran gh api repos/codefly-dev/service-warehouse/pulls/13/reviews --jq '.[-1] | {html_url,commit_id,state}'
└ {"commit_id":"fd2dab805d0c4fb3df7604ade6f06c750eb128e3","html_url":"https://github.com/codefly-dev/service-warehous… + 1 line (⌃t to expand)
• Ran cat > /tmp/pr13-green-comment.md <<'EOF' …
└ #13 (comment)
+ Show details
• Fixed F1–F9 and pushed fd2dab8. Updated the PR body and posted the finding-by-finding reply (https://github.com/ /pull/13#pullrequestreview-5483632212) and handoff (https://github.com/codefly-dev/ service-warehouse/pull/13#issuecomment-6109955289).

Build, vet, race tests and all three PR CI jobs (https://github.com/codefly-dev/service-warehouse/actions/
runs/38146292420) pass. The Go 1.27.2 agent vulnerability audit passes.

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…
• Ran cat > /tmp/pr13-review-reply.md <<'EOF' …
└ (no output)
+ Show details
• Ran gh api repos/codefly-dev/service-warehouse/pulls/13/reviews --jq '.[-1] | {html_url,commit_id,state}'
└ {"commit_id":"fd2dab805d0c4fb3df7604ade6f06c750eb128e3","html_url":"https://github.com/codefly-dev/service-warehous… + 1 line (⌃t to expand)
• Ran cat > /tmp/pr13-green-comment.md <<'EOF' …
└ #13 (comment)
+ Show details
• Fixed F1–F9 and pushed fd2dab8. Updated the PR body and posted the finding-by-finding reply (https://github.com/ /pull/13#pullrequestreview-5483632212) and handoff (https://github.com/codefly-dev/ service-warehouse/pull/13#issuecomment-6109955289).

Build, vet, race tests and all three PR CI jobs (https://github.com/codefly-dev/service-warehouse/actions/
runs/38146292420) pass. The Go 1.27.2 agent vulnerability audit passes.

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 working label has been removed; this comment is the record.

claim detail
Lazybox-Claim-Device: effacd542b611010656e
Lazybox-Claim-Session: 50667fc5cf
Lazybox-Claim-Workspace: github-codefly-dev-service-warehouse-13
Lazybox-Claim-Agent: codex
Lazybox-Claim-Model: o1.27.2agentvulnerabilityauditpasses.Full conformance still fails before lint becase the published gateway digestisabsent.Thecoordinatorownsthedocumentednine-stepv0.0.2releasesequenceandconformancererunafterthelocklands.Nomerge,dispatch,publishor release tg wa performed.  Worked for 20m 13s •› The independent review of PR #13 head 2bc9e68 is posted: https://github.com/codefly-dev/service-warehouse/pull/13#pu… 
• Ran cat > /tmp/pr13-review-reply.md <<'EOF' …
  └ (no output)
    + Show details                                                                                                      
• Ran gh api repos/codefly-dev/service-warehouse/pulls/13/reviews --jq '.[-1] | {html_url,commit_id,state}'
  └ {"commit_id":"fd2dab805d0c4fb3df7604ade6f06c750eb128e3","html_url":"https://github.com/codefly-dev/service-warehous…    + 1 line (⌃t to expand)                                                                                             
• Ran cat > /tmp/pr13-green-comment.md <<'EOF' …
  └ https://github.com/codefly-dev/service-warehouse/pull/13#issuecomment-6109955289
    + Show details                                                                                                      
• Fixed F1–F9 and pushed fd2dab8. Updated the PR body and posted the finding-by-finding reply (https://github.com/        codefly-dev/service-warehouse/pull/13#pullrequestreview-5483632212) and handoff (https://github.com/codefly-dev/        service-warehouse/pull/13#issuecomment-6109955289).

  Build, vet, race tests and all three PR CI jobs (https://github.com/codefly-dev/service-warehouse/actions/
  runs/38146292420) pass. The Go 1.27.2 agent vulnerability audit passes.

  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… 
• Ran cat > /tmp/pr13-review-reply.md <<'EOF' …
  └ (no output)
    + Show details                                                                                                      
• Ran gh api repos/codefly-dev/service-warehouse/pulls/13/reviews --jq '.[-1] | {html_url,commit_id,state}'
  └ {"commit_id":"fd2dab805d0c4fb3df7604ade6f06c750eb128e3","html_url":"https://github.com/codefly-dev/service-warehous…    + 1 line (⌃t to expand)                                                                                             
• Ran cat > /tmp/pr13-green-comment.md <<'EOF' …
  └ https://github.com/codefly-dev/service-warehouse/pull/13#issuecomment-6109955289
    + Show details                                                                                                      
• Fixed F1–F9 and pushed fd2dab8. Updated the PR body and posted the finding-by-finding reply (https://github.com/        codefly-dev/service-warehouse/pull/13#pullrequestreview-5483632212) and handoff (https://github.com/codefly-dev/        service-warehouse/pull/13#issuecomment-6109955289).

  Build, vet, race tests and all three PR CI jobs (https://github.com/codefly-dev/service-warehouse/actions/
  runs/38146292420) pass. The Go 1.27.2 agent vulnerability audit passes.

  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-Claim-Started: 2026-10-11T12:45:52Z
Lazybox-Claim-Heartbeat: 2026-10-11T18:20:15Z
Lazybox-Claim-Expires: 2026-10-11T19:15:25Z
Lazybox-Claim-Released: 2026-10-11T18:20:15Z

@antoinetoussaint-byte

Copy link
Copy Markdown
Contributor

Core v0.18.1 adoption is pushed at 2bc9e68. All three repository CI jobs are green: build/race tests, agent runtime end-to-end, and image SBOM. The end-to-end logs explicitly show PASS; the run uploaded the AMD64 CycloneDX document and index.

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: codefly agent ci passes manifest, source, native/Linux packaging and binary vulnerability audit, but its generated workspace's codefly ci run fails closed during runtime initialization because gateway-image.json has no published digest. Full conformance and drift validation remain unverified until a real gateway digest is recorded. No publication, tag or merge was performed; that prerequisite belongs to the documented release sequence after review.

@antoinetoussaint-byte antoinetoussaint-byte left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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: Create returns s.Settings with Backend: "", so the generated service.codefly.yaml names 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.Open fails. I reproduced it at this head: SWH_AUTH_TOKEN=x ./service-warehouse exits 1 with duckdb.Open: Unsupported: duckdb backend not yet implemented.
  • Effect on codefly run: WaitForReady spends 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 legacy TEST_DEPENDENCY_MODE_NONE path (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.Test returns an empty response (runtime.go:342-344).
  • Result: once a digest is recorded, codefly agent ci conformance 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, and templates/factory/GETTING_STARTED.md.tmpl says nothing about backend: 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 setting s.Settings.Backend = "mem" in Create before CreateResponse. That is a setting the user can change, not a hardcode.
    • Make readiness part of what conformance observes, for example by having Runtime.Test call WaitForReady. A gateway that dies on startup must then fail codefly ci run.
    • Test: generate a service through Create, run Init then Test against the e2e image, and assert failure when the backend is duckdb and success when it is mem.

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-75 hardcodes SWH_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-252 deliberately gives the pod its own workload identity on the warehouse.
  • Concrete failure: any workload in any namespace that can resolve <name>.<ns>.svc can call Query with 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-storage ships 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) carries row_index but only a free-form string 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 publish runs release-grade codefly agent ci in BeforeCommit (cli cmd/publish/release.go, agent_release.go runReleaseAgentCI), 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:7 pins source.agent: codefly.dev/go:0.0.56, which builds on the floating golang:1.27-alpine tag.
    • 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/go v0.0.69 pins golang:1.27.2-alpine3.23, and service-object-storage is on 0.0.69.
    • The release binaries are built by go-service-release.yml with go-version-file: go.mod, and go.mod:3 says go 1.27.0 with no toolchain line. ci.yml pins 1.27.0 too. If setup-go resolves that to go1.27.0, which I did not run, the agent binaries v0.0.2 ships would carry all eight stdlib advisories regardless of the local audit.
  • Fix:
    • Bump source.agent to codefly.dev/go:0.0.69.
    • Raise go.mod to go 1.27.2 (AGENTS.md: bump go.mod and ci.yml together) so the goreleaser build cannot pick an older toolchain.
    • Re-run codefly agent ci.

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:4 seeds version: 0.0.1. codefly publish always 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 after codefly publish has 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). Then codefly publish pushes v0.0.2, release.yml fails 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 of publish-service-image.yml exists anywhere. So this repo's first release is the first execution of both core's publisher and this go-service-release.yml.
  • The ghcr.io/codefly-dev/service-warehouse package 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 run pulls 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_PAT repository or org secret exists before step 4.

F6 (minor): release SBOM evidence expires

  • release.yml:124-128 uploads sbom/ 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 libc6 and libstdc++6 from 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-77 only asserts "some deb package". It does not assert that the library the binary actually links is present.
  • Fix: assert pkg:deb/debian/libc6 today. 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's ParseImageLock returns ErrImageUnpublished for "", a missing key, or null.
  • ci.yml:73-81 passes 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:

  1. Merge #13 to main. main is unprotected. ci.yml passes on the empty lock through the notice path.
  2. On a clean main that is in sync with origin, run codefly publish --dry-run. Expect would bump 0.0.1 → 0.0.2 and tag v0.0.2. That version is the one to use below.
  3. 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 on main.
  4. Make the new ghcr package public and confirm anonymous pull (F5).
  5. Commit the run's gateway-image.json (step summary, or artifact gateway-image.json-0.0.2) in a reviewed PR. Its CI now inventories both platforms from the registry for the first time. Merge it.
  6. Optionally dispatch agent-ci.yml on main for the first full conformance run, then switch that workflow to pull_request as its comment says.
  7. Fix F9 first (packager and toolchain bump), or codefly publish aborts at the audit. Then, with GH_PAT confirmed, run codefly publish from a clean, synced main on a host with Docker. It runs release-grade codefly agent ci on the bumped tree, commits release: v0.0.2 and pushes the tag. release.yml then 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.
  8. 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 enclosing go.work in 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 the no_credentials and wrong_token subtests) 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, cached golang: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 at ErrImageUnpublished anyway, as the PR comment says.

What I did not examine

  • I did not execute publish-service-image.yml or go-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_PAT exists 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-storage publishes the same non-$BUILDPLATFORM pattern successfully, and no cgo code compiles today.
  • I did not review the gen/ or proto contract beyond RowError, 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 antoinetoussaint-byte left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up to review r23 of 2bc9e68: the nine findings are addressed in fd2dab805d0c4fb3df7604ade6f06c750eb128e3.

  1. 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.
  2. F2: Deployment requires SWH_AUTH_TOKEN via 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.
  3. F3: Body now uses Refs #12; the tracking issue remains open through release verification. README and the body state the actual contract: RowError has row_index and free-form string error, with no permanent/retryable code. #14's separate API work is not duplicated or claimed here.
  4. F4: The first-release procedure says seed 0.0.1 → v0.0.2, with publisher input 0.0.2.
  5. F5: The procedure requires public GHCR package visibility and an anonymous digest pull using a fresh Docker configuration.
  6. F6: The release workflow now waits for GoReleaser, downloads this run's image evidence, and attaches all CycloneDX documents plus index.txt to the GitHub release. The attachment job must complete before release verification is complete.
  7. F7: The real-image SBOM test requires Debian libc6 by purl. It passes locally and in PR CI alongside the Go and OS package checks.
  8. 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.
  9. 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 ci passes 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.

@antoinetoussaint-byte

Copy link
Copy Markdown
Contributor

Pushed all nine review fixes in fd2dab8. All three PR CI jobs are green, and the finding-by-finding response is posted.

Local go build ./..., go vet ./... and go test -race ./... pass. The generated mem service passes Init → Test; a stopped gateway fails Test as required. Local ARM64 and CI AMD64 image inventories both pass the libc6 assertion (9 Go modules, 14 OS packages). Deployment rendering tests cover authenticated secret references and same-namespace NetworkPolicy in both profiles.

With packager 0.0.69 and Go 1.27.2, codefly agent ci passes manifest, source, native/Linux packaging and its vulnerability audit without skips or suppressions. Full conformance still fails on the missing published gateway digest: the generated workspace's codefly ci run stops during runtime initialization before lint. That is recorded separately from the green PR CI and binary audit.

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.

@antoinetoussaint-byte

Copy link
Copy Markdown
Contributor

Added the publisher follow-up in fc6a6eae65f6bbde08adae9c0c4622fbf0a38494, on top of all nine r23 fixes. All three final-head CI jobs are green.

publish-gateway-image.yml now defines the job in this repository and logs in with its own GITHUB_TOKEN, with packages: write. It no longer calls core's reusable publisher. Checkout has persist-credentials: false; the default-branch ancestry refusal runs before login; the two-platform build pushes by digest without tags; and the strict lock is saved as an artifact and in the run summary. QEMU supports the gateway's cgo build on the other platform.

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 codefly agent ci run passes source, native/Linux packaging and its vulnerability audit. Full conformance still stops before lint on the unpublished gateway digest. The final CI logs also show actual PASS for the generated mem service, dead-gateway rejection and libc image inventory.

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 antoinetoussaint-byte left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 uses backend=mem, and Test passes. TestRuntimeEndToEndRejectsDeadGateway passes too. I ran two mutations, and both turned the tests red:

    • Removing the mem default in Create made Test fail with "not ready after 1m", and the gateway logged duckdb backend not yet implemented.
    • Making Runtime.Test a 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-only gets 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 that runtime.go:346 returns TestResponseWithResults(...) with no TestRunResult, and CLI 0.1.185 refuses that as a verdict. I patched only that line to set Result{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 ci conformance, and with it codefly publish's BeforeCommit gate, will still fail. The author's run never got this far because it stopped earlier on the empty digest.

  • 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.2 in go.mod, ci.yml GOTOOLCHAIN=go1.27.2 and go-version: 1.27.2, and the Dockerfile builder golang:1.27.2-trixie@sha256:…. release.yml uses go-version-file: go.mod, which is now 1.27.2.

  • F2, partially fixed. The default is authenticated. Deploy refuses a missing SWH_AUTH_TOKEN secret ref, a literal token, and SWH_ALLOW_ANONYMOUS set to true, 1, TRUE or yes, 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 second SWH_ALLOW_ANONYMOUS env entry from secretKeyRef after the literal "false", through the range .Deployment.SecretReferences at 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 than SWH_AUTH_TOKEN, or at least SWH_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 closingIssuesReferences is empty. But commit 632feea's message contains "This closes #12." The repo allows merge commits, rebase merges, and squash merges with squash_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 artifact gateway-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-warehouse public 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) downloads gateway-image-sbom-* and runs gh release upload … --clobber. I checked that go run ./cmd/image-sbom -local -out d writes flat files (*.cdx.json plus index.txt), so sbom/* 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.sh against 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 only packages: write. Checkout uses persist-credentials: false, and .dockerignore excludes .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=true with no tags. The lock step requires ^sha256:[0-9a-f]{64}$ and writes {name,digest} to the gateway-image-lock-<v> artifact and the step summary. Core v0.18.1's evidence collector skips buildx unknown/unknown attestation children, so the default provenance does not break evidence. Actions are SHA-pinned, and inputs reach run: only through env. actionlint is clean.
    • One deviation from "token only at login": the guard also uses github.token for ls-remote and fetch, through git -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.
  • 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 antoinetoussaint-byte left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up to verification r26, fixed in 784ec02cdd54d7ef8c70d6cc3e99994ed978b466:

  • F1: Runtime.Test now returns TestRunResult_PASSED when readiness succeeds and FAILED when 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 full codefly 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 and test:default:app/subject pass. The only remaining failure is audit:app/subject: the published image lock records no digest. The UNKNOWN test failure is gone. agent-ci.yml now 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 keyword closes followed 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.extraheader argument. The public git ls-remote and git fetch calls 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.

@antoinetoussaint-byte

Copy link
Copy Markdown
Contributor

Pushed the r26 fixes in 784ec02 and posted the finding-by-finding verification reply. All three final-head CI jobs are green.

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 632feea; the default concatenated commit-message body is unsafe. Keep the issue open through release verification. The first image dispatch remains version=0.0.2. No merge, dispatch, publication or release tag was performed here.

@antoinetoussaint-byte antoinetoussaint-byte left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 ci at head: manifest/source/build/audit stages pass; conformance's generated-service gate reports lint, compile and test:default:app/subject passed, and the only failure is audit:app/subject — "image lock records no digest: the image has not been published". Mutation: reverting the runtime.go hunk of 784ec02 makes the new unit test TestRuntimeTestReportsRunLevelOutcome/serving fail 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"". (Without SWH_GATEWAY_IMAGE, conformance stops earlier at lint on the same unpublished-digest refusal — still the only failure, as README now documents.)
  • F2 — FIXED. TestDeployRejectsAnonymousKeyFromEveryConfigurationSource passes 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 with SWH_ALLOW_ANONYMOUS as 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 second SWH_ALLOW_ANONYMOUS entry from secretKeyRef {name: attacker, key: flag} after the literal — the r26 hole, now closed. Core v0.18.1's KubernetesDeployment proto has no ConfigMap-reference field (only secret_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 #12 and closingIssuesReferences is empty; the only closing directive in branch history is 632feea ("This closes #12"). The repo's squash_merge_commit_message is COMMIT_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-branch step has no env:, and the workflow's only token use is docker/login-action's password: secrets.GITHUB_TOKEN; git reads are plain git ls-remote/git fetch. TestPublisherRefusesCommitOutsideDefaultBranch executes the step against disposable history with no token in the environment and passes; mutation re-adding env: GH_TOKEN fails 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: the e2e-tagged Docker tests locally (covered by CI's agent-runtime-e2e).

Unfixed items: 0.

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.

2 participants