You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
An LCT's hardware-binding level is a self-declared number that nothing derives, validates, or can
falsify — and the struct cannot even express what canon requires to justify the top level. Two
concrete defects fall out, plus a semantic divergence between the code's ladder and canon's.
Raised by dp's key-custody ruling (2026-08-18, issue #729): "passphrase from environment … is NOT a
production-acceptable solution." If custody posture is going to mean anything, the capability level
that advertises it must be derived from how the key is actually held, not set by whoever
constructs the struct.
Defect 1 — the code's default sits inside canon's HARDWARE band
0.85 is outside level 4's band and inside level 5's. Every LCT built with the default therefore
advertises a ceiling canon reserves for hardware-bound identity, while its own description says "Software-bound keys (development)". Lct::trust_ceiling() (lct.rs:590) exposes it as an
accessor, so it is built to be consumed by relying parties.
Defect 2 — level 5 is unfalsifiable by construction
Canon §2.7 requires, for level 5:
binding.hardware_anchor — a valid EAT token
binding.hardware_type — "tpm2", "trustzone", or "secure_element"
HardwareBinding (lct.rs:71-83) has exactly three fields: level, description, trust_ceiling. There is no field for the anchor or the type. So an LCT can be assigned level: 5 with no attestation attached and nothing anywhere can check the claim — the evidence canon
requires has no carrier. This is the same shape as a drift check that cannot fire: the indicator
exists, and nothing can make it false.
Searched web4-core/src, hub/hub-lib/src, hub/hub-daemon/src for CapabilityLevel|capability_level: no hits. Nothing derives the level from anything.
Defect 3 — the two ladders disagree about what the levels mean
Canon documents the same 0–5 scale as STUB / MINIMAL / BASIC / STANDARD / FULL / HARDWARE, where level 4 is "Society-issued with birth certificate" — a statement about provenance, not about key
storage. The code's ladder is a key-custody ladder; canon's is a capability/provenance ladder.
They collide at every level except 5.
This matters beyond tidiness: a consumer reading level: 4 cannot tell whether it means "encrypted
keys on disk" or "society-issued with a birth certificate", and those licence very different
decisions.
Requested
Derive, don't declare. The binding level should be computed from how the key is actually held
at the time the LCT is built (in-memory / env-fed / file / OS keystore / hardware-attested), not
passed in. Where derivation is impossible, the level should be the lowest consistent with the
evidence, not the most flattering.
Give level 5 its carrier: hardware_anchor and hardware_type fields per canon §2.7, and
refuse to construct level 5 without a well-formed anchor. A level with no evidence field cannot be
audited.
Fix the default — level 4 with trust_ceiling: 0.85 is out of band. Either the default drops
into 0.6–0.8, or the default level changes, or canon's band moves; the three must agree.
Reconcile the two ladders (this issue's canon half). Decide whether 0–5 is capability or key
custody. If both are wanted they are two axes and need two fields — which is the same lesson as
the interface-planes work (canon: specify interface planes (fact planes x exposure classes) #727): orthogonal things wearing one name drift silently.
Summary
An LCT's hardware-binding level is a self-declared number that nothing derives, validates, or can
falsify — and the struct cannot even express what canon requires to justify the top level. Two
concrete defects fall out, plus a semantic divergence between the code's ladder and canon's.
Raised by dp's key-custody ruling (2026-08-18, issue #729): "passphrase from environment … is NOT a
production-acceptable solution." If custody posture is going to mean anything, the capability level
that advertises it must be derived from how the key is actually held, not set by whoever
constructs the struct.
Defect 1 — the code's default sits inside canon's HARDWARE band
web4-core/src/lct.rs:85-93:web4-standard/core-spec/lct-capability-levels.md§2.1:0.85 is outside level 4's band and inside level 5's. Every LCT built with the default therefore
advertises a ceiling canon reserves for hardware-bound identity, while its own description says
"Software-bound keys (development)".
Lct::trust_ceiling()(lct.rs:590) exposes it as anaccessor, so it is built to be consumed by relying parties.
Defect 2 — level 5 is unfalsifiable by construction
Canon §2.7 requires, for level 5:
binding.hardware_anchor— a valid EAT tokenbinding.hardware_type—"tpm2","trustzone", or"secure_element"HardwareBinding(lct.rs:71-83) has exactly three fields:level,description,trust_ceiling. There is no field for the anchor or the type. So an LCT can be assignedlevel: 5with no attestation attached and nothing anywhere can check the claim — the evidence canonrequires has no carrier. This is the same shape as a drift check that cannot fire: the indicator
exists, and nothing can make it false.
Searched
web4-core/src,hub/hub-lib/src,hub/hub-daemon/srcforCapabilityLevel|capability_level:no hits. Nothing derives the level from anything.
Defect 3 — the two ladders disagree about what the levels mean
lct.rs:73-76documents the scale as:Canon documents the same 0–5 scale as STUB / MINIMAL / BASIC / STANDARD / FULL / HARDWARE, where
level 4 is "Society-issued with birth certificate" — a statement about provenance, not about key
storage. The code's ladder is a key-custody ladder; canon's is a capability/provenance ladder.
They collide at every level except 5.
This matters beyond tidiness: a consumer reading
level: 4cannot tell whether it means "encryptedkeys on disk" or "society-issued with a birth certificate", and those licence very different
decisions.
Requested
at the time the LCT is built (in-memory / env-fed / file / OS keystore / hardware-attested), not
passed in. Where derivation is impossible, the level should be the lowest consistent with the
evidence, not the most flattering.
hardware_anchorandhardware_typefields per canon §2.7, andrefuse to construct level 5 without a well-formed anchor. A level with no evidence field cannot be
audited.
trust_ceiling: 0.85is out of band. Either the default dropsinto 0.6–0.8, or the default level changes, or canon's band moves; the three must agree.
custody. If both are wanted they are two axes and need two fields — which is the same lesson as
the interface-planes work (canon: specify interface planes (fact planes x exposure classes) #727): orthogonal things wearing one name drift silently.
Related
private-context/proposals/hub-hestia-canon-sync-review-2026-08-18.md§9.