# HORIZON-1 / HZ-1 — draft profile 1

A revocable schedule for human authority, composed with HAP-1. This is a working reference profile, not a claim of global adoption, legal validity, novelty, independent audit, or guaranteed future delivery. Time limits already exist in systems such as JWT (`nbf`, `exp`) and Bitcoin CLTV. HZ-1 specifies how a signed schedule, an encrypted payload commitment, revocation and fresh human permission work together.

## Signed object

Exactly ten top-level fields:

```json
{
  "spec": "HZ-1",
  "human": "echo:root:<HAP-1 public-key identifier>",
  "delegate": "echo:device:<HAP-1 public-key identifier>",
  "capability": "release-letter",
  "scope": { "payload_ref": "sha256:<64 lowercase hex>", "audience": "<executor key identifier>" },
  "constraints": { "maxCount": 1, "maxAmount": 0, "unit": "letter", "freshnessMs": 5000 },
  "activate_height": 1756981,
  "expire_height": 1809541,
  "reversible": false,
  "proof": { "said": "sha256:<64 lowercase hex>", "sig": "<128 lowercase hex>" }
}
```

The heights above are examples, not observations of the current chain. This profile uses Bitcoin mainnet. Both heights are integers in `[0, 500000000)` and H1 < H2. Count is 1–128; amount is a nonnegative safe integer in the declared unit; freshness is 100–5000 ms. `reversible` describes the effect; **false never prevents revocation of the permission**. The pinned human key signs the schedule. Unknown fields, keys, plaintext, personal identity data, wildcards, malformed numbers and missing constraints are rejected.

The added audience, amount, unit and freshness bounds make the action unambiguous. This deliberately tightens the original minimal sketch. Other wire profiles need a new version, not silent coercion.

## Canonicalization and signatures

Use HAP-1 canonical JSON: ASCII strings, sorted object keys, safe integer numbers, no duplicate keys, no floats, no `-0`, no whitespace on canonical wire. Plaintext can contain Unicode; its encrypted envelope is ASCII. Decode untrusted JSON with duplicate-key rejection; `hap1.parseWire` accepts canonical wire. Public export files may be pretty printed and are canonicalized after parsing.

`body` is the object **without the whole `proof` field**. `said = "sha256:" + SHA256(canonical(body))`. Sign UTF-8 bytes of `"HZ-1/schedule\n" + canonical({...body, said})` using Ed25519. The key ID is inherited from HAP-1. A public key supplied in the same passport is a convenience, not a trust anchor; independently pin it.

`payload_ref = "sha256:" + SHA256(canonical(encrypted_envelope))`. The whole envelope, including salt, IV, KDF parameters and ciphertext, is bound. The receipt contains only the reference. It contains neither the letter nor its ciphertext nor a decryption key.

The schedule preimage, with **no final newline**, is exactly:

```
HZ1|H1|H2|said|payload_ref|human
```

`hz1_commit = SHA256(UTF8(preimage))`, returned as 64 lowercase hex. This exact digest is submitted to OpenTimestamps. Do not hash the hexadecimal text a second time. A downloaded `horizon-schedule.txt.ots` pairs with `horizon-schedule.txt`, which contains that preimage. All fields exclude `|`, so there is no delimiter ambiguity. Only the hash reaches the timestamp calendar and Bitcoin aggregation; no letter, authority body, root key or inscription is submitted.

## State and action

Authenticate the object before trusting its `said` or a revocation. A valid root-signed revoke wins over height, even if the height source is unavailable. Otherwise, a missing, stale, future-dated or regressing height observation refuses. For a usable height view:

| Condition | State |
|---|---|
| H < H1 | DARK |
| H1 ≤ H < H2 | LIVE, eligible for a fresh permission |
| H ≥ H2 | EXPIRED |
| Count consumed inside the window | USED |
| A verified revoke is known | REVOKED |

`inspectAtHeight` reports eligibility. `check(action, schedule, context)` returns ALLOW only if a fresh, correctly scoped **HAP-1 human permit** is also supplied. It does not dispatch or mutate state. `createHorizonAuthority.check` reserves the lifetime schedule budget atomically and signs the HZ receipt. `createHorizonExecutor.execute` verifies that receipt, independently checks height and known revocations, durably reserves the schedule count, and dispatches through the existing HAP-1 executor. The HAP nonce, signed delegate request, executor audience, retained hash-chain checkpoint and ≤5-second permission window remain mandatory. A copied schedule or yesterday's receipt is insufficient.

The short-lived AO resource equals the schedule `said`; its audience, delegate, capability, amount, unit and reversibility are no broader than the schedule. The action digest equals the ciphertext-envelope hash. The consumer must use the HZ wrapper for an HZ resource, never a bare HAP dispatcher. All privileged effects go through the wrapper; this library cannot force an unrelated or malicious machine to obey.

Budget reservations survive crashes, failed effects and concurrent calls. Failures may consume a permission without delivering an effect; there is no automatic retry/refund. The final successful authorization check is the dispatch boundary. A revoke after dispatch cannot undo the effect. Retain durable state and HAP checkpoint pins; do not restore an old store snapshot or clone the signing authority. A checkpoint alone cannot discover an unseen fork. Reference stores are bounded to 128 schedules, 128 known revokes and HAP's existing journal limits; long-running production use needs a reviewed archival/rotation policy.

## Height and revocation trust

A height view is `{network:"bitcoin-mainnet", height, blockHash, observedAt}`. `observedAt` is a local observation time, **not** a block timestamp or an estimated height. The adapter, not an agent or receipt, supplies this view. Production integrations should obtain chain data from their independently operated, synchronized Bitcoin node and enforce their confirmation/reorg policy. A caller-supplied number, a sealed historical tip, or wall-clock extrapolation is not a fresh height oracle.

The browser reference checks matching heights and hashes from two independent explorers (mempool.space and blockstream.info). It trusts those providers; it does not validate Bitcoin consensus. Disagreement, loss of connectivity or stale observations refuse opening. Height regressions and same-height hash conflicts refuse until an explicitly reviewed recovery; the runtime does not silently reset pins. No web clock, API or JSON object establishes consensus on its own.

Revoke is `{spec:"HZ-1/revoke", human, said, sig}`. Sign `"HZ-1/revoke\n" + canonical(fields_without_sig)`. It needs no clock, height, token, server or still-live window. Receiving a valid event is permanent and idempotent. Remote runtimes must receive it, or require a fresh response from the human that has received it. Unseen revocations remain a distributed-systems limit; there is no claim of instant global revocation. The browser can revoke offline after its code is loaded; this release does not install an offline PWA shell.

## Receipts and Bitcoin

An HZ receipt signs the schedule ID and commitment, human, local authorization time, observed height view, bound action, cumulative uses/spend, short-lived HAP ticket and HAP permit. Its Ed25519 domain is `HZ-1/receipt`. It records **authorization**, not successful delivery. `verifyReceipt` reports historical integrity and the state at an explicitly supplied height/revoke set. `VALID` does not assert current authority, current chain selection or completeness of the revoke set. A height in a receipt is a signed claim until independently checked.

`verifySchedule(commit, ots, OpenTimestamps, expectedHeight?)` first binds the OTS SHA-256 file digest, then invokes standard Bitcoin proof verification. Results: SEALED, PENDING or MISMATCH. An embedded block number is not proof. SEALED only says the commitment existed by the verified block; schedules may be sealed **before H1**, and Hs need not fall inside the action window. Bitcoin does not wake the Twin or prove that no later revoke exists. The JS OTS client may use a block explorer; the standalone official Python client can verify with Bitcoin Core. Keep verification trust assumptions explicit.

The optional Money Musk submission transports a hash to the existing `echo_seals` log as HORIZON. It is included in the same ordered checkpoint calculation. Neither it nor any Money Musk API is needed to construct, revoke or independently verify HZ-1. No existing block number is reused as proof for new schedules.

## Owner encryption and long-term recovery

The browser encrypts the letter with AES-256-GCM, a random 16-byte salt and 12-byte IV, PBKDF2-SHA256 at 600,000 iterations, and AAD `HZ-1/ciphertext/1`. The passphrase stays on the device and is not stored. Keep an encrypted backup and its passphrase separately. The backup also holds an encrypted, pre-signed revocation certificate: its owner can recover and deliver a kill after losing the original device, without exporting a signing key. Do not publish that recovery certificate unless intending to revoke.

The passphrase holder can decrypt at any time. HZ-1 is **not** cryptographic timed release against its owner, automatic posthumous authorization, a legal will, perpetual hosting, key escrow or a 15/50-year security guarantee. Losing both backup/passphrase loses recovery. Preserve the public key fingerprint separately, periodically check backup recovery, and plan cryptographic migrations. 52,560 blocks per year is only a 10-minute-block estimate, never an exact calendar promise.

Taproot/Miniscript coin paths are out of this profile. CLTV constrains earliest spending; it does not implement H2 expiry or revocation. No coins or real payment rails are moved by the browser letter example.

## Conformance and falsification

L01–L17 remain in the existing Echo Law runner. L18–L24 add real signatures with synthetic heights: DARK, first LIVE height, exact expiry, revoke before wake, invalid schedule, stale height and historical stranger verification. L24a changes the signed payload reference and must be FORGED. The OTS regression includes L24b: a proof for a different digest must be MISMATCH. No vector claims a synthetic proof is a real mined timestamp.

Falsify the implementation if a DARK object dispatches; a known revoked sleeper returns DARK or ALLOW; an unrevoked expiry returns REVOKED; stale height or a historical permit dispatches; a changed ciphertext passes; a plain letter or authority body is sent for timestamping; or independent receipt verification needs a Money Musk account/API.

References: [JWT nbf/exp](https://www.rfc-editor.org/rfc/rfc7519.html), [BIP 65](https://bips.dev/65/), [OpenTimestamps](https://opentimestamps.org/).
