Skip to main content

Module plan

Module plan 

Source
Expand description

The plan gate: the front door’s one question before the bytes.

authorise_service (see crate::server::Dispatch) is the ONE choke point SSH and smart-HTTP share, and it is where a push is refused before any pack bytes, which is the rule that makes this a front-door check and not a gunnar-policy gate (a gate runs after the pack is read; that is a 1 GB upload accepted and then refused). This crate does not know what a plan is, what monetize is, or how a fact is signed; it asks the PlanGates the server hands in and does what the verdict says.

§Two implementations, one chain (decided 2026-09-04)

two implementations: 1) the free lunch, basically checking disk has size before a new repo is created; 2) the monetize-bound one

  1. crate::headroom::DiskHeadroomGate — always compiled, no monetize dependency. Refuses a push and a Repos.Create when the store root’s filesystem would drop under a floor. The community binary has this one link.
  2. gunnar-server::entitlement::EntitlementSlot (metered only) — the ladder: Suspended, Retention, the pack quota. The decision is monetize_embed::EntitlementCache’s, one atomic load and a map lookup.

crate::Control holds them as a chain, asked in order, disk first; the first Refuse wins and is the line the client is told. A box that is full is told it is full, not that its plan lapsed — the disk is the fact nobody can pay their way past. A gate that always answers Allow is invisible to a request that only pushes valid things (measured, not asserted), which is why every gate’s refusal has a test that sets the condition and watches the push die before a byte.

§What is asked, and when

requestaskedmay be refused
git-receive-pack, LFS uploadPlanAction::Write, then PlanGate::pack_quota and PlanGate::pack_ceilingSuspended, Retention, over caps["pack_bytes"] — before the bytes, and (receive-pack only) DURING them
anonymous git-upload-pack / LFS downloadPlanAction::AnonymousReadSuspended, Retention
the owner’s, or any authenticated reader’s, git-upload-packnothingnever — data is never held hostage

Asked only for a request the grant check already admitted, so a refusal here never tells a stranger anything about a repository they could not already see; and asked AFTER the standby freeze, so a standby stays a standby whatever the plan says.

§The one answer that is not a verdict

PlanGate::pack_ceiling is the exception to “the front door decides before the bytes”, and it is the exception because it has to be: a pack header carries an object count, not a byte count, so the size of a push is not knowable here. The gate therefore answers with a NUMBER rather than a verdict, the number rides on crate::ServiceRequest::pack_ceiling, and the refusal happens in gunnar-wire’s receive loop the moment the count passes it. That is still the front door’s decision — it is just carried to where the bytes are.

Structs§

PackCeiling
A byte ceiling for one push, and the line the client is told past it.

Enums§

PlanAction
What the request is about to do to the namespace’s data.
PlanVerdict
The gate’s answer.

Traits§

PlanGate
One link of the front door’s chain: “may this namespace do this, right now”.