Skip to main content

Module reload

Module reload 

Source
Expand description

Signal-driven hot reload of the catalog/policy generation (basil-y3e).

reload_generation is the single, fail-closed reload engine shared by the SIGHUP handler and (later) the permission-scoped gRPC admin-reload follow-on (basil-atq). It re-reads the catalog/policy from the same on-disk paths the broker was started with (never from the wire), runs the full startup/check validation on the candidate, enforces that only reloadable dimensions changed, and (only on success) atomically swaps in a new Generation with a bumped id. On any failure it does not swap: the previous generation keeps serving and the rejection is returned to the caller (the SIGHUP handler audits it). It never panics or exits.

§Reloadable vs restart-only

The reloadable surface is the content the Pdp and the audit trail consume: the entire policy (rules / roles / name + membership tables) and the per-key authorization attributes: writable, labels, description, missing. The routing shape is restart-only: the BackendManager and the live backend instances were built from the sealed bundle at startup, so adding/removing a backend, or changing any key’s class/backend/path/engine/key_type/ public_path, needs a re-unlock and is rejected here (the Nix module routes such edits to ExecStart, i.e. a restart). [routing_shape] captures exactly the dimensions baked into the manager; a candidate whose shape differs from the running generation is rejected with ReloadError::RoutingShapeChanged.

§Non-mutating

Reload is non-mutating: it validates (and the loader’s guardrails run) but it performs no backend I/O and no CSPRNG side effects: it never reconciles or generates missing material on the signal path. A candidate that adds a missing:error key whose material is absent is accepted (its routing shape is unchanged by construction, since a new key would change the shape and be rejected anyway); a missing:error key that already exists in both generations simply keeps failing closed at use if its material is absent. The routing-shape guard means a reload can only ever change a pre-existing key’s authorization attributes, never introduce a new key/backend that would demand fresh material, so there is no missing-material decision to make on the signal path beyond what startup reconcile already settled.

Structs§

ReloadInputs
The on-disk inputs a reload_generation re-reads: the configured catalog and policy JSON paths the broker was started with.
ReloadOutcome
The result of a successful reload_generation.

Enums§

ReloadError
Why a reload_generation was rejected. On any of these the previous generation keeps serving (fail closed); none of them swap.

Functions§

check_reload
Validate the candidate catalog/policy without swapping (the --check dry-run, basil-atq).
reload_generation
Re-read the configured catalog/policy, validate the candidate, enforce that only reloadable dimensions changed, and on success atomically swap in a new Generation with a bumped id.