xytara 3.3.0 → 3.5.0
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 +23 -3
- package/RELEASE_NOTES.md +6 -5
- package/client.js +8 -0
- package/lib/delivery_receipt_verify.js +35 -1
- package/package.json +3 -2
- package/scripts/verify_client.js +7 -3
package/README.md
CHANGED
|
@@ -135,8 +135,23 @@ POST /v1/credits/agents/:id/revoke owner key only; immediate; { reason } is stor
|
|
|
135
135
|
GET /v1/credits/activity?limit=100&since=<iso>
|
|
136
136
|
recent spends with agent id/label, units, task_ref, tool_name,
|
|
137
137
|
credit_spend_id; owner sees the account, an agent sees its own
|
|
138
|
+
GET /v1/credits/agents/log the delegation log: every mint and revoke of the account's agent
|
|
139
|
+
keys (full events); an agent key sees only its own
|
|
140
|
+
GET /v1/credits/agents/:id/proof delegation proof for one key: its events, the hash-only chain to
|
|
141
|
+
the head, the signed checkpoint, how to verify
|
|
142
|
+
GET /v1/delegation-log/head public: event count, head hash, chain continuity
|
|
143
|
+
GET /v1/delegation-log/feed public: seq, type, time and hashes only (never an account or key)
|
|
144
|
+
GET /v1/delegation-log/checkpoint public: naxytra-attestation/1 over the head (+ ctp/1 binding
|
|
145
|
+
while anchoring); POST .../checkpoint/verify is a free check
|
|
138
146
|
```
|
|
139
147
|
|
|
148
|
+
Every mint and revoke is an append-only, hash-chained event (`naxytra-delegation-log/1`:
|
|
149
|
+
`event_sha256 = sha256(JCS(event))`, `chain_hash = sha256(previous chain_hash + event_sha256)`).
|
|
150
|
+
A relying party holding a key's delegation proof and a checkpoint can establish, without asking
|
|
151
|
+
this runtime, that the key was minted with these caps before T and not revoked before a head
|
|
152
|
+
anchored after T. Set `XYTARA_EXTERNAL_BINDING_JSON` while a chronology anchoring session is open
|
|
153
|
+
and every checkpoint carries the binding inside its signed bytes.
|
|
154
|
+
|
|
140
155
|
An agent key spends exactly like the owner key (`/v1/economics/rails/credits/consume`, or
|
|
141
156
|
`credits_first` execution), but every spend is checked against its per-call, per-UTC-day and
|
|
142
157
|
lifetime caps, its tool allow-list, its expiry and revocation. Refusals are explicit and never
|
|
@@ -194,9 +209,14 @@ live RPC read, that you can hand to another party.
|
|
|
194
209
|
`subject.kind` is `x402_settlement` (method `base-rpc-logs/1`) or `transaction_status` (method
|
|
195
210
|
`base-rpc-receipt/1`, with `confirmations`). A negative answer (`claim.verified: false` — the
|
|
196
211
|
receipt does not match the chain, the transaction is unknown) is attested too; a tool error (RPC
|
|
197
|
-
unavailable) carries no attestation and is not charged. `bindings`
|
|
198
|
-
|
|
199
|
-
|
|
212
|
+
unavailable) carries no attestation and is not charged. `bindings` holds external bindings and
|
|
213
|
+
must be carried unchanged — it is inside the signed bytes. The one known scheme is a
|
|
214
|
+
chronology-protocol binding, `{ "scheme": "ctp/1", "system_id": "NAXYTRA-ATTESTATION/1", "tag":
|
|
215
|
+
"<64 hex>" }`: the tag derives from a proof-of-work block that did not exist before the issuer's
|
|
216
|
+
anchoring session opened, so an attestation signed with it inside cannot predate that block; the
|
|
217
|
+
anchor then commits to `attestation_sha256` = SHA-256 of the JCS form of the whole attestation
|
|
218
|
+
(`attestationSha256` in the client; also returned by `GET /attestations/<id>` and
|
|
219
|
+
`POST /attestations/verify`). Signed bytes = JCS of the attestation with `sig.signatures` removed
|
|
200
220
|
(`sig.suite` and `sig.kids` stay signed), with the same keys as the delivery receipts.
|
|
201
221
|
|
|
202
222
|
```js
|
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
`xytara` 3.
|
|
1
|
+
`xytara` 3.5.0 makes delegated authority provable at a point in time: the delegation log.
|
|
2
2
|
|
|
3
|
-
- **
|
|
4
|
-
- **
|
|
5
|
-
- **
|
|
6
|
-
-
|
|
3
|
+
- **Delegation log (`naxytra-delegation-log/1`)** — every agent-key mint (delegatee, key fingerprint, caps, expiry) and revoke (stated time, reason) is an append-only, hash-chained event: `event_sha256 = sha256(JCS(event))`, `chain_hash = sha256(previous chain_hash + event_sha256)`. Mint and revoke responses return the event reference (`delegation_event`).
|
|
4
|
+
- **Public, key-less surface** — `GET /v1/delegation-log/head` (count, head hash, chain continuity), `GET /v1/delegation-log/feed?since_seq=&limit=` (seq, type, time and hashes only — never an account, a key or a label), `GET /v1/delegation-log/checkpoint` (a `naxytra-attestation/1` over the head, signed with the delivery-receipt keys; `POST /v1/delegation-log/checkpoint/verify` is a free check). The keys endpoint announces the log.
|
|
5
|
+
- **Owner and agent views** — `GET /v1/credits/agents/log` (owner key: the account's full events; agent key: its own) and `GET /v1/credits/agents/:id/proof`: the key's events, the hash-only chain from its first event to the head, the current checkpoint and its digest, plus the verification recipe. A relying party holding a proof and a checkpoint establishes, without asking the runtime, that a key was minted with these caps before T and not revoked before a head anchored after T.
|
|
6
|
+
- **Chronology binding on checkpoints** — `XYTARA_EXTERNAL_BINDING_JSON` (the `{scheme, system_id, tag}` object or the bare 64-hex tag, scheme `ctp/1`, system id `NAXYTRA-DELEGATION-LOG/1`) is carried inside every checkpoint's signed bytes while an anchoring session is open; `attestation_sha256` of the checkpoint is the digest an external anchor commits to.
|
|
7
|
+
- Client package (thin): unchanged.
|
package/client.js
CHANGED
|
@@ -15,6 +15,9 @@ const {
|
|
|
15
15
|
verificationRecipe,
|
|
16
16
|
attestationSignedBytes,
|
|
17
17
|
verifyAttestation,
|
|
18
|
+
attestationSha256,
|
|
19
|
+
normalizeExternalBinding,
|
|
20
|
+
EXTERNAL_BINDING_SCHEMES,
|
|
18
21
|
attestationRecipe
|
|
19
22
|
} = require("./lib/delivery_receipt_verify");
|
|
20
23
|
const { version } = require("./package.json");
|
|
@@ -80,6 +83,11 @@ module.exports = {
|
|
|
80
83
|
attestationSignedBytes,
|
|
81
84
|
verifyAttestation,
|
|
82
85
|
attestationRecipe,
|
|
86
|
+
// External bindings (chronology anchoring): the digest an anchor commits to, the binding shape
|
|
87
|
+
// check, and the known schemes.
|
|
88
|
+
attestationSha256,
|
|
89
|
+
normalizeExternalBinding,
|
|
90
|
+
EXTERNAL_BINDING_SCHEMES,
|
|
83
91
|
// x402 header helpers for the paid command path.
|
|
84
92
|
X402_PAYMENT_HEADER,
|
|
85
93
|
X402_PAYMENT_REQUIRED_HEADER,
|
|
@@ -34,6 +34,15 @@ const ATTESTATION_VERSION = "naxytra-attestation/1";
|
|
|
34
34
|
// `sig.kids` stay INSIDE the signed bytes, so a stripped algorithm or a swapped key id fails.
|
|
35
35
|
const ATTESTATION_CANONICALIZATION = "JCS (RFC 8785) of the attestation with `sig.signatures` removed (`sig.suite` and `sig.kids` stay signed)";
|
|
36
36
|
const ATTESTATION_ID_PATTERN = /^att_[0-9a-f]{12}$/;
|
|
37
|
+
// External bindings an attestation may carry INSIDE its signed bytes (attestation.bindings[]).
|
|
38
|
+
// "ctp/1": a chronology-protocol binding tag — a value derived from a proof-of-work block that did
|
|
39
|
+
// not exist when the attestation's session opened, so an attestation signed with it inside cannot
|
|
40
|
+
// predate that block (the lower time bound); the anchor then commits to attestation_sha256 (the
|
|
41
|
+
// upper bound). The tag is the derived binding tag, never the raw challenge, so records bound in
|
|
42
|
+
// different systems cannot be correlated. Shape: { scheme: "ctp/1", system_id, tag: <64 hex> }.
|
|
43
|
+
const EXTERNAL_BINDING_SCHEMES = ["ctp/1"];
|
|
44
|
+
const EXTERNAL_BINDING_TAG_PATTERN = /^[0-9a-f]{64}$/;
|
|
45
|
+
const EXTERNAL_BINDING_SYSTEM_ID_PATTERN = /^[\x21-\x7e]{1,64}$/;
|
|
37
46
|
|
|
38
47
|
// JCS for the JSON values a receipt carries (strings, finite numbers, booleans, null, arrays,
|
|
39
48
|
// objects). Object keys sorted by UTF-16 code units; `undefined` members dropped like JSON.
|
|
@@ -193,6 +202,27 @@ function verifyAttestation(attestation, trustedKeys) {
|
|
|
193
202
|
};
|
|
194
203
|
}
|
|
195
204
|
|
|
205
|
+
// The digest an external anchor (e.g. a chronology-protocol checkpoint) commits to: sha256 of the
|
|
206
|
+
// JCS form of the WHOLE attestation, signatures included. Stable across re-serialisation because
|
|
207
|
+
// it is computed over the canonical form, not the bytes a transport happened to send.
|
|
208
|
+
function attestationSha256(attestation) {
|
|
209
|
+
return hashCanonical(attestation);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Normalizes one external binding ({ scheme, system_id, tag }) for issuing or inspection.
|
|
213
|
+
// Returns { binding } or { reason }; unknown schemes and malformed tags are refused so that an
|
|
214
|
+
// attestation never carries a binding a verifier could not interpret.
|
|
215
|
+
function normalizeExternalBinding(candidate) {
|
|
216
|
+
const c = isPlainObject(candidate) ? candidate : null;
|
|
217
|
+
if (!c) return { reason: "binding_must_be_an_object" };
|
|
218
|
+
if (!EXTERNAL_BINDING_SCHEMES.includes(c.scheme)) return { reason: "unsupported_binding_scheme", scheme: c.scheme === undefined ? null : c.scheme };
|
|
219
|
+
const systemId = typeof c.system_id === "string" ? c.system_id : "";
|
|
220
|
+
if (!EXTERNAL_BINDING_SYSTEM_ID_PATTERN.test(systemId)) return { reason: "binding_system_id_invalid" };
|
|
221
|
+
const tag = typeof c.tag === "string" ? c.tag.toLowerCase() : "";
|
|
222
|
+
if (!EXTERNAL_BINDING_TAG_PATTERN.test(tag)) return { reason: "binding_tag_must_be_64_hex" };
|
|
223
|
+
return { binding: { scheme: c.scheme, system_id: systemId, tag } };
|
|
224
|
+
}
|
|
225
|
+
|
|
196
226
|
// A short, self-contained recipe for verifying an attestation without trusting the issuer's server.
|
|
197
227
|
function attestationRecipe(keysUrl) {
|
|
198
228
|
return {
|
|
@@ -203,8 +233,9 @@ function attestationRecipe(keysUrl) {
|
|
|
203
233
|
"1. Fetch the issuer's public keys; check every kid in attestation.sig.kids is listed (and pin them).",
|
|
204
234
|
"2. Remove attestation.sig.signatures (keep sig.suite and sig.kids) and JCS-canonicalize what is left: these are the signed bytes.",
|
|
205
235
|
"3. For every alg in sig.suite, verify sig.signatures[alg] over the signed bytes with the key whose kid is sig.kids[alg] (node:crypto crypto.verify(null, bytes, spkiPublicKey, signature), or xoonya's verifyExternalProofSignature({ material, signature, algorithm, public_key, expected_key_ref: kid })).",
|
|
206
|
-
"4. Read subject (what was checked), claim.verified / claim.status / claim.details (what was observed) and claim.observed_at_iso (when). evidence_sha256 = sha256(JCS({ tool, arguments, output })) of the tool call that produced it; recompute it when you hold that call. bindings
|
|
236
|
+
"4. Read subject (what was checked), claim.verified / claim.status / claim.details (what was observed) and claim.observed_at_iso (when). evidence_sha256 = sha256(JCS({ tool, arguments, output })) of the tool call that produced it; recompute it when you hold that call. bindings[] (inside the signed bytes; carry unchanged) may hold external bindings: { scheme: \"ctp/1\", system_id, tag } is a chronology-protocol binding tag, proving the attestation was created after the proof-of-work block that minted the tag; the external anchor commits to attestation_sha256 = sha256(JCS(attestation)) for the upper bound."
|
|
207
237
|
],
|
|
238
|
+
external_bindings: { schemes: EXTERNAL_BINDING_SCHEMES.slice(), digest: "attestation_sha256 = sha256(JCS(attestation)), signatures included" },
|
|
208
239
|
boundary: "Proves this issuer observed this claim about this subject from a live chain read at observed_at_iso, unaltered since signing — not that the chain cannot reorganize, and nothing beyond the stated claim."
|
|
209
240
|
};
|
|
210
241
|
}
|
|
@@ -216,6 +247,7 @@ module.exports = {
|
|
|
216
247
|
ATTESTATION_VERSION,
|
|
217
248
|
ATTESTATION_CANONICALIZATION,
|
|
218
249
|
ATTESTATION_ID_PATTERN,
|
|
250
|
+
EXTERNAL_BINDING_SCHEMES,
|
|
219
251
|
canonicalize,
|
|
220
252
|
sha256Hex,
|
|
221
253
|
hashCanonical,
|
|
@@ -226,5 +258,7 @@ module.exports = {
|
|
|
226
258
|
verificationRecipe,
|
|
227
259
|
attestationSignedBytes,
|
|
228
260
|
verifyAttestation,
|
|
261
|
+
attestationSha256,
|
|
262
|
+
normalizeExternalBinding,
|
|
229
263
|
attestationRecipe
|
|
230
264
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xytara",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.0",
|
|
4
4
|
"description": "Client for the hosted naxytra runtime: discover a capability, pay per call with x402 (gasless USDC on Base) or credits, get the deliverable and a signed delivery receipt you can verify offline. The runtime is a hosted service; this package is the client.",
|
|
5
5
|
"main": "client.js",
|
|
6
6
|
"exports": {
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
"verify:production-readiness": "node scripts/verify_production_readiness.js",
|
|
96
96
|
"verify:final-activation": "node scripts/verify_final_activation.js",
|
|
97
97
|
"verify:x402-facilitator": "node scripts/verify_x402_facilitator.js",
|
|
98
|
-
"verify:all": "node scripts/verify_all.js && node scripts/verify_integrations.js && node scripts/verify_adapters.js && node scripts/verify_control_plane_contracts.js && node scripts/verify_control_plane_routes.js && node scripts/verify_framework_provider_promotion.js && node scripts/verify_operator_observability_boundary.js && node scripts/verify_pricing_experiment_plan.js && node scripts/verify_treasury_public_boundary.js && node scripts/verify_market_lanes.js && node scripts/verify_market_lane_depth.js && node scripts/verify_market_lane_traces.js && node scripts/verify_market_lane_promotion.js && node scripts/verify_provider_runtime_breadth.js && node scripts/verify_provider_runtime_journeys.js && node scripts/verify_lifecycle_continuity.js && node scripts/verify_first_run_conversions.js && node scripts/verify_delivery_summary.js && node scripts/verify_runtime_durability.js && node scripts/verify_revenue_launch_paths.js && node scripts/verify_full_catalog.js && node scripts/verify_tooling.js && node scripts/verify_examples.js && node scripts/verify_service.js && node scripts/verify_x402_facilitator.js && node scripts/verify_cdp_facilitator.js && node scripts/verify_a2a_rpc.js && node scripts/verify_checkout_processor.js && node scripts/verify_l402_adapter.js && node scripts/verify_bolt_adapter.js && node scripts/verify_mpp_adapter.js && node scripts/verify_rate_limiter.js && node scripts/verify_execution_surfacing.js && node scripts/verify_agent_identity.js && node scripts/verify_verify_execute_settle.js && node scripts/verify_execution_dedupe.js && node scripts/verify_refund_credit.js && node scripts/verify_commerce_bridge.js && node scripts/verify_settlement.js && node scripts/verify_provider_network.js && node scripts/verify_external_execution_retry.js && node scripts/verify_runtime_state_guard.js && node scripts/state_backup_offsite.js selftest && node scripts/verify_lifecycle_spend_binding.js && node scripts/verify_buyer_safety.js && node scripts/verify_buyer_event_log.js && node scripts/verify_x402_settlement_recovery.js && node scripts/verify_team_spend.js",
|
|
98
|
+
"verify:all": "node scripts/verify_all.js && node scripts/verify_integrations.js && node scripts/verify_adapters.js && node scripts/verify_control_plane_contracts.js && node scripts/verify_control_plane_routes.js && node scripts/verify_framework_provider_promotion.js && node scripts/verify_operator_observability_boundary.js && node scripts/verify_pricing_experiment_plan.js && node scripts/verify_treasury_public_boundary.js && node scripts/verify_market_lanes.js && node scripts/verify_market_lane_depth.js && node scripts/verify_market_lane_traces.js && node scripts/verify_market_lane_promotion.js && node scripts/verify_provider_runtime_breadth.js && node scripts/verify_provider_runtime_journeys.js && node scripts/verify_lifecycle_continuity.js && node scripts/verify_first_run_conversions.js && node scripts/verify_delivery_summary.js && node scripts/verify_runtime_durability.js && node scripts/verify_revenue_launch_paths.js && node scripts/verify_full_catalog.js && node scripts/verify_tooling.js && node scripts/verify_examples.js && node scripts/verify_service.js && node scripts/verify_x402_facilitator.js && node scripts/verify_cdp_facilitator.js && node scripts/verify_a2a_rpc.js && node scripts/verify_checkout_processor.js && node scripts/verify_l402_adapter.js && node scripts/verify_bolt_adapter.js && node scripts/verify_mpp_adapter.js && node scripts/verify_rate_limiter.js && node scripts/verify_execution_surfacing.js && node scripts/verify_agent_identity.js && node scripts/verify_verify_execute_settle.js && node scripts/verify_execution_dedupe.js && node scripts/verify_refund_credit.js && node scripts/verify_commerce_bridge.js && node scripts/verify_settlement.js && node scripts/verify_provider_network.js && node scripts/verify_external_execution_retry.js && node scripts/verify_runtime_state_guard.js && node scripts/state_backup_offsite.js selftest && node scripts/verify_lifecycle_spend_binding.js && node scripts/verify_buyer_safety.js && node scripts/verify_buyer_event_log.js && node scripts/verify_x402_settlement_recovery.js && node scripts/verify_team_spend.js && node scripts/verify_delegation_log.js",
|
|
99
99
|
"prepublishOnly": "npm run verify:release-candidate",
|
|
100
100
|
"verify:cdp-facilitator": "node scripts/verify_cdp_facilitator.js",
|
|
101
101
|
"verify:a2a-rpc": "node scripts/verify_a2a_rpc.js",
|
|
@@ -120,6 +120,7 @@
|
|
|
120
120
|
"verify:buyer-event-log": "node scripts/verify_buyer_event_log.js",
|
|
121
121
|
"verify:x402-settlement-recovery": "node scripts/verify_x402_settlement_recovery.js",
|
|
122
122
|
"verify:team-spend": "node scripts/verify_team_spend.js",
|
|
123
|
+
"verify:delegation-log": "node scripts/verify_delegation_log.js",
|
|
123
124
|
"verify:client": "node scripts/verify_client.js"
|
|
124
125
|
}
|
|
125
126
|
}
|
package/scripts/verify_client.js
CHANGED
|
@@ -252,7 +252,7 @@ function runCliAsync(args) {
|
|
|
252
252
|
async function main() {
|
|
253
253
|
check("package_surface", () => {
|
|
254
254
|
assert.strictEqual(typeof CommerceClient, "function", "CommerceClient export missing");
|
|
255
|
-
for (const name of ["verifyDeliveryReceipt", "canonicalize", "hashCanonical", "keyRef", "verificationRecipe", "verifyAttestation", "attestationRecipe", "attestationSignedBytes", "encodeX402PaymentHeader", "decodeX402Header", "summarizeCommandResultPayload", "summarizeCatalogPayload", "summarizeReceiptPayload"]) {
|
|
255
|
+
for (const name of ["verifyDeliveryReceipt", "canonicalize", "hashCanonical", "keyRef", "verificationRecipe", "verifyAttestation", "attestationRecipe", "attestationSignedBytes", "attestationSha256", "normalizeExternalBinding", "encodeX402PaymentHeader", "decodeX402Header", "summarizeCommandResultPayload", "summarizeCatalogPayload", "summarizeReceiptPayload"]) {
|
|
256
256
|
assert.strictEqual(typeof client[name], "function", `${name} export missing`);
|
|
257
257
|
}
|
|
258
258
|
assert.strictEqual(RECEIPT_VERSION, "naxytra-delivery-receipt/1", "receipt version mismatch");
|
|
@@ -309,7 +309,9 @@ async function main() {
|
|
|
309
309
|
check("attestation_offline_round_trip", () => {
|
|
310
310
|
const issuer = makeSigner();
|
|
311
311
|
const toolCall = { tool: "tx.status", arguments: { tx_hash: "0x" + "9b".repeat(32), network: "base" }, output: { ok: true, found: true, status: "success", block_number: 4080, confirmations: 17 } };
|
|
312
|
-
const bindings = [{ scheme: "ctp/1",
|
|
312
|
+
const bindings = [{ scheme: "ctp/1", system_id: "NAXYTRA-ATTESTATION/1", tag: "7d".repeat(32) }];
|
|
313
|
+
assert.deepStrictEqual(client.normalizeExternalBinding(bindings[0]).binding, bindings[0], "a ctp/1 binding { scheme, system_id, tag } normalizes to itself");
|
|
314
|
+
assert.deepStrictEqual(client.EXTERNAL_BINDING_SCHEMES, ["ctp/1"], "known binding schemes");
|
|
313
315
|
const attestation = signAttestation({
|
|
314
316
|
attestation_id: "att_0123456789ab",
|
|
315
317
|
issued_at_iso: "2026-01-01T00:00:02.000Z",
|
|
@@ -331,6 +333,8 @@ async function main() {
|
|
|
331
333
|
const reordered = JSON.parse(JSON.stringify({ sig: attestation.sig, bindings: attestation.bindings, claim: attestation.claim, ...attestation }));
|
|
332
334
|
assert.strictEqual(verifyAttestation(reordered, [issuer.trustedKey]).valid, true, "key order must not matter (JCS)");
|
|
333
335
|
assert.deepStrictEqual(reordered.bindings, bindings, "bindings survive the round trip unchanged");
|
|
336
|
+
assert.strictEqual(client.attestationSha256(reordered), client.attestationSha256(attestation), "attestation_sha256 is the same digest whatever the key order (JCS, signatures included)");
|
|
337
|
+
assert.notStrictEqual(client.attestationSha256(attestation), result.signed_bytes_sha256, "attestation_sha256 (signatures included) differs from the signed-bytes hash");
|
|
334
338
|
const negative = signAttestation({ ...attestation, claim: { ...attestation.claim, verified: false, status: "not_found" } }, issuer);
|
|
335
339
|
assert.strictEqual(verifyAttestation(negative, [issuer.trustedKey]).claim_verified, false, "a negative claim (verified:false) is a valid signed attestation");
|
|
336
340
|
// tamper -> reject
|
|
@@ -338,7 +342,7 @@ async function main() {
|
|
|
338
342
|
tamperedClaim.claim.verified = false;
|
|
339
343
|
assert.strictEqual(verifyAttestation(tamperedClaim, [issuer.trustedKey]).valid, false, "tampered claim must fail");
|
|
340
344
|
const tamperedBindings = JSON.parse(JSON.stringify(attestation));
|
|
341
|
-
tamperedBindings.bindings.push({ scheme: "ctp/1",
|
|
345
|
+
tamperedBindings.bindings.push({ scheme: "ctp/1", system_id: "LATER", tag: "00".repeat(32) });
|
|
342
346
|
assert.strictEqual(verifyAttestation(tamperedBindings, [issuer.trustedKey]).valid, false, "bindings are signed: adding one later must fail");
|
|
343
347
|
const removedBindings = JSON.parse(JSON.stringify(attestation));
|
|
344
348
|
removedBindings.bindings = [];
|