Metadata-Version: 2.4
Name: delegus-core
Version: 0.2.0
Summary: Python port of the Delegus v0.2 protocol layer (delegus-base-v1): Grant/Proof parsing, checks P1-P20, receipt assembly, signing and offline re-verification; and verification of Delegus v0.3 receipts and /verify responses (delegus-receipt-v2). No I/O; snapshots and clock are injected. Passes the 40 v0.2 conformance vectors and verifies every committed v0.3 receipt.
License-Expression: Apache-2.0
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: cryptography>=41
Dynamic: license-file

# delegus-core (Python)

A Python port of the Delegus v0.2 protocol layer (`delegus-base-v1`,
spec §15 step 1), module for module from `packages/core`: Grant and Proof
parsing (P1, P8), DID-document key lookup (P2), Ed25519 verification (P3,
P9), validity and audience (P4, P5, P7), the Bitstring Status List credential
(P6), Proof binding (P10–P14), the action vocabulary (P15–P20), the T1–T3 and
T5 seams as injected hooks in the §5.4 order, receipt assembly and signing
(§6), and offline re-verification with the historical clock (§6.4). It also
verifies Delegus v0.3 receipts and `/verify` responses (see below).

- No I/O. The DID document snapshot, status-list credential snapshot,
  replay state and the clock are inputs; the three seams are methods on a
  hooks object (see `delegus_core/memory.py` for the in-memory one).
- Fail closed and deterministic: the port reproduces every one of the 40
  conformance vectors, receipt JWS byte for byte, and passes the `htu`,
  JCS and `jti` sets.
- One dependency: `cryptography` (Ed25519). Python ≥ 3.9.

## v0.3 receipts (verification)

Delegus v0.3 (profile `delegus-base-v3`) issues `delegus-receipt-v2` receipts. They pin the matched
permission as a commitment (`authority_commitment`), and the `/verify` response returns the
permission itself beside the receipt with the key to open it (`authority_opening`). This package
**verifies** v0.3 receipts and responses; it does not evaluate v0.3 requests (the reference engine
for that is `@delegus/core`).

```python
from delegus_core import verify_response, ResponseIntegrityError

try:
    checked = verify_response(response_json, receipt_keys, "did:web:delegus.ai", action=action, requires=requires)
except ResponseIntegrityError as e:
    ...  # fail closed: do not act on this response
```

`verify_response` accepts either protocol and picks the checks by the version the receipt was
signed with, since each relying party answers in its own profile: a v0.2 receipt is checked for its
signature, its body equal to the signed payload, a decision that agrees with its checks, and a
`request_hash` that matches the action; a v0.3 receipt gets every check of `verify_response_v3`.

`verify_response_v3` checks the whole response and raises `ResponseIntegrityError` unless every check
holds: the receipt's signature under the service's receipt keys; the response body equal to the
signed payload; the decision, reason and checks agreeing with each other; `authority` opening
`authority_commitment` (and `capability_key_opening` opening
`evidence.consumption.capability_key_commitment` when a budget was spent); the dependency results
matching `relies_on_hash` and the action's declaration; `requires_hash` matching the `requires` you
sent; on ALLOW, a canonical transaction handle and an `opening` that opens its fingerprint for this
receipt; and `request_hash` matching the action. `verify_receipt_v2` checks a stored receipt on its
own: the signature and a well-formed v2 body.

New reason codes in v0.3 receipts: `AUTHORITY_EXHAUSTED` (a spending limit) and
`DEPENDENCY_NOT_DECLARED`, `DEPENDENCY_COMMITMENT_MISMATCH`, `DEPENDENCY_RECEIPT_INVALID`,
`DEPENDENCY_NOT_ALLOW`, `DEPENDENCY_TRANSACTION_MISMATCH`, `DEPENDENCY_AUTHORITY_EXPIRED` and
`DEPENDENCY_AUTHORITY_REVOKED` (checks D1 to D7). `reverify_receipt` re-runs v0.2 receipts only and
refuses a v0.3 one with a plain message.

## Run the vectors

```
python3 -m delegus_core.conformance            # finds packages/conformance/src/vectors in the monorepo
python3 -m delegus_core.conformance --dir <path with cases/ and sets/>
python3 -m delegus_core.conformance --v3       # the v0.3 set: every committed v0.3 receipt verifies, plus the commitment framing set
python3 -m unittest discover -s tests
```

Exit 0 when all vectors pass with byte-identical receipts, every committed
receipt re-verifies offline, and the three sets pass. With `--v3`: exit 0 when
every committed v0.3 receipt (every case of the v0.3 set except the one
evaluated under the v0.2 profile) verifies and agrees with its vector, and the
framing set passes.

## Use

```python
from delegus_core import EvaluateInput, evaluate, verify, MemoryService, MemorySigner
```

`evaluate(EvaluateInput(...))` returns the receipt body as a dict;
`verify(input, signer)` adds the `receipt` JWS; `reverify_receipt(...)` re-runs
the protocol layer for a receipt with `now = evaluated_at`.

## Notes on fidelity

JSON numbers follow JavaScript semantics: integral literals such as `1.0`
or `1e2` are the integers 1 and 100, integer literals outside ±(2^53 − 1)
are rejected, and canonical output uses ECMAScript `Number::toString`.
Object keys sort by UTF-16 code units (RFC 8785), and strings quote like
`JSON.stringify` (lone surrogates escaped).
