Skip to main content

assurance-authority

tests PyPI License

An agent must not become a way to read things you cannot read

Give an agent a task that needs context above your clearance and there are three honest outcomes. It fetches the context as someone else and hands you the answer — which is a permission-laundering machine with your company's name on it. It refuses. Or the task changes owner, and the answer goes to the person who was always allowed to have it.

Only the last two are acceptable, and the rule that separates them is one function:

Context acquisition never raises the initiating principal's effective authorisation. Another principal's clearance may move the task. It may never move the answer.

This package makes that rule runnable against your own people and your own tasks.

What it looks like on a real team

Real output, one declaration, three outcomes — and the middle one is the whole product.

$ assurance-authority team.json
1 of 3 tasks may proceed for the person who asked — 1 moved owner — 1 refused

  team roster      intern-42    proceed
  Q3 margin memo   intern-42    escalate_ownership -> CFO
      Priya (intern) may not receive finance-confidential, and CFO may. The task moves to
      CFO rather than the answer moving to Priya (intern).
  payroll extract  agent-a      refuse
      Drafting agent may not receive payroll, and nobody offered can. The task stops here.

The intern asks for a margin memo. She may not have it; the CFO may. So the task moves to the CFO. She is told it moved. She is never told the figure. The alternative — an agent fetching it as a service account and handing her the answer — is a permission-laundering machine with your company's name on it, and it is what most systems do by default.

An agent asks for payroll. Nobody declared may own it, so it stops. Not downgraded to a summary, not answered with a subset.

Somebody asks for what they are cleared for. It proceeds, silently, which is the point.

As a gate

assurance-authority team.json --fail-on-escalation   # exit 1 if any task can't reach its asker

Useful when a clearance change quietly breaks a workflow: the task still completes, by someone else, and nobody notices until the person who used to get the answer asks why they stopped receiving it.

This is not for you if

  • You work alone. There is no permission model to preserve, so every task proceeds and the tool tells you nothing. This is for whoever is accountable when somebody else's agent reads something it should not have.
  • You want enforcement at runtime. This is a review of declared tasks against declared clearances. Enforcing it inside your agent loop is the library — assurance_core.principal — and that is where the rule actually lives.
  • Your clearances are not expressible as labels. It compares opaque sets and never interprets them. A rule like "only during market hours" is not something it can hold.

Thirty seconds

pip install assurance-authority
assurance-authority team.json

On a system Python you may hit error: externally-managed-environment (PEP 668). That is your OS protecting its packages, not this failing: python3 -m venv .venv && .venv/bin/pip install assurance-authority

2 of 5 tasks may proceed for the person who asked — 2 moved owner — 1 refused

  team roster       intern-42    proceed
  Q3 margin memo    intern-42    escalate_ownership -> CFO
  pipeline summary  analyst-7    proceed
  board pack        analyst-7    escalate_ownership -> CFO
  payroll extract   agent-a      refuse

The intern gets the roster. The margin memo moves to the CFO rather than the answer moving to the intern. The agent's payroll request is refused, because nobody declared may own it — not silently downgraded, not answered with a subset.

The declaration

One JSON file. Labels are opaque strings: your own scheme, a Sharepoint group id, whatever your identity system reports. Nothing here interprets them, it only compares sets.

{
  "principals": [
    {"id": "intern-42", "name": "Priya (intern)", "may_receive": ["general"]},
    {"id": "cfo-1",     "name": "CFO",            "may_receive": ["general", "finance-confidential"]}
  ],
  "tasks": [
    {"name": "Q3 margin memo", "initiator": "intern-42", "requires": ["finance-confidential"]}
  ]
}

As a library

from assurance_authority import loads, review

declaration = loads("""
{
  "principals": [
    {"id": "intern-42", "name": "Priya", "may_receive": ["general"]},
    {"id": "cfo-1",     "name": "CFO",   "may_receive": ["general", "finance-confidential"]}
  ],
  "tasks": [
    {"name": "Q3 margin memo", "initiator": "intern-42", "requires": ["finance-confidential"]}
  ]
}
""")

result = review(declaration)
row = result.rows[0]

assert row.resolution.resolution.value == "escalate_ownership"
assert row.delivered is False          # the answer does NOT go back to the intern
assert row.new_owner == "CFO"          # the task does

In a pipeline

assurance-authority team.json --fail-on-escalation
exit means
0 reviewed, and every task may proceed for the person who asked
1 reviewed, and --fail-on-escalation found a task that cannot be delivered to its initiator
2 refused — the declaration could not be read, so there is no review

2 is separate from 1 on purpose. "I could not answer" and "I answered and you will not like it" are different facts, and a pipeline that treats them the same will one day treat a broken config as a policy violation, or worse, the reverse.

What it refuses to do

  • A task whose initiator is not declared. Assuming an empty clearance would produce a refusal indistinguishable from a real one.
  • A task that requires nothing. That is not an authority question, and answering it would imply one had been asked.
  • Two clearances for one principal id. That is a question about which is real, and this cannot answer it.

As an agent skill

skills/task-clearance/ — drop it in and an agent checks clearance before it fetches anything on somebody's behalf. Its real content is that an escalation is not a failure: an agent reporting "3 of 5 tasks failed" when two correctly changed owner has described a healthy access model as a broken one.

Where the rule actually lives

assurance_core.principal.resolve, in assurance-core. This package reads a file, calls it once per task, and counts the answers. The arithmetic is deliberately thin so there is exactly one implementation of the thing that must never be wrong — and you can read it in one sitting to confirm no branch returns PROCEED on the strength of somebody else's clearance.

Licence

Apache-2.0.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

assurance_authority-0.1.2.tar.gz (19.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

assurance_authority-0.1.2-py3-none-any.whl (15.7 kB view details)

Uploaded Python 3

File details

Details for the file assurance_authority-0.1.2.tar.gz.

File metadata

  • Download URL: assurance_authority-0.1.2.tar.gz
  • Upload date:
  • Size: 19.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for assurance_authority-0.1.2.tar.gz
Algorithm Hash digest
SHA256 4823bf8f1d73ec601f73046215df2d754529370d3b2244b8a7e09051793cda68
MD5 a83aa78a82bbf289f293295dc9ade50d
BLAKE2b-256 ee78e653f785f3de89d6f3dec7163d9978b2c04bf043d2ac1adfb3fc8c9c286c

See more details on using hashes here.

Provenance

The following attestation bundles were made for assurance_authority-0.1.2.tar.gz:

Publisher: publish.yml on i-ops-hq/assurance-authority

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file assurance_authority-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for assurance_authority-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 c748bb5e5235779686c244ad2316ea1bd59c44cebd64fe7b70936225559368a2
MD5 7ba9232efb4bf84d8385698daac25f0a
BLAKE2b-256 b78d092411f754bb9216cf8f402cfc6bd3975bb2f4c243285825959dff7f44ad

See more details on using hashes here.

Provenance

The following attestation bundles were made for assurance_authority-0.1.2-py3-none-any.whl:

Publisher: publish.yml on i-ops-hq/assurance-authority

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page