Metadata-Version: 2.4
Name: rttp
Version: 0.1.2
Summary: RTTP reference implementation: PulseHeader128 framing, rttp:// addressing, and self-certifying Ed25519 seals (RFC-002 §4.1 / §10 / §11).
Author: RTTP.COM Organization
License-Expression: Apache-2.0
Project-URL: Homepage, https://rttp.com/
Project-URL: Specification, https://rttp.com/RFC-002/
Keywords: rttp,protocol,ai-agents,intent-addressing,uri-scheme,ed25519,conformance
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Internet
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: ed25519
Requires-Dist: cryptography>=41; extra == "ed25519"
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == "dev"
Requires-Dist: twine>=4.0; extra == "dev"
Dynamic: license-file

# rttp

**Reference implementation of RTTP (Resonant Time Transfer Protocol): the
128-byte `PulseHeader128` frame, `rttp://` intent addressing, and self-certifying
Ed25519 seals.**

[RFC-002 §4.1](https://rttp.com/RFC-002/) · [§10](https://rttp.com/RFC-002/) · §11 · v1.2.6

---

## Verify it in one command — no trust required

```console
$ pip install rttp
$ python -m rttp.selftest
rttp 0.1.2 self-test
python 3.14.2 on win32
...
[PASS] all 53 checks passed
```

That is the point of this package. A specification is worth exactly what an
independent implementation can reproduce from it — so instead of asking you to
believe a table of numbers, this ships the vectors and replays them locally:

* **25 conformance checks** — `rttp://` parsing, fail-closed rejections, and the
  URI → `ROUTE_SHARD` → 128-byte frame chain, bit for bit.
* **2 RFC 8032 checks** — the Ed25519 backend is shown to be *standard* Ed25519,
  not a lookalike, so a failure tells you which half broke.
* **22 envelope checks** — round-trip, self-certification, freshness, and a
  14-case tamper matrix where every alteration must be rejected.
* **4 zero-dependency checks** — a static scan proving the core imports nothing
  outside the standard library.

Offline. No account. No network. `[PASS]` or it is not.

---

## Install

```console
pip install rttp              # core: zero dependencies, standard library only
pip install rttp[ed25519]     # + sovereign-profile seals (Ed25519)
```

Python 3.9+. No compiled extensions in the core.

The core deliberately has **no dependencies**. A protocol reference that cannot be
read without resolving a dependency tree is not much of a reference — and an
air-gapped reviewer should be able to check the frames.

---

## What is in the box

| Module | What it does | Authority |
|:---|:---|:---|
| `rttp.pulse_header` | `PulseHeader128` codec — build / parse / verify the 128-byte hardware-aligned header, including the v1.2.6 extension block at `0x66`–`0x7F` | RFC-002 §4.1 + `SPEC/RTTP-FRAME-EXT-v1.2.6.md` |
| `rttp.rttp_uri` | Validate, canonicalise and derive `ROUTE_SHARD` from an `rttp` URI | RFC-002 §10.2 / §10.3 ABNF |
| `rttp.seal` | **Managed profile** — symmetric HMAC-SHA256 over a pre-shared key table | — |
| `rttp.seal_asym` | **Sovereign profile** — Ed25519, self-certifying, no issuance and no registry | `SPEC/RTTP-SEAL-ENVELOPE-v1.2.6.md` (draft) |
| `rttp.aid` | Autonomous Identity derivation | RFC-001 |

Plus `rttp.vectors` — the published conformance vectors, shipped inside the wheel
so the self-test works from an installed package with no repository checkout.

---

## Quickstart

### Address an intent

```python
from rttp import rttp_uri

parsed = rttp_uri.parse("rttp://brain.epoekie.aicent/verify")
parsed["authority"]          # 'brain.epoekie.aicent'
parsed["action"]             # 'verify'
parsed["route_shard"].hex()  # 16-byte routing hash, pure computation
```

Addressing is **DNS-free** (RFC-002 §10.5): the routing hash is derived from the
authority by SHA-256, so no registry, resolver or network is involved. Malformed
input is rejected rather than normalised — a case variant is not a spelling
difference, it is a different string.

### Build a frame from a URI

```python
from rttp import pulse_header, rttp_uri

parsed = rttp_uri.parse("rttp://brain.epoekie.aicent/verify")
raw = pulse_header.build_for_uri(
    sequence_id=1, ttl=255, priority=1,
    uri=parsed["canonical_uri"],
    aid_origin=bytes.fromhex("..."),   # originator AID, 32 bytes
)
len(raw)                          # 128
pulse_header.verify(raw)["action"]  # 'verify'
```

`build_for_uri` performs the mapping RFC-002 §10.4 promises: the URI's authority
becomes `ROUTE_SHARD`, its path becomes `ACTION`. Readers that only understand
`0x00`–`0x65` keep working — the extension block occupies bytes that were already
zero, and `VERSION_ID` stays 130.

### Seal with your own identity

```python
from rttp import seal_asym

keypair = seal_asym.generate_keypair()      # nothing is issued to you
print(keypair["aid_hex"])                   # = SHA-256(public key): your identity

envelope = seal_asym.seal({"intent": "verify", "task_id": "t-1"}, keypair)

ok, reason, aid = seal_asym.verify_envelope(envelope)
# ok=True, signer identity recovered from the packet itself
```

The verifier needs **only the envelope**. There is no key directory, no
credentials to obtain, and no operator who could refuse to issue them.

---

## Two profiles, and when each applies

| | **Managed** — `seal` | **Sovereign** — `seal_asym` |
|:---|:---|:---|
| Primitive | HMAC-SHA256 | Ed25519 |
| Key material | pre-shared table | self-generated |
| Identity | a role name | `AID = SHA-256(public key)` |
| Verifier needs | the same key table | only the envelope |
| A stranger can participate | no | **yes** |
| One leaked key | can forge any peer | forges one identity |

Inside a set of symmetric secrets there is no such thing as a stranger — whoever
holds the shared key can mint anybody's seal. The managed profile is therefore for
a closed organism, where a fixed set of roles genuinely do trust each other.

A protocol that invites third parties needs the sovereign profile. That is not a
preference; it is the difference between a private system and a public one.

---

## Scope — what this package is not

| | |
|:---|:---|
| ✅ **Framing** | Real, and specified. |
| ✅ **Addressing** | Real, and specified. |
| ✅ **Sealing** | Real, and specified (draft). |
| ❌ **Transport** | **Not here.** This package encodes, addresses and seals. It does not open sockets, and there is no `send()` — a client and its transport belong to a separate package, so that the codec stays dependency-free and auditable. |
| ❌ **Routing service** | Not here. `ROUTE_SHARD` is computed locally; delivering a frame to that hash is an operator's job, not the codec's. |
| ❌ **Confidentiality** | Signing is not encryption. |

**The seal is an envelope around the frame, not bytes inside it.** A reader that
parses only the 128-byte header sees no seal at all — which is why the two
concerns are specified separately.

Unknown revisions, algorithms and malformed input **fail closed** everywhere.
Nothing in this package is ever accepted because a check could not be performed.

---

## Conformance vectors

`rttp/vectors/rttp-conformance-v1.2.6.json` is generated, not hand-edited. Each
vector is deterministic: fixed sequence numbers, fixed timestamp, fixed AID — so
two implementations either agree byte for byte or they do not.

The vector set is the intended deliverable for third-party certification: pass it
and you interoperate; fail it and you know exactly which byte is wrong, without
needing to trust the authors.

---

## Naming

| Ecosystem | Name | Status |
|:---|:---|:---|
| crates.io | `rttp` | held by this project |
| PyPI | `rttp` | **this package** — `pip install rttp` |
| npm | **`@aicent/rttp`** | the unscoped `rttp` name on npm is held by an unrelated, unmaintained 2017 REST helper, and the `rttp` scope cannot be created at all — a personal account already holds that name — so the JavaScript side is published under this project's own organization. The package name itself is still just `rttp` |

---

## Specification status

* **`rttp` URI scheme** — submitted to IANA under RFC 7595, ticket **#1459939**,
  Provisional (First Come, First Served), **under review**. It is **not yet
  registered** — as of 2026-09-15 the IANA URI Schemes registry contains no
  `rttp` entry. Please describe it that way.
* **Frame layout** — RFC-002 §4.1, extended by `SPEC/RTTP-FRAME-EXT-v1.2.6.md`.
* **Seal envelope** — `SPEC/RTTP-SEAL-ENVELOPE-v1.2.6.md`, a **draft**: the format
  is implemented and vector-tested, but it is not yet a numbered RFC-002 section.
* **Managed profile** — implementation only; it predates the sovereign profile and
  has no standalone specification.

Where this package and a specification disagree, **the specification wins and the
package is wrong.** Please report it.

---

## License

Apache-2.0. See `LICENSE`.
