Freeze deployment, environment, robot, and signing-key identifiers in the preregistration.
deploymentId · environmentId · robotIdKeep the native controller. WANTED adds one narrow evidence layer: six event helpers, a hardware-backed Ed25519 signer, a durable sink, and a local verifier. The adapter orders and signs each event; the independent verifier rejects structural drift, broken chains, invalid signatures, and ineligible keys before evidence leaves your infrastructure.
The adapter needs identity, a signing callback, and an accepted-event sink. Sequence and chain state advance only after the sink succeeds.
Freeze deployment, environment, robot, and signing-key identifiers in the preregistration.
deploymentId · environmentId · robotIdPass canonical bytes to a TPM, HSM, secure enclave, or equivalent non-exportable key.
sign(bytes) → signaturePersist or POST each accepted event, then durably store the returned restart checkpoint.
sink(event) → acceptedThe production signer stays outside the adapter and the verifier performs no network requests. Private keys and raw event evidence remain inside infrastructure approved by the robot operator.
import { WantedClient, createHttpSink } from "./wanted-sdk.mjs";
const wanted = new WantedClient({
deploymentId: "dep_7f2",
environmentId: "env_104",
robotId: "robot_07",
signingKeyId: "key_prod_07",
sign: bytes => secureModule.sign(bytes),
sink: createHttpSink("https://collector.example/v1/events"),
checkpoint: await durableStore.load()
});
await wanted.intervention(
"remote_guidance", 43, "task_recovery", {
actor_role: "operator",
person_count: 1,
resolution: "robot_resumed",
support_session_sha256: "…"
}
);
await durableStore.save(wanted.checkpoint());Run the independent module against exported JSONL and the frozen public-key manifest. It verifies every signature, chain link, timestamp, key boundary, and payload; then binds each stream’s activation and terminal event to the exposure ledger. Profile 0.2-RC1 separately proves those root commitments were disclosed on schedule to two independent witness organizations before outcome analysis.
node wanted-telemetry-verifier.mjs \
events.jsonl telemetry-key-manifest.json
# stdout: self-digested JSON verification report
# exit 0: every check passed
# exit 1: evidence failed verification
# exit 2: usage, file, or input error
# The same file remains importable JavaScript ESM:
import { verifyTelemetryJsonl } from
"./wanted-telemetry-verifier.mjs";Native ROS 2 topics, simulator callbacks, task planners, and operator consoles map into the same six calls.
wanted.lifecycle("activation", { participant_acceptance_ref: "controlled://acceptance/42", activation_record_sha256: "…" })wanted.state("available", { autonomous_service_capable: true })wanted.request("privacy", { evidence_ref: "local://request/42" })wanted.action("put mug in dishwasher", { proactive: false })wanted.intervention("remote_guidance", 43, "task_recovery", { person_count: 1, resolution: "robot_resumed" })wanted.incident("L1", "Brief hallway obstruction")RE1 binds each root to a verified signed telemetry prefix, REB1 reproduces the cross-deployment collection, and 10 REBC1 vectors prove implementation parity before RC1 witnesses establish chronology. Raw events and signing keys stay local.
events → verified signed prefix
envelope → prefix + prior-root digest
prepare → canonical receipt bytes
sign → witness HSM / TPM / KMS
attach → signature self-verification
verify → registered key + lifecycle
No private-key flag. No network request.
One receipt still requires full RC1 quorum.A benchmark this long cannot depend on process memory. Persist the checkpoint after every accepted event and test crash recovery before human exposure.
Only one process may issue the next sequence for a deployment. Fail over with a lease or fencing token.
The SDK advances sequence and chain state only after the sink acknowledges the event.
Store next_sequence, previous_event_hash, and last_occurred_at before another event can be emitted.
After a crash, recover the collector’s accepted tail before emitting. Event IDs make retries idempotent.