Metadata-Version: 2.5
Name: legion-platform-contracts
Version: 0.3.0
Summary: Legion platform authoritative shared cross-component contracts (schemas, storage SPI, token profile, TCK).
Project-URL: Homepage, https://github.com/legion-os-dragons/farm-to-table-platform-contracts
Project-URL: Source, https://github.com/legion-os-dragons/farm-to-table-platform-contracts
Project-URL: Changelog, https://github.com/legion-os-dragons/farm-to-table-platform-contracts/blob/main/CHANGELOG.md
Author: Legion platform
License: proprietary
Keywords: conformance,contracts,json-schema,storage-spi,tck
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: pydantic>=2.6
Provides-Extra: codegen
Requires-Dist: datamodel-code-generator>=0.25; extra == 'codegen'
Provides-Extra: dragons
Requires-Dist: legion-foundation==0.1.1; extra == 'dragons'
Provides-Extra: tck
Requires-Dist: jsonschema>=4.20; extra == 'tck'
Requires-Dist: pytest>=8.0; extra == 'tck'
Description-Content-Type: text/markdown

# legion-platform-contracts

The shared contracts for the Legion platform, plus the conformance suite that proves an
implementation honours them.

The platform is built from independently deployable components. Anything that binds two or
more of them — a message shape crossing a boundary, a storage interface, a capability-token
profile — belongs to none of them individually, so it lives here instead: one versioned
package that every component pins, containing both the contract and the tests for it.

## What's inside

**Wire schemas** (JSON Schema, draft 2020-12) for the events and payloads that cross
component boundaries: reference bundles, identity and association event logs, erasure
propagation, canonical entity DTOs, and inference provenance. The schema is authoritative on
any question of data shape.

**A storage-adapter SPI** — a typed Python `Protocol` for structured and vector queries,
written so no backend type leaks through the interface, with a fail-loud error taxonomy that
a conforming adapter raises identically no matter what it is built on.

**A capability-token profile** covering delegation, attenuation, and the issuer contract.

**HTTP conventions** — the clause-numbered wire contract every service is held to: the error
envelope and its schemas, the exit-code registry, the auth failure-status rule, tenancy from
verified claims, keyset pagination, idempotency, and the ops probes. Each clause is numbered
and stable, so a linter or a test can cite the exact rule it is enforcing.

**An audience gate** (`platform_contracts.authz`) that binds each invocation to exactly one
target service, so a token minted for one service is refused by another.

**An executable conformance suite (TCK)** covering all of the above. Behaviour that a schema
cannot express — ordering, idempotency, replay, refusal predicates, cryptographic invariants
— is pinned by tests rather than prose.

The whole set is versioned as **one artifact**: the TCK travels with the contracts it tests,
so pinning a version pins the shapes and the tests together. You cannot end up running one
version's tests against another version's schemas.

## Install

```bash
pip install legion-platform-contracts               # contracts + SPI + audience gate
pip install 'legion-platform-contracts[tck]'        # + the conformance suite
pip install 'legion-platform-contracts[dragons]'    # + the token/crypto conformance leg
```

Requires Python 3.11 or later. The distribution is `legion-platform-contracts`; the import
package is `platform_contracts`.

## Run the conformance suite against your implementation

```bash
pytest --pyargs platform_contracts.tck
```

Point it at your storage adapter either by setting an environment variable:

```bash
export PLATFORM_CONTRACTS_ADAPTER_FACTORY=your_package.module:make_adapter
```

— where the callable returns your adapter — or by overriding the `storage_adapter` fixture in
your own `conftest.py`. With neither set, bundled reference implementations run, so the suite
is exercisable standalone before you have an adapter to plug in.

Wire it as a CI gate. An implementation that fails the pinned suite is not conforming, and
the point of shipping the tests inside the package is that "conforming" means something
checkable rather than something asserted.

### HTTP conformance, adopted clause by clause

The HTTP leg runs black-box against a running service:

```bash
export PLATFORM_CONTRACTS_HTTP_ORIGIN=http://localhost:8080
export PLATFORM_CONTRACTS_HTTP_PROFILE=./http-conformance-profile.json
export PLATFORM_CONTRACTS_HTTP_CREDENTIAL_FACTORY=your_pkg.testing:credentials
pytest --pyargs platform_contracts.tck -m http
```

The profile declares which clauses your service currently meets. A declared clause is a hard
gate — a regression fails the build. A clause you have not declared still runs, and reports as
an expected failure: named in the summary, counted, never silently skipped. That is what lets a
service adopt the conventions one clause at a time without either blocking on a full migration
or appearing to conform in the meantime.

## Read the contracts

The prose specs and their schemas travel inside the installed package:

```python
import pathlib, platform_contracts

contracts = pathlib.Path(platform_contracts.__file__).parent / "contracts"
print(sorted(p.name for p in contracts.rglob("*.schema.json")))
```

Each prose contract sits beside the `.schema.json` it describes, under `seams/`, `storage/`,
`tokens/`, `entities/`, `provenance/`, and `http/`.

## Binding invocations to a service

Every platform invocation carries an audience naming the single service meant to execute it,
and every service checks it as a precondition of acting:

```python
from platform_contracts.authz import authorize_for_audience, service_audience

THIS_SERVICE = "..."   # the service this process is; see authz.PLATFORM_SERVICES

result = authorize_for_audience(
    invocation,
    expected_audience=service_audience(THIS_SERVICE),
    now=..., resolve_prf=..., replay=...,
)
```

The check is fail-closed on all of: a missing audience, a malformed one, one naming a
different service, and one that disagrees with the invocation's command namespace. A missing
audience is refused rather than waved through — an unset audience is not a weak binding, it
is no binding, and such an invocation would otherwise be replayable anywhere.

## Versioning and pinning

Semantic versioning, with the whole contract set moving as a unit.

**Pin an exact version — never a range.**

```
legion-platform-contracts[tck]==0.3.0
```

A floating range on a shared, security-relevant contract means a transitive bump can change
what your code must conform to without anyone deciding that it should. Moving versions is
deliberate: update the pin, run the new suite, close any gaps it reports. Add hashes to your
lockfile so the bytes are verified, not just the version string.

While the package is pre-1.0 the contract surface is still settling, so a minor version may
carry a breaking change; each release states plainly which of its changes are breaking and
which are additive.

## Contributing

Contract changes are not made by editing this package. A component that finds at build time
that a contract must change raises a proposal through the platform's review process, which
either adopts it — producing an amended contract and a new release — or declines it with a
recorded reason. This keeps one authoritative shape for each contract instead of as many
variants as there are implementations.

## License

Proprietary. © Legion platform.
