Metadata-Version: 2.4
Name: atlas-pca
Version: 0.4.1
Summary: Reference verifier for Atlas Proof-Carrying Authority (PCActn core, M0-M3)
Author: Atlas
License-Expression: MIT
Project-URL: Homepage, https://github.com/Atlas-Authorization/pca-python
Project-URL: Repository, https://github.com/Atlas-Authorization/pca-python
Project-URL: Issues, https://github.com/Atlas-Authorization/pca-python/issues
Project-URL: Specification, https://github.com/Atlas-Authorization/pca
Keywords: authorization,agents,proof-carrying-authority,pca,verifier,ed25519,ml-dsa
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Security
Classifier: Topic :: Security :: Cryptography
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: fast
Requires-Dist: cryptography>=41; extra == "fast"
Provides-Extra: pq
Requires-Dist: dilithium-py>=1.0; extra == "pq"
Provides-Extra: fastapi
Requires-Dist: fastapi>=0.110; extra == "fastapi"
Provides-Extra: django
Requires-Dist: django>=4.2; extra == "django"
Dynamic: license-file

# atlas-pca

Reference verifier for **Proof-Carrying Authority (PCA)**, an execution-authentication framework for
autonomous agents. With every action the agent presents a self-contained proof-carrying action
(PCActn); the resource server verifies the proof offline instead of trusting a bearer token.

> Status: **0.4.1, unaudited.** Not independently security-reviewed; evaluate before relying on it for
> production authorization decisions.

## Install

```sh
pip install atlas-pca
```

The verifier has no required dependencies. Optional extras: `atlas-pca[fast]` (native Ed25519 via
`cryptography`), `atlas-pca[pq]` (ML-DSA-65 post-quantum signatures via `dilithium-py`),
`atlas-pca[fastapi]`, `atlas-pca[django]`.

## Use

`verify_pcactn_core` is the **structural** verifier: it checks the proof's wire form, chain, signatures, plan
inclusion and validity against the grant you pass in. It does not evaluate the grant's predicates, limits or
caveats, plan authorization, revocation, the trust budget or the threshold, so a passing result is necessary but
not sufficient to perform the action. Pass the grant from your own store (never one the request carries), and take
the authorization decision with a full verifier (the Atlas server's action endpoint, or `verifyPCActn` /
`requirePCA` from `@atlasauth/pca`).

<!-- pca-core-verify: allow structural pre-check; the README states the authorization decision is the full verifier -->
```python
from atlas_pca import verify_pcactn_core

structural = verify_pcactn_core(pcactn, grant_from_your_store, audience="https://api.example.com")
if not structural.allow:
    raise PermissionError(f"authF failed: {structural.reason}")
# structurally valid: now ask the full verifier whether this action is inside the grant
```

## Caveat enforcement (policy layer)

`verify_pcactn_core` (and the `require_pca` / FastAPI / Django guards built on it) does **not** evaluate caveats. A
resource server that enforces a grant's caveats calls the policy helpers with its own action context:

```python
from atlas_pca import evaluate_caveats, policy_caveats

ok, failed = evaluate_caveats(policy_caveats(grant, pcactn["cap_chain"]), {
    "now": now_ms,
    "delegation_depth": len(pcactn["cap_chain"]) - 1,
    "action": {"verb": "pay", "resource": "invoice:42", "params": {"amount": 150, "currency": "usd"}},
})
if not ok:
    raise PermissionError(f"caveat(s) not satisfied: {', '.join(failed)}")
```

`policy_caveats(grant, chain)` is the grant's own caveats (the root's, without its first `envelope` caveat) followed by
the caveats the delegation hops appended. Since 0.4.1 the root's caveats are included: caveats placed on the root grant
outside the envelope are enforced exactly like delegated ones. `evaluate_caveats` implements `max_spend` (`{usd}`
against `action.params.amount`, currency absent or `"usd"`/`"USD"`), `expires`, `not_before`, `rate`,
`max_blast_radius`, `reversibility_max`, `delegation_depth` and `budget_alloc`; any other type is unsatisfied (fail
closed). It never raises.

The `PCA-Action` header is strict unpadded base64url of UTF-8 text (`decode_pca_header`): padding, the standard
alphabet, whitespace anywhere or invalid UTF-8 is a 401.

## Checks

Verification is stateless, fail-closed and runs in a fixed, normative order:
`wire`, `version`, `audience`, `validity`, `chain`, `grant_ref_bound`, `plan_inclusion`,
`leaf_signature`, `counter`.

`grant_ref_bound` (new in 0.2.0) requires the signed `grant_ref` to equal the id of the root capability
(`cap_chain[0]`), so replay state cannot be keyed on an attacker-chosen value.

The package passes the shared 172-vector PCA conformance corpus, which the TypeScript, Rust, Go and
other verifiers also pass.

## Links

- Source: https://github.com/Atlas-Authorization/pca-python
- Specification and docs: https://github.com/Atlas-Authorization/pca

License: MIT

## Suite policy defaults

- No list (`allowed_suites=None`) means no restriction: the verifier accepts every signature suite it knows.
- An empty list (`allowed_suites=[]`) means refuse everything.
- The hosted API defaults to `ed25519` plus the hybrids that include Ed25519, and refuses the pure post-quantum suites (`ml-dsa-*`, `slh-dsa-*`, `fn-dsa-*`, `less-cat1`) unless the operator lists them. To match it offline, pass `allowed_suites` exactly: `ed25519`, `hybrid-ed25519-ml-dsa-65`, `hybrid-nested-ed25519-ml-dsa-65`, `hybrid-ed25519-ml-dsa-87`, `hybrid-ed25519-slh-dsa-sha2-128f`, `hybrid-ed25519-slh-dsa-sha2-256s`, `hybrid-ed25519-less-cat1`. The effective hosted list is readable at `GET /v1/pca/suites`; see docs/pca/reference/wire-formats.md.
