Implementation Overlay Enrollment

Implementation Overlay Enrollment

Enrollment is the owner/auth path that makes a repo or owner scope able to consume the shared GloriousFlywheel runner and cache substrate. It is not runner taxonomy.

The enrollment contract exists so an operator can prove:

  • the overlay can read the reusable GloriousFlywheel core contract
  • the owner GitHub App credentials exist in the ARC namespaces
  • the desired ARC runner scale sets are registered
  • workflows can reach shared tinyland-* capability labels
  • remaining blockers are visible as control-plane debt, not hidden behind repo-specific labels

Read-Only Preflight

Run the preflight from either the core checkout or the overlay checkout before planning or applying ARC state.

From GloriousFlywheel:

just implementation-overlay-preflight \
  ../jesssullivan-infra \
  tofu/stacks/arc-runners/jesssullivan.tfvars \
  Jesssullivan/jesssullivan-infra

From an implementation overlay:

export GF_CORE_PATH=../GloriousFlywheel-infra-overlays
just enrollment-preflight

Use strict mode when a gate should fail on blockers:

just enrollment-preflight-strict

When a stable GloriousFlywheel core commit or release has been selected for an overlay promotion, assert it explicitly:

GF_EXPECTED_CORE_REF=main just enrollment-preflight-strict

From the core checkout, pass the same assertion through the generic wrapper:

just implementation-overlay-preflight \
  ../tinyland-infra \
  tofu/stacks/arc-runners/tinyland.tfvars \
  tinyland-inc/tinyland-infra \
  --expected-core-ref main \
  --strict

The preflight is read-only. It checks GitHub Actions secret metadata, recent workflow status, core-pin consistency, Kubernetes secret presence, and live AutoscalingRunnerSet registration. It does not read secret values, create secrets, or apply OpenTofu state.

The output ends with concrete next actions. Treat those actions as the operator-facing enrollment queue for the overlay; do not infer new runner taxonomy from a failed or queued workflow.

Core Pin Contract

Implementation overlays pin the reusable GloriousFlywheel core in two places:

  • config/organization.yaml under core.pinned_commit
  • MODULE.bazel through the matching git_override(... commit = "...")

Those pins must agree before the overlay can be counted as current authority. If GF_EXPECTED_CORE_REF or --expected-core-ref is set, both pins must also resolve to that selected core commit. This prevents a green overlay plan from silently mixing one Bzlmod dependency with a different operator-facing authority note.

Core pin drift is a preflight blocker, not a reason to create new labels or move live ARC state. Refresh both files together, rerun strict preflight, then review plan/apply output.

Interpreting Results

Expected early Tinyland overlay shape:

  • GF_CORE_DEPLOY_KEY is the preferred core-read path; GF_CORE_READ_TOKEN remains only a compatibility fallback
  • github-app-secret exists in arc-systems and arc-runners: ok
  • tinyland-* runner sets already registered: ok
  • recent validation should not be queued or failing after the core-read credential is installed

Current Tinyland status after the April 28 pin refresh: strict preflight passes with 0 blockers / 0 warnings against selected core 637b7167c400a842cdc7af0709b2251c0542a48a.

Current Jess personal-boundary overlay shape after the April 26 registration repair:

  • GF_CORE_DEPLOY_KEY is the preferred core-read path; GF_CORE_READ_TOKEN remains only a compatibility fallback
  • github-app-secret-jesssullivan should exist in the ARC namespaces before the overlay is counted as registered
  • jesssullivan-* runner scale sets are owner registration identities, not workflow labels
  • shared workflow labels such as tinyland-nix and tinyland-nix-heavy remain the correct targets
  • remaining work is capacity policy and compatibility-lane retirement; the selected live state rehome is complete

Current Jess status after the April 29 state rehome and apply: strict preflight passes with 0 blockers and 1 expected warning for the private personal-boundary repository registration anchor. The overlay enrollment pins still point at selected core 637b7167c400a842cdc7af0709b2251c0542a48a, while the Jess ARC deploy workflow pins the state-rehome authority commit defff7fb7d1f3457c5270ce2e57ac6077e797b1c.

Historical bootstrap symptoms that should not be reintroduced as current truth:

  • neither GF_CORE_DEPLOY_KEY nor GF_CORE_READ_TOKEN configured: blocker
  • repo-scoped github_config_url: warning, allowed only as private implementation-overlay ARC registration plumbing
  • github-app-secret-jesssullivan missing in ARC namespaces: blocker
  • jesssullivan-* runner scale sets missing: blocker
  • queued validation on tinyland-nix: historical blocker until Jess-bound ARC registration existed
  • split core.pinned_commit and MODULE.bazel commits: blocker until both pins are refreshed to the selected core commit

Do not treat a queued personal-boundary workflow as evidence that a new personal-* or repo-specific label is needed. It means the owner registration path is incomplete.

Repo-isolated organization overlays follow the same rule. A repo URL such as https://github.com/tinyland-inc/tinyland.dev may be the private ARC registration anchor when a repository needs fork-safe capacity isolated from the organization pool, but workflows still use shared labels such as tinyland-nix and tinyland-nix-heavy.

Credential Sequence

  1. Install or bind the owner GitHub App with the required Actions runner permissions. Repository-scoped registration needs the repository administration permission; organization-scoped registration uses the organization self-hosted-runner permission.

  2. Create the owner ARC GitHub App secret in both ARC namespaces through the overlay Just wrapper, not ad hoc kubectl:

    export GITHUB_APP_ID=<APP_ID>
    export GITHUB_APP_INSTALLATION_ID=<INSTALLATION_ID>
    export GITHUB_APP_PRIVATE_KEY_PATH=<PATH_TO_PRIVATE_KEY>
    
    just arc-app-secret-dry-run
    just arc-app-secret-apply

    The wrapper reads the secret name and cluster context from config/organization.yaml, then writes the same ARC GitHub App secret into arc-systems and arc-runners. From the core repo, the equivalent generic entrypoint is:

    just implementation-overlay-arc-secret ../jesssullivan-infra --dry-run
    just implementation-overlay-arc-secret ../jesssullivan-infra --apply
  3. Configure a core-read credential for the overlay repo. Preferred path: create a read-only deploy key on tinyland-inc/GloriousFlywheel and store its private key as the overlay repository secret GF_CORE_DEPLOY_KEY. Compatibility path: store a least-privilege read token as GF_CORE_READ_TOKEN. Do not use a broad personal token as the default path.

  4. Configure ATTIC_TOKEN only if trusted overlay push validation should publish warmed Nix outputs into the shared Attic cache. Pull-request validation should remain read-only and use ATTIC_PUBLIC_KEY for substituter attachment without cache publication.

  5. Run just enrollment-preflight until credential and registration blockers are gone.

  6. Run just arc-plan from the overlay and review the plan with just arc-plan-show.

  7. For overlays adopting existing releases, apply only after the state rehome or explicit teardown decision is recorded. Overlay just arc-apply runs a destroy guard by default; an intentional destructive maintenance window must set ALLOW_ARC_DESTROY=1.

  8. Prove a default-branch workflow reaches the shared label before counting the owner as enrolled authority.

Owner-Distinct Registration Names

Multiple owner overlays may target the same physical Honey cluster. Their internal Helm release names and ARC runnerScaleSetName values must be unique so Kubernetes resources and ARC registration identities do not collide.

That internal uniqueness does not change workflow-facing labels. A secondary overlay can use:

nix_runner_name           = "jesssullivan-nix"
nix_runner_scale_set_name = "jesssullivan-nix"

extra_runner_sets = {
  tinyland-nix-heavy-compute-expansion = {
    github_config_url     = "https://github.com/Jesssullivan"
    runner_label          = "tinyland-nix-heavy"
    runner_scale_set_name = "tinyland-nix-heavy-compute-expansion"
  }
}

Workflows should still use:

runs-on: tinyland-nix-heavy

Capacity limits remain per owner-specific ARC scale set. They are not yet a global concurrency contract for the shared label. For example, tinyland-nix-heavy and tinyland-nix-heavy-compute-expansion can each have maxRunners = 1; if both receive jobs at the same time, Kubernetes scheduling is the current global backpressure on sting.

Hard No

  • Do not create repo-specific runner labels to make enrollment appear green.
  • Do not put personal-account anchors in the core product stack.
  • Do not put repo-scoped organization anchors in the core product stack.
  • Do not apply a destructive core ARC plan before state rehome or teardown is explicitly decided.
  • Do not use a broad personal token as the normal core-read credential.
  • Do not count queued workflows as enrolled proof.

GloriousFlywheel