guides
Intended Documentation
Rust Safety-Critical Firmware (Roadmap)
Wire-format and verification-contract specification for the Intended edge verifier. The native Rust verifier crate is not yet shipped — this page is the spec for in-house verifier code.
Rust Safety-Critical Firmware (Roadmap)#
Audience: firmware engineers writing Rust for safety-critical motion control — ros2_control hardware interfaces, no_std / RTOS motor controllers, automotive ECUs, surgical real-time stacks.
Roadmap — the Rust verifier is not in the repository
There is no shipped Rust SDK or edge-verifier crate today. The crates/intended-verifier artifact referenced elsewhere does not exist in the repo yet. This page documents the token wire format and verification contract so you can write an in-house verifier now — and so that in-house verifier maps cleanly onto the shipped crate when it lands. The token format itself is real and stable (it is what the cloud signer emits); the Rust crate and the dedicated edge verifier binary are forward-looking.
Verify against the cloud today#
Until the crate ships, the recommended path is: fetch and cache the signer's JWKS from https://api.intended.so/.well-known/jwks.json on a non-RT thread, verify the RS256 signature and claims there, and pass a verified flag into your RT loop. The verification rules below are exactly what that thread must enforce.
The dev/sandbox signer is ephemeral
In dev/sandbox the JWKS endpoint serves an ephemeral per-process keypair that rotates whenever the API process restarts. Refresh JWKS on a kid cache miss, not only on a timer. A KMS-backed signer (INTENDED_PHYSICAL_KMS_KEY_ID) provides a stable key when configured.
Token wire format#
An Authority Token is an RS256 JWT. Header: { "alg": "RS256", "typ": "JWT", "kid": … }. Body:
exp is in seconds (RFC 7519); intended.expiresAtMs is in milliseconds — operationally useful for sub-second TTLs that round to the same exp. The token lifetime is dagNode.deadlineMs, not a fixed value. Enforce both exp and expiresAtMs.
Audience must be intended-edge-verifier
The signer mints aud: "intended-edge-verifier". The sample verifier in the intended-ros2 package defaults expected_audience="intended-edge" — a mismatch that rejects every valid token. Configure your verifier's expected audience to intended-edge-verifier.
Verification contract#
The verifier MUST reject the token if any of the following hold:
- Signature — does not validate against the issuer's published JWKS (selected by
kid). iss— not in the configured issuer allow-list.aud— notintended-edge-verifier.exp/expiresAtMs— past current attested time.actorIdentity— does not match the verifier's bound identity (typically the IEEE 802.1AR DevID provisioned at manufacture).oiCode— not in the operator's policy allow-list for this actor + cell.safetyBitmismatch — token claimssafetyBit: falsebut the action class requires safety-rated authorization on this site.
Use expiresAtMs for sub-second windows; do not rely on nbf.
Mint on ALLOW, verify against JWKS by kid, expire at deadlineMs. Revocation propagates via /v1/physical/revocations; offline verifiers cannot honor revocation until they reconnect.
Reference verifier sketch#
RT loop integration#
Verification is allocation-light with fixed-size buffers. Indicative budget on a 1 GHz Cortex-A:
| Op | Budget |
|---|---|
| Header parse + kid lookup | < 5 µs |
| RS256 signature verify | 1–4 ms (key-size dependent) |
| Claim extraction + checks | < 5 µs |
| Total hot path | ≤ 5 ms typical, 10 ms worst case |
For 10-ms control loops this fits one cycle. For sub-1ms loops, verify out-of-band on a separate core and pass a verified flag via a lock-free queue.
Time attestation#
attested_now_ms MUST come from PTP / NTP, not SystemTime::now() — spoofing system time is the obvious attack on time-bound credentials. Loss of trustworthy time must result in a defined safe state, not silent acceptance.
Revocation#
Poll GET /v1/physical/revocations?since=<asOfMs> and reject any token whose jti appears. An offline verifier cannot honor revocation until it reconnects; bound the offline window accordingly (see the operator guide).
Until the crate ships#
A minimal in-house verifier following this spec is a few hundred lines of Rust over jsonwebtoken + reqwest. Treat it as uncertified — Intended makes no certification claim about your verifier code. When the intended_verifier crate lands, migration is intended to be a crate swap against this same contract.
See also#
- Authority API reference — the issuer side of the contract.
- Edge-verifier operator guide — the planned deployment/operations model.
- Safety-case writing — how verification claims fit a deployment safety case.