@ours.network/notifications 0.1.1 → 0.3.1-nightly.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +122 -225
- package/dist/chat-target.d.ts +9 -0
- package/dist/chat-target.js +12 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +13 -445
- package/dist/presence.d.ts +12 -0
- package/dist/presence.js +55 -145
- package/dist/server.d.ts +26 -0
- package/dist/server.js +145 -0
- package/dist/store.d.ts +63 -0
- package/dist/store.js +181 -0
- package/dist/validation.d.ts +9 -0
- package/dist/validation.js +60 -0
- package/package.json +14 -24
- package/dist/config.js +0 -104
- package/dist/daemon.js +0 -353
- package/dist/http.js +0 -31
- package/dist/log-store.js +0 -48
- package/dist/provision.js +0 -29
- package/dist/push.js +0 -6
- package/dist/web-push-sender.js +0 -41
- package/mufl_code/20E39399689579D5AFA5132C59DEDDD328C3BCA1A74D546F2193B36585DDD283.muflo +0 -0
- package/mufl_code/config.mufl +0 -21
- package/mufl_code/core/.github/FUNDING.yml +0 -3
- package/mufl_code/core/.github/workflows/docs.yml +0 -39
- package/mufl_code/core/.github/workflows/tests.yml +0 -66
- package/mufl_code/core/COMMERCIAL-LICENCE.md +0 -25
- package/mufl_code/core/COMPATIBILITY.md +0 -221
- package/mufl_code/core/CONTRIBUTING.md +0 -37
- package/mufl_code/core/LICENSE +0 -98
- package/mufl_code/core/NOTIFICATIONS_CONTRACT.md +0 -290
- package/mufl_code/core/README.md +0 -91
- package/mufl_code/core/SECURITY.md +0 -40
- package/mufl_code/core/TRADEMARKS.md +0 -24
- package/mufl_code/core/a2a_capabilities.mm +0 -449
- package/mufl_code/core/a2a_cluster.mm +0 -601
- package/mufl_code/core/a2a_control.mm +0 -90
- package/mufl_code/core/a2a_messaging.mm +0 -4817
- package/mufl_code/core/a2a_monitoring.mm +0 -94
- package/mufl_code/core/a2a_notification_integration.mm +0 -144
- package/mufl_code/core/a2a_notifications.mm +0 -1127
- package/mufl_code/core/a2a_protocol.mm +0 -246
- package/mufl_code/core/a2a_versions.mm +0 -801
- package/mufl_code/core/config.mufl +0 -29
- package/mufl_code/core/docs/.vitepress/config.mts +0 -58
- package/mufl_code/core/docs/citations.json +0 -688
- package/mufl_code/core/docs/guide/01-vendor-the-core.md +0 -50
- package/mufl_code/core/docs/guide/02-configure-and-compile.md +0 -100
- package/mufl_code/core/docs/guide/03-wire-the-host.md +0 -154
- package/mufl_code/core/docs/guide/04-connect-and-message.md +0 -156
- package/mufl_code/core/docs/guide/05-test-your-app.md +0 -75
- package/mufl_code/core/docs/guide/index.md +0 -63
- package/mufl_code/core/docs/how-it-works/capabilities-and-control.md +0 -77
- package/mufl_code/core/docs/how-it-works/cluster.md +0 -65
- package/mufl_code/core/docs/how-it-works/identity.md +0 -56
- package/mufl_code/core/docs/how-it-works/invites-and-contacts.md +0 -76
- package/mufl_code/core/docs/how-it-works/messaging.md +0 -55
- package/mufl_code/core/docs/how-it-works/monitoring-and-config.md +0 -72
- package/mufl_code/core/docs/how-it-works/overview.md +0 -45
- package/mufl_code/core/docs/how-it-works/versioning.md +0 -116
- package/mufl_code/core/docs/index.md +0 -27
- package/mufl_code/core/docs/package-lock.json +0 -3467
- package/mufl_code/core/docs/package.json +0 -15
- package/mufl_code/core/docs/reference/contributing.md +0 -26
- package/mufl_code/core/docs/reference/glossary.md +0 -108
- package/mufl_code/core/docs/reference/implementations.md +0 -23
- package/mufl_code/core/docs/reference/modules.md +0 -19
- package/mufl_code/core/docs/scripts/check-citations.mjs +0 -36
- package/mufl_code/core/docs/scripts/check-denylist.mjs +0 -30
- package/mufl_code/core/docs/scripts/gen-llms.mjs +0 -32
- package/mufl_code/core/docs/workflows/cluster.md +0 -89
- package/mufl_code/core/docs/workflows/contact-exchange.md +0 -60
- package/mufl_code/core/docs/workflows/contact-restore.md +0 -60
- package/mufl_code/core/docs/workflows/control-verbs.md +0 -70
- package/mufl_code/core/docs/workflows/index.md +0 -57
- package/mufl_code/core/docs/workflows/introductions.md +0 -60
- package/mufl_code/core/docs/workflows/messaging.md +0 -75
- package/mufl_code/core/docs/workflows/monitoring.md +0 -84
- package/mufl_code/core/docs/workflows/notifications.md +0 -109
- package/mufl_code/core/release-notes/0.1.md +0 -60
- package/mufl_code/core/release-notes/0.3.md +0 -22
- package/mufl_code/core/release-notes/0.4.md +0 -97
- package/mufl_code/core/tests/README.md +0 -83
- package/mufl_code/core/tests/compat/README.md +0 -82
- package/mufl_code/core/tests/compat/compat.mjs +0 -245
- package/mufl_code/core/tests/compat/compat_peer.mjs +0 -146
- package/mufl_code/core/tests/compat/run_compat.sh +0 -96
- package/mufl_code/core/tests/corpus.mjs +0 -139
- package/mufl_code/core/tests/corpus_actor.mu +0 -242
- package/mufl_code/core/tests/fatcompile_actor.mu +0 -52
- package/mufl_code/core/tests/mig.mjs +0 -805
- package/mufl_code/core/tests/mig_actor.mu +0 -518
- package/mufl_code/core/tests/migapp.mjs +0 -431
- package/mufl_code/core/tests/migapp_actor.mu +0 -294
- package/mufl_code/core/tests/mufl_semantics/run.sh +0 -69
- package/mufl_code/core/tests/mufl_semantics/t11_three_version.mufl +0 -47
- package/mufl_code/core/tests/mufl_semantics/t2_extra_fields.mufl +0 -11
- package/mufl_code/core/tests/mufl_semantics/t7_runtime.mufl +0 -30
- package/mufl_code/core/tests/mufl_semantics/t9_passthrough.mufl +0 -19
- package/mufl_code/core/tests/mufl_semantics/t_str_order.mufl +0 -19
- package/mufl_code/core/tests/notif.mjs +0 -755
- package/mufl_code/core/tests/notif_actor.mu +0 -450
- package/mufl_code/core/tests/protocol_container.mm +0 -18
- package/mufl_code/core/tests/run.sh +0 -65
- package/mufl_code/core/tests/run_corpus.sh +0 -51
- package/mufl_code/core/tests/run_fatcompile.sh +0 -40
- package/mufl_code/core/tests/run_mig.sh +0 -51
- package/mufl_code/core/tests/run_migapp.sh +0 -51
- package/mufl_code/core/tests/run_notif.sh +0 -57
- package/mufl_code/core/tests/test.mjs +0 -750
- package/mufl_code/core/tests/test_actor.mu +0 -564
- package/mufl_code/core/tests/test_common.mjs +0 -93
- package/mufl_code/core/version.mm +0 -24
- package/mufl_code/packet.mu +0 -170
- package/mufl_code/protocol_container.mm +0 -18
- package/scripts/gen-vapid.mjs +0 -16
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
// Shared ours protocol library.
|
|
2
|
-
//
|
|
3
|
-
// The wire-facing shapes and verification logic common to every ours
|
|
4
|
-
// packet (the agent/MCP packet, the web messenger, and future clients).
|
|
5
|
-
// Everything here is network protocol surface: peers exchange these shapes
|
|
6
|
-
// byte-for-byte, so any change is a protocol revision — keep the shapes
|
|
7
|
-
// backward-compatible and bump version.mm with every edit to this core.
|
|
8
|
-
library a2a_protocol loads library
|
|
9
|
-
key_utils,
|
|
10
|
-
key_storage,
|
|
11
|
-
address_document_types,
|
|
12
|
-
a2a_capabilities
|
|
13
|
-
{
|
|
14
|
-
metadef contact_t: ($name -> str, $container_id -> global_id).
|
|
15
|
-
|
|
16
|
-
// ---- identity hierarchy wire shapes ---------------------------------
|
|
17
|
-
// Delegation certificate: "role X belongs to root Y, signed by Y". The
|
|
18
|
-
// signature is over the core's _value_id, binding the role's container
|
|
19
|
-
// id AND its full key material (the address-document hash) to one root.
|
|
20
|
-
// An identity carrying NIL here is a root (or a legacy flat identity) —
|
|
21
|
-
// detection is structural, not a flag. v1 revocation == delete the role.
|
|
22
|
-
metadef delegation_core_t: (
|
|
23
|
-
$version -> int,
|
|
24
|
-
$role_cid -> global_id,
|
|
25
|
-
$role_ad_hash -> hash_code,
|
|
26
|
-
$role_id -> str,
|
|
27
|
-
$root_cid -> global_id,
|
|
28
|
-
$issued_at -> time
|
|
29
|
-
).
|
|
30
|
-
metadef delegation_cert_t: ($c -> delegation_core_t, $s -> crypto_signature).
|
|
31
|
-
// Self-signed root profile, carried in role invites so an external peer
|
|
32
|
-
// learns WHO is behind the role. It includes the root's key list, so the
|
|
33
|
-
// receiver can verify both this signature and the delegation cert with
|
|
34
|
-
// no prior knowledge of the root.
|
|
35
|
-
metadef root_profile_core_t: (
|
|
36
|
-
$version -> int,
|
|
37
|
-
$root_cid -> global_id,
|
|
38
|
-
$name -> str,
|
|
39
|
-
$bio -> str,
|
|
40
|
-
$keys -> key_utils::t_publickey(,)
|
|
41
|
-
).
|
|
42
|
-
metadef root_profile_t: ($p -> root_profile_core_t, $s -> crypto_signature).
|
|
43
|
-
|
|
44
|
-
// §3c root-half CP binding. The root self-signs {version, context_tag,
|
|
45
|
-
// root_cid, cid_cp} — see the verifier and context tag lower in this library
|
|
46
|
-
// for the full rationale. Carried (as a blob) on the leg-1/leg-3 identity bundle.
|
|
47
|
-
metadef root_cp_binding_core_t: (
|
|
48
|
-
$version -> int,
|
|
49
|
-
$context_tag -> str,
|
|
50
|
-
$root_cid -> global_id,
|
|
51
|
-
$cid_cp -> global_id
|
|
52
|
-
).
|
|
53
|
-
metadef root_cp_binding_t: ($c -> root_cp_binding_core_t, $s -> crypto_signature).
|
|
54
|
-
// Verified root linkage learned about a contact (from its role invite or
|
|
55
|
-
// a sibling introduction). Kept beside `contacts` so old state blobs
|
|
56
|
-
// (whose contact_t has no such fields) import unchanged.
|
|
57
|
-
metadef contact_root_t: ($root_cid -> global_id, $root_name -> str, $role_id -> str).
|
|
58
|
-
|
|
59
|
-
// ---- core 3.0 ephemeral-key slim invite -----------------------------
|
|
60
|
-
// THE invite shape (the fat invite_t / invite_role_t were removed in core 3.0
|
|
61
|
-
// together with the old offline-redeem path). Carries ONLY an ephemeral
|
|
62
|
-
// encryption pubkey, the inviter's routing/identity cid, a display name, and
|
|
63
|
-
// the crypto scheme id — NO identity keys, NO self-sigs, NO cert, NO root
|
|
64
|
-
// profile. The inviter's (and responder's) address documents + delegation
|
|
65
|
-
// chains move to a two-message ENCRYPTED hop after redemption:
|
|
66
|
-
//
|
|
67
|
-
// (OOB) inviter ─► responder : invite_eph_t (this shape)
|
|
68
|
-
// leg 1 responder ─► inviter : submit_invite_response (BARE send; a box to
|
|
69
|
-
// eph_pub_inviter) — cleartext envelope:
|
|
70
|
-
// { $invite_id -> global_id, $epk -> publickey_encrypt /*responder eph pub*/,
|
|
71
|
-
// $v -> int /*scheme*/, $data -> crypto_message }
|
|
72
|
-
// leg 3 inviter ─► responder : complete_invite (ALSO a BARE send; a box to the
|
|
73
|
-
// RESPONDER's eph pub from leg 1 — it cannot ride encrypted_channel because
|
|
74
|
-
// the responder has not registered the inviter yet, and the stdlib exposes
|
|
75
|
-
// no raw long-term privkey to box against instead). Same envelope shape:
|
|
76
|
-
// { $invite_id -> global_id, $epk -> publickey_encrypt /*inviter eph pub*/,
|
|
77
|
-
// $v -> int /*scheme*/, $data -> crypto_message }
|
|
78
|
-
// Both boxes' `data` decrypt to the SAME identity bundle:
|
|
79
|
-
// { $ad -> t_address_document, $cert -> bin+, $root_profile -> bin+,
|
|
80
|
-
// $cp_binding -> bin+, $invite_id -> global_id }
|
|
81
|
-
// After leg 3, both sides hold the other's verified AD and encrypted_channel
|
|
82
|
-
// resumes for all subsequent send_message traffic.
|
|
83
|
-
// $d invite_id (correlates leg-1 to the stored eph privkey; single-use)
|
|
84
|
-
// $c inviter container_id (routing target + identity pin)
|
|
85
|
-
// $n inviter display name (metadata only) $k eph_pub_inviter $v scheme id
|
|
86
|
-
// $iv invite-format version (NULLABLE). The version of the invite/handshake
|
|
87
|
-
// contract the inviter speaks. A redeemer that reads it as NIL treats the
|
|
88
|
-
// inviter as a pre-versioning node (one that predates this field) and
|
|
89
|
-
// down-levels its own address document to v1 (omits $e2e_bundle, sets
|
|
90
|
-
// $version->1) so that older peer accepts it; a present value means the
|
|
91
|
-
// inviter understands this contract. The field is wire-safe in BOTH
|
|
92
|
-
// directions: an older decoder ignores the extra member and a newer decoder
|
|
93
|
-
// reads a missing one as NIL, because mufl metadefs are name-keyed and this
|
|
94
|
-
// field is nullable. Bump it ONLY for a change that breaks cross-version
|
|
95
|
-
// invite/handshake compatibility — one that forces the sender to know the
|
|
96
|
-
// peer's version to interoperate. The confirmed cases are:
|
|
97
|
-
// - invite_eph_t changing shape such that an older decoder cannot consume it;
|
|
98
|
-
// - the address-document format moving to an incompatible version (the
|
|
99
|
-
// v1->v2 $e2e_bundle bump) so a v1 peer would reject a v2 AD.
|
|
100
|
-
metadef invite_eph_t: (
|
|
101
|
-
$d -> global_id,
|
|
102
|
-
$c -> global_id,
|
|
103
|
-
$n -> str,
|
|
104
|
-
$k -> publickey_encrypt,
|
|
105
|
-
$v -> int,
|
|
106
|
-
$iv -> int+
|
|
107
|
-
).
|
|
108
|
-
|
|
109
|
-
// A reply pointer carried on a message: the stable wire id of the message
|
|
110
|
-
// being replied to, plus an optional 1-based sentence index into that
|
|
111
|
-
// message's text. wire_id is the stringified _new_id the sender stamped on
|
|
112
|
-
// the original (msg_id is receiver-local, so it cannot be referenced across
|
|
113
|
-
// sides). The recipient resolves this against its own copy of the referenced
|
|
114
|
-
// message IF it still holds it — agents GC fast, so this is best-effort
|
|
115
|
-
// context for the recipient, not durable thread state.
|
|
116
|
-
metadef reply_ref_t: ($wire_id -> str, $sentence -> int+).
|
|
117
|
-
|
|
118
|
-
// ---- local contact book wire shapes ---------------------------------
|
|
119
|
-
// Introduction credential, minted PER CONNECT ATTEMPT by the host's
|
|
120
|
-
// registrar packet (never stored in the book). It binds the joiner's
|
|
121
|
-
// identity AND address document to one target, with freshness + a nonce,
|
|
122
|
-
// so possession of book material alone authorizes nothing: only the
|
|
123
|
-
// registrar (whose key never leaves the host) can mint one, which is
|
|
124
|
-
// what makes "local" a cryptographic property rather than a convention.
|
|
125
|
-
metadef intro_t: (
|
|
126
|
-
$version -> int,
|
|
127
|
-
$joiner_cid -> global_id,
|
|
128
|
-
$joiner_ad_hash -> hash_code,
|
|
129
|
-
$target_cid -> global_id,
|
|
130
|
-
$iat -> time,
|
|
131
|
-
$nonce -> global_id
|
|
132
|
-
).
|
|
133
|
-
metadef signed_intro_t: ($i -> intro_t, $s -> crypto_signature).
|
|
134
|
-
// What the registrar signs for a contact-book entry (tamper-evidence for
|
|
135
|
-
// the host-side book file; verified by the SENDER before connecting).
|
|
136
|
-
metadef book_entry_t: ($version -> int, $name -> str, $ad_hash -> hash_code).
|
|
137
|
-
|
|
138
|
-
// Verify a delegation chain presented by a peer: the root profile is
|
|
139
|
-
// internally consistent and the cert binds the peer's container id AND
|
|
140
|
-
// its address document to that root, both signed by the root's keys.
|
|
141
|
-
// The chain is self-contained (the profile carries the root's key list),
|
|
142
|
-
// so it proves "this role belongs to the root that signed it" — it does
|
|
143
|
-
// NOT vouch for who the root is (root verification is deferred to v2).
|
|
144
|
-
// Aborts on any mismatch; returns the linkage to record.
|
|
145
|
-
fn verify_peer_delegation (peer_cid: global_id, peer_ad_hash: hash_code, cert: delegation_cert_t, rp: root_profile_t) -> contact_root_t
|
|
146
|
-
{
|
|
147
|
-
abort "Unsupported delegation certificate version." when (cert $c $version) != 1.
|
|
148
|
-
abort "Unsupported root profile version." when (rp $p $version) != 1.
|
|
149
|
-
abort "Delegation certificate was issued for a different identity." when (cert $c $role_cid) != peer_cid.
|
|
150
|
-
abort "Delegation certificate does not match the peer's address document." when (cert $c $role_ad_hash) != peer_ad_hash.
|
|
151
|
-
abort "Root profile does not match the delegation certificate's root." when (rp $p $root_cid) != (cert $c $root_cid).
|
|
152
|
-
abort "Root profile signature is invalid." when key_storage::check_signature_new_container (_value_id (rp $p)) (rp $s) (rp $p $keys) != TRUE.
|
|
153
|
-
abort "Delegation certificate was not signed by its root." when key_storage::check_signature_new_container (_value_id (cert $c)) (cert $s) (rp $p $keys) != TRUE.
|
|
154
|
-
return ($root_cid -> cert $c $root_cid, $root_name -> rp $p $name, $role_id -> cert $c $role_id).
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// (core 3.0: rebuild_peer_address_document was removed — the inviter's address
|
|
158
|
-
// document now travels whole, inside the boxed leg-1/leg-3 identity bundle, and
|
|
159
|
-
// is replayed directly through address_document::process_address_document; there
|
|
160
|
-
// is no longer a key-list-only invite to reconstruct an AD from.)
|
|
161
|
-
|
|
162
|
-
// ---- CP->root governance attestation (§3c, core 1.8) -----------------
|
|
163
|
-
// NON-enforcing visibility only — the sole monitoring gate stays the 6-digit
|
|
164
|
-
// proxy-bind ceremony. cid_cp is the CP's container_id, which IS the key-
|
|
165
|
-
// derived commitment over the CP's SIGN key (P3, adapt-toolkit #77:
|
|
166
|
-
// container_id == key_storage::address_of_key(sign_pub), a hash of the SIGN
|
|
167
|
-
// key alone — NOT _value_id of the whole key_list), so pinning cid_cp pins
|
|
168
|
-
// the CP's signing key and lazy resolution cannot substitute a different CP
|
|
169
|
-
// without breaking it.
|
|
170
|
-
metadef cp_attestation_commitment_t: (
|
|
171
|
-
$version -> int,
|
|
172
|
-
$cid_cp -> global_id
|
|
173
|
-
).
|
|
174
|
-
|
|
175
|
-
// The lazily-resolved full attestation: the CP signs the ROOT's container_id
|
|
176
|
-
// (the key-derived commitment over the root's SIGN key, P3) — key material,
|
|
177
|
-
// never a label. cp_cid pins it to the same CP as the inline commitment.
|
|
178
|
-
metadef cp_attestation_core_t: (
|
|
179
|
-
$version -> int,
|
|
180
|
-
$root_cid -> global_id,
|
|
181
|
-
$cp_cid -> global_id
|
|
182
|
-
).
|
|
183
|
-
metadef cp_attestation_t: ($c -> cp_attestation_core_t, $s -> crypto_signature).
|
|
184
|
-
|
|
185
|
-
// P3 (adapt-toolkit #77): container_id == key_storage::address_of_key(sign_pub)
|
|
186
|
-
// — a hash of the SIGN key alone, not _value_id of the whole key_list. This
|
|
187
|
-
// re-derives that commitment from an identity's own key material so
|
|
188
|
-
// verify_cp_attestation below stays a SELF-CONTAINED check (independent of
|
|
189
|
-
// whatever the caller already validated), mirroring address_document.mm's
|
|
190
|
-
// own "container id does not commit to signing key" check and
|
|
191
|
-
// identity_proof_document_impl.mm::validate.
|
|
192
|
-
fn _address_of_signing_key (key_list: key_utils::t_publickey(,), default_keys: key_utils::t_function->>key_utils::t_key_id) -> global_id
|
|
193
|
-
{
|
|
194
|
-
sign_key_id = default_keys $SIGN.
|
|
195
|
-
sign_pub IS publickey_sign+ = NIL.
|
|
196
|
-
sc key_list -- (k->) {
|
|
197
|
-
if _crypto_get_key_id k == sign_key_id {
|
|
198
|
-
sign_pub -> k SAFE(publickey_sign).
|
|
199
|
-
break.
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
abort "verify_cp_attestation: SIGN key not found in cp_ad key_list" WHEN sign_pub == NIL.
|
|
203
|
-
return key_storage::address_of_key sign_pub?.
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// Verify a resolved §3c attestation. TRUE only when the commitment binds the
|
|
207
|
-
// CP keys (cp_ad's key-derived container_id AND its own re-derived
|
|
208
|
-
// address-of-SIGN-key both equal cid_cp), the attestation is pinned to that
|
|
209
|
-
// same CP, it attests the ACTUAL root, and it is CP-signed. The CALLER must
|
|
210
|
-
// have run process_address_document on cp_ad first (that enforces the CP AD
|
|
211
|
-
// proof-of-possession self-sig) and must render an UNRESOLVABLE cp_ad as
|
|
212
|
-
// present-but-unverified — never call this without a resolved, PoP-checked
|
|
213
|
-
// cp_ad.
|
|
214
|
-
fn verify_cp_attestation (commitment: cp_attestation_commitment_t, cp_ad: address_document_types::t_address_document, att: cp_attestation_t, root_cid: global_id) -> bool
|
|
215
|
-
{
|
|
216
|
-
return (commitment $version) == 1
|
|
217
|
-
&& (att $c $version) == 1
|
|
218
|
-
&& (cp_ad $identity $container_id) == (commitment $cid_cp)
|
|
219
|
-
&& (_address_of_signing_key (cp_ad $identity $key_list) (cp_ad $identity $default_keys)) == (commitment $cid_cp)
|
|
220
|
-
&& (att $c $cp_cid) == (commitment $cid_cp)
|
|
221
|
-
&& (att $c $root_cid) == root_cid
|
|
222
|
-
&& key_storage::check_signature_new_container (_value_id (att $c)) (att $s) (cp_ad $identity $key_list) == TRUE.
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// ---- §3c root half: root-signed CP binding (core 1.9) ----------------
|
|
226
|
-
// The root self-signs its governance edge so peers TOFU-pin "root R is
|
|
227
|
-
// managed by CP cid_cp". A SEPARATE artifact from root_profile — keeps its
|
|
228
|
-
// signature and persisted state byte-identical (no migration, no sig
|
|
229
|
-
// invalidation), crypto-confirmed to preserve the §3c binding. Strip-evident
|
|
230
|
-
// only via TOFU: a genesis-time strip downgrades to a visible "no attestation
|
|
231
|
-
// present" — costs visibility, not security, since the edge is non-enforcing.
|
|
232
|
-
cp_attestation_context_tag = "ours:cp-attestation:v1".
|
|
233
|
-
|
|
234
|
-
// Verify the root half: root-signed and domain-separated, binding the root's
|
|
235
|
-
// OWN key-derived container_id (P3 — NEVER a free root_cid label, the D1
|
|
236
|
-
// trap) to the CP commitment. root_keys is the root key list the caller
|
|
237
|
-
// already pins (the delegation chain / root_ad), so this proves the EDGE,
|
|
238
|
-
// not who the root is.
|
|
239
|
-
fn verify_root_cp_binding (binding: root_cp_binding_t, root_cid: global_id, root_keys: key_utils::t_publickey(,)) -> bool
|
|
240
|
-
{
|
|
241
|
-
return (binding $c $version) == 1
|
|
242
|
-
&& (binding $c $context_tag) == cp_attestation_context_tag
|
|
243
|
-
&& (binding $c $root_cid) == root_cid
|
|
244
|
-
&& key_storage::check_signature_new_container (_value_id (binding $c)) (binding $s) root_keys == TRUE.
|
|
245
|
-
}
|
|
246
|
-
}
|