pub struct AnonPolicy {Show 14 fields
pub mode: String,
pub categories: BTreeMap<String, String>,
pub default_action: String,
pub custom_terms: Vec<String>,
pub term_sets: BTreeMap<String, Vec<String>>,
pub co_occurrence: Vec<CoOccurrence>,
pub scope: String,
pub placeholder: String,
pub min_confidence: f32,
pub detectors: Vec<String>,
pub vault: bool,
pub vault_ttl_days: Option<f64>,
pub because: Option<String>,
pub known: Vec<KnownIdentity>,
}Expand description
The declarative anonymization policy (proposal §8.1). Serialized as the
JSON value of an anon:<ns> meta row from P1 on; in P0 it is supplied
explicitly to the text APIs.
deny_unknown_fields is the fail-closed half of D3: a policy field this
build does not understand could be the field that strengthens the
policy, so refusing it loudly beats silently ignoring it.
Fields§
§mode: String§categories: BTreeMap<String, String>category → action (“pseudonym” | “mask” | “redact” | “allow”).
default_action: StringAction for categories a detector emits but the map omits — the chain fails closed on categories it didn’t anticipate, not open.
custom_terms: Vec<String>User dictionary; matches become category custom.
term_sets: BTreeMap<String, Vec<String>>Named dictionaries: category -> terms. Each set’s matches carry that
category, so the policy can act on them separately and — the reason
they exist — so a CoOccurrence rule can NAME one side of the
relationship. The single custom_terms bucket cannot express
“a person near a condition” because both halves land in custom.
co_occurrence: Vec<CoOccurrence>Context-sensitive escalation: re-categorize a detection when another category appears close to it.
This is the rule healthcare actually needs and no per-category action can express. A name alone may be acceptable in a prompt; a name together with a condition, medication or procedure in the same span is health data under most privacy regimes. The distinction is not a property of either detection — it is a property of the pair.
scope: StringPseudonym stability scope. P0 supports context only (per-call
numbering); session/memory arrive with the store boundary.
placeholder: StringPlaceholder template; must contain {CATEGORY} and {ID}.
min_confidence: f32§detectors: Vec<String>Which chain links this policy demands (proposal §5.4): “tier0” runs
in-tree; “ner”/“llm” require a host-installed DetectorBackend of
that kind and FAIL CLOSED without one (D6).
vault: boolPersist the pseudonym mapping to the file’s sealed vault (proposal
§7). Requires scope session/memory and an encrypted memory.
vault_ttl_days: Option<f64>Storage limitation for vault rows (REQ-ANON-6), in days.
because: Option<String>§known: Vec<KnownIdentity>Caller-supplied identities to detect verbatim in free text (issue
#32’s escape hatch): a host that hasn’t interned the identity as a
grain subject first — an email’s From header, a CRM row, a project
codename — still gets it detected and pseudonymized, without
writing it to the store just to make it detectable. Distinct from
the automatic propagation scan_text/anonymize_text already pull
from the store’s own interned subjects for the call’s namespace
(same table the grain-egress path builds).