sc deploy cannot build a service whose build needs a secret #46

Open
opened 2026-08-26 12:29:34 +00:00 by geusebio · 0 comments
Owner

What's missing

sc deploy has no way to carry a build-time secret (e.g. GIT_AUTH_TOKEN for a
private git build context or context authenticated composer/npm install) from
a compose file's build.secrets: through to the platform. Confirmed against a
real service (minf's sw-front/sw-core, git.grey.ooo/Shapeways):

  • App\Service\Compose\ComposeParser::build() on the server side (Someones.Computer)
    keeps only dockerfile and additional_contexts from a service's build: block —
    args and secrets are dropped before the manifest is even built. Documented in
    docs/agent-cli.md, closed out of #704 as a real gap ("build-time args,
    dockerfile_inline and secrets are not supported anywhere in the pipeline
    today... a feature request rather than a doc fix").
  • The sc CLI (this repo) has no corresponding client-side support either —
    nothing reads build.secrets, packages secret material, or sends it in the
    bundle manifest.

Impact

Any service whose Dockerfile needs a secret to build — a private git context, an
authenticated composer/npm install to dodge GitHub's unauthenticated rate limit —
cannot be built by sc deploy at all today. The only workaround is building the
image locally (where the secret is available) and letting sc forward the
already-built image instead of building it — works, but means sc deploy isn't
actually driving the build for those services, which defeats a chunk of the point
of sc deploy for exactly the kind of private-repo service most teams have.

Scope (rough — needs real design, not a docs tweak)

  • Wire contract: a way for the manifest to declare contexts[].secrets[] (name +
    how the client should resolve its value — an env var, a file, a credential
    helper) without ever writing the value to disk unencrypted or logging it.
  • sc (client): read build.secrets: from the compose file, resolve each
    named secret the same way docker compose build does (env var interpolation,
    .env, etc.), and send it alongside the bundle — analogous to how contexts are
    packaged and uploaded today, but for a value that must never land in the
    uploaded tarball itself or in any log.
  • Someones.Computer (server): ComposeParser needs to keep build.secrets,
    BundleContext/BundleManifest need a field for it, and
    App\Service\Build\BuildKitBuilder needs to mount each one as a BuildKit
    --secret for the build (the same mechanism it already uses for its own
    GIT_AUTH_TOKEN when cloning a primary git context — this would extend that
    to tenant-supplied secrets).
  • Security surface worth designing carefully: a build secret is real tenant
    credential material crossing the trust boundary into the platform's build
    worker. It should probably be short-lived, scoped to the one build, and never
    persisted past that build's lifetime — closer to how the registry push token
    is handled than to how a Variable (/cli/applications/{slug}/variables) is.

Where this came from

Hit while getting minf (git.grey.ooo/Shapeways/minf) running on
someones.computer service-by-service: sw-front's only build context is a
private Forgejo repo (needs FORGEJO_AUTH_TOKEN just to clone), and sw-core's
composer install needs GIT_AUTH_TOKEN to avoid GitHub's rate limit on ~78
concurrent dist fetches (minf's own compose.yml flags this exact problem as
unresolved for its own local builds). Both are cross-built locally and forwarded
as a workaround for now; this issue is what would let sc deploy build them
directly instead.

## What's missing `sc deploy` has no way to carry a build-time secret (e.g. `GIT_AUTH_TOKEN` for a private git build context or context authenticated composer/npm install) from a compose file's `build.secrets:` through to the platform. Confirmed against a real service (minf's `sw-front`/`sw-core`, git.grey.ooo/Shapeways): - `App\Service\Compose\ComposeParser::build()` on the server side (Someones.Computer) keeps only `dockerfile` and `additional_contexts` from a service's `build:` block — `args` and `secrets` are dropped before the manifest is even built. Documented in docs/agent-cli.md, closed out of #704 as a real gap ("build-time `args`, `dockerfile_inline` and `secrets` are not supported anywhere in the pipeline today... a feature request rather than a doc fix"). - The `sc` CLI (this repo) has no corresponding client-side support either — nothing reads `build.secrets`, packages secret material, or sends it in the bundle manifest. ## Impact Any service whose Dockerfile needs a secret to build — a private git context, an authenticated composer/npm install to dodge GitHub's unauthenticated rate limit — cannot be built by `sc deploy` at all today. The only workaround is building the image locally (where the secret is available) and letting `sc` forward the already-built image instead of building it — works, but means `sc deploy` isn't actually driving the build for those services, which defeats a chunk of the point of `sc deploy` for exactly the kind of private-repo service most teams have. ## Scope (rough — needs real design, not a docs tweak) - Wire contract: a way for the manifest to declare `contexts[].secrets[]` (name + how the client should resolve its value — an env var, a file, a credential helper) without ever writing the value to disk unencrypted or logging it. - `sc` (client): read `build.secrets:` from the compose file, resolve each named secret the same way `docker compose build` does (env var interpolation, `.env`, etc.), and send it alongside the bundle — analogous to how contexts are packaged and uploaded today, but for a value that must never land in the uploaded tarball itself or in any log. - Someones.Computer (server): `ComposeParser` needs to keep `build.secrets`, `BundleContext`/`BundleManifest` need a field for it, and `App\Service\Build\BuildKitBuilder` needs to mount each one as a BuildKit `--secret` for the build (the same mechanism it already uses for its own `GIT_AUTH_TOKEN` when cloning a *primary* git context — this would extend that to tenant-supplied secrets). - Security surface worth designing carefully: a build secret is real tenant credential material crossing the trust boundary into the platform's build worker. It should probably be short-lived, scoped to the one build, and never persisted past that build's lifetime — closer to how the registry push token is handled than to how a `Variable` (`/cli/applications/{slug}/variables`) is. ## Where this came from Hit while getting minf (git.grey.ooo/Shapeways/minf) running on someones.computer service-by-service: `sw-front`'s only build context is a private Forgejo repo (needs `FORGEJO_AUTH_TOKEN` just to clone), and `sw-core`'s composer install needs `GIT_AUTH_TOKEN` to avoid GitHub's rate limit on ~78 concurrent dist fetches (minf's own compose.yml flags this exact problem as unresolved for its own local builds). Both are cross-built locally and forwarded as a workaround for now; this issue is what would let `sc deploy` build them directly instead.
Sign in to join this conversation.
No labels
in-progress
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Grey.ooo/someones.computer_agent#46
No description provided.