Skip to content

fix(render): promote the secret keys the environment generates for a service - #1296

Merged
antoinetoussaint-byte merged 1 commit into
mainfrom
fix/render-declares-generated-service-secrets
Nov 4, 2026
Merged

antoinetoussaint-byte merged 1 commit into
mainfrom
fix/render-declares-generated-service-secrets

Conversation

@antoinetoussaint-byte

Copy link
Copy Markdown
Contributor

What breaks

codefly deploy gitops render <module> --env blue on obin-ai/platform-obin stops, from the postgres agent, with

postgres deployment requires a typed Kubernetes Secret reference for
CODEFLY__SERVICE_SECRET_CONFIGURATION__MODEL__STORE__POSTGRES__POSTGRES_USER

for every module, because the snapshot deploys model/store and the agent requires a typed reference for each of its four primitives.

Why

The restricted render promotes into a typed Secret reference every secret key the service's own configuration declares (promotableConfiguration), and that configuration is read from the service's own configurations/<profile>/ — in a composition, the module cache the CLI materialized and never writes to. obin-ai/module-model-gateway (and module-directory, per directory#25) ship no *.secret.env: by their decision, the run that composes the store generates it. A local run does (cmd/run/generated_secrets.go, before loading configuration); a hosted render has no analogue — codefly deploy secrets mints, in the cell's store, only the keys a render already emitted, and nothing in the render path read service-secrets.generate. So nothing declared the four keys, the render promoted nothing, and the agent refused. Modules that render (robin, records, …) do so only because they commit a key-names file in local/.

The fix (a fix at the owner, not a hack)

withEnvironmentDeclaredSecrets (pkg/orchestration/builder_deploy.go), on the restricted path, adds to a service's configuration every key a service generator naming the service declares that the configuration does not — as a secret with no value — and the existing promotion turns it into the same secretKeyRef a declared key gets. The key name reaches the manifest and its ExternalSecret; deploy secrets plans it as generate; no module tree is written or widened. A key the service declares keeps its declaration; a generator naming other services, or the workspace, adds nothing. The Generate field comment and docs/commands.md say so.

Reused: the environment's existing service-secrets.generate declaration (the same one cmd/run and deploy secrets read), promotableConfiguration and core's ConfigurationAsEnvironmentVariables for the key spelling, resources.Match for name matching. Deliberately not built: writing a generated file into the module cache (a composition never writes there), a second key-declaration source in the agent, or a committed throwaway secret file per module (refused by module-directory#25 and module-model-gateway 87b43cb).

Evidence

  • TestEnvironmentDeclaredSecretsPromoteToReferencesWhenTheServiceShipsNoFile does not compile on main (the seam does not exist) and passes here; go test ./pkg/orchestration/ ./pkg/environments/ ./pkg/deploysecrets/ green; golangci-lint 0 issues.
  • On platform-obin (blue), v0.1.234 and main 91ed65c refuse model/store; supplying the same four key names through the module tree instead clears the postgres deployment (and then fails on the changed module tree's digest), which isolates the missing declaration as the cause.
  • Not yet verified: a complete render with this build. Every run since platform-obin moved robin to dc892ada stops earlier, in the build phase, on robin/chat:0.1.36 is already published from other code (robin/chat's go.mod/go.sum moved without its version; the published label matches the 6030951b tree byte for byte) — a module-robin release matter, independent of this seam.

🤖 Generated with Claude Code

…service

A hosted render of a composition pinning obin-ai/module-model-gateway stopped,
from the postgres agent, with

  postgres deployment requires a typed Kubernetes Secret reference for
  CODEFLY__SERVICE_SECRET_CONFIGURATION__MODEL__STORE__POSTGRES__POSTGRES_USER

The render promotes into a typed Secret reference every secret key a service's
own configuration declares (promotableConfiguration), and that configuration
is read from the service's own directory, `configurations/<profile>/`. A
composition resolves a pinned module into a module cache it never writes to,
and module-model-gateway, by decision, ships no `*.secret.env` (the run that
composes the store generates it). A local run does generate it
(cmd/run/generated_secrets.go, before loading); a hosted render has no
analogue: `codefly deploy secrets` mints, in the cell's store, only the keys a
render already emitted. So nothing declared the four primitives, the render
promoted nothing, and the agent refused.

The environment's service-secrets.generate IS the declaration that those keys
exist for that service and that the cell's store holds them. The restricted
render now adds, to a service's configuration, every key a generator naming
the service declares that the configuration does not, as a secret with no
value, and promotes it with the rest: the key name reaches the manifest and
its ExternalSecret, `deploy secrets` mints the value, and no module tree is
written or widened. A key the service declares itself keeps its declaration;
a generator naming other services, or the workspace, adds nothing.

Evidence: the new test fails to compile on main (the seam does not exist) and
passes here. On obin-ai/platform-obin (blue), v0.1.234 and main refuse
model/store; the same four key names supplied through the module tree instead
clear the postgres deployment, which isolates the missing declaration as the
cause. A full render with this build is still owed: every run since the
workspace moved robin to dc892ada stops earlier, in the build phase, on
robin/chat:0.1.36 "already published from other code", which is a module-robin
release matter and not this seam.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@antoinetoussaint-byte
antoinetoussaint-byte added this pull request to the merge queue Nov 4, 2026
Merged via the queue into main with commit 3d259c6 Nov 4, 2026
18 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant