# PULSE-1 accepted-lease inspection kit

Reference release 0.9.1. Open specification and code under 0BSD. No token,
authority server, mandatory Money Musk domain or registration with this project.

This kit gives implementers a reproducible target for **read-only inspection of
an already accepted lease**. It contains 110 public adversarial fixtures, golden
signing bytes, a JavaScript inspector and a separately implemented Python verifier.
The Python implementation uses `cryptography` and the project's Python HAP ticket
verifier; it never loads or calls JavaScript. Both implementations are authored by
this project. This is not independent adoption, an independent audit, full executor
compatibility, physical proximity testing or biological-presence validation.

The [external adapter runner](PULSE-ADAPTER.md) lets another team run its own
verifier against this exact corpus and retain a reproducible local report. It
does not fetch implementations, assess independence, certify a deployment or
authorize any action. Reports account for every case and distinguish evidence
refusals from adapter failures.

The HAP-1/1, WA-1 and PULSE-1 signed grammars are unchanged. The inspection, pin,
context and corpus schemas each have their own version. A future incompatible
inspection contract needs a new inspection version; signed grammar changes still
require a new signed profile.

## Reproduce locally

Unpack the complete reference archive, then use a local Python environment with
the dependency versions in `requirements-verify.txt`:

```sh
python3 -m venv /tmp/pulse-verify
/tmp/pulse-verify/bin/pip install -r hap1/requirements-verify.txt
/tmp/pulse-verify/bin/python scripts/hap1-pulse-vectors.py --check
HAP1_PYTHON=/tmp/pulse-verify/bin/python node --test scripts/hap1-pulse-conformance.mjs
node --test scripts/hap1-pulse-regressions.mjs
python3 scripts/build-hap1.py --check
```

Install dependencies before disconnecting. Verification has no network dependency.
The conformance tests disable the JavaScript and Python networking APIs. This is
a test guard, not an OS sandbox for untrusted implementations.

Corpus `PULSE-1/conformance/1` is the exact file `pulse-vectors.json`:

```text
SHA-256 32136bfd8268dddf971dab2982db8588d0a1619a94e90f4689cb46d99ee95d1c
Cases   110
Scope   accepted-lease-inspection-only
```

Every case has a unique `name`, `operation:"inspect"`, `input`, and exact
`expected` report. Compare the complete report, not only an exit code or a count.
The generator uses deliberately public Ed25519 seeds and imports neither PULSE
verifier. Many hostile specimens are re-signed so validation must catch invalid
fields and bindings even when the signature is authentic. **Never provision a
fixture key, ticket or sensor claim in a real deployment.**

Coverage includes wrong issuers/executors, ticket/policy substitution, unknown
versions/fields, altered signature domains, unsafe counters, stale/replaced cached
pulses, quiet radio at 2 seconds, the exclusive 5-second boundary, 40-second and
hour-old leases, stopped/revoked/used state, restart/reconnect, clock rollback,
heartbeat failure/expiry, private-field leakage, fixture sensor opt-in and silent
policy downgrade. Separate tests check canonical file input and CLI deadlines.

## Inspection contract, version 1

JavaScript: `inspectPulse({pin,context,ticket,policy,pulse,now})` from
`pulse-inspect.mjs` or the package export `./pulse-inspect`.
Python: `inspect_pulse(value)` in `pulse-verify.py` takes that same object.

The entire input must fit in 32,768 bytes of canonical HAP JSON. It has exactly
those six fields. Strings are printable ASCII, object members are sorted, numbers
are safe integers, and unknown fields refuse. `now` is an explicit nonnegative
Unix millisecond time for reproducible or historical inspection, not an attested
clock. The local operator CLI chooses its own time.

**Pin and context must come from trusted executor state retained independently
of the candidate evidence.** A sender cannot choose or reset them. Splitting
them into files does not authenticate their provenance. The reference does not
automatically export a live executor snapshot; integrations must capture and
protect their own consistent state.

| Object | Exact fields and meaning |
| --- | --- |
| `pin` | `schema`, `issuerPublicKey`, `executorPublicKey`, `ticketHash`, `policyHash`, `acceptTestSensors` |
| `pin.schema` | `PULSE-1/pin/1` |
| Pin keys and hashes | 32-byte lowercase hex. Policy hash pins the immutable heartbeat policy independently of the candidate. Executor key must identify the ticket audience. |
| `pin.acceptTestSensors` | Boolean, normally `false`. Only an explicit trusted test configuration accepts source `fixture`. |
| `context` | `schema`, `session`, `maxCounter`, `acceptedPulseHash`, `used`, `revoked`, `stopped`, `radio`, `lastTime` |
| `context.schema` | `PULSE-1/context/1` |
| `session`, `acceptedPulseHash` | 32-byte lowercase hex, or null for absent state. Both must match the accepted pulse for a successful inspection. |
| `maxCounter`, `lastTime` | Retained nonnegative safe integers. Counter must equal the accepted pulse counter. Clock high-water mark must be at least the pulse's signing time and no later than `now`. |
| `used`, `revoked`, `stopped` | Actual booleans. Each must be false for success. |
| `radio` | `NEARBY` or `QUIET`. Both can retain a previously accepted pulse within its original deadline. These labels do not measure physical distance. |
| `ticket`, `policy`, `pulse` | Exact signed objects defined by HAP-1 and [PULSE-1](PULSE.md). No private band, BPM or waveform belongs in the signed evidence. |

The inspector verifies the ticket and policy signatures, pinned keys and hashes,
pulse signature and exact bindings, retained session/counter/accepted hash, local
state flags, ticket/pulse deadlines and optional heartbeat freshness. All deadlines
are exclusive, with no grace period. Freshness never depends on internet status.

Successful report:

```json
{"schema":"PULSE-1/inspection/1","profile":"PULSE-1","verified":true,"code":"PULSE_VERIFIED","executionAuthorized":false,"consumed":false,"counterPersisted":false,"statePersisted":false}
```

Refusal changes `verified` to false and `code` to `INVALID_PULSE_EVIDENCE`.
The report contains no keys, identifiers, readings, paths or input excerpts.

**Success is not ALLOW.** This interface does not verify an exact-action HAP
permit, payload, remaining budget, pending challenge or unseen revocation. It
cannot discover state rollback or a newer snapshot. Inspection can be repeated;
it never consumes or persists anything. In particular, the same retained counter
is expected for cached inspection. Incoming pulse acceptance still requires a
strictly newer counter in an atomic durable transaction.

An authentic newer pulse carrying a failed heartbeat must supersede the older
passing pulse in the executor. A negative inspection report must not be used to
discard that state transition. Keep `accept()`, `execute()` and final
`permit.dispatch()` in the dedicated wrapper; never add an inspection-based bypass.
The tests deliberately pass a positive inspection report to the real executor:
it refuses, and only the actual owner permit can dispatch once.

## Local operator command

```sh
/tmp/pulse-verify/bin/python hap1/pulse-verify.py \
  --pin retained-pin.json --context retained-context.json \
  --ticket ticket.json --policy policy.json --pulse pulse.json
```

Each file must be a regular file of at most 32,768 bytes, containing canonical
HAP JSON with at most one trailing LF. Total canonical evidence, including the
clock field, is also bounded to 32,768 bytes. Duplicate fields, alternate numeric
spellings, BOMs, invalid UTF-8, final-component symlinks, special files, unknown
flags, repeated flags and missing files refuse. Parent-directory integrity remains
the operator's responsibility. Platforms without `O_NOFOLLOW` and `O_NONBLOCK`
refuse rather than weaken file handling.

The CLI checks its local clock before and after verification and refuses expiry
or an observed backward step. There is no `--now` override. It exits 0 for verified
evidence and 1 for refusal, with one metadata-only JSON report on stdout and no
input diagnostics. This does not provide hardware monotonic time or permission
for a later action. The explicit-clock test drivers are test utilities only.

## Evidence for independent deployment

Other implementers can use the same corpus without approval from Money Musk.
Publish authors, source repository, exact commit, platform/dependency versions,
corpus hash, per-case results and the precise components implemented. A second
team's passing inspector is evidence about inspection only. Full execution needs
durable state, crash/rollback, concurrent replay, caps, permit and final provider
boundary tests as well as the shared cases.

| Field trial | Required observation |
| --- | --- |
| Two actual devices, internet disabled, local link available | Local pulse/permit exchange and a simulated act succeed without an authority server. |
| Radio link removed after acceptance | One prepared act can use a remaining valid window; no act occurs at or after the original deadline. |
| Revoke delivered while a fresh pulse exists | Durable acknowledgement precedes refusal of later dispatch; an unreachable executor is never reported as acknowledged. |
| Suspend/resume, restart, storage failure and clock changes | No restored old lease or permissive fallback; record the platform's real clock and backgrounding limits. |
| Heartbeat enabled with sensor loss or stale/failed contact | Refusal, no automatic downgrade, and no raw readings in executor storage or exported reports. |
| Provider preparation crosses the deadline | No irreversible send after final refusal; receipts and reconnection cannot revive the operation. |

Use synthetic accounts and publish aggregate results without private keys,
personal readings or correlated identifiers. Physical tests, independent security
review and independent operation remain outstanding for this reference. Passing
the corpus does not establish identity, informed consent or biological liveness.
