Charter as code¶
The Charter is the signed collection of your mandates, the standing law every agent action is judged against. Phase 4 makes it behave like code: every mandate carries tests, the rules are linted for contradictions and dead rules, a mandate can be probed for evasions before it is signed, the Charter has levels that can only narrow, you can ask it questions, and every version comes with a signed plain-language diff of what authority changed.
Tests¶
When a mandate compiles, Xybern generates must-refuse and must-allow examples from its primitives: for a threshold rule, a value past the threshold, one inside it, and one exactly at it; for a family refusal, an action in the family and one outside; for a content pattern, a sample that matches and ordinary content that does not. Semantic, risk-verdict and sequence primitives cannot be exercised without a model, a live verdict or history, so their tests are recorded as skipped with the reason: the report is honest about what was and was not proven.
Tests run against the mandate's own compiled rules, model off, on every recompile and before signing. Open a mandate's Tests in the Charter view to read them, run them, regenerate them after a change, add your own (a concrete action, its metadata, and whether it must be refused or allowed), or delete a manual one. Each mandate shows a pill with passing over total and any failures.
A mandate with failing tests cannot be activated. The Activate button returns the failures; to proceed anyway you must give an override reason, which is sealed to the Provenance Vault as charter_test_override with the failing tests listed.
API: GET /v1/enforce/mandates/<id>/tests, POST /v1/enforce/mandates/<id>/tests/run, dashboard POST /enforcement/mandates/<id>/tests (add), DELETE .../tests/<test_id>, activation with override_reason.
Probing¶
Probe runs adversarial variants against a mandate before you sign it. Deterministic probes are always available: a value one past the threshold, exactly at it, as a string, the bounded field missing, a negative amount, a decoy field name, case and whitespace variants of enumerated values, spaced identifiers, an identifier moved into metadata. When a model provider is configured, a free-reasoning agent adds paraphrases and evasions.
Each probe is judged against what the mandate intends: a leak is something the outcome would refuse that passes (for example an in rule on ["ir", "kp"] misses "IR"); a hazard is a gap the deterministic layer cannot see (a missing field, a renamed field, a negative amount) that a semantic guard may or may not cover. Save leaks as tests turns every leak into a must-refuse test in one click.
Lint¶
The Charter lint card runs on every load and on GET /v1/enforce/charter/lint:
| Finding | Meaning |
|---|---|
| contradiction | Rules with the same scope and conditions decide differently; the stricter one wins, the other misleads |
| unreachable | A rule whose families are already refused outright by a rule of equal or higher priority at the same or a higher level; it can never change an outcome |
| redundant | The same primitive materialised more than once (duplicate mandates) |
| untested, failing_tests | A mandate with no tests, or with failures |
| semantic_load | More than one semantic guard on the same family (each is a model call per action) |
| level_widening | A lower level pre-authorises what a higher level refuses outright |
Levels: organisation, department, agent¶
A mandate is organisation-wide, scoped to a department, or scoped to one agent. All applicable levels evaluate together on every action (organisation rules plus the acting agent's departments' rules plus its own), so a lower level can never remove a restriction by construction. The one primitive that widens authority, the authority_request auto-grant, is checked at compile time: a department or agent mandate may not pre-authorise a family a higher level refuses outright, and its caps (amount, duration, actions) may not exceed a higher level's caps for the same family. The refusal message says which higher-level mandate stands in the way.
Pick the scope in the wizard (organisation, a department, or an agent). Departments come from the Organisation view. Every decision's lineage records the level of each mandate that spoke.
Ask the Charter¶
Open Ask Xybern (the ⌘K palette, from any view) and type a permission question: Can the Refund Agent make a payment of SAR 5,000 to acc-9 in KSA? Ask Xybern recognises it as a question about authority and answers it from the rules rather than from the model. The question is parsed deterministically (agent by name, action from your observed catalogue and common verbs, amount, currency, region, recipient, PII and external markers) into one pre-flight step and answered by a dry run through the real rules, with the mandates that decide it cited and what it would take. No decision is recorded. A configured model can improve the parse and the phrasing; the verdict always comes from the rules. Also POST /v1/enforce/charter/ask.
Signed semantic diff¶
Every Charter change creates a version (Phase 0) and now attaches a signed diff from the previous one: mandates added, removed or moved between active and shadow; and inside a recompiled mandate, thresholds raised or lowered ("amount threshold raised from 1,000 to 5,000", loosened), decisions weakened or strengthened ("block to escalate", loosened), families and conditions added or removed. Each line carries a direction (tightened, loosened, neutral) and the diff is signed with the vault key. The Charter versions card shows the last versions with their headlines; GET /v1/enforce/charter/versions returns them with the diff, and a receipt's Charter hash resolves to the version that carries it.