Gate dependency download caches and credentials
Dependency-adapter manifests (homeboy-extension/dependency-adapter-manifest/v1)
may opt a package manager into a shared download cache:
{
"package_managers": [
{
"id": "example",
"download_cache": { "env": "EXAMPLE_DOWNLOAD_CACHE" }
}
]
}The snippet shows only the new fields; existing selection and command declarations
are still required. env must be an environment-variable name. The manager ID
must be a single directory name containing ASCII letters, digits, dots, hyphens,
or underscores, and cannot be . or ...
During dependency hydration with gate HOME or XDG isolation enabled, Homeboy
sets this variable to <homeboy data>/controller-state/dependency-download-cache/<id>.
The runner creates private, runner-owned directories, rejects symlink roots and
directories writable by others, and reuses the same directory across gates.
Package managers remain responsible for concurrent cache access. HOME remains
isolated; this mapping does not expose credentials or the operator’s home cache.
An explicit --gate-env or --gate-env-from value for the declared variable wins.
Gate-setup outcomes record the effective mapping in download_cache, including
on install failure. Without isolation or without a declaration, behavior is
unchanged. Only hydration subprocesses receive the automatic mapping; it does
not modify the controller’s process environment.
The separately maintained homeboy-extensions repository needs a follow-up:
add "download_cache": { "env": "COMPOSER_CACHE_DIR" } to the composer
package_managers entry, and "download_cache": { "env": "npm_config_cache" }
to the npm entry. No package-manager-specific mapping is built into Homeboy.
Declared download credentials
A package-manager entry may also declare:
"download_auth": { "env": "EXAMPLE_DOWNLOAD_AUTH", "file": ".config/example/auth.json", "as": "content" }Like download_cache, this applies only during isolated gate dependency
hydration (including reusable-state assessment). The source resolves against
the runner’s real HOME, before subprocess HOME/XDG isolation, not the gate HOME.
as: content injects UTF-8 file contents; as: path injects the absolute source
path. Homeboy never copies the file into the gate HOME. Path mode gives the tool
access to the original file, not a read-only copy; tools must not mutate it.
env must be an environment-variable name. file must be a nonempty relative
path with only normal components (no absolute paths, .., or symlinks), naming
a regular file owned by the runner user. Invalid or unreadable sources fail
closed with a generic error, without file contents. A missing file is not an
error: hydration proceeds without the automatic mapping and records
download_auth: { "EXAMPLE_DOWNLOAD_AUTH": "unavailable" }.
Explicit --gate-env / --gate-env-from values win, even if the declared file
is missing. Evidence records only the env name and absolute source path, or
operator_override. Credential values are registered with the hydration’s
secret-aware redaction policy: command stdout/stderr, structured progress, and
serialized outcome strings are scrubbed. File contents (including JSON string
values) are treated as secrets in both modes. Operator overrides are also secret.
No process-global environment or redaction state is modified.
homeboy-extensions follow-up
Add these exact fields to the respective package_managers entries (alongside
the cache declarations above):
- composer:
"download_auth": { "env": "COMPOSER_AUTH", "file": ".config/composer/auth.json", "as": "content" } - npm:
"download_auth": { "env": "NPM_CONFIG_USERCONFIG", "file": ".npmrc", "as": "path" }
The npm mapping is appropriate when the runner’s .npmrc carries download
authentication. It exposes the whole declared configuration to npm; use only a
runner-managed file intended for dependency setup.
Related: #17455, #17347 and #17261.