Cache Exposure And Package Canaries

Cache Exposure And Package Canaries

This page defines the current enterprise/package onboarding contract for Bazel cache use. It is deliberately narrower than Bazel remote execution.

Supported Exposure Model

Current supported Bazel cache exposure is:

  • self-hosted CI runners receive BAZEL_REMOTE_CACHE through the runner bootstrap environment
  • internal developer machines attach through a product-owned consumer profile that carries an operator-provided real endpoint, then just cache-contract-strict must pass
  • pull requests use read-only remote-cache behavior
  • trusted default-branch pushes may upload action results when the repo owner explicitly opts in

Current unsupported exposure:

  • no stable public Bazel cache hostname is promised
  • no arbitrary internet consumer cache endpoint is promised
  • no default Bazel remote execution or consumer-facing --remote_executor path is selected

This is enough for enterprise package canaries that run on enrolled capability-class lanes. It is not enough to advertise public Bazel cache service access. The explicit GF REAPI proof lane is separate from this cache exposure model.

Developer-Machine Policy

Policy decision: product-owned profile, operator-owned endpoint authority.

The current supported developer-machine Bazel path is a consumer profile rendered by GloriousFlywheel tooling from a real endpoint supplied by an operator. Use just flywheel-consumer-env shared-cache-backed --cache-endpoint "$BAZEL_REMOTE_CACHE" --write .env.flywheel.local to materialize a non-secret local profile after endpoint authority is available, then source that profile or load it through direnv before running the strict contract.

The current proven local route is still a bounded Honey svc/bazel-cache port-forward. That route is only a proof lane: it must use the port-forward-cache profile or set GF_BAZEL_LOCAL_PROOF=port-forward. A future tailnet-routable endpoint or authenticated public hostname must be tracked as a separate infrastructure and auth decision before it is advertised as default product behavior.

Developer-machine attachment rules:

  • just info reports compatibility-local-only until BAZEL_REMOTE_CACHE is explicitly set
  • just cache-contract-strict must pass before cache-backed local Bazel work counts as substrate-attached
  • localhost Bazel endpoints fail unless GF_BAZEL_LOCAL_PROOF=port-forward
  • just developer-cache-attachment-proof //:deployment_bundle false is the bounded proof command
  • read-only remote-cache behavior is the safe baseline
  • cache writes require an explicit trusted-operator opt-in

The guard for this policy is:

just bazel-cache-exposure-policy-check

Package Canary Workflow

Use the public example:

examples/github/package-cache-canary.yml

Required properties:

  • runs-on uses a shared capability class such as your-org-nix
  • the workflow fails early when BAZEL_REMOTE_CACHE is absent
  • the workflow verifies GF_BAZEL_SUBSTRATE_MODE=shared-cache-backed
  • the workflow prints only attachment state, not private endpoint values
  • pull requests leave GF_BAZEL_REMOTE_UPLOAD=false
  • trusted default-branch pushes may set GF_BAZEL_REMOTE_UPLOAD=true

The copied consumer wrapper is:

examples/bazel/gloriousflywheel-bazel.sh

It passes --remote_cache="$BAZEL_REMOTE_CACHE" explicitly and defaults to --remote_upload_local_results=false unless GF_BAZEL_REMOTE_UPLOAD is true. That makes package pull requests safe to run against a shared cache without turning untrusted PRs into cache writers.

The same wrapper can pass external input authority into consumer repositories: BAZEL_REPOSITORY_CACHE becomes --repository_cache, BAZEL_DISTDIR becomes repeated --distdir, GF_BAZEL_REPOSITORY_DISABLE_DOWNLOAD=true becomes --repository_disable_download, and GF_BAZEL_INJECT_REPOSITORIES becomes repeated --inject_repository for verified local generated repositories.

Use GF_BAZEL_REPOSITORY_DISABLE_DOWNLOAD=true only in an explicit repository-cache/distdir proof lane after the expected inputs are already pre-populated. It is a completeness check for the external-input authority path, not a default developer setting.

Nix Cache Boundary

ATTIC_PUBLIC_KEY is public trust material for Nix substituter attachment. ATTIC_TOKEN is credential material for private reads or trusted writes.

Package canaries should pass ATTIC_PUBLIC_KEY when available. They should only pass ATTIC_TOKEN when private reads or explicitly trusted writes are required. Pull requests should remain read-only. Default-branch publication must be token-gated, and broad repo proof workflow writes remain behind the RustFS/backend publication guardrail rather than becoming ordinary canary behavior.

External Repository Fetches

Bazel remote cache covers action outputs. It does not make external repository archives cache-authoritative.

Run:

just bazel-external-fetch-authority

Current source-truth may still be upstream-with-retries unless an operator provides BAZEL_REPOSITORY_CACHE or BAZEL_DISTDIR. Treat that as separate from remote action-cache attachment and separate from remote execution.

The repeatable offline guard is:

just bazel-external-fetch-authority-self-test

Use non-strict authority reporting for ordinary package canaries until a repository-cache or distdir authority is configured. Use strict mode only when the canary is meant to prove external archive fetch authority in addition to remote action-cache attachment.

For pinned public source inputs, such as a generated WAS-110 public-community vendor repository, materialize and verify the local repository before invoking Bazel, then pass it with an absolute-path entry such as:

GF_BAZEL_INJECT_REPOSITORIES=was110_vendor_blobs=/absolute/vendor/repo

This is a consumer wiring contract. It does not publish the mirror, bless a mutable upstream URL, or make private blobs eligible for public cache/CAS. The explicit RBE proof wrapper accepts the same handoff when a canary is meant to prove both input authority and remote action execution.

Promotion Criteria

Count a package canary as attached when:

  • the workflow runs on an enrolled self-hosted capability lane
  • BAZEL_REMOTE_CACHE is present
  • GF_BAZEL_SUBSTRATE_MODE is shared-cache-backed
  • the Bazel wrapper builds or tests a small package target
  • logs show cache attachment and upload mode without printing the endpoint

Do not count it as RBE. The current capability is shared cache acceleration with local Bazel execution on the runner.

GloriousFlywheel