Skip to main content

Crate didbot_policy

Crate didbot_policy 

Source
Expand description

The policy machinery: what a policy declares, the tree that indexes it, and deny-only evaluation over the ordered list the tree produces.

This is the core plan/policy.md describes — not a policy language, not an evaluator, not I/O. Two sibling crates use it: didbot-policy-regex is a deterministic in-process Evaluator, and didbot-pds’s write path drives evaluate() per write, outside its store lock, and turns a Verdict::Freeze into the queue-draining behaviour plan/policy.md describes under “Outcomes” — this crate produces the verdict and stops there.

§What is here, and why

§What is deliberately not here

No I/O, no async, anywhere in this crate. Evaluators do the work — some of them out of process, some of them with a model or a network resolution in the loop — and this crate stays the thing that is testable without a runtime and cheap to reason about under a deadline. See Evaluator’s doc comment for what that implies for anyone implementing one.

No storage of policies, no polling, no wrapper metadata (source, format version, which PDS a record applies to). plan/policy.md calls that “a policy is not its wrapper” and leaves the wrapper’s shape and the lexicon that carries it unsettled; this crate only consumes the PolicyDeclaration a wrapper resolves to, never the wrapper itself.

No position on what a delete means. Diff makes exact every path whose value differs between before and after, absence included as a value, and WriteAction says which kind of write it was. A policy can declare it applies only to deletes; an evaluator decides what a delete means for its own rules.

Modules§

client_id 🔒
An OAuth client’s identifier, in the one spelling a policy matches.
evaluate 🔒
Ordered evaluation with deny-only semantics, made structural rather than conventional.
index 🔒
The applicability index: the tree that turns a subject into an ordered list of candidate policies.
json 🔒
JSON text that does not depend on the order a client wrote its keys in.
language 🔒
The language a policy’s predicate is written in — an open union, the same shape bot.did.registration’s actor union already uses and the same shape this crate gave SubjectKind: Known plus Unknown.
outcome 🔒
The evaluator contract: what a policy decides, how stale its view may be, and the three channels an evaluator is asked to answer on.
policy 🔒
What a policy declares about itself, statically — the data the applicability index is built from.
subject 🔒
What a policy is asked about.

Structs§

ActionSet
Which WriteActions a write-shaped applicability declaration covers.
Change
One field’s value before and after a write, at a dotted path such as "displayName" or "profile.bio".
ClientId
An OAuth client_id, known to be in canonical form.
CompiledId
A compiled predicate, as an evaluator itself names it.
DeploymentAttributes
Facts about this deployment a policy may reference, independent of the account or the write — a different kind of fact from SubjectAttributes, which is why it is its own type rather than a field folded into that one. An evaluator asking for the PDS’s own DID or hostname is asking a different question than one asking about the account, and naming them separately keeps that visible at the call site — for a rule like “deny a handle that is not under this deployment’s zone”.
Diff
What changed in a write, as the applicability index’s key.
EvaluatorId
An evaluator, registered once and referenced by any number of policies.
KindSet
Which account kinds a write-shaped applicability declaration covers.
Lookup
What a policy’s declared lookup found in somebody else’s repository.
Observed
One evaluator’s account of a single policy’s attempt and outcome, on its declared observation surface.
PolicyDeclaration
One policy: its applicability, its observation surface, its staleness mode, its predicate, and its own revision.
PolicyId
A policy, identified by its position in a PolicyTree.
PolicyTree
The built applicability index: every registered policy’s predicate, and the decision and observation trees to route a subject through.
PolicyTreeBuilder
Builds a PolicyTree from a set of evaluators and the policies that use them.
Revision
A policy record’s own revision, for detecting a stale observation.
SubjectAttributes
Attributes about the writing account a policy may need beyond its DID, explicit and extensible rather than a bag.
Universal
Facts that do not belong to the account or the write, but that a stateless predicate is still allowed to reference — grouped into one field per Subject variant rather than left flat, since the field list otherwise grows by one every time a new universal fact is added.

Enums§

AccountKind
One of the four account kinds this build recognizes.
Applicability
What a policy statically applies to — the data the tree indexes on.
Asked
How a create asked for its account’s name.
ClientIdError
Why a string is not a ClientId.
CompileOutcome
What Evaluator::compile decided about one predicate document.
EvalError
Why an evaluator could not produce an Outcome.
Found
What reading one declared lookup established.
KnownLanguage
The evaluator languages this workspace names. Naming a member here is naming a sibling crate that implements Evaluator for it — a decision for whoever maintains this workspace, not something a policy record can request into existence — but naming one ahead of the crate that implements it is exactly what an open union is for: it makes that crate’s later arrival an addition to this list, not a change to its shape.
Language
A policy language, known to this build or not.
Lifecycle
An account-lifecycle event, so an evaluator’s per-account state does not outlive the account it belongs to. Not agent-only — any AccountKind can be frozen, unfrozen or deleted.
Outcome
What one policy decides about one subject.
PolicyLifecycle
A policy-lifecycle event, parallel to Lifecycle but scoped to a compiled artifact rather than an account. Without it, an evaluator that accumulates state per compiled policy (a cache, a counter) has no way to learn that one of its artifacts no longer corresponds to anything the tree will ever route to again, and keeps it forever.
Predicate
What decides this policy’s outcome, once its applicability is already established.
Scope
Whether a declarative dimension is unconstrained, or limited to a specific set of values.
Staleness
How stale an evaluator’s view of the world may be before it is unhealthy.
Subject
What one policy is asked to decide about.
SubjectKind
What kind of account a subject is, including a kind this build has never heard of.
Verdict
The result of evaluating a subject against every candidate policy.
WriteAction
What kind of write this is, carried alongside the diff rather than inferred from it.

Traits§

Evaluator
What judges one or more policies.

Functions§

combine
Fold a set of (policy, outcome) pairs into one Verdict, taking the most severe outcome regardless of the order the pairs arrive in — the structural half of “order is presentational, not semantic”.
evaluate
Evaluate a subject against a PolicyTree, in the tree’s presentational order.
is_local_origin
Whether origin is the origin of the profile’s local form, http://localhost. A client the server shows with this origin built its own metadata from its client_id, so any process on its machine can send the same one. A client fetched from http://localhost/… on a development deployment has this origin too.
sorted_json
The compact JSON text of value, with every object’s keys sorted.
worst
Fold outcomes into the most severe one, taking Allow < Reject < Freeze — the same total order combine folds by, exposed for callers that hold outcomes without a PolicyId to attribute each one to.