Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Verification

Verification is one pure function. The chain, the KYB attestation, the consent grant, the revocation set, the current time, and the verifier’s list of trusted attesters all arrive as arguments — the function does no I/O and reads no clock. The identical logic runs in the verifier portal, the worker wallet, and the dependency-free offline page, and is mirrored byte-for-byte in TypeScript. The implementation is crates/tenure-core/src/verify.rs.

Because the current time and the freshness window are inputs rather than globals, the same bundle yields a deterministic verdict for any chosen clock and recency policy — and the verifier owns its trusted-attester list the way a browser owns its root store.

The five checks

The predicate runs in order and returns the first failure, or Verified. (A prerequisite step first confirms the employer descriptor is signed by the employer key it declares.)

  1. KYB. A valid, unexpired KYB attestation binds the employer key to the displayed legal entity, and the attester that signed it is in the verifier’s trust list. A failure here always names which attester signed — even an untrusted one — so the verifier can decide for itself.
  2. Chain. The epoch chain verifies back to the employer key; each attestation is signed by the registrar of its epoch, sits inside that epoch’s sequence range, and is covered by a delegation that allows its type and contains its as_of. A mint outside every delegation is rejected here even though it is signed.
  3. Consent. The share grant is signed by the worker’s per-employer key, is unexpired, names every presented attestation, and matches the audience presenting it.
  4. Freshness. If any presented attestation is in the revocation set, the verdict is Revoked regardless of head age. Otherwise, if the checkpoint is older than the freshness window, the verdict is StaleHead — evidence decays by design, so a saved bundle past the window can never read Verified.
  5. Resolution. A claim verifies only if its family is the latest unsuperseded family for its fact; a stale variant — exact, band, or threshold — is rejected, as is any attestation whose own valid_until has passed.

Verdicts

The verdict is explicit and never scored. Verified proves the employer signed the statements — not that they are true.

VerdictMeaning
VerifiedAll checks pass. Carries the employer’s legal name, the attester and its methods, the claims at the granted granularity, and the “not revoked as of” time and head age
RevokedA presented attestation or its family is revoked or superseded
GrantExpiredThe share grant has expired
ChainInvalidA structural failure — broken chain, mint outside delegation, tampered bytes — with a reason
EmployerUnverifiedKYB failed or the attester is not trusted; names the attester that signed
StaleHeadThe checkpoint is older than the freshness window

The verdict card distinguishes an offline check (against a head from, say, 13:40) from a live recency check, and shows the head age explicitly.

Importing a full log

Verifying a presented bundle is the common path. Importing an entire log — a ragequit file, or a new registrar adopting an employer — is stricter and runs once: it verifies the descriptor, the KYB attestation, the epoch chain, and every delegation, then replays every entry (registrar signatures, hash-chain continuity, and type/rate-cap accounting), verifies the final signed head, and materializes the current state plus the revocation set. A new registrar runs exactly this before reporting its head, which the Signer then cross-checks against the heads it witnessed. See Misbehavior & switching.