@nextera.one/axis-server-sdk 1.5.0 → 1.7.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/dist/index.d.mts +1358 -832
- package/dist/index.d.ts +1358 -832
- package/dist/index.js +1597 -198
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1592 -206
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -64,6 +64,9 @@ __export(index_exports, {
|
|
|
64
64
|
BAND: () => BAND,
|
|
65
65
|
BodyProfile: () => import_axis_protocol2.BodyProfile,
|
|
66
66
|
CAPABILITIES: () => CAPABILITIES,
|
|
67
|
+
CCE_ERROR: () => CCE_ERROR,
|
|
68
|
+
CCE_PROTOCOL_VERSION: () => CCE_PROTOCOL_VERSION,
|
|
69
|
+
CceError: () => CceError,
|
|
67
70
|
ContractViolationError: () => ContractViolationError,
|
|
68
71
|
DEFAULT_CONTRACTS: () => DEFAULT_CONTRACTS,
|
|
69
72
|
DEFAULT_TIMEOUT: () => DEFAULT_TIMEOUT,
|
|
@@ -123,6 +126,7 @@ __export(index_exports, {
|
|
|
123
126
|
RESPONSE_TAG_ID: () => RESPONSE_TAG_ID,
|
|
124
127
|
RESPONSE_TAG_UPDATED_AT: () => RESPONSE_TAG_UPDATED_AT,
|
|
125
128
|
RESPONSE_TAG_UPDATED_BY: () => RESPONSE_TAG_UPDATED_BY,
|
|
129
|
+
ResponseObserver: () => verifyResponse,
|
|
126
130
|
RiskDecision: () => RiskDecision,
|
|
127
131
|
SENSOR_METADATA_KEY: () => SENSOR_METADATA_KEY,
|
|
128
132
|
Schema2002_PasskeyLoginOptionsRes: () => Schema2002_PasskeyLoginOptionsRes,
|
|
@@ -156,6 +160,7 @@ __export(index_exports, {
|
|
|
156
160
|
TLV_OFFSET: () => import_axis_protocol2.TLV_OFFSET,
|
|
157
161
|
TLV_OK: () => import_axis_protocol2.TLV_OK,
|
|
158
162
|
TLV_PID: () => import_axis_protocol2.TLV_PID,
|
|
163
|
+
TLV_PRESENCE_ID: () => import_axis_protocol2.TLV_LOOM_PRESENCE_ID,
|
|
159
164
|
TLV_PREV_HASH: () => import_axis_protocol2.TLV_PREV_HASH,
|
|
160
165
|
TLV_PROOF_REF: () => import_axis_protocol2.TLV_PROOF_REF,
|
|
161
166
|
TLV_PROOF_TYPE: () => import_axis_protocol2.TLV_PROOF_TYPE,
|
|
@@ -163,10 +168,12 @@ __export(index_exports, {
|
|
|
163
168
|
TLV_RECEIPT_HASH: () => import_axis_protocol2.TLV_RECEIPT_HASH,
|
|
164
169
|
TLV_RID: () => import_axis_protocol2.TLV_RID,
|
|
165
170
|
TLV_SHA256_CHUNK: () => import_axis_protocol2.TLV_SHA256_CHUNK,
|
|
171
|
+
TLV_THREAD_HASH: () => import_axis_protocol2.TLV_LOOM_THREAD_HASH,
|
|
166
172
|
TLV_TRACE_ID: () => import_axis_protocol2.TLV_TRACE_ID,
|
|
167
173
|
TLV_TS: () => import_axis_protocol2.TLV_TS,
|
|
168
174
|
TLV_UPLOAD_ID: () => import_axis_protocol2.TLV_UPLOAD_ID,
|
|
169
175
|
TLV_VALIDATORS_KEY: () => TLV_VALIDATORS_KEY,
|
|
176
|
+
TLV_WRIT: () => import_axis_protocol2.TLV_LOOM_WRIT,
|
|
170
177
|
TlvEnum: () => TlvEnum,
|
|
171
178
|
TlvField: () => TlvField,
|
|
172
179
|
TlvMinLen: () => TlvMinLen,
|
|
@@ -189,7 +196,10 @@ __export(index_exports, {
|
|
|
189
196
|
canAccessResource: () => canAccessResource,
|
|
190
197
|
canonicalJson: () => canonicalJson,
|
|
191
198
|
canonicalJsonExcluding: () => canonicalJsonExcluding,
|
|
199
|
+
canonicalizeGrant: () => canonicalizeGrant,
|
|
192
200
|
canonicalizeObservation: () => canonicalizeObservation,
|
|
201
|
+
canonicalizeWrit: () => canonicalizeWrit,
|
|
202
|
+
cce: () => cce_exports,
|
|
193
203
|
classifyIntent: () => classifyIntent,
|
|
194
204
|
computeReceiptHash: () => computeReceiptHash,
|
|
195
205
|
computeSignaturePayload: () => computeSignaturePayload,
|
|
@@ -205,14 +215,17 @@ __export(index_exports, {
|
|
|
205
215
|
decodeTLVsList: () => import_axis_protocol.decodeTLVsList,
|
|
206
216
|
decodeVarint: () => import_axis_protocol3.decodeVarint,
|
|
207
217
|
decorators: () => decorators_exports,
|
|
218
|
+
deriveAnchorReflection: () => deriveAnchorReflection,
|
|
208
219
|
encVarint: () => encVarint,
|
|
209
220
|
encodeAxis1Frame: () => encodeAxis1Frame,
|
|
221
|
+
encodeAxisTlvDto: () => encodeAxisTlvDto,
|
|
210
222
|
encodeFrame: () => encodeFrame,
|
|
211
223
|
encodeQueueMessage: () => encodeQueueMessage,
|
|
212
224
|
encodeTLVs: () => import_axis_protocol.encodeTLVs,
|
|
213
225
|
encodeVarint: () => import_axis_protocol3.encodeVarint,
|
|
214
226
|
endStage: () => endStage,
|
|
215
227
|
engine: () => engine_exports,
|
|
228
|
+
executeCcePipeline: () => executeCcePipeline,
|
|
216
229
|
extractDtoSchema: () => extractDtoSchema,
|
|
217
230
|
finalizeObservation: () => finalizeObservation,
|
|
218
231
|
generateEd25519KeyPair: () => generateEd25519KeyPair,
|
|
@@ -239,7 +252,7 @@ __export(index_exports, {
|
|
|
239
252
|
security: () => security_exports,
|
|
240
253
|
sensitivityName: () => sensitivityName,
|
|
241
254
|
sensors: () => sensors_exports,
|
|
242
|
-
sha256: () =>
|
|
255
|
+
sha256: () => sha2564,
|
|
243
256
|
signFrame: () => signFrame,
|
|
244
257
|
stableJsonStringify: () => stableJsonStringify,
|
|
245
258
|
startStage: () => startStage,
|
|
@@ -636,6 +649,626 @@ var SensorDecisions = {
|
|
|
636
649
|
}
|
|
637
650
|
};
|
|
638
651
|
|
|
652
|
+
// src/cce/cce-derivation.service.ts
|
|
653
|
+
var import_utils = require("@noble/hashes/utils.js");
|
|
654
|
+
var import_hkdf = require("@noble/hashes/hkdf.js");
|
|
655
|
+
var import_sha2 = require("@noble/hashes/sha2.js");
|
|
656
|
+
|
|
657
|
+
// src/cce/cce.types.ts
|
|
658
|
+
var CCE_PROTOCOL_VERSION = "cce-v1";
|
|
659
|
+
var CCE_DERIVATION = {
|
|
660
|
+
/** Request execution context */
|
|
661
|
+
REQUEST: "axis:cce:req:v1",
|
|
662
|
+
/** Response execution context */
|
|
663
|
+
RESPONSE: "axis:cce:resp:v1",
|
|
664
|
+
/** Witness binding context */
|
|
665
|
+
WITNESS: "axis:cce:witness:v1"
|
|
666
|
+
};
|
|
667
|
+
var CCE_AES_KEY_BYTES = 32;
|
|
668
|
+
var CCE_IV_BYTES = 12;
|
|
669
|
+
var CCE_TAG_BYTES = 16;
|
|
670
|
+
var CCE_NONCE_BYTES = 32;
|
|
671
|
+
var CCE_ERROR = {
|
|
672
|
+
// Envelope errors
|
|
673
|
+
INVALID_ENVELOPE: "CCE_INVALID_ENVELOPE",
|
|
674
|
+
UNSUPPORTED_VERSION: "CCE_UNSUPPORTED_VERSION",
|
|
675
|
+
MISSING_CAPSULE: "CCE_MISSING_CAPSULE",
|
|
676
|
+
MISSING_ENCRYPTED_KEY: "CCE_MISSING_ENCRYPTED_KEY",
|
|
677
|
+
// Signature errors
|
|
678
|
+
CLIENT_SIG_INVALID: "CCE_CLIENT_SIG_INVALID",
|
|
679
|
+
CLIENT_KEY_NOT_FOUND: "CCE_CLIENT_KEY_NOT_FOUND",
|
|
680
|
+
// Capsule errors
|
|
681
|
+
CAPSULE_SIG_INVALID: "CCE_CAPSULE_SIG_INVALID",
|
|
682
|
+
CAPSULE_EXPIRED: "CCE_CAPSULE_EXPIRED",
|
|
683
|
+
CAPSULE_NOT_YET_VALID: "CCE_CAPSULE_NOT_YET_VALID",
|
|
684
|
+
CAPSULE_REVOKED: "CCE_CAPSULE_REVOKED",
|
|
685
|
+
CAPSULE_CONSUMED: "CCE_CAPSULE_CONSUMED",
|
|
686
|
+
// Binding errors
|
|
687
|
+
AUDIENCE_MISMATCH: "CCE_AUDIENCE_MISMATCH",
|
|
688
|
+
INTENT_MISMATCH: "CCE_INTENT_MISMATCH",
|
|
689
|
+
TPS_WINDOW_EXPIRED: "CCE_TPS_WINDOW_EXPIRED",
|
|
690
|
+
TPS_WINDOW_FUTURE: "CCE_TPS_WINDOW_FUTURE",
|
|
691
|
+
// Replay / nonce errors
|
|
692
|
+
REPLAY_DETECTED: "CCE_REPLAY_DETECTED",
|
|
693
|
+
NONCE_REUSED: "CCE_NONCE_REUSED",
|
|
694
|
+
// Decryption errors
|
|
695
|
+
DECRYPTION_FAILED: "CCE_DECRYPTION_FAILED",
|
|
696
|
+
KEY_UNWRAP_FAILED: "CCE_KEY_UNWRAP_FAILED",
|
|
697
|
+
AEAD_TAG_MISMATCH: "CCE_AEAD_TAG_MISMATCH",
|
|
698
|
+
PAYLOAD_TOO_LARGE: "CCE_PAYLOAD_TOO_LARGE",
|
|
699
|
+
// Schema / validation errors
|
|
700
|
+
PAYLOAD_SCHEMA_INVALID: "CCE_PAYLOAD_SCHEMA_INVALID",
|
|
701
|
+
INTENT_SCHEMA_MISMATCH: "CCE_INTENT_SCHEMA_MISMATCH",
|
|
702
|
+
// Policy errors
|
|
703
|
+
POLICY_DENIED: "CCE_POLICY_DENIED",
|
|
704
|
+
CONSTRAINT_VIOLATED: "CCE_CONSTRAINT_VIOLATED",
|
|
705
|
+
// Handler errors
|
|
706
|
+
HANDLER_NOT_FOUND: "CCE_HANDLER_NOT_FOUND",
|
|
707
|
+
HANDLER_EXECUTION_FAILED: "CCE_HANDLER_EXECUTION_FAILED",
|
|
708
|
+
HANDLER_TIMEOUT: "CCE_HANDLER_TIMEOUT",
|
|
709
|
+
// Response errors
|
|
710
|
+
RESPONSE_ENCRYPTION_FAILED: "CCE_RESPONSE_ENCRYPTION_FAILED"
|
|
711
|
+
};
|
|
712
|
+
var CceError = class extends Error {
|
|
713
|
+
constructor(code, message, metadata) {
|
|
714
|
+
super(`[${code}] ${message}`);
|
|
715
|
+
this.code = code;
|
|
716
|
+
this.metadata = metadata;
|
|
717
|
+
this.name = "CceError";
|
|
718
|
+
}
|
|
719
|
+
/** Whether this error is safe to expose to the client */
|
|
720
|
+
get clientSafe() {
|
|
721
|
+
const internal = [
|
|
722
|
+
CCE_ERROR.DECRYPTION_FAILED,
|
|
723
|
+
CCE_ERROR.KEY_UNWRAP_FAILED,
|
|
724
|
+
CCE_ERROR.AEAD_TAG_MISMATCH,
|
|
725
|
+
CCE_ERROR.HANDLER_EXECUTION_FAILED,
|
|
726
|
+
CCE_ERROR.RESPONSE_ENCRYPTION_FAILED
|
|
727
|
+
];
|
|
728
|
+
return !internal.includes(this.code);
|
|
729
|
+
}
|
|
730
|
+
/** Get client-safe representation */
|
|
731
|
+
toClientError() {
|
|
732
|
+
if (this.clientSafe) {
|
|
733
|
+
return { code: this.code, message: this.message };
|
|
734
|
+
}
|
|
735
|
+
return {
|
|
736
|
+
code: CCE_ERROR.DECRYPTION_FAILED,
|
|
737
|
+
message: "Request processing failed"
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
};
|
|
741
|
+
|
|
742
|
+
// src/cce/cce-derivation.service.ts
|
|
743
|
+
function buildSalt(capsuleId, capsuleNonce, requestNonce) {
|
|
744
|
+
const encoder = new TextEncoder();
|
|
745
|
+
const data = encoder.encode(
|
|
746
|
+
capsuleId + "|" + capsuleNonce + "|" + requestNonce
|
|
747
|
+
);
|
|
748
|
+
return (0, import_sha2.sha256)(data);
|
|
749
|
+
}
|
|
750
|
+
function buildInfo(contextPrefix, capsule, extraNonce) {
|
|
751
|
+
const encoder = new TextEncoder();
|
|
752
|
+
const parts = [
|
|
753
|
+
contextPrefix,
|
|
754
|
+
capsule.sub,
|
|
755
|
+
capsule.kid,
|
|
756
|
+
capsule.intent,
|
|
757
|
+
capsule.aud,
|
|
758
|
+
String(capsule.tps_from),
|
|
759
|
+
String(capsule.tps_to),
|
|
760
|
+
capsule.policy_hash ?? "",
|
|
761
|
+
capsule.ver
|
|
762
|
+
];
|
|
763
|
+
if (extraNonce) {
|
|
764
|
+
parts.push(extraNonce);
|
|
765
|
+
}
|
|
766
|
+
return encoder.encode(parts.join("|"));
|
|
767
|
+
}
|
|
768
|
+
function deriveRequestExecutionKey(input) {
|
|
769
|
+
const ikm = (0, import_utils.hexToBytes)(input.axisLocalSecret);
|
|
770
|
+
const salt = buildSalt(
|
|
771
|
+
input.capsule.capsule_id,
|
|
772
|
+
input.capsule.capsule_nonce,
|
|
773
|
+
input.requestNonce
|
|
774
|
+
);
|
|
775
|
+
const info = buildInfo(CCE_DERIVATION.REQUEST, input.capsule);
|
|
776
|
+
return (0, import_hkdf.hkdf)(import_sha2.sha256, ikm, salt, info, CCE_AES_KEY_BYTES);
|
|
777
|
+
}
|
|
778
|
+
function deriveResponseExecutionKey(input) {
|
|
779
|
+
const ikm = (0, import_utils.hexToBytes)(input.axisLocalSecret);
|
|
780
|
+
const encoder = new TextEncoder();
|
|
781
|
+
const saltData = encoder.encode(
|
|
782
|
+
input.capsule.capsule_id + "|" + input.capsule.capsule_nonce + "|" + input.requestNonce + "|" + input.responseNonce
|
|
783
|
+
);
|
|
784
|
+
const salt = (0, import_sha2.sha256)(saltData);
|
|
785
|
+
const info = buildInfo(
|
|
786
|
+
CCE_DERIVATION.RESPONSE,
|
|
787
|
+
input.capsule,
|
|
788
|
+
input.responseNonce
|
|
789
|
+
);
|
|
790
|
+
return (0, import_hkdf.hkdf)(import_sha2.sha256, ikm, salt, info, CCE_AES_KEY_BYTES);
|
|
791
|
+
}
|
|
792
|
+
function deriveWitnessKey(input) {
|
|
793
|
+
const ikm = (0, import_utils.hexToBytes)(input.axisLocalSecret);
|
|
794
|
+
const salt = buildSalt(
|
|
795
|
+
input.capsule.capsule_id,
|
|
796
|
+
input.capsule.capsule_nonce,
|
|
797
|
+
input.requestNonce
|
|
798
|
+
);
|
|
799
|
+
const info = buildInfo(CCE_DERIVATION.WITNESS, input.capsule);
|
|
800
|
+
return (0, import_hkdf.hkdf)(import_sha2.sha256, ikm, salt, info, CCE_AES_KEY_BYTES);
|
|
801
|
+
}
|
|
802
|
+
function buildExecutionContext(input, requestId) {
|
|
803
|
+
const executionKey = deriveRequestExecutionKey(input);
|
|
804
|
+
const keyHash = (0, import_utils.bytesToHex)((0, import_sha2.sha256)(executionKey));
|
|
805
|
+
executionKey.fill(0);
|
|
806
|
+
return {
|
|
807
|
+
execution_key_hash: keyHash,
|
|
808
|
+
request_id: requestId,
|
|
809
|
+
capsule_id: input.capsule.capsule_id,
|
|
810
|
+
sub: input.capsule.sub,
|
|
811
|
+
kid: input.capsule.kid,
|
|
812
|
+
intent: input.capsule.intent,
|
|
813
|
+
aud: input.capsule.aud,
|
|
814
|
+
tps_from: input.capsule.tps_from,
|
|
815
|
+
tps_to: input.capsule.tps_to,
|
|
816
|
+
policy_hash: input.capsule.policy_hash,
|
|
817
|
+
derived_at: Math.floor(Date.now() / 1e3),
|
|
818
|
+
valid: true
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
function generateCceNonce() {
|
|
822
|
+
const bytes2 = new Uint8Array(CCE_NONCE_BYTES);
|
|
823
|
+
crypto.getRandomValues(bytes2);
|
|
824
|
+
return (0, import_utils.bytesToHex)(bytes2);
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
// src/cce/cce-response.service.ts
|
|
828
|
+
var import_utils3 = require("@noble/hashes/utils.js");
|
|
829
|
+
var import_crypto2 = require("crypto");
|
|
830
|
+
|
|
831
|
+
// src/cce/cce-crypto.ts
|
|
832
|
+
var import_utils2 = require("@noble/hashes/utils.js");
|
|
833
|
+
var import_sha22 = require("@noble/hashes/sha2.js");
|
|
834
|
+
var import_crypto = require("crypto");
|
|
835
|
+
function aesGcmEncrypt(key, plaintext, aad) {
|
|
836
|
+
if (key.length !== CCE_AES_KEY_BYTES) {
|
|
837
|
+
throw new Error(`AES key must be ${CCE_AES_KEY_BYTES} bytes`);
|
|
838
|
+
}
|
|
839
|
+
const iv = (0, import_crypto.randomBytes)(CCE_IV_BYTES);
|
|
840
|
+
const cipher = (0, import_crypto.createCipheriv)("aes-256-gcm", key, iv);
|
|
841
|
+
if (aad) {
|
|
842
|
+
cipher.setAAD(aad);
|
|
843
|
+
}
|
|
844
|
+
const encrypted = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
845
|
+
const tag = cipher.getAuthTag();
|
|
846
|
+
return {
|
|
847
|
+
iv: new Uint8Array(iv),
|
|
848
|
+
ciphertext: new Uint8Array(encrypted),
|
|
849
|
+
tag: new Uint8Array(tag)
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
function aesGcmDecrypt(key, iv, ciphertext, tag, aad) {
|
|
853
|
+
if (key.length !== CCE_AES_KEY_BYTES) {
|
|
854
|
+
throw new Error(`AES key must be ${CCE_AES_KEY_BYTES} bytes`);
|
|
855
|
+
}
|
|
856
|
+
if (iv.length !== CCE_IV_BYTES) {
|
|
857
|
+
throw new Error(`IV must be ${CCE_IV_BYTES} bytes`);
|
|
858
|
+
}
|
|
859
|
+
if (tag.length !== CCE_TAG_BYTES) {
|
|
860
|
+
throw new Error(`Tag must be ${CCE_TAG_BYTES} bytes`);
|
|
861
|
+
}
|
|
862
|
+
try {
|
|
863
|
+
const decipher = (0, import_crypto.createDecipheriv)("aes-256-gcm", key, iv);
|
|
864
|
+
decipher.setAuthTag(tag);
|
|
865
|
+
if (aad) {
|
|
866
|
+
decipher.setAAD(aad);
|
|
867
|
+
}
|
|
868
|
+
const decrypted = Buffer.concat([
|
|
869
|
+
decipher.update(ciphertext),
|
|
870
|
+
decipher.final()
|
|
871
|
+
]);
|
|
872
|
+
return new Uint8Array(decrypted);
|
|
873
|
+
} catch {
|
|
874
|
+
return null;
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
function generateAesKey() {
|
|
878
|
+
return new Uint8Array((0, import_crypto.randomBytes)(CCE_AES_KEY_BYTES));
|
|
879
|
+
}
|
|
880
|
+
function generateIv() {
|
|
881
|
+
return new Uint8Array((0, import_crypto.randomBytes)(CCE_IV_BYTES));
|
|
882
|
+
}
|
|
883
|
+
function base64UrlEncode(bytes2) {
|
|
884
|
+
return Buffer.from(bytes2).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
885
|
+
}
|
|
886
|
+
function base64UrlDecode(input) {
|
|
887
|
+
const base64 = input.replace(/-/g, "+").replace(/_/g, "/");
|
|
888
|
+
const padding = "=".repeat((4 - base64.length % 4) % 4);
|
|
889
|
+
return new Uint8Array(Buffer.from(base64 + padding, "base64"));
|
|
890
|
+
}
|
|
891
|
+
function hashPayload(payload) {
|
|
892
|
+
return (0, import_utils2.bytesToHex)((0, import_sha22.sha256)(payload));
|
|
893
|
+
}
|
|
894
|
+
var nodeAesGcmProvider = {
|
|
895
|
+
async decrypt(key, iv, ciphertext, tag, aad) {
|
|
896
|
+
return aesGcmDecrypt(key, iv, ciphertext, tag, aad);
|
|
897
|
+
}
|
|
898
|
+
};
|
|
899
|
+
|
|
900
|
+
// src/cce/cce-response.service.ts
|
|
901
|
+
async function buildCceResponse(options, clientKeyEncryptor, axisSigner) {
|
|
902
|
+
const { request, capsule, status, body, clientPublicKeyHex, witnessRef } = options;
|
|
903
|
+
const responseNonce = (0, import_utils3.bytesToHex)(
|
|
904
|
+
new Uint8Array((0, import_crypto2.randomBytes)(CCE_NONCE_BYTES))
|
|
905
|
+
);
|
|
906
|
+
const responseId = generateResponseId();
|
|
907
|
+
const aesKey = generateAesKey();
|
|
908
|
+
const aad = buildResponseAad(
|
|
909
|
+
request.request_id,
|
|
910
|
+
responseId,
|
|
911
|
+
request.correlation_id,
|
|
912
|
+
capsule.capsule_id,
|
|
913
|
+
responseNonce
|
|
914
|
+
);
|
|
915
|
+
const { iv, ciphertext, tag } = aesGcmEncrypt(aesKey, body, aad);
|
|
916
|
+
const encryptedKey = await clientKeyEncryptor.wrapKey(
|
|
917
|
+
aesKey,
|
|
918
|
+
request.client_kid,
|
|
919
|
+
clientPublicKeyHex
|
|
920
|
+
);
|
|
921
|
+
aesKey.fill(0);
|
|
922
|
+
const encryptedPayload = {
|
|
923
|
+
alg: "AES-256-GCM",
|
|
924
|
+
iv: base64UrlEncode(iv),
|
|
925
|
+
ciphertext: base64UrlEncode(ciphertext),
|
|
926
|
+
tag: base64UrlEncode(tag)
|
|
927
|
+
};
|
|
928
|
+
const algorithms = {
|
|
929
|
+
kem: encryptedKey.alg,
|
|
930
|
+
enc: "AES-256-GCM",
|
|
931
|
+
kdf: "HKDF-SHA256",
|
|
932
|
+
sig: "EdDSA"
|
|
933
|
+
};
|
|
934
|
+
const unsignedResponse = {
|
|
935
|
+
ver: CCE_PROTOCOL_VERSION,
|
|
936
|
+
response_id: responseId,
|
|
937
|
+
request_id: request.request_id,
|
|
938
|
+
correlation_id: request.correlation_id,
|
|
939
|
+
encrypted_key: encryptedKey,
|
|
940
|
+
encrypted_payload: encryptedPayload,
|
|
941
|
+
response_nonce: responseNonce,
|
|
942
|
+
algorithms,
|
|
943
|
+
status,
|
|
944
|
+
...witnessRef ? { witness_ref: witnessRef } : {}
|
|
945
|
+
};
|
|
946
|
+
const signPayload = new TextEncoder().encode(canonicalize(unsignedResponse));
|
|
947
|
+
const axisSig = await axisSigner.sign(signPayload);
|
|
948
|
+
const envelope = {
|
|
949
|
+
...unsignedResponse,
|
|
950
|
+
axis_sig: axisSig
|
|
951
|
+
};
|
|
952
|
+
return {
|
|
953
|
+
envelope,
|
|
954
|
+
responsePayloadHash: hashPayload(body)
|
|
955
|
+
};
|
|
956
|
+
}
|
|
957
|
+
function buildCceErrorResponse(requestId, correlationId, status, errorCode, message) {
|
|
958
|
+
return {
|
|
959
|
+
ver: CCE_PROTOCOL_VERSION,
|
|
960
|
+
request_id: requestId,
|
|
961
|
+
correlation_id: correlationId,
|
|
962
|
+
status,
|
|
963
|
+
error: { code: errorCode, message }
|
|
964
|
+
};
|
|
965
|
+
}
|
|
966
|
+
function generateResponseId() {
|
|
967
|
+
const bytes2 = (0, import_crypto2.randomBytes)(16);
|
|
968
|
+
return "resp_" + (0, import_utils3.bytesToHex)(new Uint8Array(bytes2)).slice(0, 24);
|
|
969
|
+
}
|
|
970
|
+
function buildResponseAad(requestId, responseId, correlationId, capsuleId, responseNonce) {
|
|
971
|
+
const parts = [
|
|
972
|
+
requestId,
|
|
973
|
+
responseId,
|
|
974
|
+
correlationId,
|
|
975
|
+
capsuleId,
|
|
976
|
+
responseNonce
|
|
977
|
+
];
|
|
978
|
+
return new TextEncoder().encode(parts.join("|"));
|
|
979
|
+
}
|
|
980
|
+
function canonicalize(obj) {
|
|
981
|
+
if (Array.isArray(obj)) {
|
|
982
|
+
return "[" + obj.map(canonicalize).join(",") + "]";
|
|
983
|
+
}
|
|
984
|
+
if (obj !== null && typeof obj === "object") {
|
|
985
|
+
const sorted = Object.keys(obj).sort().map(
|
|
986
|
+
(k) => JSON.stringify(k) + ":" + canonicalize(obj[k])
|
|
987
|
+
);
|
|
988
|
+
return "{" + sorted.join(",") + "}";
|
|
989
|
+
}
|
|
990
|
+
return JSON.stringify(obj);
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
// src/cce/cce-witness.observer.ts
|
|
994
|
+
var import_utils4 = require("@noble/hashes/utils.js");
|
|
995
|
+
var import_hkdf2 = require("@noble/hashes/hkdf.js");
|
|
996
|
+
var import_sha23 = require("@noble/hashes/sha2.js");
|
|
997
|
+
var InMemoryCceWitnessStore = class {
|
|
998
|
+
constructor() {
|
|
999
|
+
this.records = [];
|
|
1000
|
+
}
|
|
1001
|
+
async record(witness) {
|
|
1002
|
+
this.records.push(witness);
|
|
1003
|
+
}
|
|
1004
|
+
getByRequestId(requestId) {
|
|
1005
|
+
return this.records.find((w) => w.request_id === requestId);
|
|
1006
|
+
}
|
|
1007
|
+
getByCapsuleId(capsuleId) {
|
|
1008
|
+
return this.records.filter((w) => w.capsule_id === capsuleId);
|
|
1009
|
+
}
|
|
1010
|
+
};
|
|
1011
|
+
function buildWitnessRecord(envelope, capsule, verification, execution, options) {
|
|
1012
|
+
const witnessId = generateWitnessId(envelope.request_id, capsule.capsule_id);
|
|
1013
|
+
const executionContextHash = computeExecutionContextHash(
|
|
1014
|
+
options.axisLocalSecret,
|
|
1015
|
+
capsule,
|
|
1016
|
+
envelope.request_nonce
|
|
1017
|
+
);
|
|
1018
|
+
return {
|
|
1019
|
+
witness_id: witnessId,
|
|
1020
|
+
request_id: envelope.request_id,
|
|
1021
|
+
capsule_id: capsule.capsule_id,
|
|
1022
|
+
sub: capsule.sub,
|
|
1023
|
+
intent: capsule.intent,
|
|
1024
|
+
aud: capsule.aud,
|
|
1025
|
+
tps_from: capsule.tps_from,
|
|
1026
|
+
tps_to: capsule.tps_to,
|
|
1027
|
+
timestamp: Math.floor(Date.now() / 1e3),
|
|
1028
|
+
verification: {
|
|
1029
|
+
client_sig: verification.clientSigVerified,
|
|
1030
|
+
capsule_sig: verification.capsuleSigVerified,
|
|
1031
|
+
tps_valid: verification.tpsValid,
|
|
1032
|
+
audience_match: verification.audienceMatch,
|
|
1033
|
+
intent_match: verification.intentMatch,
|
|
1034
|
+
replay_clean: verification.replayClean,
|
|
1035
|
+
nonce_unique: verification.nonceUnique,
|
|
1036
|
+
decryption_ok: verification.decryptionOk
|
|
1037
|
+
},
|
|
1038
|
+
execution: {
|
|
1039
|
+
status: execution.status,
|
|
1040
|
+
handler_duration_ms: execution.handlerDurationMs,
|
|
1041
|
+
...execution.effect ? { effect: execution.effect } : {}
|
|
1042
|
+
},
|
|
1043
|
+
response_encrypted: options.responseEncrypted,
|
|
1044
|
+
execution_context_hash: executionContextHash,
|
|
1045
|
+
...options.requestPayload ? { request_payload_hash: hashPayload(options.requestPayload) } : {},
|
|
1046
|
+
...options.responsePayload ? { response_payload_hash: hashPayload(options.responsePayload) } : {}
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
function extractVerificationState(metadata) {
|
|
1050
|
+
return {
|
|
1051
|
+
clientSigVerified: metadata.cceClientSigVerified === true,
|
|
1052
|
+
capsuleSigVerified: metadata.cceCapsuleVerified === true,
|
|
1053
|
+
tpsValid: metadata.cceTpsValid === true,
|
|
1054
|
+
audienceMatch: metadata.cceBindingVerified === true,
|
|
1055
|
+
intentMatch: metadata.cceBindingVerified === true,
|
|
1056
|
+
replayClean: metadata.cceReplayClean === true,
|
|
1057
|
+
nonceUnique: metadata.cceReplayClean === true,
|
|
1058
|
+
decryptionOk: metadata.cceDecryptionOk === true
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1061
|
+
function generateWitnessId(requestId, capsuleId) {
|
|
1062
|
+
const input = `witness:${requestId}:${capsuleId}:${Date.now()}`;
|
|
1063
|
+
const hash = (0, import_sha23.sha256)(new TextEncoder().encode(input));
|
|
1064
|
+
return "wit_" + (0, import_utils4.bytesToHex)(hash).slice(0, 24);
|
|
1065
|
+
}
|
|
1066
|
+
function computeExecutionContextHash(axisLocalSecret, capsule, requestNonce) {
|
|
1067
|
+
const encoder = new TextEncoder();
|
|
1068
|
+
const ikm = hexToBytes2(axisLocalSecret);
|
|
1069
|
+
const salt = (0, import_sha23.sha256)(
|
|
1070
|
+
encoder.encode(
|
|
1071
|
+
capsule.capsule_id + "|" + capsule.capsule_nonce + "|" + requestNonce
|
|
1072
|
+
)
|
|
1073
|
+
);
|
|
1074
|
+
const info = encoder.encode(
|
|
1075
|
+
[
|
|
1076
|
+
CCE_DERIVATION.WITNESS,
|
|
1077
|
+
capsule.sub,
|
|
1078
|
+
capsule.kid,
|
|
1079
|
+
capsule.intent,
|
|
1080
|
+
capsule.aud,
|
|
1081
|
+
String(capsule.tps_from),
|
|
1082
|
+
String(capsule.tps_to),
|
|
1083
|
+
capsule.policy_hash ?? "",
|
|
1084
|
+
capsule.ver
|
|
1085
|
+
].join("|")
|
|
1086
|
+
);
|
|
1087
|
+
const witnessKey = (0, import_hkdf2.hkdf)(import_sha23.sha256, ikm, salt, info, 32);
|
|
1088
|
+
const hash = (0, import_utils4.bytesToHex)((0, import_sha23.sha256)(witnessKey));
|
|
1089
|
+
witnessKey.fill(0);
|
|
1090
|
+
return hash;
|
|
1091
|
+
}
|
|
1092
|
+
function hexToBytes2(hex) {
|
|
1093
|
+
const bytes2 = new Uint8Array(hex.length / 2);
|
|
1094
|
+
for (let i = 0; i < bytes2.length; i++) {
|
|
1095
|
+
bytes2[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
1096
|
+
}
|
|
1097
|
+
return bytes2;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
// src/cce/cce-pipeline.ts
|
|
1101
|
+
async function executeCcePipeline(envelope, config) {
|
|
1102
|
+
const startTime = Date.now();
|
|
1103
|
+
if (envelope.ver !== CCE_PROTOCOL_VERSION) {
|
|
1104
|
+
return {
|
|
1105
|
+
ok: false,
|
|
1106
|
+
error: {
|
|
1107
|
+
code: CCE_ERROR.UNSUPPORTED_VERSION,
|
|
1108
|
+
message: `Unsupported version: ${envelope.ver}`
|
|
1109
|
+
},
|
|
1110
|
+
status: "ERROR"
|
|
1111
|
+
};
|
|
1112
|
+
}
|
|
1113
|
+
const sensorInput = {
|
|
1114
|
+
intent: envelope.capsule.intent,
|
|
1115
|
+
metadata: {
|
|
1116
|
+
cce: true,
|
|
1117
|
+
cceEnvelope: envelope,
|
|
1118
|
+
contentType: "application/axis-cce"
|
|
1119
|
+
}
|
|
1120
|
+
};
|
|
1121
|
+
const sortedSensors = [...config.sensors].sort(
|
|
1122
|
+
(a, b) => (a.order ?? 999) - (b.order ?? 999)
|
|
1123
|
+
);
|
|
1124
|
+
for (const sensor of sortedSensors) {
|
|
1125
|
+
if (sensor.supports && !sensor.supports(sensorInput)) {
|
|
1126
|
+
continue;
|
|
1127
|
+
}
|
|
1128
|
+
let decision;
|
|
1129
|
+
try {
|
|
1130
|
+
decision = await sensor.run(sensorInput);
|
|
1131
|
+
} catch (err) {
|
|
1132
|
+
return {
|
|
1133
|
+
ok: false,
|
|
1134
|
+
error: {
|
|
1135
|
+
code: CCE_ERROR.DECRYPTION_FAILED,
|
|
1136
|
+
message: `Sensor ${sensor.name} failed`
|
|
1137
|
+
},
|
|
1138
|
+
status: "ERROR"
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
const normalized = normalizeSensorDecision(decision);
|
|
1142
|
+
if (!normalized.allow) {
|
|
1143
|
+
const code = normalized.reasons[0]?.split(":")[0] ?? CCE_ERROR.DECRYPTION_FAILED;
|
|
1144
|
+
return {
|
|
1145
|
+
ok: false,
|
|
1146
|
+
error: { code, message: normalized.reasons.join("; ") },
|
|
1147
|
+
status: "DENIED"
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
const capsule = sensorInput.metadata?.cceCapsule;
|
|
1152
|
+
const decryptedPayload = sensorInput.metadata?.cceDecryptedPayload;
|
|
1153
|
+
const clientKey = sensorInput.metadata?.cceClientKey;
|
|
1154
|
+
if (!capsule || !decryptedPayload || !clientKey) {
|
|
1155
|
+
return {
|
|
1156
|
+
ok: false,
|
|
1157
|
+
error: {
|
|
1158
|
+
code: CCE_ERROR.DECRYPTION_FAILED,
|
|
1159
|
+
message: "Sensor chain did not produce required outputs"
|
|
1160
|
+
},
|
|
1161
|
+
status: "ERROR"
|
|
1162
|
+
};
|
|
1163
|
+
}
|
|
1164
|
+
const derivationInput = {
|
|
1165
|
+
axisLocalSecret: config.axisLocalSecret,
|
|
1166
|
+
capsule,
|
|
1167
|
+
requestNonce: envelope.request_nonce
|
|
1168
|
+
};
|
|
1169
|
+
const executionContext = buildExecutionContext(
|
|
1170
|
+
derivationInput,
|
|
1171
|
+
envelope.request_id
|
|
1172
|
+
);
|
|
1173
|
+
const handler = config.handlers.get(capsule.intent);
|
|
1174
|
+
if (!handler) {
|
|
1175
|
+
return {
|
|
1176
|
+
ok: false,
|
|
1177
|
+
error: {
|
|
1178
|
+
code: CCE_ERROR.HANDLER_NOT_FOUND,
|
|
1179
|
+
message: `No handler for intent: ${capsule.intent}`
|
|
1180
|
+
},
|
|
1181
|
+
status: "ERROR"
|
|
1182
|
+
};
|
|
1183
|
+
}
|
|
1184
|
+
const handlerContext = {
|
|
1185
|
+
capsule,
|
|
1186
|
+
executionContext,
|
|
1187
|
+
envelope,
|
|
1188
|
+
clientPublicKeyHex: clientKey.publicKeyHex,
|
|
1189
|
+
intent: capsule.intent,
|
|
1190
|
+
sub: capsule.sub
|
|
1191
|
+
};
|
|
1192
|
+
let result;
|
|
1193
|
+
const handlerStart = Date.now();
|
|
1194
|
+
try {
|
|
1195
|
+
result = await handler(decryptedPayload, handlerContext);
|
|
1196
|
+
} catch (err) {
|
|
1197
|
+
const handlerDuration2 = Date.now() - handlerStart;
|
|
1198
|
+
const verification2 = extractVerificationState(sensorInput.metadata ?? {});
|
|
1199
|
+
const witness2 = buildWitnessRecord(
|
|
1200
|
+
envelope,
|
|
1201
|
+
capsule,
|
|
1202
|
+
verification2,
|
|
1203
|
+
{ status: "FAILED", handlerDurationMs: handlerDuration2 },
|
|
1204
|
+
{
|
|
1205
|
+
axisLocalSecret: config.axisLocalSecret,
|
|
1206
|
+
requestPayload: decryptedPayload,
|
|
1207
|
+
responseEncrypted: false
|
|
1208
|
+
}
|
|
1209
|
+
);
|
|
1210
|
+
await config.witnessStore.record(witness2);
|
|
1211
|
+
return {
|
|
1212
|
+
ok: false,
|
|
1213
|
+
error: {
|
|
1214
|
+
code: CCE_ERROR.HANDLER_EXECUTION_FAILED,
|
|
1215
|
+
message: "Handler execution failed"
|
|
1216
|
+
},
|
|
1217
|
+
status: "FAILED"
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
const handlerDuration = Date.now() - handlerStart;
|
|
1221
|
+
let responseEnvelope;
|
|
1222
|
+
let responsePayloadHash;
|
|
1223
|
+
try {
|
|
1224
|
+
const responseResult = await buildCceResponse(
|
|
1225
|
+
{
|
|
1226
|
+
request: envelope,
|
|
1227
|
+
capsule,
|
|
1228
|
+
status: result.status,
|
|
1229
|
+
body: result.body,
|
|
1230
|
+
clientPublicKeyHex: clientKey.publicKeyHex
|
|
1231
|
+
},
|
|
1232
|
+
config.clientKeyEncryptor,
|
|
1233
|
+
config.axisSigner
|
|
1234
|
+
);
|
|
1235
|
+
responseEnvelope = responseResult.envelope;
|
|
1236
|
+
responsePayloadHash = responseResult.responsePayloadHash;
|
|
1237
|
+
} catch (err) {
|
|
1238
|
+
return {
|
|
1239
|
+
ok: false,
|
|
1240
|
+
error: {
|
|
1241
|
+
code: CCE_ERROR.RESPONSE_ENCRYPTION_FAILED,
|
|
1242
|
+
message: "Response encryption failed"
|
|
1243
|
+
},
|
|
1244
|
+
status: "ERROR"
|
|
1245
|
+
};
|
|
1246
|
+
}
|
|
1247
|
+
const verification = extractVerificationState(sensorInput.metadata ?? {});
|
|
1248
|
+
const witness = buildWitnessRecord(
|
|
1249
|
+
envelope,
|
|
1250
|
+
capsule,
|
|
1251
|
+
verification,
|
|
1252
|
+
{
|
|
1253
|
+
status: result.status,
|
|
1254
|
+
handlerDurationMs: handlerDuration,
|
|
1255
|
+
effect: result.effect
|
|
1256
|
+
},
|
|
1257
|
+
{
|
|
1258
|
+
axisLocalSecret: config.axisLocalSecret,
|
|
1259
|
+
requestPayload: decryptedPayload,
|
|
1260
|
+
responsePayload: result.body,
|
|
1261
|
+
responseEncrypted: true
|
|
1262
|
+
}
|
|
1263
|
+
);
|
|
1264
|
+
await config.witnessStore.record(witness);
|
|
1265
|
+
return {
|
|
1266
|
+
ok: true,
|
|
1267
|
+
response: responseEnvelope,
|
|
1268
|
+
witnessId: witness.witness_id
|
|
1269
|
+
};
|
|
1270
|
+
}
|
|
1271
|
+
|
|
639
1272
|
// src/engine/intent.router.ts
|
|
640
1273
|
var IntentRouter = class {
|
|
641
1274
|
constructor(moduleRef) {
|
|
@@ -653,6 +1286,10 @@ var IntentRouter = class {
|
|
|
653
1286
|
this.intentValidators = /* @__PURE__ */ new Map();
|
|
654
1287
|
/** Per-intent operation kind */
|
|
655
1288
|
this.intentKinds = /* @__PURE__ */ new Map();
|
|
1289
|
+
/** CCE handler registry */
|
|
1290
|
+
this.cceHandlers = /* @__PURE__ */ new Map();
|
|
1291
|
+
/** CCE pipeline configuration (set via configureCce) */
|
|
1292
|
+
this.ccePipelineConfig = null;
|
|
656
1293
|
}
|
|
657
1294
|
getSchema(intent) {
|
|
658
1295
|
return this.intentSchemas.get(intent);
|
|
@@ -916,6 +1553,58 @@ var IntentRouter = class {
|
|
|
916
1553
|
}
|
|
917
1554
|
}
|
|
918
1555
|
}
|
|
1556
|
+
// ===========================================================================
|
|
1557
|
+
// CCE — Capsule-Carried Encryption Support
|
|
1558
|
+
// ===========================================================================
|
|
1559
|
+
/**
|
|
1560
|
+
* Configure the CCE pipeline.
|
|
1561
|
+
* Must be called before routeCce() can process encrypted requests.
|
|
1562
|
+
*/
|
|
1563
|
+
configureCce(config) {
|
|
1564
|
+
this.ccePipelineConfig = config;
|
|
1565
|
+
this.logger.log("CCE pipeline configured");
|
|
1566
|
+
}
|
|
1567
|
+
/**
|
|
1568
|
+
* Register a CCE-encrypted intent handler.
|
|
1569
|
+
* CCE handlers receive decrypted payloads and execution context.
|
|
1570
|
+
*/
|
|
1571
|
+
registerCceHandler(intent, handler) {
|
|
1572
|
+
this.cceHandlers.set(intent, handler);
|
|
1573
|
+
this.logger.debug(`CCE handler registered: ${intent}`);
|
|
1574
|
+
}
|
|
1575
|
+
/**
|
|
1576
|
+
* Check if a CCE handler exists for the given intent.
|
|
1577
|
+
*/
|
|
1578
|
+
hasCceHandler(intent) {
|
|
1579
|
+
return this.cceHandlers.has(intent);
|
|
1580
|
+
}
|
|
1581
|
+
/**
|
|
1582
|
+
* Route a CCE-encrypted request through the full pipeline.
|
|
1583
|
+
*
|
|
1584
|
+
* Steps:
|
|
1585
|
+
* 1. Sensor chain (envelope validation → capsule verification → replay → decrypt)
|
|
1586
|
+
* 2. Execution context derivation
|
|
1587
|
+
* 3. Handler execution
|
|
1588
|
+
* 4. Response encryption
|
|
1589
|
+
* 5. Witness recording
|
|
1590
|
+
*/
|
|
1591
|
+
async routeCce(envelope) {
|
|
1592
|
+
if (!this.ccePipelineConfig) {
|
|
1593
|
+
return {
|
|
1594
|
+
ok: false,
|
|
1595
|
+
error: {
|
|
1596
|
+
code: "CCE_NOT_CONFIGURED",
|
|
1597
|
+
message: "CCE pipeline not configured. Call configureCce() first."
|
|
1598
|
+
},
|
|
1599
|
+
status: "ERROR"
|
|
1600
|
+
};
|
|
1601
|
+
}
|
|
1602
|
+
const config = {
|
|
1603
|
+
...this.ccePipelineConfig,
|
|
1604
|
+
handlers: this.cceHandlers
|
|
1605
|
+
};
|
|
1606
|
+
return executeCcePipeline(envelope, config);
|
|
1607
|
+
}
|
|
919
1608
|
storeSchema(meta) {
|
|
920
1609
|
if (meta.dto) {
|
|
921
1610
|
if (meta.tlv && meta.tlv.length > 0) {
|
|
@@ -1095,7 +1784,7 @@ function fieldsToMap(fields) {
|
|
|
1095
1784
|
}
|
|
1096
1785
|
|
|
1097
1786
|
// src/engine/observation/observation-hash.ts
|
|
1098
|
-
var
|
|
1787
|
+
var import_crypto3 = require("crypto");
|
|
1099
1788
|
function canonicalizeObservation(obs) {
|
|
1100
1789
|
const obj = {
|
|
1101
1790
|
id: obs.id,
|
|
@@ -1132,7 +1821,7 @@ function canonicalizeObservation(obs) {
|
|
|
1132
1821
|
}
|
|
1133
1822
|
function hashObservation(obs) {
|
|
1134
1823
|
const canonical = canonicalizeObservation(obs);
|
|
1135
|
-
return (0,
|
|
1824
|
+
return (0, import_crypto3.createHash)("sha256").update(canonical).digest("hex");
|
|
1136
1825
|
}
|
|
1137
1826
|
function buildUnsignedWitness(obs) {
|
|
1138
1827
|
if (!obs.decision || !obs.endMs) {
|
|
@@ -1207,7 +1896,7 @@ function verifyResponse(ctx, response) {
|
|
|
1207
1896
|
var import_axis_protocol3 = require("@nextera.one/axis-protocol");
|
|
1208
1897
|
|
|
1209
1898
|
// src/core/signature.ts
|
|
1210
|
-
var
|
|
1899
|
+
var crypto2 = __toESM(require("crypto"));
|
|
1211
1900
|
|
|
1212
1901
|
// src/core/axis-bin.ts
|
|
1213
1902
|
var z = __toESM(require("zod"));
|
|
@@ -1337,19 +2026,19 @@ function signFrame(frame, privateKey) {
|
|
|
1337
2026
|
32
|
|
1338
2027
|
]);
|
|
1339
2028
|
const pkcs8Key = Buffer.concat([pkcs8Prefix, privateKey]);
|
|
1340
|
-
keyObject =
|
|
2029
|
+
keyObject = crypto2.createPrivateKey({
|
|
1341
2030
|
key: pkcs8Key,
|
|
1342
2031
|
format: "der",
|
|
1343
2032
|
type: "pkcs8"
|
|
1344
2033
|
});
|
|
1345
2034
|
} else {
|
|
1346
|
-
keyObject =
|
|
2035
|
+
keyObject = crypto2.createPrivateKey({
|
|
1347
2036
|
key: privateKey,
|
|
1348
2037
|
format: "der",
|
|
1349
2038
|
type: "pkcs8"
|
|
1350
2039
|
});
|
|
1351
2040
|
}
|
|
1352
|
-
const signature =
|
|
2041
|
+
const signature = crypto2.sign(null, payload, keyObject);
|
|
1353
2042
|
if (signature.length !== 64) {
|
|
1354
2043
|
throw new Error("Ed25519 signature must be 64 bytes");
|
|
1355
2044
|
}
|
|
@@ -1381,19 +2070,19 @@ function verifyFrameSignature(frame, publicKey) {
|
|
|
1381
2070
|
0
|
|
1382
2071
|
]);
|
|
1383
2072
|
const spkiKey = Buffer.concat([spkiPrefix, publicKey]);
|
|
1384
|
-
keyObject =
|
|
2073
|
+
keyObject = crypto2.createPublicKey({
|
|
1385
2074
|
key: spkiKey,
|
|
1386
2075
|
format: "der",
|
|
1387
2076
|
type: "spki"
|
|
1388
2077
|
});
|
|
1389
2078
|
} else {
|
|
1390
|
-
keyObject =
|
|
2079
|
+
keyObject = crypto2.createPublicKey({
|
|
1391
2080
|
key: publicKey,
|
|
1392
2081
|
format: "der",
|
|
1393
2082
|
type: "spki"
|
|
1394
2083
|
});
|
|
1395
2084
|
}
|
|
1396
|
-
const valid =
|
|
2085
|
+
const valid = crypto2.verify(
|
|
1397
2086
|
null,
|
|
1398
2087
|
payload,
|
|
1399
2088
|
keyObject,
|
|
@@ -1405,17 +2094,17 @@ function verifyFrameSignature(frame, publicKey) {
|
|
|
1405
2094
|
}
|
|
1406
2095
|
}
|
|
1407
2096
|
function generateEd25519KeyPair() {
|
|
1408
|
-
const { privateKey, publicKey } =
|
|
2097
|
+
const { privateKey, publicKey } = crypto2.generateKeyPairSync("ed25519");
|
|
1409
2098
|
return {
|
|
1410
2099
|
privateKey: privateKey.export({ type: "pkcs8", format: "der" }),
|
|
1411
2100
|
publicKey: publicKey.export({ type: "spki", format: "der" })
|
|
1412
2101
|
};
|
|
1413
2102
|
}
|
|
1414
|
-
function
|
|
1415
|
-
return
|
|
2103
|
+
function sha2564(data) {
|
|
2104
|
+
return crypto2.createHash("sha256").update(data).digest();
|
|
1416
2105
|
}
|
|
1417
2106
|
function computeReceiptHash(receiptBytes, prevHash) {
|
|
1418
|
-
const hasher =
|
|
2107
|
+
const hasher = crypto2.createHash("sha256");
|
|
1419
2108
|
hasher.update(receiptBytes);
|
|
1420
2109
|
if (prevHash && prevHash.length > 0) {
|
|
1421
2110
|
hasher.update(prevHash);
|
|
@@ -1473,12 +2162,12 @@ __export(ats1_exports, {
|
|
|
1473
2162
|
encodeU64BE: () => encodeU64BE,
|
|
1474
2163
|
encodeUVarint: () => encodeUVarint,
|
|
1475
2164
|
logicalBodyToTLVs: () => logicalBodyToTLVs,
|
|
1476
|
-
sha256: () =>
|
|
2165
|
+
sha256: () => sha2565,
|
|
1477
2166
|
tlvsToLogicalBody: () => tlvsToLogicalBody,
|
|
1478
2167
|
tlvsToMap: () => tlvsToMap,
|
|
1479
2168
|
validateTLVsAgainstSchema: () => validateTLVsAgainstSchema
|
|
1480
2169
|
});
|
|
1481
|
-
var
|
|
2170
|
+
var import_crypto4 = require("crypto");
|
|
1482
2171
|
var DEFAULT_LIMITS = {
|
|
1483
2172
|
maxVarintBytes: 10,
|
|
1484
2173
|
maxTlvCount: 512,
|
|
@@ -1527,8 +2216,8 @@ function decodeU64BE(buf) {
|
|
|
1527
2216
|
if (buf.length !== 8) throw new Error("decodeU64BE: length must be 8");
|
|
1528
2217
|
return buf.readBigUInt64BE(0);
|
|
1529
2218
|
}
|
|
1530
|
-
function
|
|
1531
|
-
return (0,
|
|
2219
|
+
function sha2565(data) {
|
|
2220
|
+
return (0, import_crypto4.createHash)("sha256").update(data).digest();
|
|
1532
2221
|
}
|
|
1533
2222
|
function encodeTLV(tag, value) {
|
|
1534
2223
|
if (!Number.isInteger(tag) || tag <= 0)
|
|
@@ -1844,7 +2533,7 @@ function decodeAxisHeaderFromTLVs(hdrTlvs, limits = DEFAULT_LIMITS) {
|
|
|
1844
2533
|
function encodeAxisRequestBinary(schema, req, limits = DEFAULT_LIMITS) {
|
|
1845
2534
|
const bodyTlvs = logicalBodyToTLVs(schema, req.body, limits);
|
|
1846
2535
|
const bodyBytes = encodeTLVStreamCanonical(bodyTlvs);
|
|
1847
|
-
const bodyHash =
|
|
2536
|
+
const bodyHash = sha2565(bodyBytes);
|
|
1848
2537
|
const hdr = {
|
|
1849
2538
|
...req.hdr,
|
|
1850
2539
|
schemaId: schema.schemaId,
|
|
@@ -1860,7 +2549,7 @@ function decodeAxisRequestBinary(schema, hdrBytes, bodyBytes, limits = DEFAULT_L
|
|
|
1860
2549
|
const hdr = decodeAxisHeaderFromTLVs(hdrTlvs, limits);
|
|
1861
2550
|
if (hdr.schemaId !== schema.schemaId)
|
|
1862
2551
|
throw new Error("decodeAxisRequestBinary: schemaId mismatch");
|
|
1863
|
-
const bh =
|
|
2552
|
+
const bh = sha2565(bodyBytes);
|
|
1864
2553
|
if (!Buffer.from(hdr.bodyHash).equals(bh))
|
|
1865
2554
|
throw new Error("decodeAxisRequestBinary: body_hash mismatch");
|
|
1866
2555
|
const body = tlvsToLogicalBody(schema, bodyTlvs, limits);
|
|
@@ -1933,7 +2622,7 @@ function packPasskeyLoginOptionsReq(params) {
|
|
|
1933
2622
|
}
|
|
1934
2623
|
);
|
|
1935
2624
|
const body = encodeTLVStreamCanonical(bodyTlvs);
|
|
1936
|
-
const bodyHash =
|
|
2625
|
+
const bodyHash = sha2565(body);
|
|
1937
2626
|
const hdr = buildAts1Hdr({
|
|
1938
2627
|
intentId: params.intentId,
|
|
1939
2628
|
schemaId: ATS1_SCHEMA.PASSKEY_LOGIN_OPTIONS_REQ,
|
|
@@ -2002,7 +2691,7 @@ function packPasskeyRegisterOptionsReq(params) {
|
|
|
2002
2691
|
}
|
|
2003
2692
|
);
|
|
2004
2693
|
const body = encodeTLVStreamCanonical(bodyTlvs);
|
|
2005
|
-
const bodyHash =
|
|
2694
|
+
const bodyHash = sha2565(body);
|
|
2006
2695
|
const hdr = buildAts1Hdr({
|
|
2007
2696
|
intentId: params.intentId,
|
|
2008
2697
|
schemaId: ATS1_SCHEMA.PASSKEY_REGISTER_OPTIONS_REQ,
|
|
@@ -2033,7 +2722,7 @@ function packPasskeyLoginVerifyReq(params) {
|
|
|
2033
2722
|
}
|
|
2034
2723
|
});
|
|
2035
2724
|
const body = encodeTLVStreamCanonical(bodyTlvs);
|
|
2036
|
-
const bodyHash =
|
|
2725
|
+
const bodyHash = sha2565(body);
|
|
2037
2726
|
const hdr = buildAts1Hdr({
|
|
2038
2727
|
intentId: params.intentId,
|
|
2039
2728
|
schemaId: ATS1_SCHEMA.PASSKEY_LOGIN_VERIFY_REQ,
|
|
@@ -2117,7 +2806,7 @@ function packPasskeyLoginVerifyRes(params) {
|
|
|
2117
2806
|
}
|
|
2118
2807
|
|
|
2119
2808
|
// src/codec/tlv.encode.ts
|
|
2120
|
-
var
|
|
2809
|
+
var import_crypto5 = require("crypto");
|
|
2121
2810
|
function encVarint(x) {
|
|
2122
2811
|
if (x < 0n) throw new Error("VARINT_NEG");
|
|
2123
2812
|
const out = [];
|
|
@@ -2145,7 +2834,7 @@ function bytes(b) {
|
|
|
2145
2834
|
return Buffer.isBuffer(b) ? b : Buffer.from(b);
|
|
2146
2835
|
}
|
|
2147
2836
|
function nonce16() {
|
|
2148
|
-
return (0,
|
|
2837
|
+
return (0, import_crypto5.randomBytes)(16);
|
|
2149
2838
|
}
|
|
2150
2839
|
function tlv(type, value) {
|
|
2151
2840
|
if (!Number.isSafeInteger(type) || type < 0) throw new Error("TLV_BAD_TYPE");
|
|
@@ -2691,9 +3380,9 @@ function isAdminOpcode(op) {
|
|
|
2691
3380
|
}
|
|
2692
3381
|
|
|
2693
3382
|
// src/core/receipt.ts
|
|
2694
|
-
var
|
|
3383
|
+
var import_crypto6 = require("crypto");
|
|
2695
3384
|
function buildReceiptHash(prevHash, pid, actorId, intent, effect, ts) {
|
|
2696
|
-
const h = (0,
|
|
3385
|
+
const h = (0, import_crypto6.createHash)("sha256");
|
|
2697
3386
|
if (prevHash) h.update(prevHash);
|
|
2698
3387
|
h.update(pid);
|
|
2699
3388
|
h.update(Buffer.from(actorId, "utf8"));
|
|
@@ -2873,7 +3562,7 @@ function isTimestampValid(ts, skewSeconds = 120) {
|
|
|
2873
3562
|
|
|
2874
3563
|
// src/upload/axis-files.handlers.ts
|
|
2875
3564
|
var import_common4 = require("@nestjs/common");
|
|
2876
|
-
var
|
|
3565
|
+
var crypto3 = __toESM(require("crypto"));
|
|
2877
3566
|
|
|
2878
3567
|
// src/upload/upload.tokens.ts
|
|
2879
3568
|
var AXIS_UPLOAD_SESSION_STORE = "AXIS_UPLOAD_SESSION_STORE";
|
|
@@ -2974,7 +3663,7 @@ var AxisFilesFinalizeHandler = class {
|
|
|
2974
3663
|
if (!await this.files.hasTemp(fileId)) {
|
|
2975
3664
|
throw new Error("CHUNKS_NOT_FOUND");
|
|
2976
3665
|
}
|
|
2977
|
-
const hash =
|
|
3666
|
+
const hash = crypto3.createHash("sha256");
|
|
2978
3667
|
const rs = this.files.createTempReadStream(fileId);
|
|
2979
3668
|
for await (const chunk of rs) {
|
|
2980
3669
|
hash.update(chunk);
|
|
@@ -3394,10 +4083,10 @@ SensorRegistry = __decorateClass([
|
|
|
3394
4083
|
], SensorRegistry);
|
|
3395
4084
|
|
|
3396
4085
|
// src/engine/axis-observation.ts
|
|
3397
|
-
var
|
|
4086
|
+
var import_crypto7 = require("crypto");
|
|
3398
4087
|
function createObservation(transport, ip) {
|
|
3399
4088
|
return {
|
|
3400
|
-
id: (0,
|
|
4089
|
+
id: (0, import_crypto7.randomBytes)(16).toString("hex"),
|
|
3401
4090
|
startMs: Date.now(),
|
|
3402
4091
|
transport,
|
|
3403
4092
|
ip,
|
|
@@ -3555,88 +4244,857 @@ AxisSensorChainService = __decorateClass([
|
|
|
3555
4244
|
(0, import_common9.Injectable)()
|
|
3556
4245
|
], AxisSensorChainService);
|
|
3557
4246
|
|
|
3558
|
-
// src/
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
4247
|
+
// src/utils/axis-tlv-codec.ts
|
|
4248
|
+
function encodeAxisTlvDto(dtoClass, data) {
|
|
4249
|
+
const schema = extractDtoSchema(dtoClass);
|
|
4250
|
+
const items = schema.fields.flatMap((field) => {
|
|
4251
|
+
const value = data[field.name];
|
|
4252
|
+
if (value === void 0 || value === null) {
|
|
4253
|
+
if (field.required) {
|
|
4254
|
+
throw new Error(`Missing required TLV response field: ${field.name}`);
|
|
4255
|
+
}
|
|
4256
|
+
return [];
|
|
4257
|
+
}
|
|
4258
|
+
return [{ type: field.tag, value: encodeField(field, value) }];
|
|
4259
|
+
});
|
|
4260
|
+
return buildTLVs(items);
|
|
4261
|
+
}
|
|
4262
|
+
function encodeField(field, value) {
|
|
4263
|
+
switch (field.kind) {
|
|
4264
|
+
case "utf8":
|
|
4265
|
+
return Buffer.from(String(value), "utf8");
|
|
4266
|
+
case "u64":
|
|
4267
|
+
return encodeU64(value);
|
|
4268
|
+
case "bytes":
|
|
4269
|
+
case "bytes16":
|
|
4270
|
+
return toBuffer(value);
|
|
4271
|
+
case "bool":
|
|
4272
|
+
return Buffer.from([value ? 1 : 0]);
|
|
4273
|
+
case "obj":
|
|
4274
|
+
case "arr":
|
|
4275
|
+
return Buffer.from(JSON.stringify(value), "utf8");
|
|
4276
|
+
default:
|
|
4277
|
+
return toBuffer(value);
|
|
4278
|
+
}
|
|
4279
|
+
}
|
|
4280
|
+
function encodeU64(value) {
|
|
4281
|
+
const encoded = Buffer.alloc(8);
|
|
4282
|
+
encoded.writeBigUInt64BE(
|
|
4283
|
+
typeof value === "bigint" ? value : BigInt(value)
|
|
4284
|
+
);
|
|
4285
|
+
return encoded;
|
|
4286
|
+
}
|
|
4287
|
+
function toBuffer(value) {
|
|
4288
|
+
if (Buffer.isBuffer(value)) {
|
|
4289
|
+
return value;
|
|
4290
|
+
}
|
|
4291
|
+
if (value instanceof Uint8Array) {
|
|
4292
|
+
return Buffer.from(value);
|
|
4293
|
+
}
|
|
4294
|
+
if (typeof value === "string") {
|
|
4295
|
+
return Buffer.from(value, "utf8");
|
|
4296
|
+
}
|
|
4297
|
+
throw new Error(`Unsupported TLV bytes value: ${typeof value}`);
|
|
4298
|
+
}
|
|
4299
|
+
|
|
4300
|
+
// src/loom/loom.types.ts
|
|
4301
|
+
function deriveAnchorReflection(softid, context = "openlogs", scope = "loom") {
|
|
4302
|
+
return `ar:${context}:${scope}:${softid}`;
|
|
4303
|
+
}
|
|
4304
|
+
function canonicalizeWrit(writ) {
|
|
4305
|
+
const ordered = {
|
|
4306
|
+
head: { tid: writ.head.tid, seq: writ.head.seq },
|
|
4307
|
+
body: {
|
|
4308
|
+
who: writ.body.who,
|
|
4309
|
+
act: writ.body.act,
|
|
4310
|
+
res: writ.body.res,
|
|
4311
|
+
law: writ.body.law
|
|
4312
|
+
},
|
|
4313
|
+
meta: { iat: writ.meta.iat, exp: writ.meta.exp, prev: writ.meta.prev }
|
|
4314
|
+
};
|
|
4315
|
+
return JSON.stringify(ordered);
|
|
4316
|
+
}
|
|
4317
|
+
function canonicalizeGrant(grant) {
|
|
4318
|
+
const ordered = {
|
|
4319
|
+
grant_id: grant.grant_id,
|
|
4320
|
+
issuer: grant.issuer,
|
|
4321
|
+
subject: grant.subject,
|
|
4322
|
+
grant_type: grant.grant_type,
|
|
4323
|
+
caps: grant.caps,
|
|
4324
|
+
meta: grant.meta
|
|
4325
|
+
};
|
|
4326
|
+
return JSON.stringify(ordered);
|
|
4327
|
+
}
|
|
4328
|
+
|
|
4329
|
+
// src/cce/index.ts
|
|
4330
|
+
var cce_exports = {};
|
|
4331
|
+
__export(cce_exports, {
|
|
4332
|
+
CCE_AES_KEY_BYTES: () => CCE_AES_KEY_BYTES,
|
|
4333
|
+
CCE_DERIVATION: () => CCE_DERIVATION,
|
|
4334
|
+
CCE_ERROR: () => CCE_ERROR,
|
|
4335
|
+
CCE_IV_BYTES: () => CCE_IV_BYTES,
|
|
4336
|
+
CCE_NONCE_BYTES: () => CCE_NONCE_BYTES,
|
|
4337
|
+
CCE_PROTOCOL_VERSION: () => CCE_PROTOCOL_VERSION,
|
|
4338
|
+
CCE_TAG_BYTES: () => CCE_TAG_BYTES,
|
|
4339
|
+
CceAudienceIntentBindingSensor: () => CceAudienceIntentBindingSensor,
|
|
4340
|
+
CceCapsuleVerificationSensor: () => CceCapsuleVerificationSensor,
|
|
4341
|
+
CceClientSignatureSensor: () => CceClientSignatureSensor,
|
|
4342
|
+
CceEnvelopeValidationSensor: () => CceEnvelopeValidationSensor,
|
|
4343
|
+
CceError: () => CceError,
|
|
4344
|
+
CcePayloadDecryptionSensor: () => CcePayloadDecryptionSensor,
|
|
4345
|
+
CceReplayProtectionSensor: () => CceReplayProtectionSensor,
|
|
4346
|
+
CceTpsWindowSensor: () => CceTpsWindowSensor,
|
|
4347
|
+
InMemoryCceReplayStore: () => InMemoryCceReplayStore,
|
|
4348
|
+
InMemoryCceWitnessStore: () => InMemoryCceWitnessStore,
|
|
4349
|
+
aesGcmDecrypt: () => aesGcmDecrypt,
|
|
4350
|
+
aesGcmEncrypt: () => aesGcmEncrypt,
|
|
4351
|
+
base64UrlDecode: () => base64UrlDecode,
|
|
4352
|
+
base64UrlEncode: () => base64UrlEncode,
|
|
4353
|
+
buildCceErrorResponse: () => buildCceErrorResponse,
|
|
4354
|
+
buildCceResponse: () => buildCceResponse,
|
|
4355
|
+
buildExecutionContext: () => buildExecutionContext,
|
|
4356
|
+
buildWitnessRecord: () => buildWitnessRecord,
|
|
4357
|
+
deriveRequestExecutionKey: () => deriveRequestExecutionKey,
|
|
4358
|
+
deriveResponseExecutionKey: () => deriveResponseExecutionKey,
|
|
4359
|
+
deriveWitnessKey: () => deriveWitnessKey,
|
|
4360
|
+
executeCcePipeline: () => executeCcePipeline,
|
|
4361
|
+
extractVerificationState: () => extractVerificationState,
|
|
4362
|
+
generateAesKey: () => generateAesKey,
|
|
4363
|
+
generateCceNonce: () => generateCceNonce,
|
|
4364
|
+
generateIv: () => generateIv,
|
|
4365
|
+
hashPayload: () => hashPayload,
|
|
4366
|
+
nodeAesGcmProvider: () => nodeAesGcmProvider
|
|
4367
|
+
});
|
|
4368
|
+
|
|
4369
|
+
// src/cce/sensors/cce-envelope-validation.sensor.ts
|
|
4370
|
+
var REQUIRED_FIELDS = [
|
|
4371
|
+
"ver",
|
|
4372
|
+
"request_id",
|
|
4373
|
+
"correlation_id",
|
|
4374
|
+
"client_kid",
|
|
4375
|
+
"capsule",
|
|
4376
|
+
"encrypted_key",
|
|
4377
|
+
"encrypted_payload",
|
|
4378
|
+
"request_nonce",
|
|
4379
|
+
"client_sig",
|
|
4380
|
+
"algorithms"
|
|
4381
|
+
];
|
|
4382
|
+
var CceEnvelopeValidationSensor = class {
|
|
4383
|
+
constructor() {
|
|
4384
|
+
this.name = "cce.envelope.validation";
|
|
4385
|
+
this.order = 5;
|
|
4386
|
+
this.phase = "PRE_DECODE";
|
|
4387
|
+
}
|
|
4388
|
+
supports(input) {
|
|
4389
|
+
return input.metadata?.cce === true || input.metadata?.contentType === "application/axis-cce";
|
|
4390
|
+
}
|
|
4391
|
+
async run(input) {
|
|
4392
|
+
const envelope = input.metadata?.cceEnvelope;
|
|
4393
|
+
if (!envelope) {
|
|
4394
|
+
return {
|
|
4395
|
+
allow: false,
|
|
4396
|
+
riskScore: 100,
|
|
4397
|
+
reasons: [CCE_ERROR.INVALID_ENVELOPE],
|
|
4398
|
+
code: CCE_ERROR.INVALID_ENVELOPE
|
|
4399
|
+
};
|
|
4400
|
+
}
|
|
4401
|
+
for (const field of REQUIRED_FIELDS) {
|
|
4402
|
+
if (envelope[field] === void 0 || envelope[field] === null) {
|
|
4403
|
+
return {
|
|
4404
|
+
allow: false,
|
|
4405
|
+
riskScore: 100,
|
|
4406
|
+
reasons: [`${CCE_ERROR.INVALID_ENVELOPE}: missing ${field}`],
|
|
4407
|
+
code: CCE_ERROR.INVALID_ENVELOPE
|
|
4408
|
+
};
|
|
4409
|
+
}
|
|
4410
|
+
}
|
|
4411
|
+
if (envelope.ver !== CCE_PROTOCOL_VERSION) {
|
|
4412
|
+
return {
|
|
4413
|
+
allow: false,
|
|
4414
|
+
riskScore: 100,
|
|
4415
|
+
reasons: [`${CCE_ERROR.UNSUPPORTED_VERSION}: ${envelope.ver}`],
|
|
4416
|
+
code: CCE_ERROR.UNSUPPORTED_VERSION
|
|
4417
|
+
};
|
|
4418
|
+
}
|
|
4419
|
+
if (!/^[0-9a-f]+$/i.test(envelope.request_nonce)) {
|
|
4420
|
+
return {
|
|
4421
|
+
allow: false,
|
|
4422
|
+
riskScore: 100,
|
|
4423
|
+
reasons: [
|
|
4424
|
+
`${CCE_ERROR.INVALID_ENVELOPE}: invalid request_nonce format`
|
|
4425
|
+
],
|
|
4426
|
+
code: CCE_ERROR.INVALID_ENVELOPE
|
|
4427
|
+
};
|
|
4428
|
+
}
|
|
4429
|
+
if (envelope.request_nonce.length !== CCE_NONCE_BYTES * 2) {
|
|
4430
|
+
return {
|
|
4431
|
+
allow: false,
|
|
4432
|
+
riskScore: 100,
|
|
4433
|
+
reasons: [`${CCE_ERROR.INVALID_ENVELOPE}: request_nonce wrong length`],
|
|
4434
|
+
code: CCE_ERROR.INVALID_ENVELOPE
|
|
4435
|
+
};
|
|
4436
|
+
}
|
|
4437
|
+
const capsule = envelope.capsule;
|
|
4438
|
+
if (!capsule.capsule_id || !capsule.ver || !capsule.sub || !capsule.kid || !capsule.intent || !capsule.aud || !capsule.issuer_sig) {
|
|
4439
|
+
return {
|
|
4440
|
+
allow: false,
|
|
4441
|
+
riskScore: 100,
|
|
4442
|
+
reasons: [`${CCE_ERROR.MISSING_CAPSULE}: incomplete capsule claims`],
|
|
4443
|
+
code: CCE_ERROR.MISSING_CAPSULE
|
|
4444
|
+
};
|
|
4445
|
+
}
|
|
4446
|
+
if (!envelope.encrypted_key.ciphertext || !envelope.encrypted_key.alg) {
|
|
4447
|
+
return {
|
|
4448
|
+
allow: false,
|
|
4449
|
+
riskScore: 100,
|
|
4450
|
+
reasons: [
|
|
4451
|
+
`${CCE_ERROR.MISSING_ENCRYPTED_KEY}: incomplete encrypted_key`
|
|
4452
|
+
],
|
|
4453
|
+
code: CCE_ERROR.MISSING_ENCRYPTED_KEY
|
|
4454
|
+
};
|
|
4455
|
+
}
|
|
4456
|
+
input.metadata = input.metadata ?? {};
|
|
4457
|
+
input.metadata.cceEnvelopeValid = true;
|
|
4458
|
+
return {
|
|
4459
|
+
decision: "ALLOW" /* ALLOW */,
|
|
4460
|
+
allow: true,
|
|
4461
|
+
riskScore: 0,
|
|
4462
|
+
reasons: []
|
|
4463
|
+
};
|
|
4464
|
+
}
|
|
4465
|
+
};
|
|
4466
|
+
|
|
4467
|
+
// src/cce/sensors/cce-client-signature.sensor.ts
|
|
4468
|
+
var CceClientSignatureSensor = class {
|
|
4469
|
+
constructor(keyResolver, signatureVerifier) {
|
|
4470
|
+
this.keyResolver = keyResolver;
|
|
4471
|
+
this.signatureVerifier = signatureVerifier;
|
|
4472
|
+
this.name = "cce.client.signature";
|
|
4473
|
+
this.order = 45;
|
|
4474
|
+
this.phase = "POST_DECODE";
|
|
4475
|
+
}
|
|
4476
|
+
supports(input) {
|
|
4477
|
+
return input.metadata?.cceEnvelopeValid === true;
|
|
4478
|
+
}
|
|
4479
|
+
async run(input) {
|
|
4480
|
+
const envelope = input.metadata?.cceEnvelope;
|
|
4481
|
+
if (!envelope) {
|
|
4482
|
+
return {
|
|
4483
|
+
allow: false,
|
|
4484
|
+
riskScore: 100,
|
|
4485
|
+
reasons: [CCE_ERROR.INVALID_ENVELOPE],
|
|
4486
|
+
code: CCE_ERROR.INVALID_ENVELOPE
|
|
4487
|
+
};
|
|
4488
|
+
}
|
|
4489
|
+
const keyRecord = await this.keyResolver.resolve(envelope.client_kid);
|
|
4490
|
+
if (!keyRecord) {
|
|
4491
|
+
return {
|
|
4492
|
+
allow: false,
|
|
4493
|
+
riskScore: 100,
|
|
4494
|
+
reasons: [
|
|
4495
|
+
`${CCE_ERROR.CLIENT_KEY_NOT_FOUND}: kid=${envelope.client_kid}`
|
|
4496
|
+
],
|
|
4497
|
+
code: CCE_ERROR.CLIENT_KEY_NOT_FOUND
|
|
4498
|
+
};
|
|
4499
|
+
}
|
|
4500
|
+
const { client_sig, ...signable } = envelope;
|
|
4501
|
+
const canonical = canonicalize2(signable);
|
|
4502
|
+
const message = new TextEncoder().encode(canonical);
|
|
4503
|
+
const valid = await this.signatureVerifier.verify(
|
|
4504
|
+
message,
|
|
4505
|
+
client_sig.value,
|
|
4506
|
+
keyRecord.publicKeyHex,
|
|
4507
|
+
keyRecord.alg
|
|
4508
|
+
);
|
|
4509
|
+
if (!valid) {
|
|
4510
|
+
return {
|
|
4511
|
+
allow: false,
|
|
4512
|
+
riskScore: 100,
|
|
4513
|
+
reasons: [CCE_ERROR.CLIENT_SIG_INVALID],
|
|
4514
|
+
code: CCE_ERROR.CLIENT_SIG_INVALID
|
|
4515
|
+
};
|
|
4516
|
+
}
|
|
4517
|
+
input.metadata = input.metadata ?? {};
|
|
4518
|
+
input.metadata.cceClientKey = keyRecord;
|
|
4519
|
+
input.metadata.cceClientSigVerified = true;
|
|
4520
|
+
return {
|
|
4521
|
+
decision: "ALLOW" /* ALLOW */,
|
|
4522
|
+
allow: true,
|
|
4523
|
+
riskScore: 0,
|
|
4524
|
+
reasons: [],
|
|
4525
|
+
meta: { kid: envelope.client_kid }
|
|
4526
|
+
};
|
|
4527
|
+
}
|
|
4528
|
+
};
|
|
4529
|
+
function canonicalize2(obj) {
|
|
4530
|
+
if (Array.isArray(obj)) {
|
|
4531
|
+
return "[" + obj.map(canonicalize2).join(",") + "]";
|
|
4532
|
+
}
|
|
4533
|
+
if (obj !== null && typeof obj === "object") {
|
|
4534
|
+
const sorted = Object.keys(obj).sort().map(
|
|
4535
|
+
(k) => JSON.stringify(k) + ":" + canonicalize2(obj[k])
|
|
4536
|
+
);
|
|
4537
|
+
return "{" + sorted.join(",") + "}";
|
|
4538
|
+
}
|
|
4539
|
+
return JSON.stringify(obj);
|
|
4540
|
+
}
|
|
4541
|
+
|
|
4542
|
+
// src/cce/sensors/cce-capsule-verification.sensor.ts
|
|
4543
|
+
var import_blake3 = require("@noble/hashes/blake3.js");
|
|
4544
|
+
var import_utils5 = require("@noble/hashes/utils.js");
|
|
4545
|
+
var CceCapsuleVerificationSensor = class {
|
|
4546
|
+
constructor(issuerKeyResolver, capsuleVerifier) {
|
|
4547
|
+
this.issuerKeyResolver = issuerKeyResolver;
|
|
4548
|
+
this.capsuleVerifier = capsuleVerifier;
|
|
4549
|
+
this.name = "cce.capsule.verification";
|
|
4550
|
+
this.order = 50;
|
|
4551
|
+
this.phase = "POST_DECODE";
|
|
4552
|
+
}
|
|
4553
|
+
supports(input) {
|
|
4554
|
+
return input.metadata?.cceEnvelopeValid === true;
|
|
4555
|
+
}
|
|
4556
|
+
async run(input) {
|
|
4557
|
+
const capsule = input.metadata?.cceEnvelope?.capsule;
|
|
4558
|
+
if (!capsule) {
|
|
4559
|
+
return {
|
|
4560
|
+
allow: false,
|
|
4561
|
+
riskScore: 100,
|
|
4562
|
+
reasons: [CCE_ERROR.MISSING_CAPSULE],
|
|
4563
|
+
code: CCE_ERROR.MISSING_CAPSULE
|
|
4564
|
+
};
|
|
4565
|
+
}
|
|
4566
|
+
if (capsule.ver !== CCE_PROTOCOL_VERSION) {
|
|
4567
|
+
return {
|
|
4568
|
+
allow: false,
|
|
4569
|
+
riskScore: 100,
|
|
4570
|
+
reasons: [
|
|
4571
|
+
`${CCE_ERROR.CAPSULE_SIG_INVALID}: wrong version ${capsule.ver}`
|
|
4572
|
+
],
|
|
4573
|
+
code: CCE_ERROR.CAPSULE_SIG_INVALID
|
|
4574
|
+
};
|
|
4575
|
+
}
|
|
4576
|
+
const { capsule_id, issuer_sig, ...claimsBody } = capsule;
|
|
4577
|
+
const expectedId = computeCceCapsuleId(claimsBody);
|
|
4578
|
+
if (capsule_id !== expectedId) {
|
|
4579
|
+
return {
|
|
4580
|
+
allow: false,
|
|
4581
|
+
riskScore: 100,
|
|
4582
|
+
reasons: [`${CCE_ERROR.CAPSULE_SIG_INVALID}: content hash mismatch`],
|
|
4583
|
+
code: CCE_ERROR.CAPSULE_SIG_INVALID
|
|
4584
|
+
};
|
|
4585
|
+
}
|
|
4586
|
+
const issuerKey = await this.issuerKeyResolver.resolve(
|
|
4587
|
+
capsule.issuer_sig.kid
|
|
4588
|
+
);
|
|
4589
|
+
if (!issuerKey) {
|
|
4590
|
+
return {
|
|
4591
|
+
allow: false,
|
|
4592
|
+
riskScore: 100,
|
|
4593
|
+
reasons: [`${CCE_ERROR.CAPSULE_SIG_INVALID}: issuer key not found`],
|
|
4594
|
+
code: CCE_ERROR.CAPSULE_SIG_INVALID
|
|
4595
|
+
};
|
|
4596
|
+
}
|
|
4597
|
+
const { issuer_sig: sig, ...rest } = capsule;
|
|
4598
|
+
const sigValid = await this.capsuleVerifier.verify(
|
|
4599
|
+
rest,
|
|
4600
|
+
sig,
|
|
4601
|
+
issuerKey.publicKeyHex
|
|
4602
|
+
);
|
|
4603
|
+
if (!sigValid) {
|
|
4604
|
+
return {
|
|
4605
|
+
allow: false,
|
|
4606
|
+
riskScore: 100,
|
|
4607
|
+
reasons: [CCE_ERROR.CAPSULE_SIG_INVALID],
|
|
4608
|
+
code: CCE_ERROR.CAPSULE_SIG_INVALID
|
|
4609
|
+
};
|
|
4610
|
+
}
|
|
4611
|
+
const nowSeconds = Math.floor(Date.now() / 1e3);
|
|
4612
|
+
if (capsule.exp < nowSeconds) {
|
|
4613
|
+
return {
|
|
4614
|
+
allow: false,
|
|
4615
|
+
riskScore: 100,
|
|
4616
|
+
reasons: [`${CCE_ERROR.CAPSULE_EXPIRED}: exp=${capsule.exp}`],
|
|
4617
|
+
code: CCE_ERROR.CAPSULE_EXPIRED
|
|
4618
|
+
};
|
|
4619
|
+
}
|
|
4620
|
+
if (capsule.iat > nowSeconds + 5) {
|
|
4621
|
+
return {
|
|
4622
|
+
allow: false,
|
|
4623
|
+
riskScore: 100,
|
|
4624
|
+
reasons: [`${CCE_ERROR.CAPSULE_NOT_YET_VALID}: iat=${capsule.iat}`],
|
|
4625
|
+
code: CCE_ERROR.CAPSULE_NOT_YET_VALID
|
|
4626
|
+
};
|
|
4627
|
+
}
|
|
4628
|
+
input.metadata = input.metadata ?? {};
|
|
4629
|
+
input.metadata.cceCapsuleVerified = true;
|
|
4630
|
+
input.metadata.cceCapsule = capsule;
|
|
4631
|
+
return {
|
|
4632
|
+
decision: "ALLOW" /* ALLOW */,
|
|
4633
|
+
allow: true,
|
|
4634
|
+
riskScore: 0,
|
|
4635
|
+
reasons: [],
|
|
4636
|
+
meta: { capsule_id: capsule.capsule_id }
|
|
4637
|
+
};
|
|
4638
|
+
}
|
|
4639
|
+
};
|
|
4640
|
+
function canonicalize3(obj) {
|
|
4641
|
+
if (Array.isArray(obj)) {
|
|
4642
|
+
return "[" + obj.map(canonicalize3).join(",") + "]";
|
|
4643
|
+
}
|
|
4644
|
+
if (obj !== null && typeof obj === "object") {
|
|
4645
|
+
const sorted = Object.keys(obj).sort().map(
|
|
4646
|
+
(k) => JSON.stringify(k) + ":" + canonicalize3(obj[k])
|
|
4647
|
+
);
|
|
4648
|
+
return "{" + sorted.join(",") + "}";
|
|
4649
|
+
}
|
|
4650
|
+
return JSON.stringify(obj);
|
|
4651
|
+
}
|
|
4652
|
+
function computeCceCapsuleId(claims) {
|
|
4653
|
+
const canonical = canonicalize3(claims);
|
|
4654
|
+
const hash = (0, import_blake3.blake3)(new TextEncoder().encode(canonical));
|
|
4655
|
+
return "cce_b3_" + (0, import_utils5.bytesToHex)(hash).slice(0, 32);
|
|
4656
|
+
}
|
|
4657
|
+
|
|
4658
|
+
// src/cce/sensors/cce-tps-window.sensor.ts
|
|
4659
|
+
var DEFAULT_SKEW_MS = 5e3;
|
|
4660
|
+
var CceTpsWindowSensor = class {
|
|
4661
|
+
constructor(skewMs = DEFAULT_SKEW_MS) {
|
|
4662
|
+
this.skewMs = skewMs;
|
|
4663
|
+
this.name = "cce.tps.window";
|
|
4664
|
+
this.order = 92;
|
|
4665
|
+
this.phase = "POST_DECODE";
|
|
4666
|
+
}
|
|
4667
|
+
supports(input) {
|
|
4668
|
+
return input.metadata?.cceCapsuleVerified === true;
|
|
4669
|
+
}
|
|
4670
|
+
async run(input) {
|
|
4671
|
+
const capsule = input.metadata?.cceCapsule;
|
|
4672
|
+
if (!capsule) {
|
|
4673
|
+
return {
|
|
4674
|
+
allow: false,
|
|
4675
|
+
riskScore: 100,
|
|
4676
|
+
reasons: [CCE_ERROR.MISSING_CAPSULE],
|
|
4677
|
+
code: CCE_ERROR.MISSING_CAPSULE
|
|
4678
|
+
};
|
|
4679
|
+
}
|
|
4680
|
+
const nowMs = Date.now();
|
|
4681
|
+
if (nowMs > capsule.tps_to + this.skewMs) {
|
|
4682
|
+
return {
|
|
4683
|
+
allow: false,
|
|
4684
|
+
riskScore: 100,
|
|
4685
|
+
reasons: [
|
|
4686
|
+
`${CCE_ERROR.TPS_WINDOW_EXPIRED}: window ended at ${capsule.tps_to}, now=${nowMs}`
|
|
4687
|
+
],
|
|
4688
|
+
code: CCE_ERROR.TPS_WINDOW_EXPIRED
|
|
4689
|
+
};
|
|
4690
|
+
}
|
|
4691
|
+
if (nowMs < capsule.tps_from - this.skewMs) {
|
|
4692
|
+
return {
|
|
4693
|
+
allow: false,
|
|
4694
|
+
riskScore: 100,
|
|
4695
|
+
reasons: [
|
|
4696
|
+
`${CCE_ERROR.TPS_WINDOW_FUTURE}: window starts at ${capsule.tps_from}, now=${nowMs}`
|
|
4697
|
+
],
|
|
4698
|
+
code: CCE_ERROR.TPS_WINDOW_FUTURE
|
|
4699
|
+
};
|
|
4700
|
+
}
|
|
4701
|
+
input.metadata = input.metadata ?? {};
|
|
4702
|
+
input.metadata.cceTpsValid = true;
|
|
4703
|
+
return {
|
|
4704
|
+
decision: "ALLOW" /* ALLOW */,
|
|
4705
|
+
allow: true,
|
|
4706
|
+
riskScore: 0,
|
|
4707
|
+
reasons: []
|
|
4708
|
+
};
|
|
4709
|
+
}
|
|
4710
|
+
};
|
|
4711
|
+
|
|
4712
|
+
// src/cce/sensors/cce-audience-intent-binding.sensor.ts
|
|
4713
|
+
var CceAudienceIntentBindingSensor = class {
|
|
4714
|
+
constructor(axisAudience) {
|
|
4715
|
+
this.axisAudience = axisAudience;
|
|
4716
|
+
this.name = "cce.audience.intent.binding";
|
|
4717
|
+
this.order = 95;
|
|
4718
|
+
this.phase = "POST_DECODE";
|
|
4719
|
+
}
|
|
4720
|
+
supports(input) {
|
|
4721
|
+
return input.metadata?.cceCapsuleVerified === true;
|
|
4722
|
+
}
|
|
4723
|
+
async run(input) {
|
|
4724
|
+
const capsule = input.metadata?.cceCapsule;
|
|
4725
|
+
const envelope = input.metadata?.cceEnvelope;
|
|
4726
|
+
if (!capsule || !envelope) {
|
|
4727
|
+
return {
|
|
4728
|
+
allow: false,
|
|
4729
|
+
riskScore: 100,
|
|
4730
|
+
reasons: [CCE_ERROR.MISSING_CAPSULE],
|
|
4731
|
+
code: CCE_ERROR.MISSING_CAPSULE
|
|
4732
|
+
};
|
|
4733
|
+
}
|
|
4734
|
+
if (capsule.aud !== this.axisAudience) {
|
|
4735
|
+
return {
|
|
4736
|
+
allow: false,
|
|
4737
|
+
riskScore: 100,
|
|
4738
|
+
reasons: [
|
|
4739
|
+
`${CCE_ERROR.AUDIENCE_MISMATCH}: capsule.aud=${capsule.aud}, expected=${this.axisAudience}`
|
|
4740
|
+
],
|
|
4741
|
+
code: CCE_ERROR.AUDIENCE_MISMATCH
|
|
4742
|
+
};
|
|
4743
|
+
}
|
|
4744
|
+
const requestIntent = input.intent ?? input.metadata?.cceRequestIntent;
|
|
4745
|
+
if (requestIntent && capsule.intent !== requestIntent) {
|
|
4746
|
+
return {
|
|
4747
|
+
allow: false,
|
|
4748
|
+
riskScore: 100,
|
|
4749
|
+
reasons: [
|
|
4750
|
+
`${CCE_ERROR.INTENT_MISMATCH}: capsule.intent=${capsule.intent}, request=${requestIntent}`
|
|
4751
|
+
],
|
|
4752
|
+
code: CCE_ERROR.INTENT_MISMATCH
|
|
4753
|
+
};
|
|
4754
|
+
}
|
|
4755
|
+
if (envelope.client_kid !== capsule.kid) {
|
|
4756
|
+
return {
|
|
4757
|
+
allow: false,
|
|
4758
|
+
riskScore: 100,
|
|
4759
|
+
reasons: [
|
|
4760
|
+
`${CCE_ERROR.INTENT_MISMATCH}: envelope.kid=${envelope.client_kid}, capsule.kid=${capsule.kid}`
|
|
4761
|
+
],
|
|
4762
|
+
code: CCE_ERROR.INTENT_MISMATCH
|
|
4763
|
+
};
|
|
4764
|
+
}
|
|
4765
|
+
input.metadata = input.metadata ?? {};
|
|
4766
|
+
input.metadata.cceBindingVerified = true;
|
|
4767
|
+
return {
|
|
4768
|
+
decision: "ALLOW" /* ALLOW */,
|
|
4769
|
+
allow: true,
|
|
4770
|
+
riskScore: 0,
|
|
4771
|
+
reasons: []
|
|
4772
|
+
};
|
|
4773
|
+
}
|
|
4774
|
+
};
|
|
4775
|
+
|
|
4776
|
+
// src/cce/sensors/cce-replay-protection.sensor.ts
|
|
4777
|
+
var InMemoryCceReplayStore = class {
|
|
4778
|
+
constructor() {
|
|
4779
|
+
this.nonces = /* @__PURE__ */ new Map();
|
|
4780
|
+
this.consumed = /* @__PURE__ */ new Set();
|
|
4781
|
+
this.revoked = /* @__PURE__ */ new Set();
|
|
4782
|
+
}
|
|
4783
|
+
async checkAndMark(key, ttlMs) {
|
|
4784
|
+
this.cleanup();
|
|
4785
|
+
if (this.nonces.has(key)) return false;
|
|
4786
|
+
this.nonces.set(key, Date.now() + ttlMs);
|
|
4787
|
+
return true;
|
|
4788
|
+
}
|
|
4789
|
+
async isCapsuleConsumed(capsuleId) {
|
|
4790
|
+
return this.consumed.has(capsuleId);
|
|
4791
|
+
}
|
|
4792
|
+
async markCapsuleConsumed(capsuleId, _ttlMs) {
|
|
4793
|
+
this.consumed.add(capsuleId);
|
|
4794
|
+
}
|
|
4795
|
+
async isCapsuleRevoked(capsuleId) {
|
|
4796
|
+
return this.revoked.has(capsuleId);
|
|
4797
|
+
}
|
|
4798
|
+
/** Revoke a capsule (for testing/admin) */
|
|
4799
|
+
revoke(capsuleId) {
|
|
4800
|
+
this.revoked.add(capsuleId);
|
|
4801
|
+
}
|
|
4802
|
+
cleanup() {
|
|
4803
|
+
const now = Date.now();
|
|
4804
|
+
for (const [key, expiresAt] of this.nonces) {
|
|
4805
|
+
if (expiresAt < now) this.nonces.delete(key);
|
|
4806
|
+
}
|
|
4807
|
+
}
|
|
4808
|
+
};
|
|
4809
|
+
var CceReplayProtectionSensor = class {
|
|
4810
|
+
constructor(replayStore, options) {
|
|
4811
|
+
this.replayStore = replayStore;
|
|
4812
|
+
this.name = "cce.replay.protection";
|
|
4813
|
+
this.order = 98;
|
|
4814
|
+
this.phase = "POST_DECODE";
|
|
4815
|
+
this.nonceTtlMs = options?.nonceTtlMs ?? 5 * 60 * 1e3;
|
|
4816
|
+
}
|
|
4817
|
+
supports(input) {
|
|
4818
|
+
return input.metadata?.cceCapsuleVerified === true;
|
|
4819
|
+
}
|
|
4820
|
+
async run(input) {
|
|
4821
|
+
const capsule = input.metadata?.cceCapsule;
|
|
4822
|
+
const envelope = input.metadata?.cceEnvelope;
|
|
4823
|
+
if (!capsule || !envelope) {
|
|
4824
|
+
return {
|
|
4825
|
+
allow: false,
|
|
4826
|
+
riskScore: 100,
|
|
4827
|
+
reasons: [CCE_ERROR.MISSING_CAPSULE],
|
|
4828
|
+
code: CCE_ERROR.MISSING_CAPSULE
|
|
4829
|
+
};
|
|
4830
|
+
}
|
|
4831
|
+
const revoked = await this.replayStore.isCapsuleRevoked(capsule.capsule_id);
|
|
4832
|
+
if (revoked) {
|
|
4833
|
+
return {
|
|
4834
|
+
allow: false,
|
|
4835
|
+
riskScore: 100,
|
|
4836
|
+
reasons: [`${CCE_ERROR.CAPSULE_REVOKED}: ${capsule.capsule_id}`],
|
|
4837
|
+
code: CCE_ERROR.CAPSULE_REVOKED
|
|
4838
|
+
};
|
|
4839
|
+
}
|
|
4840
|
+
if (capsule.mode === "SINGLE_USE") {
|
|
4841
|
+
const consumed = await this.replayStore.isCapsuleConsumed(
|
|
4842
|
+
capsule.capsule_id
|
|
4843
|
+
);
|
|
4844
|
+
if (consumed) {
|
|
4845
|
+
return {
|
|
4846
|
+
allow: false,
|
|
4847
|
+
riskScore: 100,
|
|
4848
|
+
reasons: [`${CCE_ERROR.CAPSULE_CONSUMED}: ${capsule.capsule_id}`],
|
|
4849
|
+
code: CCE_ERROR.CAPSULE_CONSUMED
|
|
4850
|
+
};
|
|
4851
|
+
}
|
|
4852
|
+
}
|
|
4853
|
+
const nonceKey = `cce:nonce:${capsule.sub}:${capsule.aud}:${capsule.intent}:${envelope.request_nonce}`;
|
|
4854
|
+
const nonceValid = await this.replayStore.checkAndMark(
|
|
4855
|
+
nonceKey,
|
|
4856
|
+
this.nonceTtlMs
|
|
4857
|
+
);
|
|
4858
|
+
if (!nonceValid) {
|
|
4859
|
+
return {
|
|
4860
|
+
allow: false,
|
|
4861
|
+
riskScore: 100,
|
|
4862
|
+
reasons: [
|
|
4863
|
+
`${CCE_ERROR.NONCE_REUSED}: ${envelope.request_nonce.slice(0, 16)}...`
|
|
4864
|
+
],
|
|
4865
|
+
code: CCE_ERROR.NONCE_REUSED
|
|
4866
|
+
};
|
|
4867
|
+
}
|
|
4868
|
+
if (capsule.mode === "SINGLE_USE") {
|
|
4869
|
+
const capsuleTtl = (capsule.exp - capsule.iat) * 1e3 + 6e4;
|
|
4870
|
+
await this.replayStore.markCapsuleConsumed(
|
|
4871
|
+
capsule.capsule_id,
|
|
4872
|
+
capsuleTtl
|
|
4873
|
+
);
|
|
4874
|
+
}
|
|
4875
|
+
input.metadata = input.metadata ?? {};
|
|
4876
|
+
input.metadata.cceReplayClean = true;
|
|
4877
|
+
return {
|
|
4878
|
+
decision: "ALLOW" /* ALLOW */,
|
|
4879
|
+
allow: true,
|
|
4880
|
+
riskScore: 0,
|
|
4881
|
+
reasons: []
|
|
4882
|
+
};
|
|
4883
|
+
}
|
|
4884
|
+
};
|
|
4885
|
+
|
|
4886
|
+
// src/cce/sensors/cce-payload-decryption.sensor.ts
|
|
4887
|
+
var CcePayloadDecryptionSensor = class {
|
|
4888
|
+
constructor(keyProvider, aesProvider, maxPayloadBytes = 64 * 1024) {
|
|
4889
|
+
this.keyProvider = keyProvider;
|
|
4890
|
+
this.aesProvider = aesProvider;
|
|
4891
|
+
this.maxPayloadBytes = maxPayloadBytes;
|
|
4892
|
+
this.name = "cce.payload.decryption";
|
|
4893
|
+
this.order = 145;
|
|
4894
|
+
this.phase = "POST_DECODE";
|
|
4895
|
+
}
|
|
4896
|
+
supports(input) {
|
|
4897
|
+
return input.metadata?.cceEnvelopeValid === true && input.metadata?.cceClientSigVerified === true && input.metadata?.cceCapsuleVerified === true && input.metadata?.cceReplayClean === true;
|
|
4898
|
+
}
|
|
4899
|
+
async run(input) {
|
|
4900
|
+
const envelope = input.metadata?.cceEnvelope;
|
|
4901
|
+
if (!envelope) {
|
|
4902
|
+
return {
|
|
4903
|
+
allow: false,
|
|
4904
|
+
riskScore: 100,
|
|
4905
|
+
reasons: [CCE_ERROR.INVALID_ENVELOPE],
|
|
4906
|
+
code: CCE_ERROR.INVALID_ENVELOPE
|
|
4907
|
+
};
|
|
4908
|
+
}
|
|
4909
|
+
let aesKey;
|
|
4910
|
+
try {
|
|
4911
|
+
aesKey = await this.keyProvider.unwrapKey(
|
|
4912
|
+
envelope.encrypted_key.ciphertext,
|
|
4913
|
+
envelope.encrypted_key.alg,
|
|
4914
|
+
envelope.encrypted_key.axis_kid,
|
|
4915
|
+
envelope.encrypted_key.ephemeral_pk
|
|
4916
|
+
);
|
|
4917
|
+
} catch {
|
|
4918
|
+
return {
|
|
4919
|
+
allow: false,
|
|
4920
|
+
riskScore: 100,
|
|
4921
|
+
reasons: [CCE_ERROR.KEY_UNWRAP_FAILED],
|
|
4922
|
+
code: CCE_ERROR.KEY_UNWRAP_FAILED
|
|
4923
|
+
};
|
|
4924
|
+
}
|
|
4925
|
+
if (!aesKey) {
|
|
4926
|
+
return {
|
|
4927
|
+
allow: false,
|
|
4928
|
+
riskScore: 100,
|
|
4929
|
+
reasons: [CCE_ERROR.KEY_UNWRAP_FAILED],
|
|
4930
|
+
code: CCE_ERROR.KEY_UNWRAP_FAILED
|
|
4931
|
+
};
|
|
4932
|
+
}
|
|
4933
|
+
let iv;
|
|
4934
|
+
let ciphertext;
|
|
4935
|
+
let tag;
|
|
4936
|
+
try {
|
|
4937
|
+
iv = base64UrlDecode2(envelope.encrypted_payload.iv);
|
|
4938
|
+
ciphertext = base64UrlDecode2(envelope.encrypted_payload.ciphertext);
|
|
4939
|
+
tag = base64UrlDecode2(envelope.encrypted_payload.tag);
|
|
4940
|
+
} catch {
|
|
4941
|
+
return {
|
|
4942
|
+
allow: false,
|
|
4943
|
+
riskScore: 100,
|
|
4944
|
+
reasons: [`${CCE_ERROR.DECRYPTION_FAILED}: invalid base64url encoding`],
|
|
4945
|
+
code: CCE_ERROR.DECRYPTION_FAILED
|
|
4946
|
+
};
|
|
4947
|
+
}
|
|
4948
|
+
if (ciphertext.length > this.maxPayloadBytes) {
|
|
4949
|
+
return {
|
|
4950
|
+
allow: false,
|
|
4951
|
+
riskScore: 100,
|
|
4952
|
+
reasons: [
|
|
4953
|
+
`${CCE_ERROR.PAYLOAD_TOO_LARGE}: ${ciphertext.length} > ${this.maxPayloadBytes}`
|
|
4954
|
+
],
|
|
4955
|
+
code: CCE_ERROR.PAYLOAD_TOO_LARGE
|
|
4956
|
+
};
|
|
4957
|
+
}
|
|
4958
|
+
const aad = buildAad(envelope);
|
|
4959
|
+
let plaintext;
|
|
4960
|
+
try {
|
|
4961
|
+
plaintext = await this.aesProvider.decrypt(
|
|
4962
|
+
aesKey,
|
|
4963
|
+
iv,
|
|
4964
|
+
ciphertext,
|
|
4965
|
+
tag,
|
|
4966
|
+
aad
|
|
4967
|
+
);
|
|
4968
|
+
} catch {
|
|
4969
|
+
plaintext = null;
|
|
4970
|
+
} finally {
|
|
4971
|
+
aesKey.fill(0);
|
|
4972
|
+
}
|
|
4973
|
+
if (!plaintext) {
|
|
4974
|
+
return {
|
|
4975
|
+
allow: false,
|
|
4976
|
+
riskScore: 100,
|
|
4977
|
+
reasons: [CCE_ERROR.AEAD_TAG_MISMATCH],
|
|
4978
|
+
code: CCE_ERROR.AEAD_TAG_MISMATCH
|
|
4979
|
+
};
|
|
4980
|
+
}
|
|
4981
|
+
input.metadata = input.metadata ?? {};
|
|
4982
|
+
input.metadata.cceDecryptedPayload = plaintext;
|
|
4983
|
+
input.metadata.cceDecryptionOk = true;
|
|
4984
|
+
return {
|
|
4985
|
+
decision: "ALLOW" /* ALLOW */,
|
|
4986
|
+
allow: true,
|
|
4987
|
+
riskScore: 0,
|
|
4988
|
+
reasons: []
|
|
4989
|
+
};
|
|
4990
|
+
}
|
|
4991
|
+
};
|
|
4992
|
+
function buildAad(envelope) {
|
|
4993
|
+
const parts = [
|
|
4994
|
+
envelope.ver,
|
|
4995
|
+
envelope.request_id,
|
|
4996
|
+
envelope.correlation_id,
|
|
4997
|
+
envelope.client_kid,
|
|
4998
|
+
envelope.capsule.capsule_id,
|
|
4999
|
+
envelope.capsule.intent,
|
|
5000
|
+
envelope.capsule.aud,
|
|
5001
|
+
envelope.request_nonce
|
|
5002
|
+
];
|
|
5003
|
+
return new TextEncoder().encode(parts.join("|"));
|
|
5004
|
+
}
|
|
5005
|
+
function base64UrlDecode2(input) {
|
|
5006
|
+
const base64 = input.replace(/-/g, "+").replace(/_/g, "/");
|
|
5007
|
+
const padding = "=".repeat((4 - base64.length % 4) % 4);
|
|
5008
|
+
const binary = atob(base64 + padding);
|
|
5009
|
+
const bytes2 = new Uint8Array(binary.length);
|
|
5010
|
+
for (let i = 0; i < binary.length; i++) {
|
|
5011
|
+
bytes2[i] = binary.charCodeAt(i);
|
|
5012
|
+
}
|
|
5013
|
+
return bytes2;
|
|
5014
|
+
}
|
|
5015
|
+
|
|
5016
|
+
// src/core/index.ts
|
|
5017
|
+
var core_exports = {};
|
|
5018
|
+
__export(core_exports, {
|
|
5019
|
+
AXIS_MAGIC: () => import_axis_protocol2.AXIS_MAGIC,
|
|
5020
|
+
AXIS_VERSION: () => import_axis_protocol2.AXIS_VERSION,
|
|
5021
|
+
AxisError: () => AxisError,
|
|
5022
|
+
AxisFrameZ: () => AxisFrameZ,
|
|
5023
|
+
BodyProfile: () => import_axis_protocol2.BodyProfile,
|
|
5024
|
+
ERR_BAD_SIGNATURE: () => import_axis_protocol2.ERR_BAD_SIGNATURE,
|
|
5025
|
+
ERR_CONTRACT_VIOLATION: () => import_axis_protocol2.ERR_CONTRACT_VIOLATION,
|
|
5026
|
+
ERR_INVALID_PACKET: () => import_axis_protocol2.ERR_INVALID_PACKET,
|
|
5027
|
+
ERR_REPLAY_DETECTED: () => import_axis_protocol2.ERR_REPLAY_DETECTED,
|
|
5028
|
+
FLAG_BODY_TLV: () => import_axis_protocol2.FLAG_BODY_TLV,
|
|
5029
|
+
FLAG_CHAIN_REQ: () => import_axis_protocol2.FLAG_CHAIN_REQ,
|
|
5030
|
+
FLAG_HAS_WITNESS: () => import_axis_protocol2.FLAG_HAS_WITNESS,
|
|
5031
|
+
MAX_BODY_LEN: () => import_axis_protocol2.MAX_BODY_LEN,
|
|
5032
|
+
MAX_FRAME_LEN: () => import_axis_protocol2.MAX_FRAME_LEN,
|
|
5033
|
+
MAX_HDR_LEN: () => import_axis_protocol2.MAX_HDR_LEN,
|
|
5034
|
+
MAX_SIG_LEN: () => import_axis_protocol2.MAX_SIG_LEN,
|
|
5035
|
+
NCERT_ALG: () => import_axis_protocol2.NCERT_ALG,
|
|
5036
|
+
NCERT_EXP: () => import_axis_protocol2.NCERT_EXP,
|
|
5037
|
+
NCERT_ISSUER_KID: () => import_axis_protocol2.NCERT_ISSUER_KID,
|
|
5038
|
+
NCERT_KID: () => import_axis_protocol2.NCERT_KID,
|
|
5039
|
+
NCERT_NBF: () => import_axis_protocol2.NCERT_NBF,
|
|
5040
|
+
NCERT_NODE_ID: () => import_axis_protocol2.NCERT_NODE_ID,
|
|
5041
|
+
NCERT_PAYLOAD: () => import_axis_protocol2.NCERT_PAYLOAD,
|
|
5042
|
+
NCERT_PUB: () => import_axis_protocol2.NCERT_PUB,
|
|
5043
|
+
NCERT_SCOPE: () => import_axis_protocol2.NCERT_SCOPE,
|
|
5044
|
+
NCERT_SIG: () => import_axis_protocol2.NCERT_SIG,
|
|
5045
|
+
PROOF_CAPSULE: () => import_axis_protocol2.PROOF_CAPSULE,
|
|
5046
|
+
PROOF_JWT: () => import_axis_protocol2.PROOF_JWT,
|
|
5047
|
+
PROOF_LOOM: () => import_axis_protocol2.PROOF_LOOM,
|
|
5048
|
+
PROOF_MTLS: () => import_axis_protocol2.PROOF_MTLS,
|
|
5049
|
+
PROOF_NONE: () => import_axis_protocol2.PROOF_NONE,
|
|
5050
|
+
PROOF_WITNESS: () => import_axis_protocol2.PROOF_WITNESS,
|
|
5051
|
+
ProofType: () => import_axis_protocol2.ProofType,
|
|
5052
|
+
TLV: () => import_axis_protocol.TLV,
|
|
5053
|
+
TLV_ACTOR_ID: () => import_axis_protocol2.TLV_ACTOR_ID,
|
|
5054
|
+
TLV_AUD: () => import_axis_protocol2.TLV_AUD,
|
|
5055
|
+
TLV_BODY_ARR: () => import_axis_protocol2.TLV_BODY_ARR,
|
|
5056
|
+
TLV_BODY_OBJ: () => import_axis_protocol2.TLV_BODY_OBJ,
|
|
5057
|
+
TLV_CAPSULE: () => import_axis_protocol2.TLV_CAPSULE,
|
|
5058
|
+
TLV_EFFECT: () => import_axis_protocol2.TLV_EFFECT,
|
|
5059
|
+
TLV_ERROR_CODE: () => import_axis_protocol2.TLV_ERROR_CODE,
|
|
5060
|
+
TLV_ERROR_MSG: () => import_axis_protocol2.TLV_ERROR_MSG,
|
|
5061
|
+
TLV_INDEX: () => import_axis_protocol2.TLV_INDEX,
|
|
5062
|
+
TLV_INTENT: () => import_axis_protocol2.TLV_INTENT,
|
|
5063
|
+
TLV_KID: () => import_axis_protocol2.TLV_KID,
|
|
5064
|
+
TLV_LOOM_PRESENCE_ID: () => import_axis_protocol2.TLV_LOOM_PRESENCE_ID,
|
|
5065
|
+
TLV_LOOM_THREAD_HASH: () => import_axis_protocol2.TLV_LOOM_THREAD_HASH,
|
|
5066
|
+
TLV_LOOM_WRIT: () => import_axis_protocol2.TLV_LOOM_WRIT,
|
|
5067
|
+
TLV_NODE: () => import_axis_protocol2.TLV_NODE,
|
|
5068
|
+
TLV_NODE_CERT_HASH: () => import_axis_protocol2.TLV_NODE_CERT_HASH,
|
|
5069
|
+
TLV_NODE_KID: () => import_axis_protocol2.TLV_NODE_KID,
|
|
5070
|
+
TLV_NONCE: () => import_axis_protocol2.TLV_NONCE,
|
|
5071
|
+
TLV_OFFSET: () => import_axis_protocol2.TLV_OFFSET,
|
|
5072
|
+
TLV_OK: () => import_axis_protocol2.TLV_OK,
|
|
5073
|
+
TLV_PID: () => import_axis_protocol2.TLV_PID,
|
|
5074
|
+
TLV_PREV_HASH: () => import_axis_protocol2.TLV_PREV_HASH,
|
|
5075
|
+
TLV_PROOF_REF: () => import_axis_protocol2.TLV_PROOF_REF,
|
|
5076
|
+
TLV_PROOF_TYPE: () => import_axis_protocol2.TLV_PROOF_TYPE,
|
|
5077
|
+
TLV_REALM: () => import_axis_protocol2.TLV_REALM,
|
|
5078
|
+
TLV_RECEIPT_HASH: () => import_axis_protocol2.TLV_RECEIPT_HASH,
|
|
5079
|
+
TLV_RID: () => import_axis_protocol2.TLV_RID,
|
|
5080
|
+
TLV_SHA256_CHUNK: () => import_axis_protocol2.TLV_SHA256_CHUNK,
|
|
5081
|
+
TLV_TRACE_ID: () => import_axis_protocol2.TLV_TRACE_ID,
|
|
5082
|
+
TLV_TS: () => import_axis_protocol2.TLV_TS,
|
|
5083
|
+
TLV_UPLOAD_ID: () => import_axis_protocol2.TLV_UPLOAD_ID,
|
|
5084
|
+
computeReceiptHash: () => computeReceiptHash,
|
|
5085
|
+
computeSignaturePayload: () => computeSignaturePayload,
|
|
5086
|
+
decodeArray: () => import_axis_protocol.decodeArray,
|
|
5087
|
+
decodeFrame: () => decodeFrame,
|
|
5088
|
+
decodeObject: () => import_axis_protocol.decodeObject,
|
|
5089
|
+
decodeTLVs: () => import_axis_protocol.decodeTLVs,
|
|
5090
|
+
decodeTLVsList: () => import_axis_protocol.decodeTLVsList,
|
|
5091
|
+
decodeVarint: () => import_axis_protocol3.decodeVarint,
|
|
5092
|
+
encodeFrame: () => encodeFrame,
|
|
3635
5093
|
encodeTLVs: () => import_axis_protocol.encodeTLVs,
|
|
3636
5094
|
encodeVarint: () => import_axis_protocol3.encodeVarint,
|
|
3637
5095
|
generateEd25519KeyPair: () => generateEd25519KeyPair,
|
|
3638
5096
|
getSignTarget: () => getSignTarget,
|
|
3639
|
-
sha256: () =>
|
|
5097
|
+
sha256: () => sha2564,
|
|
3640
5098
|
signFrame: () => signFrame,
|
|
3641
5099
|
varintLength: () => import_axis_protocol3.varintLength,
|
|
3642
5100
|
verifyFrameSignature: () => verifyFrameSignature
|
|
@@ -3656,7 +5114,7 @@ __export(crypto_exports, {
|
|
|
3656
5114
|
|
|
3657
5115
|
// src/crypto/proof-verification.service.ts
|
|
3658
5116
|
var import_common10 = require("@nestjs/common");
|
|
3659
|
-
var
|
|
5117
|
+
var crypto4 = __toESM(require("crypto"));
|
|
3660
5118
|
var nacl = __toESM(require("tweetnacl"));
|
|
3661
5119
|
var ProofVerificationService = class {
|
|
3662
5120
|
constructor() {
|
|
@@ -3868,7 +5326,7 @@ var ProofVerificationService = class {
|
|
|
3868
5326
|
certPem.replace(/-----BEGIN CERTIFICATE-----/, "").replace(/-----END CERTIFICATE-----/, "").replace(/\s/g, ""),
|
|
3869
5327
|
"base64"
|
|
3870
5328
|
);
|
|
3871
|
-
return
|
|
5329
|
+
return crypto4.createHash("sha256").update(der).digest("hex");
|
|
3872
5330
|
}
|
|
3873
5331
|
};
|
|
3874
5332
|
ProofVerificationService = __decorateClass([
|
|
@@ -3915,12 +5373,22 @@ __export(engine_exports, {
|
|
|
3915
5373
|
PRE_DECODE_BOUNDARY: () => PRE_DECODE_BOUNDARY,
|
|
3916
5374
|
SensorDiscoveryService: () => SensorDiscoveryService,
|
|
3917
5375
|
SensorRegistry: () => SensorRegistry,
|
|
5376
|
+
buildQueueMessage: () => buildQueueMessage,
|
|
5377
|
+
buildUnsignedWitness: () => buildUnsignedWitness,
|
|
5378
|
+
canonicalizeObservation: () => canonicalizeObservation,
|
|
3918
5379
|
createObservation: () => createObservation,
|
|
5380
|
+
decodeQueueMessage: () => decodeQueueMessage,
|
|
5381
|
+
encodeQueueMessage: () => encodeQueueMessage,
|
|
3919
5382
|
endStage: () => endStage,
|
|
3920
5383
|
finalizeObservation: () => finalizeObservation,
|
|
5384
|
+
hashObservation: () => hashObservation,
|
|
3921
5385
|
observation: () => observation_exports,
|
|
5386
|
+
parseAutoClaimEntries: () => parseAutoClaimEntries,
|
|
5387
|
+
parseStreamEntries: () => parseStreamEntries,
|
|
3922
5388
|
recordSensor: () => recordSensor,
|
|
3923
|
-
|
|
5389
|
+
stableJsonStringify: () => stableJsonStringify,
|
|
5390
|
+
startStage: () => startStage,
|
|
5391
|
+
verifyResponse: () => verifyResponse
|
|
3924
5392
|
});
|
|
3925
5393
|
|
|
3926
5394
|
// src/engine/observation/index.ts
|
|
@@ -3950,35 +5418,6 @@ __export(loom_exports, {
|
|
|
3950
5418
|
deriveAnchorReflection: () => deriveAnchorReflection
|
|
3951
5419
|
});
|
|
3952
5420
|
|
|
3953
|
-
// src/loom/loom.types.ts
|
|
3954
|
-
function deriveAnchorReflection(softid, context = "openlogs", scope = "loom") {
|
|
3955
|
-
return `ar:${context}:${scope}:${softid}`;
|
|
3956
|
-
}
|
|
3957
|
-
function canonicalizeWrit(writ) {
|
|
3958
|
-
const ordered = {
|
|
3959
|
-
head: { tid: writ.head.tid, seq: writ.head.seq },
|
|
3960
|
-
body: {
|
|
3961
|
-
who: writ.body.who,
|
|
3962
|
-
act: writ.body.act,
|
|
3963
|
-
res: writ.body.res,
|
|
3964
|
-
law: writ.body.law
|
|
3965
|
-
},
|
|
3966
|
-
meta: { iat: writ.meta.iat, exp: writ.meta.exp, prev: writ.meta.prev }
|
|
3967
|
-
};
|
|
3968
|
-
return JSON.stringify(ordered);
|
|
3969
|
-
}
|
|
3970
|
-
function canonicalizeGrant(grant) {
|
|
3971
|
-
const ordered = {
|
|
3972
|
-
grant_id: grant.grant_id,
|
|
3973
|
-
issuer: grant.issuer,
|
|
3974
|
-
subject: grant.subject,
|
|
3975
|
-
grant_type: grant.grant_type,
|
|
3976
|
-
caps: grant.caps,
|
|
3977
|
-
meta: grant.meta
|
|
3978
|
-
};
|
|
3979
|
-
return JSON.stringify(ordered);
|
|
3980
|
-
}
|
|
3981
|
-
|
|
3982
5421
|
// src/schemas/index.ts
|
|
3983
5422
|
var schemas_exports = {};
|
|
3984
5423
|
__export(schemas_exports, {
|
|
@@ -4681,7 +6120,7 @@ CapabilityEnforcementSensor = __decorateClass([
|
|
|
4681
6120
|
|
|
4682
6121
|
// src/sensors/chunk-hash.sensor.ts
|
|
4683
6122
|
var import_common15 = require("@nestjs/common");
|
|
4684
|
-
var
|
|
6123
|
+
var import_crypto8 = require("crypto");
|
|
4685
6124
|
var ChunkHashSensor = class {
|
|
4686
6125
|
constructor() {
|
|
4687
6126
|
/** Sensor identifier */
|
|
@@ -4740,7 +6179,7 @@ var ChunkHashSensor = class {
|
|
|
4740
6179
|
reason: "Missing sha256Chunk TLV in header"
|
|
4741
6180
|
};
|
|
4742
6181
|
}
|
|
4743
|
-
const actual = (0,
|
|
6182
|
+
const actual = (0, import_crypto8.createHash)("sha256").update(bodyBytes).digest();
|
|
4744
6183
|
if (!Buffer.from(actual).equals(Buffer.from(expected))) {
|
|
4745
6184
|
return {
|
|
4746
6185
|
action: "DENY",
|
|
@@ -4758,7 +6197,7 @@ ChunkHashSensor = __decorateClass([
|
|
|
4758
6197
|
|
|
4759
6198
|
// src/sensors/entropy.sensor.ts
|
|
4760
6199
|
var import_common16 = require("@nestjs/common");
|
|
4761
|
-
var
|
|
6200
|
+
var crypto5 = __toESM(require("crypto"));
|
|
4762
6201
|
var EntropySensor = class {
|
|
4763
6202
|
constructor() {
|
|
4764
6203
|
this.logger = new import_common16.Logger(EntropySensor.name);
|
|
@@ -4926,7 +6365,7 @@ var EntropySensor = class {
|
|
|
4926
6365
|
* @returns {Uint8Array} Cryptographically secure random bytes
|
|
4927
6366
|
*/
|
|
4928
6367
|
static generateSecureRandom(length) {
|
|
4929
|
-
return new Uint8Array(
|
|
6368
|
+
return new Uint8Array(crypto5.randomBytes(length));
|
|
4930
6369
|
}
|
|
4931
6370
|
};
|
|
4932
6371
|
EntropySensor = __decorateClass([
|
|
@@ -5989,59 +7428,6 @@ var utils_exports = {};
|
|
|
5989
7428
|
__export(utils_exports, {
|
|
5990
7429
|
encodeAxisTlvDto: () => encodeAxisTlvDto
|
|
5991
7430
|
});
|
|
5992
|
-
|
|
5993
|
-
// src/utils/axis-tlv-codec.ts
|
|
5994
|
-
function encodeAxisTlvDto(dtoClass, data) {
|
|
5995
|
-
const schema = extractDtoSchema(dtoClass);
|
|
5996
|
-
const items = schema.fields.flatMap((field) => {
|
|
5997
|
-
const value = data[field.name];
|
|
5998
|
-
if (value === void 0 || value === null) {
|
|
5999
|
-
if (field.required) {
|
|
6000
|
-
throw new Error(`Missing required TLV response field: ${field.name}`);
|
|
6001
|
-
}
|
|
6002
|
-
return [];
|
|
6003
|
-
}
|
|
6004
|
-
return [{ type: field.tag, value: encodeField(field, value) }];
|
|
6005
|
-
});
|
|
6006
|
-
return buildTLVs(items);
|
|
6007
|
-
}
|
|
6008
|
-
function encodeField(field, value) {
|
|
6009
|
-
switch (field.kind) {
|
|
6010
|
-
case "utf8":
|
|
6011
|
-
return Buffer.from(String(value), "utf8");
|
|
6012
|
-
case "u64":
|
|
6013
|
-
return encodeU64(value);
|
|
6014
|
-
case "bytes":
|
|
6015
|
-
case "bytes16":
|
|
6016
|
-
return toBuffer(value);
|
|
6017
|
-
case "bool":
|
|
6018
|
-
return Buffer.from([value ? 1 : 0]);
|
|
6019
|
-
case "obj":
|
|
6020
|
-
case "arr":
|
|
6021
|
-
return Buffer.from(JSON.stringify(value), "utf8");
|
|
6022
|
-
default:
|
|
6023
|
-
return toBuffer(value);
|
|
6024
|
-
}
|
|
6025
|
-
}
|
|
6026
|
-
function encodeU64(value) {
|
|
6027
|
-
const encoded = Buffer.alloc(8);
|
|
6028
|
-
encoded.writeBigUInt64BE(
|
|
6029
|
-
typeof value === "bigint" ? value : BigInt(value)
|
|
6030
|
-
);
|
|
6031
|
-
return encoded;
|
|
6032
|
-
}
|
|
6033
|
-
function toBuffer(value) {
|
|
6034
|
-
if (Buffer.isBuffer(value)) {
|
|
6035
|
-
return value;
|
|
6036
|
-
}
|
|
6037
|
-
if (value instanceof Uint8Array) {
|
|
6038
|
-
return Buffer.from(value);
|
|
6039
|
-
}
|
|
6040
|
-
if (typeof value === "string") {
|
|
6041
|
-
return Buffer.from(value, "utf8");
|
|
6042
|
-
}
|
|
6043
|
-
throw new Error(`Unsupported TLV bytes value: ${typeof value}`);
|
|
6044
|
-
}
|
|
6045
7431
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6046
7432
|
0 && (module.exports = {
|
|
6047
7433
|
ATS1_HDR,
|
|
@@ -6070,6 +7456,9 @@ function toBuffer(value) {
|
|
|
6070
7456
|
BAND,
|
|
6071
7457
|
BodyProfile,
|
|
6072
7458
|
CAPABILITIES,
|
|
7459
|
+
CCE_ERROR,
|
|
7460
|
+
CCE_PROTOCOL_VERSION,
|
|
7461
|
+
CceError,
|
|
6073
7462
|
ContractViolationError,
|
|
6074
7463
|
DEFAULT_CONTRACTS,
|
|
6075
7464
|
DEFAULT_TIMEOUT,
|
|
@@ -6129,6 +7518,7 @@ function toBuffer(value) {
|
|
|
6129
7518
|
RESPONSE_TAG_ID,
|
|
6130
7519
|
RESPONSE_TAG_UPDATED_AT,
|
|
6131
7520
|
RESPONSE_TAG_UPDATED_BY,
|
|
7521
|
+
ResponseObserver,
|
|
6132
7522
|
RiskDecision,
|
|
6133
7523
|
SENSOR_METADATA_KEY,
|
|
6134
7524
|
Schema2002_PasskeyLoginOptionsRes,
|
|
@@ -6162,6 +7552,7 @@ function toBuffer(value) {
|
|
|
6162
7552
|
TLV_OFFSET,
|
|
6163
7553
|
TLV_OK,
|
|
6164
7554
|
TLV_PID,
|
|
7555
|
+
TLV_PRESENCE_ID,
|
|
6165
7556
|
TLV_PREV_HASH,
|
|
6166
7557
|
TLV_PROOF_REF,
|
|
6167
7558
|
TLV_PROOF_TYPE,
|
|
@@ -6169,10 +7560,12 @@ function toBuffer(value) {
|
|
|
6169
7560
|
TLV_RECEIPT_HASH,
|
|
6170
7561
|
TLV_RID,
|
|
6171
7562
|
TLV_SHA256_CHUNK,
|
|
7563
|
+
TLV_THREAD_HASH,
|
|
6172
7564
|
TLV_TRACE_ID,
|
|
6173
7565
|
TLV_TS,
|
|
6174
7566
|
TLV_UPLOAD_ID,
|
|
6175
7567
|
TLV_VALIDATORS_KEY,
|
|
7568
|
+
TLV_WRIT,
|
|
6176
7569
|
TlvEnum,
|
|
6177
7570
|
TlvField,
|
|
6178
7571
|
TlvMinLen,
|
|
@@ -6195,7 +7588,10 @@ function toBuffer(value) {
|
|
|
6195
7588
|
canAccessResource,
|
|
6196
7589
|
canonicalJson,
|
|
6197
7590
|
canonicalJsonExcluding,
|
|
7591
|
+
canonicalizeGrant,
|
|
6198
7592
|
canonicalizeObservation,
|
|
7593
|
+
canonicalizeWrit,
|
|
7594
|
+
cce,
|
|
6199
7595
|
classifyIntent,
|
|
6200
7596
|
computeReceiptHash,
|
|
6201
7597
|
computeSignaturePayload,
|
|
@@ -6211,14 +7607,17 @@ function toBuffer(value) {
|
|
|
6211
7607
|
decodeTLVsList,
|
|
6212
7608
|
decodeVarint,
|
|
6213
7609
|
decorators,
|
|
7610
|
+
deriveAnchorReflection,
|
|
6214
7611
|
encVarint,
|
|
6215
7612
|
encodeAxis1Frame,
|
|
7613
|
+
encodeAxisTlvDto,
|
|
6216
7614
|
encodeFrame,
|
|
6217
7615
|
encodeQueueMessage,
|
|
6218
7616
|
encodeTLVs,
|
|
6219
7617
|
encodeVarint,
|
|
6220
7618
|
endStage,
|
|
6221
7619
|
engine,
|
|
7620
|
+
executeCcePipeline,
|
|
6222
7621
|
extractDtoSchema,
|
|
6223
7622
|
finalizeObservation,
|
|
6224
7623
|
generateEd25519KeyPair,
|