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
-
Deploy substrate — Stand up the Kubernetes cluster, install ARC controller, deploy Attic and Bazel remote cache. This is Layer 1 of the platform architecture.
-
Create forge adapter — Install the GitHub App (or register GitLab/ Forgejo runners) at the chosen scope level. Configure webhook routing and token exchange.
-
Define scale sets — Create AutoScalingRunnerSets for each execution pool the tenant needs. Set resource limits, runner image, and warm-pool schedule.
-
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.
-
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.