Enrollment Model

Enrollment Model

The enrollment model defines how repositories, teams, and organizations join the GloriousFlywheel runner and cache platform. It replaces the earlier flattened model that relied on runner labels and overlay language with a structured four-dimension approach.

An enrollment is fully described by its position in four dimensions: forge scope, operator tenant, execution pool, and cache/state plane.

Dimension 1: Forge Scope

Each forge defines its own hierarchy of scopes at which runners can be registered. The forge adapter (Layer 2 of the platform architecture) maps these scopes into ARC scale sets or GitLab runner registrations.

Forge Scope Levels
GitHub Repository, Organization, Enterprise
GitLab Project, Group, Instance
Forgejo Repository, Organization, Account

Organization-scoped registration is the default for GitHub. It installs a single GitHub App and makes all scale sets available to every repository in the org without per-repo configuration.

Dimension 2: Operator Tenant

The operator tenant identifies who owns and pays for the runner capacity. Tenant boundaries control resource quotas, secret isolation, and billing attribution.

Tenant Description
Team Single team within an org, scoped namespace
Organization Full org enrollment, shared runner pool
Enterprise Multiple orgs under one enterprise billing account
Managed Customer External customer whose runners are operator-managed

Each tenant maps to one or more Kubernetes namespaces. Secrets, RBAC, and network policies are scoped to the tenant namespace boundary.

Dimension 3: Execution Pool

Execution pools define the resource profile and intended workload class for a set of runners. Each pool corresponds to an ARC AutoScalingRunnerSet (or GitLab runner deployment) with specific resource limits.

Pool CPU / Mem Use Case
docker 2 CPU / 4Gi General CI
nix 4 CPU / 8Gi Nix builds
nix-heavy 8 CPU / 16Gi Rust + Nix heavy compilation
gpu TBD ML training
kvm TBD VM-based testing

Workflows select a pool via the runs-on label (GitHub) or tags field (GitLab/Forgejo). The label format is <pool> for the default tenant or <tenant>-<pool> for multi-tenant disambiguation.

Dimension 4: Cache and State Plane

Each enrolled entity participates in one or more cache and state planes. Multi-tenancy determines whether data is shared or isolated across tenant boundaries.

Plane Isolation Multi-Tenant Notes
Attic Per-cache view Yes Global dedup across tenants
Bazel remote cache Per-namespace Yes Namespace-scoped cache entries
State backend Per-stack No Operator-owned, not shared

Attic uses cache views to give each tenant a logical partition while deduplicating store paths at the storage layer. Bazel remote cache isolates by Kubernetes namespace. The OpenTofu state backend is always operator-owned and never shared across tenants.

Enrollment Flow

  1. Deploy substrate — Stand up the Kubernetes cluster, install ARC controller, deploy Attic and Bazel remote cache. This is Layer 1 of the platform architecture.

  2. Create forge adapter — Install the GitHub App (or register GitLab/ Forgejo runners) at the chosen scope level. Configure webhook routing and token exchange.

  3. Define scale sets — Create AutoScalingRunnerSets for each execution pool the tenant needs. Set resource limits, runner image, and warm-pool schedule.

  4. Configure cache plane — Provision an Attic cache view and Bazel remote cache namespace for the tenant. Distribute cache tokens to the runner pods via Kubernetes secrets.

  5. Repos use labels — Repository workflows reference the pool label in runs-on. No per-repo runner registration is needed when the forge adapter is scoped at org level or above.

Cross-Org Enrollment

A single GloriousFlywheel cluster can serve multiple GitHub organizations (or GitLab groups, Forgejo accounts) simultaneously. The mechanism:

  • GitHub App per org: Each org installs its own instance of the GloriousFlywheel GitHub App. The ARC controller routes jobs to the correct scale set based on the installation ID.

  • Separate or shared scale sets: Orgs can share execution pools (cost efficiency) or run dedicated scale sets (isolation). The choice is a tenant-level decision configured in the OpenTofu stack.

  • Attic tenant views: Each org gets its own Attic cache view. Store paths are deduplicated globally, so cross-org builds of the same derivation hit cache without leaking private paths.

  • Bazel namespaces: Each org’s Bazel remote cache lives in its own Kubernetes namespace, enforcing hard isolation at the storage layer.

Current Model

The production deployment uses two enrollment positions as proof of the cross-org model:

  • tinyland-inc: Organization-scoped enrollment with org-wide scale sets (docker, nix, nix-heavy). This is the primary tenant and dogfood target.

  • cmux (under JessSullivan): Cross-org canary enrolled at repository scope. The infrastructure path exists to validate GitHub App installation, cache view isolation, and label routing across org boundaries, but the public enrollment-check workflow is still opt-in rather than a continuously exercised proof contract.

This two-position setup exercises the full enrollment model without requiring enterprise-tier GitHub features.

GloriousFlywheel