@riddledc/riddle-proof 0.8.83 → 0.8.84
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 +55 -30
- package/dist/advanced/index.d.cts +1 -1
- package/dist/advanced/index.d.ts +1 -1
- package/dist/advanced/proof-run-engine.d.cts +1 -1
- package/dist/advanced/proof-run-engine.d.ts +1 -1
- package/dist/chunk-AQTCU6W5.js +1086 -0
- package/dist/index.cjs +569 -62
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +14 -2
- package/dist/{proof-run-engine-MiKZt9oY.d.ts → proof-run-engine-BqRoA3Do.d.ts} +3 -3
- package/dist/{proof-run-engine-Baiv6l3A.d.cts → proof-run-engine-DpChFR5H.d.cts} +3 -3
- package/dist/proof-run-engine.d.cts +1 -1
- package/dist/proof-run-engine.d.ts +1 -1
- package/dist/semantic-certificate.cjs +571 -64
- package/dist/semantic-certificate.d.cts +120 -1
- package/dist/semantic-certificate.d.ts +120 -1
- package/dist/semantic-certificate.js +15 -3
- package/package.json +1 -1
- package/dist/chunk-DB5ZHRUP.js +0 -585
package/dist/index.cjs
CHANGED
|
@@ -3442,6 +3442,8 @@ __export(index_exports, {
|
|
|
3442
3442
|
RIDDLE_PROOF_PR_COMMENT_MARKER: () => RIDDLE_PROOF_PR_COMMENT_MARKER,
|
|
3443
3443
|
RIDDLE_PROOF_RUN_CARD_VERSION: () => RIDDLE_PROOF_RUN_CARD_VERSION,
|
|
3444
3444
|
RIDDLE_PROOF_RUN_STATE_VERSION: () => RIDDLE_PROOF_RUN_STATE_VERSION,
|
|
3445
|
+
RIDDLE_PROOF_SEMANTIC_CERTIFICATE_CLOSURE_MAX_CERTIFICATES: () => RIDDLE_PROOF_SEMANTIC_CERTIFICATE_CLOSURE_MAX_CERTIFICATES,
|
|
3446
|
+
RIDDLE_PROOF_SEMANTIC_CERTIFICATE_CLOSURE_VERSION: () => RIDDLE_PROOF_SEMANTIC_CERTIFICATE_CLOSURE_VERSION,
|
|
3445
3447
|
RIDDLE_PROOF_SEMANTIC_CERTIFICATE_VERSION: () => RIDDLE_PROOF_SEMANTIC_CERTIFICATE_VERSION,
|
|
3446
3448
|
RIDDLE_PROOF_VISUAL_SESSION_FINGERPRINT_VERSION: () => RIDDLE_PROOF_VISUAL_SESSION_FINGERPRINT_VERSION,
|
|
3447
3449
|
RIDDLE_PROOF_VISUAL_SESSION_VERSION: () => RIDDLE_PROOF_VISUAL_SESSION_VERSION,
|
|
@@ -3484,6 +3486,7 @@ __export(index_exports, {
|
|
|
3484
3486
|
compactBasicGameplayText: () => compactBasicGameplayText,
|
|
3485
3487
|
compactRecord: () => compactRecord,
|
|
3486
3488
|
compareVisualProofSessionFingerprint: () => compareVisualProofSessionFingerprint,
|
|
3489
|
+
composeRiddleProofSemanticCertificateClosures: () => composeRiddleProofSemanticCertificateClosures,
|
|
3487
3490
|
composeRiddleProofSemanticCertificates: () => composeRiddleProofSemanticCertificates,
|
|
3488
3491
|
createBasicGameplayCatchRecords: () => createBasicGameplayCatchRecords,
|
|
3489
3492
|
createBasicGameplayCatchSummary: () => createBasicGameplayCatchSummary,
|
|
@@ -3502,6 +3505,7 @@ __export(index_exports, {
|
|
|
3502
3505
|
createRiddleProofProfileEnvironmentBlockedResult: () => createRiddleProofProfileEnvironmentBlockedResult,
|
|
3503
3506
|
createRiddleProofProfileInsufficientResult: () => createRiddleProofProfileInsufficientResult,
|
|
3504
3507
|
createRiddleProofRunCard: () => createRiddleProofRunCard,
|
|
3508
|
+
createRiddleProofSemanticAtomicCertificateClosure: () => createRiddleProofSemanticAtomicCertificateClosure,
|
|
3505
3509
|
createRiddleProofSemanticCertificate: () => createRiddleProofSemanticCertificate,
|
|
3506
3510
|
createRunResult: () => createRunResult,
|
|
3507
3511
|
createRunState: () => createRunState,
|
|
@@ -3521,6 +3525,7 @@ __export(index_exports, {
|
|
|
3521
3525
|
isTerminalRiddleJobStatus: () => isTerminalRiddleJobStatus,
|
|
3522
3526
|
isTerminalStatus: () => isTerminalStatus,
|
|
3523
3527
|
matchRiddleProofSemanticCertificate: () => matchRiddleProofSemanticCertificate,
|
|
3528
|
+
matchRiddleProofSemanticCertificateClosure: () => matchRiddleProofSemanticCertificateClosure,
|
|
3524
3529
|
migrateRiddleProofChangeReceipt: () => migrateRiddleProofChangeReceipt,
|
|
3525
3530
|
nonEmptyString: () => nonEmptyString,
|
|
3526
3531
|
normalizeCheckpointResponse: () => normalizeCheckpointResponse,
|
|
@@ -3578,6 +3583,7 @@ __export(index_exports, {
|
|
|
3578
3583
|
summarizeRiddleProofProfileResult: () => summarizeRiddleProofProfileResult,
|
|
3579
3584
|
summarizeRiddleProofPublicConsumerSurface: () => summarizeRiddleProofPublicConsumerSurface,
|
|
3580
3585
|
summarizeRiddleProofPublicState: () => summarizeRiddleProofPublicState,
|
|
3586
|
+
validateRiddleProofSemanticCertificateClosure: () => validateRiddleProofSemanticCertificateClosure,
|
|
3581
3587
|
visualSessionFingerprint: () => visualSessionFingerprint,
|
|
3582
3588
|
visualSessionFingerprintBasis: () => visualSessionFingerprintBasis
|
|
3583
3589
|
});
|
|
@@ -20575,6 +20581,8 @@ function parseRiddleProofObservationReceipt(value) {
|
|
|
20575
20581
|
// src/semantic-certificate.ts
|
|
20576
20582
|
var import_node_crypto5 = require("crypto");
|
|
20577
20583
|
var RIDDLE_PROOF_SEMANTIC_CERTIFICATE_VERSION = "riddle-proof.semantic-certificate.v0";
|
|
20584
|
+
var RIDDLE_PROOF_SEMANTIC_CERTIFICATE_CLOSURE_VERSION = "riddle-proof.semantic-certificate-closure.v0";
|
|
20585
|
+
var RIDDLE_PROOF_SEMANTIC_CERTIFICATE_CLOSURE_MAX_CERTIFICATES = 4096;
|
|
20578
20586
|
var SCOPE_FIELDS = [
|
|
20579
20587
|
"repository",
|
|
20580
20588
|
"revision",
|
|
@@ -20606,7 +20614,9 @@ var CERTIFICATE_FIELDS = /* @__PURE__ */ new Set([
|
|
|
20606
20614
|
"issued_at"
|
|
20607
20615
|
]);
|
|
20608
20616
|
function isRecord4(value) {
|
|
20609
|
-
|
|
20617
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
20618
|
+
const prototype = Object.getPrototypeOf(value);
|
|
20619
|
+
return prototype === Object.prototype || prototype === null;
|
|
20610
20620
|
}
|
|
20611
20621
|
function safeErrorMessage(error) {
|
|
20612
20622
|
try {
|
|
@@ -20621,51 +20631,129 @@ function safeErrorMessage(error) {
|
|
|
20621
20631
|
}
|
|
20622
20632
|
function assertOnlyKeys(record, allowed, context) {
|
|
20623
20633
|
const allowedSet = new Set(allowed);
|
|
20624
|
-
for (const key of
|
|
20634
|
+
for (const key of Reflect.ownKeys(record)) {
|
|
20635
|
+
if (typeof key !== "string") {
|
|
20636
|
+
throw new Error(`${context} contains an unsupported symbol field.`);
|
|
20637
|
+
}
|
|
20625
20638
|
if (!allowedSet.has(key)) {
|
|
20626
20639
|
throw new Error(`${context} contains unsupported field ${key}.`);
|
|
20627
20640
|
}
|
|
20641
|
+
const descriptor = Object.getOwnPropertyDescriptor(record, key);
|
|
20642
|
+
if (!descriptor || descriptor.enumerable !== true || descriptor.get !== void 0 || descriptor.set !== void 0) {
|
|
20643
|
+
throw new Error(`${context}.${key} must be an enumerable data field.`);
|
|
20644
|
+
}
|
|
20628
20645
|
}
|
|
20629
20646
|
}
|
|
20647
|
+
function readDenseDataArray(value, context, maximumLength) {
|
|
20648
|
+
if (!Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype) {
|
|
20649
|
+
throw new Error(`${context} must be a plain array.`);
|
|
20650
|
+
}
|
|
20651
|
+
const lengthDescriptor = Object.getOwnPropertyDescriptor(value, "length");
|
|
20652
|
+
if (!lengthDescriptor || typeof lengthDescriptor.value !== "number" || !Number.isSafeInteger(lengthDescriptor.value) || lengthDescriptor.value < 0) {
|
|
20653
|
+
throw new Error(`${context}.length must be an own data field.`);
|
|
20654
|
+
}
|
|
20655
|
+
const length = lengthDescriptor.value;
|
|
20656
|
+
if (maximumLength !== void 0 && length > maximumLength) {
|
|
20657
|
+
throw new Error(`${context} exceeds ${maximumLength} entries.`);
|
|
20658
|
+
}
|
|
20659
|
+
const indexedElements = [];
|
|
20660
|
+
let elementCount = 0;
|
|
20661
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
20662
|
+
if (key === "length") continue;
|
|
20663
|
+
if (typeof key !== "string") {
|
|
20664
|
+
throw new Error(`${context} contains an unsupported symbol field.`);
|
|
20665
|
+
}
|
|
20666
|
+
const index = Number(key);
|
|
20667
|
+
if (!Number.isInteger(index) || index < 0 || index >= length || index >= 2 ** 32 - 1 || String(index) !== key) {
|
|
20668
|
+
throw new Error(`${context} contains unsupported array field ${key}.`);
|
|
20669
|
+
}
|
|
20670
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
20671
|
+
if (!descriptor || descriptor.enumerable !== true || descriptor.get !== void 0 || descriptor.set !== void 0) {
|
|
20672
|
+
throw new Error(`${context}[${key}] must be an enumerable data field.`);
|
|
20673
|
+
}
|
|
20674
|
+
indexedElements.push([index, descriptor.value]);
|
|
20675
|
+
elementCount += 1;
|
|
20676
|
+
}
|
|
20677
|
+
if (elementCount !== length) {
|
|
20678
|
+
throw new Error(`${context} must not contain sparse or inherited entries.`);
|
|
20679
|
+
}
|
|
20680
|
+
indexedElements.sort(([left], [right]) => left - right);
|
|
20681
|
+
return indexedElements.map(([, entry]) => entry);
|
|
20682
|
+
}
|
|
20683
|
+
function requiredField(record, key, context) {
|
|
20684
|
+
const descriptor = Object.getOwnPropertyDescriptor(record, key);
|
|
20685
|
+
if (!descriptor) {
|
|
20686
|
+
throw new Error(`${context}.${key} is required.`);
|
|
20687
|
+
}
|
|
20688
|
+
if (descriptor.enumerable !== true || descriptor.get !== void 0 || descriptor.set !== void 0) {
|
|
20689
|
+
throw new Error(`${context}.${key} must be an enumerable data field.`);
|
|
20690
|
+
}
|
|
20691
|
+
return descriptor.value;
|
|
20692
|
+
}
|
|
20693
|
+
function optionalField(record, key) {
|
|
20694
|
+
const descriptor = Object.getOwnPropertyDescriptor(record, key);
|
|
20695
|
+
if (!descriptor) return void 0;
|
|
20696
|
+
if (descriptor.enumerable !== true || descriptor.get !== void 0 || descriptor.set !== void 0) {
|
|
20697
|
+
throw new Error(`${key} must be an enumerable data field.`);
|
|
20698
|
+
}
|
|
20699
|
+
return descriptor.value;
|
|
20700
|
+
}
|
|
20630
20701
|
function requiredString2(record, key, context) {
|
|
20631
|
-
const value = record
|
|
20702
|
+
const value = requiredField(record, key, context);
|
|
20632
20703
|
if (typeof value !== "string" || !value.trim()) {
|
|
20633
20704
|
throw new Error(`${context}.${key} must be a non-empty string.`);
|
|
20634
20705
|
}
|
|
20635
20706
|
return value.trim();
|
|
20636
20707
|
}
|
|
20637
20708
|
function optionalString(record, key, context) {
|
|
20638
|
-
if (record
|
|
20709
|
+
if (optionalField(record, key) === void 0) return void 0;
|
|
20639
20710
|
return requiredString2(record, key, context);
|
|
20640
20711
|
}
|
|
20641
|
-
function
|
|
20712
|
+
function cloneJsonValue(value, context, ancestors = /* @__PURE__ */ new Set()) {
|
|
20642
20713
|
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
20643
|
-
return
|
|
20714
|
+
return value;
|
|
20715
|
+
}
|
|
20716
|
+
if (typeof value === "number") {
|
|
20717
|
+
if (!Number.isFinite(value)) throw new Error(`${context} must contain only finite numbers.`);
|
|
20718
|
+
return value;
|
|
20644
20719
|
}
|
|
20645
|
-
if (typeof value === "number") return Number.isFinite(value);
|
|
20646
20720
|
if (Array.isArray(value)) {
|
|
20647
|
-
|
|
20721
|
+
const elements = readDenseDataArray(value, context);
|
|
20722
|
+
if (ancestors.has(value)) throw new Error(`${context} must not be cyclic.`);
|
|
20648
20723
|
ancestors.add(value);
|
|
20649
|
-
const
|
|
20724
|
+
const cloned2 = elements.map((entry, index) => cloneJsonValue(entry, `${context}[${index}]`, ancestors));
|
|
20650
20725
|
ancestors.delete(value);
|
|
20651
|
-
return
|
|
20726
|
+
return cloned2;
|
|
20652
20727
|
}
|
|
20653
|
-
if (!isRecord4(value))
|
|
20654
|
-
|
|
20655
|
-
if (prototype !== Object.prototype && prototype !== null) return false;
|
|
20656
|
-
if (ancestors.has(value)) return false;
|
|
20728
|
+
if (!isRecord4(value)) throw new Error(`${context} must contain only JSON values.`);
|
|
20729
|
+
if (ancestors.has(value)) throw new Error(`${context} must not be cyclic.`);
|
|
20657
20730
|
ancestors.add(value);
|
|
20658
|
-
const
|
|
20731
|
+
const cloned = {};
|
|
20732
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
20733
|
+
if (typeof key !== "string") {
|
|
20734
|
+
throw new Error(`${context} contains an unsupported symbol field.`);
|
|
20735
|
+
}
|
|
20736
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
20737
|
+
if (!descriptor || descriptor.enumerable !== true || descriptor.get !== void 0 || descriptor.set !== void 0) {
|
|
20738
|
+
throw new Error(`${context}.${key} must be an enumerable data field.`);
|
|
20739
|
+
}
|
|
20740
|
+
Object.defineProperty(cloned, key, {
|
|
20741
|
+
value: cloneJsonValue(descriptor.value, `${context}.${key}`, ancestors),
|
|
20742
|
+
enumerable: true,
|
|
20743
|
+
configurable: true,
|
|
20744
|
+
writable: true
|
|
20745
|
+
});
|
|
20746
|
+
}
|
|
20659
20747
|
ancestors.delete(value);
|
|
20660
|
-
return
|
|
20748
|
+
return cloned;
|
|
20661
20749
|
}
|
|
20662
20750
|
function parseJsonObject2(value, context) {
|
|
20663
20751
|
if (value === void 0) return void 0;
|
|
20664
|
-
if (!isRecord4(value)
|
|
20752
|
+
if (!isRecord4(value)) {
|
|
20665
20753
|
throw new Error(`${context} must be a JSON object.`);
|
|
20666
20754
|
}
|
|
20667
|
-
const cloned =
|
|
20668
|
-
if (!isRecord4(cloned)
|
|
20755
|
+
const cloned = cloneJsonValue(value, context);
|
|
20756
|
+
if (!isRecord4(cloned)) {
|
|
20669
20757
|
throw new Error(`${context} must remain a JSON object when serialized.`);
|
|
20670
20758
|
}
|
|
20671
20759
|
return cloned;
|
|
@@ -20690,7 +20778,7 @@ function parseScope(value, context) {
|
|
|
20690
20778
|
function parseClaimRef(value, context, allowedExtras = []) {
|
|
20691
20779
|
if (!isRecord4(value)) throw new Error(`${context} must be an object.`);
|
|
20692
20780
|
assertOnlyKeys(value, ["claim_id", "claim_version", "parameters", ...allowedExtras], context);
|
|
20693
|
-
const parameters = parseJsonObject2(value
|
|
20781
|
+
const parameters = parseJsonObject2(optionalField(value, "parameters"), `${context}.parameters`);
|
|
20694
20782
|
return {
|
|
20695
20783
|
claim_id: requiredString2(value, "claim_id", context),
|
|
20696
20784
|
claim_version: requiredString2(value, "claim_version", context),
|
|
@@ -20726,10 +20814,11 @@ function parseEvidenceRef(value, context) {
|
|
|
20726
20814
|
};
|
|
20727
20815
|
}
|
|
20728
20816
|
function parseEvidenceBundle(value, context) {
|
|
20729
|
-
|
|
20817
|
+
const entries = readDenseDataArray(value, context);
|
|
20818
|
+
if (entries.length === 0) {
|
|
20730
20819
|
throw new Error(`${context} must contain at least one evidence reference.`);
|
|
20731
20820
|
}
|
|
20732
|
-
return
|
|
20821
|
+
return entries.map((entry, index) => parseEvidenceRef(entry, `${context}[${index}]`));
|
|
20733
20822
|
}
|
|
20734
20823
|
function parseContractRef(value, context) {
|
|
20735
20824
|
if (!isRecord4(value)) throw new Error(`${context} must be an object.`);
|
|
@@ -20746,30 +20835,32 @@ function parseContract(value, context, allowRuntimePredicate = false) {
|
|
|
20746
20835
|
["contract_id", "contract_version", "label", "claim", ...allowRuntimePredicate ? ["accepts"] : []],
|
|
20747
20836
|
context
|
|
20748
20837
|
);
|
|
20749
|
-
if (allowRuntimePredicate && typeof value
|
|
20838
|
+
if (allowRuntimePredicate && typeof requiredField(value, "accepts", context) !== "function") {
|
|
20750
20839
|
throw new Error(`${context}.accepts must be a function.`);
|
|
20751
20840
|
}
|
|
20752
20841
|
return {
|
|
20753
20842
|
...parseContractRef(value, context),
|
|
20754
|
-
claim: parseClaim(value
|
|
20843
|
+
claim: parseClaim(requiredField(value, "claim", context), `${context}.claim`)
|
|
20755
20844
|
};
|
|
20756
20845
|
}
|
|
20757
20846
|
function parseRule(value, context, allowFullPremises = false) {
|
|
20758
20847
|
if (!isRecord4(value)) throw new Error(`${context} must be an object.`);
|
|
20759
20848
|
assertOnlyKeys(value, ["rule_id", "rule_version", "label", "premises", "conclusion"], context);
|
|
20760
|
-
|
|
20849
|
+
const premises = requiredField(value, "premises", context);
|
|
20850
|
+
const premiseValues = readDenseDataArray(premises, `${context}.premises`);
|
|
20851
|
+
if (premiseValues.length === 0) {
|
|
20761
20852
|
throw new Error(`${context}.premises must contain at least one claim reference.`);
|
|
20762
20853
|
}
|
|
20763
20854
|
return {
|
|
20764
20855
|
rule_id: requiredString2(value, "rule_id", context),
|
|
20765
20856
|
rule_version: requiredString2(value, "rule_version", context),
|
|
20766
20857
|
label: requiredString2(value, "label", context),
|
|
20767
|
-
premises:
|
|
20858
|
+
premises: premiseValues.map((premise, index) => parseClaimRef(
|
|
20768
20859
|
premise,
|
|
20769
20860
|
`${context}.premises[${index}]`,
|
|
20770
20861
|
allowFullPremises ? ["label"] : []
|
|
20771
20862
|
)),
|
|
20772
|
-
conclusion: parseClaim(value
|
|
20863
|
+
conclusion: parseClaim(requiredField(value, "conclusion", context), `${context}.conclusion`)
|
|
20773
20864
|
};
|
|
20774
20865
|
}
|
|
20775
20866
|
function parsePremise(value, context) {
|
|
@@ -20789,9 +20880,9 @@ function parsePremise(value, context) {
|
|
|
20789
20880
|
certificate_id: requiredString2(value, "certificate_id", context),
|
|
20790
20881
|
derivation_kind: derivationKind,
|
|
20791
20882
|
assurance,
|
|
20792
|
-
scope: parseScope(value
|
|
20793
|
-
claim: parseClaim(value
|
|
20794
|
-
evidence: parseEvidenceBundle(value
|
|
20883
|
+
scope: parseScope(requiredField(value, "scope", context), `${context}.scope`),
|
|
20884
|
+
claim: parseClaim(requiredField(value, "claim", context), `${context}.claim`),
|
|
20885
|
+
evidence: parseEvidenceBundle(requiredField(value, "evidence", context), `${context}.evidence`)
|
|
20795
20886
|
};
|
|
20796
20887
|
}
|
|
20797
20888
|
function stableJson3(value) {
|
|
@@ -20821,28 +20912,30 @@ function parseDerivation(value, context) {
|
|
|
20821
20912
|
const kind = requiredString2(value, "kind", context);
|
|
20822
20913
|
if (kind === "contract") {
|
|
20823
20914
|
assertOnlyKeys(value, ["kind", "assurance", "contract"], context);
|
|
20824
|
-
if (value
|
|
20915
|
+
if (requiredField(value, "assurance", context) !== "runtime_contract_accepted") {
|
|
20825
20916
|
throw new Error(`${context}.assurance must be runtime_contract_accepted.`);
|
|
20826
20917
|
}
|
|
20827
20918
|
return {
|
|
20828
20919
|
kind,
|
|
20829
20920
|
assurance: "runtime_contract_accepted",
|
|
20830
|
-
contract: parseContract(value
|
|
20921
|
+
contract: parseContract(requiredField(value, "contract", context), `${context}.contract`)
|
|
20831
20922
|
};
|
|
20832
20923
|
}
|
|
20833
20924
|
if (kind === "composition") {
|
|
20834
20925
|
assertOnlyKeys(value, ["kind", "assurance", "rule", "premises"], context);
|
|
20835
|
-
if (value
|
|
20926
|
+
if (requiredField(value, "assurance", context) !== "declared_runtime_rule") {
|
|
20836
20927
|
throw new Error(`${context}.assurance must be declared_runtime_rule.`);
|
|
20837
20928
|
}
|
|
20838
|
-
|
|
20929
|
+
const premises = requiredField(value, "premises", context);
|
|
20930
|
+
const premiseValues = readDenseDataArray(premises, `${context}.premises`);
|
|
20931
|
+
if (premiseValues.length === 0) {
|
|
20839
20932
|
throw new Error(`${context}.premises must contain at least one certificate premise.`);
|
|
20840
20933
|
}
|
|
20841
20934
|
return {
|
|
20842
20935
|
kind,
|
|
20843
20936
|
assurance: "declared_runtime_rule",
|
|
20844
|
-
rule: parseRule(value
|
|
20845
|
-
premises:
|
|
20937
|
+
rule: parseRule(requiredField(value, "rule", context), `${context}.rule`),
|
|
20938
|
+
premises: premiseValues.map((premise, index) => parsePremise(premise, `${context}.premises[${index}]`))
|
|
20846
20939
|
};
|
|
20847
20940
|
}
|
|
20848
20941
|
throw new Error(`${context}.kind must be contract or composition.`);
|
|
@@ -20857,9 +20950,25 @@ function createRiddleProofSemanticCertificate(input) {
|
|
|
20857
20950
|
["scope", "evidence", "observation", "contract", "issued_at"],
|
|
20858
20951
|
"semantic certificate input"
|
|
20859
20952
|
);
|
|
20860
|
-
const scope = parseScope(input
|
|
20861
|
-
const evidence = parseEvidenceBundle(
|
|
20862
|
-
|
|
20953
|
+
const scope = parseScope(requiredField(input, "scope", "semantic certificate input"), "semantic certificate scope");
|
|
20954
|
+
const evidence = parseEvidenceBundle(
|
|
20955
|
+
requiredField(input, "evidence", "semantic certificate input"),
|
|
20956
|
+
"semantic certificate evidence"
|
|
20957
|
+
);
|
|
20958
|
+
const runtimeContract = requiredField(
|
|
20959
|
+
input,
|
|
20960
|
+
"contract",
|
|
20961
|
+
"semantic certificate input"
|
|
20962
|
+
);
|
|
20963
|
+
const contract = parseContract(runtimeContract, "semantic certificate contract", true);
|
|
20964
|
+
const accepts = requiredField(
|
|
20965
|
+
runtimeContract,
|
|
20966
|
+
"accepts",
|
|
20967
|
+
"semantic certificate contract"
|
|
20968
|
+
);
|
|
20969
|
+
if (typeof accepts !== "function") {
|
|
20970
|
+
throw new Error("semantic certificate contract.accepts must be a function.");
|
|
20971
|
+
}
|
|
20863
20972
|
const contractRef = {
|
|
20864
20973
|
contract_id: contract.contract_id,
|
|
20865
20974
|
contract_version: contract.contract_version,
|
|
@@ -20868,14 +20977,17 @@ function createRiddleProofSemanticCertificate(input) {
|
|
|
20868
20977
|
const claim = contract.claim;
|
|
20869
20978
|
let accepted;
|
|
20870
20979
|
try {
|
|
20871
|
-
accepted =
|
|
20980
|
+
accepted = accepts(
|
|
20981
|
+
{ ...scope },
|
|
20982
|
+
requiredField(input, "observation", "semantic certificate input")
|
|
20983
|
+
) === true;
|
|
20872
20984
|
} catch (error) {
|
|
20873
20985
|
return {
|
|
20874
20986
|
ok: false,
|
|
20875
20987
|
error: {
|
|
20876
20988
|
code: "contract_error",
|
|
20877
20989
|
contract: contractRef,
|
|
20878
|
-
message: `Semantic contract evaluation failed: ${
|
|
20990
|
+
message: `Semantic contract evaluation failed: ${safeErrorMessage(error)}.`
|
|
20879
20991
|
}
|
|
20880
20992
|
};
|
|
20881
20993
|
}
|
|
@@ -20895,29 +21007,35 @@ function createRiddleProofSemanticCertificate(input) {
|
|
|
20895
21007
|
claim,
|
|
20896
21008
|
evidence,
|
|
20897
21009
|
derivation: { kind: "contract", assurance: "runtime_contract_accepted", contract },
|
|
20898
|
-
issued_at: parseIssuedAt(
|
|
21010
|
+
issued_at: parseIssuedAt(
|
|
21011
|
+
optionalField(input, "issued_at") || (/* @__PURE__ */ new Date()).toISOString(),
|
|
21012
|
+
"semantic certificate issued_at"
|
|
21013
|
+
)
|
|
20899
21014
|
};
|
|
20900
21015
|
return { ok: true, certificate: withCertificateId(body) };
|
|
20901
21016
|
}
|
|
20902
21017
|
function parseRiddleProofSemanticCertificate(value) {
|
|
20903
21018
|
if (!isRecord4(value)) throw new Error("Semantic certificate must be an object.");
|
|
20904
|
-
|
|
20905
|
-
|
|
21019
|
+
const version = optionalField(value, "version");
|
|
21020
|
+
if (version !== RIDDLE_PROOF_SEMANTIC_CERTIFICATE_VERSION) {
|
|
21021
|
+
throw new Error(`Unsupported Semantic certificate version ${String(version || "missing")}.`);
|
|
20906
21022
|
}
|
|
20907
21023
|
for (const field of AUTHORITY_FIELDS) {
|
|
20908
21024
|
if (Object.prototype.hasOwnProperty.call(value, field)) {
|
|
20909
21025
|
throw new Error(`Semantic certificate must not contain authority field ${field}.`);
|
|
20910
21026
|
}
|
|
20911
21027
|
}
|
|
20912
|
-
|
|
20913
|
-
|
|
20914
|
-
|
|
20915
|
-
|
|
20916
|
-
|
|
20917
|
-
|
|
20918
|
-
|
|
20919
|
-
const
|
|
20920
|
-
|
|
21028
|
+
assertOnlyKeys(value, [...CERTIFICATE_FIELDS], "Semantic certificate");
|
|
21029
|
+
const scope = parseScope(requiredField(value, "scope", "semantic certificate"), "semantic certificate scope");
|
|
21030
|
+
const claim = parseClaim(requiredField(value, "claim", "semantic certificate"), "semantic certificate claim");
|
|
21031
|
+
const evidence = parseEvidenceBundle(
|
|
21032
|
+
requiredField(value, "evidence", "semantic certificate"),
|
|
21033
|
+
"semantic certificate evidence"
|
|
21034
|
+
);
|
|
21035
|
+
const derivation = parseDerivation(
|
|
21036
|
+
requiredField(value, "derivation", "semantic certificate"),
|
|
21037
|
+
"semantic certificate derivation"
|
|
21038
|
+
);
|
|
20921
21039
|
if (derivation.kind === "contract" && !sameClaimRef(claim, derivation.contract.claim)) {
|
|
20922
21040
|
throw new Error("Semantic contract-derived claim must match its contract claim.");
|
|
20923
21041
|
}
|
|
@@ -20947,7 +21065,10 @@ function parseRiddleProofSemanticCertificate(value) {
|
|
|
20947
21065
|
claim,
|
|
20948
21066
|
evidence,
|
|
20949
21067
|
derivation,
|
|
20950
|
-
issued_at: parseIssuedAt(
|
|
21068
|
+
issued_at: parseIssuedAt(
|
|
21069
|
+
requiredField(value, "issued_at", "semantic certificate"),
|
|
21070
|
+
"semantic certificate issued_at"
|
|
21071
|
+
)
|
|
20951
21072
|
};
|
|
20952
21073
|
const observedId = requiredString2(value, "certificate_id", "semantic certificate");
|
|
20953
21074
|
const expectedId = certificateId(body);
|
|
@@ -20957,7 +21078,7 @@ function parseRiddleProofSemanticCertificate(value) {
|
|
|
20957
21078
|
return { ...body, certificate_id: observedId };
|
|
20958
21079
|
}
|
|
20959
21080
|
function matchRiddleProofSemanticCertificate(input) {
|
|
20960
|
-
if (!isRecord4(input)) throw new Error("Semantic certificate match input must be
|
|
21081
|
+
if (!isRecord4(input)) throw new Error("Semantic certificate match input must be a plain object.");
|
|
20961
21082
|
assertOnlyKeys(
|
|
20962
21083
|
input,
|
|
20963
21084
|
[
|
|
@@ -20980,11 +21101,11 @@ function matchRiddleProofSemanticCertificate(input) {
|
|
|
20980
21101
|
);
|
|
20981
21102
|
}
|
|
20982
21103
|
const expectedScope = parseScope(
|
|
20983
|
-
input
|
|
21104
|
+
requiredField(input, "expected_scope", "semantic certificate match input"),
|
|
20984
21105
|
"semantic certificate match expected_scope"
|
|
20985
21106
|
);
|
|
20986
21107
|
const expectedClaim = parseClaimRef(
|
|
20987
|
-
input
|
|
21108
|
+
requiredField(input, "expected_claim", "semantic certificate match input"),
|
|
20988
21109
|
"semantic certificate match expected_claim",
|
|
20989
21110
|
["label"]
|
|
20990
21111
|
);
|
|
@@ -21000,7 +21121,9 @@ function matchRiddleProofSemanticCertificate(input) {
|
|
|
21000
21121
|
}
|
|
21001
21122
|
let certificate;
|
|
21002
21123
|
try {
|
|
21003
|
-
certificate = parseRiddleProofSemanticCertificate(
|
|
21124
|
+
certificate = parseRiddleProofSemanticCertificate(
|
|
21125
|
+
requiredField(input, "certificate", "semantic certificate match input")
|
|
21126
|
+
);
|
|
21004
21127
|
} catch (error) {
|
|
21005
21128
|
return {
|
|
21006
21129
|
ok: false,
|
|
@@ -21085,11 +21208,20 @@ function composeRiddleProofSemanticCertificates(input) {
|
|
|
21085
21208
|
["rule", "certificates", "issued_at"],
|
|
21086
21209
|
"semantic composition input"
|
|
21087
21210
|
);
|
|
21088
|
-
const rule = parseRule(
|
|
21089
|
-
|
|
21211
|
+
const rule = parseRule(
|
|
21212
|
+
requiredField(input, "rule", "semantic composition input"),
|
|
21213
|
+
"semantic composition rule",
|
|
21214
|
+
true
|
|
21215
|
+
);
|
|
21216
|
+
const inputCertificates = requiredField(input, "certificates", "semantic composition input");
|
|
21217
|
+
const certificateValues = readDenseDataArray(
|
|
21218
|
+
inputCertificates,
|
|
21219
|
+
"semantic composition input.certificates"
|
|
21220
|
+
);
|
|
21221
|
+
if (certificateValues.length === 0) {
|
|
21090
21222
|
throw new Error("Semantic composition requires at least one certificate.");
|
|
21091
21223
|
}
|
|
21092
|
-
const certificates =
|
|
21224
|
+
const certificates = certificateValues.map((certificate) => parseRiddleProofSemanticCertificate(certificate));
|
|
21093
21225
|
if (certificates.length !== rule.premises.length) {
|
|
21094
21226
|
return {
|
|
21095
21227
|
ok: false,
|
|
@@ -21144,10 +21276,379 @@ function composeRiddleProofSemanticCertificates(input) {
|
|
|
21144
21276
|
rule,
|
|
21145
21277
|
premises: certificates.map(premiseFromCertificate)
|
|
21146
21278
|
},
|
|
21147
|
-
issued_at: parseIssuedAt(
|
|
21279
|
+
issued_at: parseIssuedAt(
|
|
21280
|
+
optionalField(input, "issued_at") || (/* @__PURE__ */ new Date()).toISOString(),
|
|
21281
|
+
"semantic certificate issued_at"
|
|
21282
|
+
)
|
|
21148
21283
|
};
|
|
21149
21284
|
return { ok: true, certificate: withCertificateId(body) };
|
|
21150
21285
|
}
|
|
21286
|
+
function invalidClosure(message) {
|
|
21287
|
+
return { ok: false, error: { code: "invalid_closure", message } };
|
|
21288
|
+
}
|
|
21289
|
+
function firstPremiseSnapshotMismatch(snapshot, certificate) {
|
|
21290
|
+
const observed = premiseFromCertificate(certificate);
|
|
21291
|
+
if (snapshot.derivation_kind !== observed.derivation_kind) return "derivation_kind";
|
|
21292
|
+
if (snapshot.assurance !== observed.assurance) return "assurance";
|
|
21293
|
+
if (stableJson3(snapshot.scope) !== stableJson3(observed.scope)) return "scope";
|
|
21294
|
+
if (stableJson3(snapshot.claim) !== stableJson3(observed.claim)) return "claim";
|
|
21295
|
+
if (stableJson3(snapshot.evidence) !== stableJson3(observed.evidence)) return "evidence";
|
|
21296
|
+
return void 0;
|
|
21297
|
+
}
|
|
21298
|
+
function validateSemanticCertificateClosureInternal(value) {
|
|
21299
|
+
if (!isRecord4(value)) {
|
|
21300
|
+
return invalidClosure("Semantic certificate closure must be a plain object.");
|
|
21301
|
+
}
|
|
21302
|
+
assertOnlyKeys(
|
|
21303
|
+
value,
|
|
21304
|
+
["version", "root_certificate_id", "certificates"],
|
|
21305
|
+
"Semantic certificate closure"
|
|
21306
|
+
);
|
|
21307
|
+
if (requiredField(value, "version", "Semantic certificate closure") !== RIDDLE_PROOF_SEMANTIC_CERTIFICATE_CLOSURE_VERSION) {
|
|
21308
|
+
return invalidClosure("Unsupported Semantic certificate closure version.");
|
|
21309
|
+
}
|
|
21310
|
+
const rootCertificateId = requiredString2(
|
|
21311
|
+
value,
|
|
21312
|
+
"root_certificate_id",
|
|
21313
|
+
"Semantic certificate closure"
|
|
21314
|
+
);
|
|
21315
|
+
if (!/^rpsc_[0-9a-f]{64}$/u.test(rootCertificateId)) {
|
|
21316
|
+
return invalidClosure(
|
|
21317
|
+
"Semantic certificate closure.root_certificate_id must be a full rpsc content ID."
|
|
21318
|
+
);
|
|
21319
|
+
}
|
|
21320
|
+
const inputCertificates = requiredField(
|
|
21321
|
+
value,
|
|
21322
|
+
"certificates",
|
|
21323
|
+
"Semantic certificate closure"
|
|
21324
|
+
);
|
|
21325
|
+
const certificateValues = readDenseDataArray(
|
|
21326
|
+
inputCertificates,
|
|
21327
|
+
"Semantic certificate closure.certificates",
|
|
21328
|
+
RIDDLE_PROOF_SEMANTIC_CERTIFICATE_CLOSURE_MAX_CERTIFICATES
|
|
21329
|
+
);
|
|
21330
|
+
if (certificateValues.length === 0) {
|
|
21331
|
+
return invalidClosure("Semantic certificate closure must contain at least one certificate.");
|
|
21332
|
+
}
|
|
21333
|
+
const certificates = [];
|
|
21334
|
+
for (let index = 0; index < certificateValues.length; index += 1) {
|
|
21335
|
+
try {
|
|
21336
|
+
certificates.push(parseRiddleProofSemanticCertificate(certificateValues[index]));
|
|
21337
|
+
} catch (error) {
|
|
21338
|
+
return {
|
|
21339
|
+
ok: false,
|
|
21340
|
+
error: {
|
|
21341
|
+
code: "invalid_closure_certificate",
|
|
21342
|
+
input_index: index,
|
|
21343
|
+
message: `Semantic certificate closure certificate ${index} did not parse: ${safeErrorMessage(error)}`
|
|
21344
|
+
}
|
|
21345
|
+
};
|
|
21346
|
+
}
|
|
21347
|
+
}
|
|
21348
|
+
const certificatesById = /* @__PURE__ */ new Map();
|
|
21349
|
+
const firstIndexById = /* @__PURE__ */ new Map();
|
|
21350
|
+
for (let index = 0; index < certificates.length; index += 1) {
|
|
21351
|
+
const certificate = certificates[index];
|
|
21352
|
+
const firstIndex = firstIndexById.get(certificate.certificate_id);
|
|
21353
|
+
if (firstIndex !== void 0) {
|
|
21354
|
+
return {
|
|
21355
|
+
ok: false,
|
|
21356
|
+
error: {
|
|
21357
|
+
code: "duplicate_certificate_id",
|
|
21358
|
+
certificate_id: certificate.certificate_id,
|
|
21359
|
+
first_index: firstIndex,
|
|
21360
|
+
duplicate_index: index,
|
|
21361
|
+
message: `Semantic certificate closure repeats certificate ${certificate.certificate_id}.`
|
|
21362
|
+
}
|
|
21363
|
+
};
|
|
21364
|
+
}
|
|
21365
|
+
firstIndexById.set(certificate.certificate_id, index);
|
|
21366
|
+
certificatesById.set(certificate.certificate_id, certificate);
|
|
21367
|
+
}
|
|
21368
|
+
const rootCertificate = certificatesById.get(rootCertificateId);
|
|
21369
|
+
if (!rootCertificate) {
|
|
21370
|
+
return {
|
|
21371
|
+
ok: false,
|
|
21372
|
+
error: {
|
|
21373
|
+
code: "root_certificate_missing",
|
|
21374
|
+
root_certificate_id: rootCertificateId,
|
|
21375
|
+
message: "Semantic certificate closure does not contain its declared root certificate."
|
|
21376
|
+
}
|
|
21377
|
+
};
|
|
21378
|
+
}
|
|
21379
|
+
const states = /* @__PURE__ */ new Map();
|
|
21380
|
+
const stack = [{ certificate: rootCertificate, next_premise_index: 0 }];
|
|
21381
|
+
const dependencyFirst = [];
|
|
21382
|
+
states.set(rootCertificateId, "visiting");
|
|
21383
|
+
while (stack.length > 0) {
|
|
21384
|
+
const frame = stack[stack.length - 1];
|
|
21385
|
+
const premises = frame.certificate.derivation.kind === "composition" ? frame.certificate.derivation.premises : [];
|
|
21386
|
+
if (frame.next_premise_index < premises.length) {
|
|
21387
|
+
const premiseIndex = frame.next_premise_index;
|
|
21388
|
+
frame.next_premise_index += 1;
|
|
21389
|
+
const snapshot = premises[premiseIndex];
|
|
21390
|
+
const child = certificatesById.get(snapshot.certificate_id);
|
|
21391
|
+
if (!child) {
|
|
21392
|
+
return {
|
|
21393
|
+
ok: false,
|
|
21394
|
+
error: {
|
|
21395
|
+
code: "dangling_premise",
|
|
21396
|
+
parent_certificate_id: frame.certificate.certificate_id,
|
|
21397
|
+
premise_index: premiseIndex,
|
|
21398
|
+
premise_certificate_id: snapshot.certificate_id,
|
|
21399
|
+
message: `Semantic certificate ${frame.certificate.certificate_id} premise ${premiseIndex} has no full certificate body.`
|
|
21400
|
+
}
|
|
21401
|
+
};
|
|
21402
|
+
}
|
|
21403
|
+
const mismatch = firstPremiseSnapshotMismatch(snapshot, child);
|
|
21404
|
+
if (mismatch) {
|
|
21405
|
+
return {
|
|
21406
|
+
ok: false,
|
|
21407
|
+
error: {
|
|
21408
|
+
code: "premise_snapshot_mismatch",
|
|
21409
|
+
parent_certificate_id: frame.certificate.certificate_id,
|
|
21410
|
+
premise_index: premiseIndex,
|
|
21411
|
+
premise_certificate_id: snapshot.certificate_id,
|
|
21412
|
+
field: mismatch,
|
|
21413
|
+
message: `Semantic certificate ${frame.certificate.certificate_id} premise ${premiseIndex} has a different ${mismatch} than its full certificate body.`
|
|
21414
|
+
}
|
|
21415
|
+
};
|
|
21416
|
+
}
|
|
21417
|
+
const childState = states.get(child.certificate_id);
|
|
21418
|
+
if (childState === "visiting") {
|
|
21419
|
+
const cycleStart = stack.findIndex(
|
|
21420
|
+
(candidate) => candidate.certificate.certificate_id === child.certificate_id
|
|
21421
|
+
);
|
|
21422
|
+
const certificateIds = stack.slice(Math.max(0, cycleStart)).map((candidate) => candidate.certificate.certificate_id);
|
|
21423
|
+
certificateIds.push(child.certificate_id);
|
|
21424
|
+
return {
|
|
21425
|
+
ok: false,
|
|
21426
|
+
error: {
|
|
21427
|
+
code: "certificate_cycle",
|
|
21428
|
+
certificate_ids: certificateIds,
|
|
21429
|
+
message: "Semantic certificate closure contains a certificate cycle."
|
|
21430
|
+
}
|
|
21431
|
+
};
|
|
21432
|
+
}
|
|
21433
|
+
if (childState !== "visited") {
|
|
21434
|
+
states.set(child.certificate_id, "visiting");
|
|
21435
|
+
stack.push({ certificate: child, next_premise_index: 0 });
|
|
21436
|
+
}
|
|
21437
|
+
continue;
|
|
21438
|
+
}
|
|
21439
|
+
stack.pop();
|
|
21440
|
+
states.set(frame.certificate.certificate_id, "visited");
|
|
21441
|
+
dependencyFirst.push(frame.certificate);
|
|
21442
|
+
}
|
|
21443
|
+
if (dependencyFirst.length !== certificates.length) {
|
|
21444
|
+
const reachable = new Set(dependencyFirst.map((certificate) => certificate.certificate_id));
|
|
21445
|
+
const unreachable = certificates.filter((certificate) => !reachable.has(certificate.certificate_id)).map((certificate) => certificate.certificate_id).sort();
|
|
21446
|
+
return {
|
|
21447
|
+
ok: false,
|
|
21448
|
+
error: {
|
|
21449
|
+
code: "unreachable_certificates",
|
|
21450
|
+
certificate_ids: unreachable,
|
|
21451
|
+
message: "Semantic certificate closure contains certificates unreachable from its root."
|
|
21452
|
+
}
|
|
21453
|
+
};
|
|
21454
|
+
}
|
|
21455
|
+
const closure = {
|
|
21456
|
+
version: RIDDLE_PROOF_SEMANTIC_CERTIFICATE_CLOSURE_VERSION,
|
|
21457
|
+
root_certificate_id: rootCertificateId,
|
|
21458
|
+
certificates: dependencyFirst
|
|
21459
|
+
};
|
|
21460
|
+
return { ok: true, closure, root_certificate: rootCertificate };
|
|
21461
|
+
}
|
|
21462
|
+
function validateRiddleProofSemanticCertificateClosure(value) {
|
|
21463
|
+
try {
|
|
21464
|
+
return validateSemanticCertificateClosureInternal(value);
|
|
21465
|
+
} catch (error) {
|
|
21466
|
+
return invalidClosure(
|
|
21467
|
+
`Semantic certificate closure did not parse: ${safeErrorMessage(error)}`
|
|
21468
|
+
);
|
|
21469
|
+
}
|
|
21470
|
+
}
|
|
21471
|
+
function createRiddleProofSemanticAtomicCertificateClosure(input) {
|
|
21472
|
+
if (!isRecord4(input)) throw new Error("Semantic certificate closure input must be a plain object.");
|
|
21473
|
+
assertOnlyKeys(input, ["certificate"], "Semantic certificate closure input");
|
|
21474
|
+
const certificate = requiredField(input, "certificate", "Semantic certificate closure input");
|
|
21475
|
+
let parsedCertificate;
|
|
21476
|
+
try {
|
|
21477
|
+
parsedCertificate = parseRiddleProofSemanticCertificate(certificate);
|
|
21478
|
+
} catch (error) {
|
|
21479
|
+
return {
|
|
21480
|
+
ok: false,
|
|
21481
|
+
error: {
|
|
21482
|
+
code: "invalid_closure_certificate",
|
|
21483
|
+
input_index: 0,
|
|
21484
|
+
message: `Semantic certificate closure certificate 0 did not parse: ${safeErrorMessage(error)}`
|
|
21485
|
+
}
|
|
21486
|
+
};
|
|
21487
|
+
}
|
|
21488
|
+
if (parsedCertificate.derivation.kind !== "contract") {
|
|
21489
|
+
return invalidClosure(
|
|
21490
|
+
"An atomic Semantic certificate closure requires a contract-derived certificate."
|
|
21491
|
+
);
|
|
21492
|
+
}
|
|
21493
|
+
return validateRiddleProofSemanticCertificateClosure({
|
|
21494
|
+
version: RIDDLE_PROOF_SEMANTIC_CERTIFICATE_CLOSURE_VERSION,
|
|
21495
|
+
root_certificate_id: parsedCertificate.certificate_id,
|
|
21496
|
+
certificates: [certificate]
|
|
21497
|
+
});
|
|
21498
|
+
}
|
|
21499
|
+
function composeRiddleProofSemanticCertificateClosures(input) {
|
|
21500
|
+
if (!isRecord4(input)) throw new Error("Semantic closure composition input must be a plain object.");
|
|
21501
|
+
assertOnlyKeys(
|
|
21502
|
+
input,
|
|
21503
|
+
["rule", "closures", "issued_at"],
|
|
21504
|
+
"Semantic closure composition input"
|
|
21505
|
+
);
|
|
21506
|
+
const inputClosures = requiredField(
|
|
21507
|
+
input,
|
|
21508
|
+
"closures",
|
|
21509
|
+
"Semantic closure composition input"
|
|
21510
|
+
);
|
|
21511
|
+
const closureValues = readDenseDataArray(
|
|
21512
|
+
inputClosures,
|
|
21513
|
+
"Semantic closure composition input.closures"
|
|
21514
|
+
);
|
|
21515
|
+
if (closureValues.length === 0) {
|
|
21516
|
+
throw new Error("Semantic closure composition requires at least one closure.");
|
|
21517
|
+
}
|
|
21518
|
+
const validatedClosures = [];
|
|
21519
|
+
for (let index = 0; index < closureValues.length; index += 1) {
|
|
21520
|
+
const result = validateRiddleProofSemanticCertificateClosure(closureValues[index]);
|
|
21521
|
+
if (!result.ok) {
|
|
21522
|
+
return {
|
|
21523
|
+
ok: false,
|
|
21524
|
+
error: {
|
|
21525
|
+
code: "input_closure_invalid",
|
|
21526
|
+
input_index: index,
|
|
21527
|
+
cause: result.error,
|
|
21528
|
+
message: `Semantic input closure ${index} is invalid: ${result.error.message}`
|
|
21529
|
+
}
|
|
21530
|
+
};
|
|
21531
|
+
}
|
|
21532
|
+
validatedClosures.push(result);
|
|
21533
|
+
}
|
|
21534
|
+
const roots = validatedClosures.map((result) => {
|
|
21535
|
+
if (!result.ok) throw new Error("Validated Semantic closure unexpectedly became invalid.");
|
|
21536
|
+
return result.root_certificate;
|
|
21537
|
+
});
|
|
21538
|
+
const composition = composeRiddleProofSemanticCertificates({
|
|
21539
|
+
rule: requiredField(input, "rule", "Semantic closure composition input"),
|
|
21540
|
+
certificates: roots,
|
|
21541
|
+
issued_at: optionalField(input, "issued_at")
|
|
21542
|
+
});
|
|
21543
|
+
if (!composition.ok) return composition;
|
|
21544
|
+
const merged = [];
|
|
21545
|
+
const byId = /* @__PURE__ */ new Map();
|
|
21546
|
+
for (const result of validatedClosures) {
|
|
21547
|
+
if (!result.ok) continue;
|
|
21548
|
+
for (const certificate of result.closure.certificates) {
|
|
21549
|
+
const existing = byId.get(certificate.certificate_id);
|
|
21550
|
+
if (existing) {
|
|
21551
|
+
if (stableJson3(existing) !== stableJson3(certificate)) {
|
|
21552
|
+
return {
|
|
21553
|
+
ok: false,
|
|
21554
|
+
error: {
|
|
21555
|
+
code: "certificate_id_collision",
|
|
21556
|
+
certificate_id: certificate.certificate_id,
|
|
21557
|
+
message: `Semantic closures contain unequal bodies for ${certificate.certificate_id}.`
|
|
21558
|
+
}
|
|
21559
|
+
};
|
|
21560
|
+
}
|
|
21561
|
+
continue;
|
|
21562
|
+
}
|
|
21563
|
+
byId.set(certificate.certificate_id, certificate);
|
|
21564
|
+
merged.push(certificate);
|
|
21565
|
+
}
|
|
21566
|
+
}
|
|
21567
|
+
if (byId.has(composition.certificate.certificate_id)) {
|
|
21568
|
+
return {
|
|
21569
|
+
ok: false,
|
|
21570
|
+
error: {
|
|
21571
|
+
code: "certificate_id_collision",
|
|
21572
|
+
certificate_id: composition.certificate.certificate_id,
|
|
21573
|
+
message: "Semantic composition produced a root ID already present in its premise closures."
|
|
21574
|
+
}
|
|
21575
|
+
};
|
|
21576
|
+
}
|
|
21577
|
+
merged.push(composition.certificate);
|
|
21578
|
+
const validation = validateRiddleProofSemanticCertificateClosure({
|
|
21579
|
+
version: RIDDLE_PROOF_SEMANTIC_CERTIFICATE_CLOSURE_VERSION,
|
|
21580
|
+
root_certificate_id: composition.certificate.certificate_id,
|
|
21581
|
+
certificates: merged
|
|
21582
|
+
});
|
|
21583
|
+
if (!validation.ok) {
|
|
21584
|
+
return {
|
|
21585
|
+
ok: false,
|
|
21586
|
+
error: {
|
|
21587
|
+
code: "closure_construction_failed",
|
|
21588
|
+
cause: validation.error,
|
|
21589
|
+
message: `Semantic closure construction failed: ${validation.error.message}`
|
|
21590
|
+
}
|
|
21591
|
+
};
|
|
21592
|
+
}
|
|
21593
|
+
return {
|
|
21594
|
+
ok: true,
|
|
21595
|
+
certificate: composition.certificate,
|
|
21596
|
+
closure: validation.closure
|
|
21597
|
+
};
|
|
21598
|
+
}
|
|
21599
|
+
function matchRiddleProofSemanticCertificateClosure(input) {
|
|
21600
|
+
if (!isRecord4(input)) throw new Error("Semantic certificate closure match input must be a plain object.");
|
|
21601
|
+
assertOnlyKeys(
|
|
21602
|
+
input,
|
|
21603
|
+
[
|
|
21604
|
+
"closure",
|
|
21605
|
+
"expected_root_certificate_id",
|
|
21606
|
+
"expected_scope",
|
|
21607
|
+
"expected_claim",
|
|
21608
|
+
"expected_assurance"
|
|
21609
|
+
],
|
|
21610
|
+
"Semantic certificate closure match input"
|
|
21611
|
+
);
|
|
21612
|
+
const validation = validateRiddleProofSemanticCertificateClosure(
|
|
21613
|
+
requiredField(input, "closure", "Semantic certificate closure match input")
|
|
21614
|
+
);
|
|
21615
|
+
if (!validation.ok) return validation;
|
|
21616
|
+
const expectedRootCertificateId = requiredString2(
|
|
21617
|
+
input,
|
|
21618
|
+
"expected_root_certificate_id",
|
|
21619
|
+
"Semantic certificate closure match input"
|
|
21620
|
+
);
|
|
21621
|
+
if (!/^rpsc_[0-9a-f]{64}$/u.test(expectedRootCertificateId)) {
|
|
21622
|
+
throw new Error(
|
|
21623
|
+
"Semantic certificate closure match input.expected_root_certificate_id must be a full rpsc content ID."
|
|
21624
|
+
);
|
|
21625
|
+
}
|
|
21626
|
+
const rootMatch = matchRiddleProofSemanticCertificate({
|
|
21627
|
+
certificate: validation.root_certificate,
|
|
21628
|
+
expected_certificate_id: expectedRootCertificateId,
|
|
21629
|
+
expected_scope: requiredField(
|
|
21630
|
+
input,
|
|
21631
|
+
"expected_scope",
|
|
21632
|
+
"Semantic certificate closure match input"
|
|
21633
|
+
),
|
|
21634
|
+
expected_claim: requiredField(
|
|
21635
|
+
input,
|
|
21636
|
+
"expected_claim",
|
|
21637
|
+
"Semantic certificate closure match input"
|
|
21638
|
+
),
|
|
21639
|
+
expected_assurance: requiredField(
|
|
21640
|
+
input,
|
|
21641
|
+
"expected_assurance",
|
|
21642
|
+
"Semantic certificate closure match input"
|
|
21643
|
+
)
|
|
21644
|
+
});
|
|
21645
|
+
if (!rootMatch.ok) return rootMatch;
|
|
21646
|
+
return {
|
|
21647
|
+
ok: true,
|
|
21648
|
+
closure: validation.closure,
|
|
21649
|
+
root_certificate: rootMatch.certificate
|
|
21650
|
+
};
|
|
21651
|
+
}
|
|
21151
21652
|
|
|
21152
21653
|
// src/change-proof.ts
|
|
21153
21654
|
var RIDDLE_PROOF_CHANGE_CONTRACT_VERSION = "riddle-proof.change-contract.v1";
|
|
@@ -23199,6 +23700,8 @@ function buildRiddleProofPrCommentMarkdown(input) {
|
|
|
23199
23700
|
RIDDLE_PROOF_PR_COMMENT_MARKER,
|
|
23200
23701
|
RIDDLE_PROOF_RUN_CARD_VERSION,
|
|
23201
23702
|
RIDDLE_PROOF_RUN_STATE_VERSION,
|
|
23703
|
+
RIDDLE_PROOF_SEMANTIC_CERTIFICATE_CLOSURE_MAX_CERTIFICATES,
|
|
23704
|
+
RIDDLE_PROOF_SEMANTIC_CERTIFICATE_CLOSURE_VERSION,
|
|
23202
23705
|
RIDDLE_PROOF_SEMANTIC_CERTIFICATE_VERSION,
|
|
23203
23706
|
RIDDLE_PROOF_VISUAL_SESSION_FINGERPRINT_VERSION,
|
|
23204
23707
|
RIDDLE_PROOF_VISUAL_SESSION_VERSION,
|
|
@@ -23241,6 +23744,7 @@ function buildRiddleProofPrCommentMarkdown(input) {
|
|
|
23241
23744
|
compactBasicGameplayText,
|
|
23242
23745
|
compactRecord,
|
|
23243
23746
|
compareVisualProofSessionFingerprint,
|
|
23747
|
+
composeRiddleProofSemanticCertificateClosures,
|
|
23244
23748
|
composeRiddleProofSemanticCertificates,
|
|
23245
23749
|
createBasicGameplayCatchRecords,
|
|
23246
23750
|
createBasicGameplayCatchSummary,
|
|
@@ -23259,6 +23763,7 @@ function buildRiddleProofPrCommentMarkdown(input) {
|
|
|
23259
23763
|
createRiddleProofProfileEnvironmentBlockedResult,
|
|
23260
23764
|
createRiddleProofProfileInsufficientResult,
|
|
23261
23765
|
createRiddleProofRunCard,
|
|
23766
|
+
createRiddleProofSemanticAtomicCertificateClosure,
|
|
23262
23767
|
createRiddleProofSemanticCertificate,
|
|
23263
23768
|
createRunResult,
|
|
23264
23769
|
createRunState,
|
|
@@ -23278,6 +23783,7 @@ function buildRiddleProofPrCommentMarkdown(input) {
|
|
|
23278
23783
|
isTerminalRiddleJobStatus,
|
|
23279
23784
|
isTerminalStatus,
|
|
23280
23785
|
matchRiddleProofSemanticCertificate,
|
|
23786
|
+
matchRiddleProofSemanticCertificateClosure,
|
|
23281
23787
|
migrateRiddleProofChangeReceipt,
|
|
23282
23788
|
nonEmptyString,
|
|
23283
23789
|
normalizeCheckpointResponse,
|
|
@@ -23335,6 +23841,7 @@ function buildRiddleProofPrCommentMarkdown(input) {
|
|
|
23335
23841
|
summarizeRiddleProofProfileResult,
|
|
23336
23842
|
summarizeRiddleProofPublicConsumerSurface,
|
|
23337
23843
|
summarizeRiddleProofPublicState,
|
|
23844
|
+
validateRiddleProofSemanticCertificateClosure,
|
|
23338
23845
|
visualSessionFingerprint,
|
|
23339
23846
|
visualSessionFingerprintBasis
|
|
23340
23847
|
});
|