# Contract
## Public API
```rust
pub const REVISION: u64 = 1;
pub fn text() -> &'static str;
pub fn sha256() -> [u8; 32];
pub fn verify_acceptance(
public_key: &[u8; 32],
signature: &[u8; 64],
) -> Result<(), AcceptanceError>;
pub fn endpoint() -> axum::routing::MethodRouter;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum AcceptanceError {
MalformedPublicKey,
VerificationFailed,
}
```
`AcceptanceError` implements `Display` and `std::error::Error`.
## Canonical bytes
`REVISION` is `1` for this unchanged approved terms text and its SHA-256 digest. It is the sole public revision owner for these canonical bytes.
`text()` returns the approved UTF-8 terms as one immutable static string. Paragraphs are separated by one LF blank line, and the final period is the final byte with no trailing LF. The terms are exactly 2,490 bytes. The complete terms occur only in source so documentation and tests cannot become competing copies.
`sha256()` hashes exactly `text().as_bytes()` with SHA-256 and returns the 32 digest bytes.
## Acceptance verification
`verify_acceptance()` performs strict Ed25519 verification directly over exactly `text().as_bytes()`. It does not verify a digest, prefix, serialization, JSON value, or wrapper. `MalformedPublicKey` means the supplied 32 bytes cannot decode as an Ed25519 public key. Every signature rejection is reported only as `VerificationFailed`.
## HTTP behavior
`endpoint()` constructs a pathless `MethodRouter` for the caller to mount. GET returns exactly the canonical text bytes with `Content-Type: text/plain; charset=utf-8`. HEAD uses Axum's ordinary GET-derived HEAD behavior: it succeeds with the same content type and no response body. The router does not accept or retain acceptance submissions.
## Integration boundary
A future account record outside this feature will store both the exact terms digest and the acceptance signature. The separately signed K1 registration request will bind that acceptance signature in its body. Any byte change creates a new digest and requires a new acceptance. Account persistence, registration, identity, authorization, and submission handling remain outside this API.
## Operational properties
- Dimensions are 32 public-key bytes, 64 signature bytes, 32 digest bytes, and 2,490 canonical text bytes.
- `text()` returns borrowed static storage. Digest and verification use fixed-size values and create no package-owned heap buffers. Axum controls any routing and response allocations.
- All operations are stateless and safe to call concurrently. There is no I/O, network access, locking, logging, retry, or background work.
- Hashing is linear in the fixed text length; strict verification has the cost of one Ed25519 verification. The broad managed-Linux canary permits 1,000 hashes and 16 strict verifications up to 30 seconds; no tighter latency or throughput guarantee is made.