Metadata-Version: 2.4
Name: bitspark-archon-sdk
Version: 0.13.0
Summary: archon sdk: proof of possession and the signed envelope, one layer above the identity floor. Deterministic given its inputs; no RNG, no clock, no socket.
Author: Bitspark
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/Bitspark/archon
Project-URL: Documentation, https://github.com/Bitspark/archon/tree/main/docs
Project-URL: Repository, https://github.com/Bitspark/archon
Project-URL: Issues, https://github.com/Bitspark/archon/issues
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Security :: Cryptography
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: bitspark-archon-core~=0.13.0
Dynamic: license-file

# archon sdk — Python

One layer above the identity floor: proof of possession and the signed envelope.

```console
pip install bitspark-archon-sdk
```

The distribution is `bitspark-archon-sdk`; the import is `archon_sdk`. It depends on
[`bitspark-archon-core`](https://pypi.org/project/bitspark-archon-core/) and nothing else, and
pip installs the floor with it.

```python
from archon_core import public_key_from_seed
from archon_sdk import envelope, possession

seed = bytes(range(32))
pub  = public_key_from_seed(seed)

# Proof of possession: the challenger picks the nonce and the channel binding.
nonce, binding = bytes(range(16)), b"tls-exporter-bytes"
proof = possession.prove(seed, "example/pop/v1", nonce, binding)
possession.verify(pub, "example/pop/v1", nonce, binding, proof)        # True
possession.verify(pub, "example/pop/v1", nonce, b"another channel", proof)  # False

# The signed envelope: the verifier chooses the domain, never the envelope.
sealed = envelope.seal(seed, "example/env/v1", b"payload")
opened = envelope.open(sealed, "example/env/v1")   # Opened(pubkey=…, payload=b'payload')
envelope.open(sealed, "example/env/other")         # ValueError: claims a different domain
```

## What it is

| | |
|---|---|
| `possession` | `prove`, `verify`, `message_bytes` — *can they sign, right now, for this channel?* — and `prepare`, `complete`, `prove_with` |
| `envelope` | `seal`, `open`, `message_bytes`, `Opened` — *these bytes, signed by this key, in this domain* — and `prepare_seal`, `complete_seal`, `seal_with` |
| `signer` | `Signer`, `SigningRequest`, `Raw`, `PhContext`, `Capabilities`, `SeedSigner`, `sign_with`, `check_signature` — sign through a signer instead of a seed ([ADR 0009](../../docs/architecture/decisions/0009-the-signing-boundary-and-the-signer-contract.md) §4): the request is validated and the signer's capabilities checked before it is called, and every signature it returns is verified against what was asked for |

Both sign in the **caller's** domain through `archon_core.sign_in_domain`, and each prefixes
its layout with a one-byte scheme tag so a possession proof and an envelope payload in the
same domain can never be the same bytes.

**Entropy, time and channel binding are arguments.** This package never sources them, which
is what makes every byte it emits a deterministic function of its inputs. Verification is
total: `possession.verify` returns `False` on any shape failure and never raises;
`envelope.open` raises `ValueError` and never returns an unverified payload.

**Not here yet: the login scheme.** The Go, Rust and TypeScript sdks also carry
`archon-login/1` ([docs/login.md](https://github.com/Bitspark/archon/blob/main/docs/login.md));
this one does not.

## Agreement is the claim

This sdk is held to the same hand-authored oracle as the Go, Rust and TypeScript sdks — 38
cases in [`vectors/sdk.json`](https://github.com/Bitspark/archon/blob/main/vectors/sdk.json),
recomputed rather than echoed. If it disagrees with them about a proof or an envelope, that
disagreement is the defect.

## Verification

```console
node conformance/check-py-sdk.mjs          # the oracle, against this tree
node conformance/check-py-sdk-package.mjs  # the built wheel, installed from nothing
```

## License

Apache-2.0.
