@nextera.one/axis-server-sdk 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -0
- package/dist/index.d.mts +207 -111
- package/dist/index.d.ts +207 -111
- package/dist/index.js +252 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +237 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -718,6 +718,165 @@ IntentRouter = __decorateClass([
|
|
|
718
718
|
__decorateParam(0, Optional())
|
|
719
719
|
], IntentRouter);
|
|
720
720
|
|
|
721
|
+
// src/engine/observation/stable-json.ts
|
|
722
|
+
function normalize(value) {
|
|
723
|
+
if (Array.isArray(value)) {
|
|
724
|
+
return value.map((item) => normalize(item));
|
|
725
|
+
}
|
|
726
|
+
if (value && typeof value === "object") {
|
|
727
|
+
const entries = Object.entries(value).filter(([, nested]) => nested !== void 0).sort(([left], [right]) => left.localeCompare(right));
|
|
728
|
+
const normalized = {};
|
|
729
|
+
for (const [key, nested] of entries) {
|
|
730
|
+
normalized[key] = normalize(nested);
|
|
731
|
+
}
|
|
732
|
+
return normalized;
|
|
733
|
+
}
|
|
734
|
+
return value;
|
|
735
|
+
}
|
|
736
|
+
function stableJsonStringify(value) {
|
|
737
|
+
return JSON.stringify(normalize(value));
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// src/engine/observation/observation-queue.codec.ts
|
|
741
|
+
function buildQueueMessage(observation, sourceNodeId, previous, lastError) {
|
|
742
|
+
const now = Date.now();
|
|
743
|
+
return {
|
|
744
|
+
v: 1,
|
|
745
|
+
observation,
|
|
746
|
+
attempts: previous ? previous.attempts + 1 : 0,
|
|
747
|
+
firstEnqueuedAt: previous?.firstEnqueuedAt ?? now,
|
|
748
|
+
lastEnqueuedAt: now,
|
|
749
|
+
sourceNodeId,
|
|
750
|
+
lastError
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
function encodeQueueMessage(message) {
|
|
754
|
+
return JSON.stringify(message);
|
|
755
|
+
}
|
|
756
|
+
function decodeQueueMessage(raw) {
|
|
757
|
+
try {
|
|
758
|
+
const parsed = JSON.parse(raw);
|
|
759
|
+
if (!parsed || parsed.v !== 1 || !parsed.observation?.id) {
|
|
760
|
+
return null;
|
|
761
|
+
}
|
|
762
|
+
return parsed;
|
|
763
|
+
} catch {
|
|
764
|
+
return null;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
function parseStreamEntries(raw) {
|
|
768
|
+
if (!Array.isArray(raw)) {
|
|
769
|
+
return [];
|
|
770
|
+
}
|
|
771
|
+
const entries = [];
|
|
772
|
+
for (const streamRow of raw) {
|
|
773
|
+
if (!Array.isArray(streamRow) || streamRow.length < 2) {
|
|
774
|
+
continue;
|
|
775
|
+
}
|
|
776
|
+
const messageRows = streamRow[1];
|
|
777
|
+
if (!Array.isArray(messageRows)) {
|
|
778
|
+
continue;
|
|
779
|
+
}
|
|
780
|
+
for (const row of messageRows) {
|
|
781
|
+
if (!Array.isArray(row) || row.length < 2) {
|
|
782
|
+
continue;
|
|
783
|
+
}
|
|
784
|
+
const id = String(row[0]);
|
|
785
|
+
const fields = Array.isArray(row[1]) ? row[1] : [];
|
|
786
|
+
const fieldMap = fieldsToMap(fields);
|
|
787
|
+
const payload = fieldMap.get("payload");
|
|
788
|
+
if (!payload) {
|
|
789
|
+
continue;
|
|
790
|
+
}
|
|
791
|
+
const message = decodeQueueMessage(payload);
|
|
792
|
+
if (!message) {
|
|
793
|
+
continue;
|
|
794
|
+
}
|
|
795
|
+
entries.push({ id, message });
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
return entries;
|
|
799
|
+
}
|
|
800
|
+
function parseAutoClaimEntries(raw) {
|
|
801
|
+
if (!Array.isArray(raw) || raw.length < 2) {
|
|
802
|
+
return [];
|
|
803
|
+
}
|
|
804
|
+
const rows = Array.isArray(raw[1]) ? raw[1] : [];
|
|
805
|
+
return parseStreamEntries([["stream", rows]]);
|
|
806
|
+
}
|
|
807
|
+
function fieldsToMap(fields) {
|
|
808
|
+
const map3 = /* @__PURE__ */ new Map();
|
|
809
|
+
for (let i = 0; i < fields.length; i += 2) {
|
|
810
|
+
const key = fields[i];
|
|
811
|
+
const value = fields[i + 1];
|
|
812
|
+
if (key !== void 0 && value !== void 0) {
|
|
813
|
+
map3.set(String(key), String(value));
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
return map3;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
// src/engine/observation/observation-hash.ts
|
|
820
|
+
import { createHash } from "crypto";
|
|
821
|
+
function canonicalizeObservation(obs) {
|
|
822
|
+
const obj = {
|
|
823
|
+
id: obs.id,
|
|
824
|
+
startMs: obs.startMs,
|
|
825
|
+
endMs: obs.endMs,
|
|
826
|
+
transport: obs.transport,
|
|
827
|
+
ip: obs.ip,
|
|
828
|
+
intent: obs.intent,
|
|
829
|
+
actorId: obs.actorId,
|
|
830
|
+
capsuleId: obs.capsuleId,
|
|
831
|
+
decision: obs.decision,
|
|
832
|
+
resultCode: obs.resultCode,
|
|
833
|
+
statusCode: obs.statusCode,
|
|
834
|
+
durationMs: obs.durationMs,
|
|
835
|
+
stages: obs.stages.map((s) => ({
|
|
836
|
+
name: s.name,
|
|
837
|
+
status: s.status,
|
|
838
|
+
startMs: s.startMs,
|
|
839
|
+
endMs: s.endMs,
|
|
840
|
+
durationMs: s.durationMs,
|
|
841
|
+
reason: s.reason,
|
|
842
|
+
code: s.code
|
|
843
|
+
})),
|
|
844
|
+
sensors: obs.sensors.map((s) => ({
|
|
845
|
+
name: s.name,
|
|
846
|
+
allowed: s.allowed,
|
|
847
|
+
riskScore: s.riskScore,
|
|
848
|
+
durationMs: s.durationMs,
|
|
849
|
+
reasons: s.reasons,
|
|
850
|
+
code: s.code
|
|
851
|
+
}))
|
|
852
|
+
};
|
|
853
|
+
return stableJsonStringify(obj);
|
|
854
|
+
}
|
|
855
|
+
function hashObservation(obs) {
|
|
856
|
+
const canonical = canonicalizeObservation(obs);
|
|
857
|
+
return createHash("sha256").update(canonical).digest("hex");
|
|
858
|
+
}
|
|
859
|
+
function buildUnsignedWitness(obs) {
|
|
860
|
+
if (!obs.decision || !obs.endMs) {
|
|
861
|
+
return null;
|
|
862
|
+
}
|
|
863
|
+
return {
|
|
864
|
+
v: 1,
|
|
865
|
+
observationId: obs.id,
|
|
866
|
+
payloadHash: hashObservation(obs),
|
|
867
|
+
sealedAt: Date.now(),
|
|
868
|
+
summary: {
|
|
869
|
+
intent: obs.intent,
|
|
870
|
+
actorId: obs.actorId,
|
|
871
|
+
decision: obs.decision,
|
|
872
|
+
statusCode: obs.statusCode,
|
|
873
|
+
durationMs: obs.durationMs,
|
|
874
|
+
sensorCount: obs.sensors.length,
|
|
875
|
+
stageCount: obs.stages.length
|
|
876
|
+
}
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
|
|
721
880
|
// src/core/constants.ts
|
|
722
881
|
import {
|
|
723
882
|
AXIS_MAGIC,
|
|
@@ -784,6 +943,51 @@ import {
|
|
|
784
943
|
ERR_CONTRACT_VIOLATION
|
|
785
944
|
} from "@nextera.one/axis-protocol";
|
|
786
945
|
|
|
946
|
+
// src/engine/observation/response-observer.ts
|
|
947
|
+
var SENSITIVE_RESPONSE_TAGS = [4, 5, 6];
|
|
948
|
+
function verifyResponse(ctx, response) {
|
|
949
|
+
if (!response.effect || typeof response.effect !== "string") {
|
|
950
|
+
return {
|
|
951
|
+
passed: false,
|
|
952
|
+
code: "OBSERVER_INVALID_EFFECT",
|
|
953
|
+
reason: "Response effect is missing or invalid"
|
|
954
|
+
};
|
|
955
|
+
}
|
|
956
|
+
if (response.ok && (!response.body || response.body.length === 0)) {
|
|
957
|
+
return {
|
|
958
|
+
passed: false,
|
|
959
|
+
code: "OBSERVER_EMPTY_BODY",
|
|
960
|
+
reason: "Successful response must contain a body"
|
|
961
|
+
};
|
|
962
|
+
}
|
|
963
|
+
if (response.body && response.body.length > MAX_BODY_LEN) {
|
|
964
|
+
return {
|
|
965
|
+
passed: false,
|
|
966
|
+
code: "OBSERVER_BODY_OVERFLOW",
|
|
967
|
+
reason: `Response body exceeds ${MAX_BODY_LEN} bytes`
|
|
968
|
+
};
|
|
969
|
+
}
|
|
970
|
+
if (response.headers) {
|
|
971
|
+
for (const tag of SENSITIVE_RESPONSE_TAGS) {
|
|
972
|
+
if (response.headers.has(tag)) {
|
|
973
|
+
return {
|
|
974
|
+
passed: false,
|
|
975
|
+
code: "OBSERVER_DATA_LEAK",
|
|
976
|
+
reason: `Response must not contain sensitive TLV tag ${tag}`
|
|
977
|
+
};
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
if (response.effect.includes("Error:") || response.effect.includes("stack") || response.effect.includes("at /")) {
|
|
982
|
+
return {
|
|
983
|
+
passed: false,
|
|
984
|
+
code: "OBSERVER_INFO_LEAK",
|
|
985
|
+
reason: "Response effect may contain internal error details"
|
|
986
|
+
};
|
|
987
|
+
}
|
|
988
|
+
return { passed: true };
|
|
989
|
+
}
|
|
990
|
+
|
|
787
991
|
// src/core/varint.ts
|
|
788
992
|
import { encodeVarint, decodeVarint, varintLength } from "@nextera.one/axis-protocol";
|
|
789
993
|
|
|
@@ -1059,7 +1263,7 @@ __export(ats1_exports, {
|
|
|
1059
1263
|
tlvsToMap: () => tlvsToMap,
|
|
1060
1264
|
validateTLVsAgainstSchema: () => validateTLVsAgainstSchema
|
|
1061
1265
|
});
|
|
1062
|
-
import { createHash as
|
|
1266
|
+
import { createHash as createHash3 } from "crypto";
|
|
1063
1267
|
var DEFAULT_LIMITS = {
|
|
1064
1268
|
maxVarintBytes: 10,
|
|
1065
1269
|
maxTlvCount: 512,
|
|
@@ -1109,7 +1313,7 @@ function decodeU64BE(buf) {
|
|
|
1109
1313
|
return buf.readBigUInt64BE(0);
|
|
1110
1314
|
}
|
|
1111
1315
|
function sha2562(data) {
|
|
1112
|
-
return
|
|
1316
|
+
return createHash3("sha256").update(data).digest();
|
|
1113
1317
|
}
|
|
1114
1318
|
function encodeTLV(tag, value) {
|
|
1115
1319
|
if (!Number.isInteger(tag) || tag <= 0)
|
|
@@ -2272,9 +2476,9 @@ function isAdminOpcode(op) {
|
|
|
2272
2476
|
}
|
|
2273
2477
|
|
|
2274
2478
|
// src/core/receipt.ts
|
|
2275
|
-
import { createHash as
|
|
2479
|
+
import { createHash as createHash4 } from "crypto";
|
|
2276
2480
|
function buildReceiptHash(prevHash, pid, actorId, intent, effect, ts) {
|
|
2277
|
-
const h =
|
|
2481
|
+
const h = createHash4("sha256");
|
|
2278
2482
|
if (prevHash) h.update(prevHash);
|
|
2279
2483
|
h.update(pid);
|
|
2280
2484
|
h.update(Buffer.from(actorId, "utf8"));
|
|
@@ -3109,6 +3313,7 @@ __export(engine_exports, {
|
|
|
3109
3313
|
createObservation: () => createObservation,
|
|
3110
3314
|
endStage: () => endStage,
|
|
3111
3315
|
finalizeObservation: () => finalizeObservation,
|
|
3316
|
+
observation: () => observation_exports,
|
|
3112
3317
|
recordSensor: () => recordSensor,
|
|
3113
3318
|
startStage: () => startStage
|
|
3114
3319
|
});
|
|
@@ -3395,6 +3600,21 @@ SensorRegistry = __decorateClass([
|
|
|
3395
3600
|
Injectable7()
|
|
3396
3601
|
], SensorRegistry);
|
|
3397
3602
|
|
|
3603
|
+
// src/engine/observation/index.ts
|
|
3604
|
+
var observation_exports = {};
|
|
3605
|
+
__export(observation_exports, {
|
|
3606
|
+
buildQueueMessage: () => buildQueueMessage,
|
|
3607
|
+
buildUnsignedWitness: () => buildUnsignedWitness,
|
|
3608
|
+
canonicalizeObservation: () => canonicalizeObservation,
|
|
3609
|
+
decodeQueueMessage: () => decodeQueueMessage,
|
|
3610
|
+
encodeQueueMessage: () => encodeQueueMessage,
|
|
3611
|
+
hashObservation: () => hashObservation,
|
|
3612
|
+
parseAutoClaimEntries: () => parseAutoClaimEntries,
|
|
3613
|
+
parseStreamEntries: () => parseStreamEntries,
|
|
3614
|
+
stableJsonStringify: () => stableJsonStringify,
|
|
3615
|
+
verifyResponse: () => verifyResponse
|
|
3616
|
+
});
|
|
3617
|
+
|
|
3398
3618
|
// src/loom/index.ts
|
|
3399
3619
|
var loom_exports = {};
|
|
3400
3620
|
__export(loom_exports, {
|
|
@@ -4137,7 +4357,7 @@ CapabilityEnforcementSensor = __decorateClass([
|
|
|
4137
4357
|
|
|
4138
4358
|
// src/sensors/chunk-hash.sensor.ts
|
|
4139
4359
|
import { Injectable as Injectable12 } from "@nestjs/common";
|
|
4140
|
-
import { createHash as
|
|
4360
|
+
import { createHash as createHash7 } from "crypto";
|
|
4141
4361
|
var ChunkHashSensor = class {
|
|
4142
4362
|
constructor() {
|
|
4143
4363
|
/** Sensor identifier */
|
|
@@ -4196,7 +4416,7 @@ var ChunkHashSensor = class {
|
|
|
4196
4416
|
reason: "Missing sha256Chunk TLV in header"
|
|
4197
4417
|
};
|
|
4198
4418
|
}
|
|
4199
|
-
const actual =
|
|
4419
|
+
const actual = createHash7("sha256").update(bodyBytes).digest();
|
|
4200
4420
|
if (!Buffer.from(actual).equals(Buffer.from(expected))) {
|
|
4201
4421
|
return {
|
|
4202
4422
|
action: "DENY",
|
|
@@ -5627,12 +5847,15 @@ export {
|
|
|
5627
5847
|
buildAts1Hdr,
|
|
5628
5848
|
buildDtoDecoder,
|
|
5629
5849
|
buildPacket,
|
|
5850
|
+
buildQueueMessage,
|
|
5630
5851
|
buildReceiptHash,
|
|
5631
5852
|
buildTLVs,
|
|
5853
|
+
buildUnsignedWitness,
|
|
5632
5854
|
bytes,
|
|
5633
5855
|
canAccessResource,
|
|
5634
5856
|
canonicalJson,
|
|
5635
5857
|
canonicalJsonExcluding,
|
|
5858
|
+
canonicalizeObservation,
|
|
5636
5859
|
classifyIntent,
|
|
5637
5860
|
computeReceiptHash,
|
|
5638
5861
|
computeSignaturePayload,
|
|
@@ -5642,6 +5865,7 @@ export {
|
|
|
5642
5865
|
decodeAxis1Frame,
|
|
5643
5866
|
decodeFrame,
|
|
5644
5867
|
decodeObject,
|
|
5868
|
+
decodeQueueMessage,
|
|
5645
5869
|
decodeTLVs,
|
|
5646
5870
|
decodeTLVsList,
|
|
5647
5871
|
decodeVarint,
|
|
@@ -5649,6 +5873,7 @@ export {
|
|
|
5649
5873
|
encVarint,
|
|
5650
5874
|
encodeAxis1Frame,
|
|
5651
5875
|
encodeFrame,
|
|
5876
|
+
encodeQueueMessage,
|
|
5652
5877
|
encodeTLVs,
|
|
5653
5878
|
encodeVarint,
|
|
5654
5879
|
engine_exports as engine,
|
|
@@ -5656,6 +5881,7 @@ export {
|
|
|
5656
5881
|
generateEd25519KeyPair,
|
|
5657
5882
|
getSignTarget,
|
|
5658
5883
|
hasScope,
|
|
5884
|
+
hashObservation,
|
|
5659
5885
|
isAdminOpcode,
|
|
5660
5886
|
isKnownOpcode,
|
|
5661
5887
|
isTimestampValid,
|
|
@@ -5667,7 +5893,9 @@ export {
|
|
|
5667
5893
|
packPasskeyLoginVerifyReq,
|
|
5668
5894
|
packPasskeyLoginVerifyRes,
|
|
5669
5895
|
packPasskeyRegisterOptionsReq,
|
|
5896
|
+
parseAutoClaimEntries,
|
|
5670
5897
|
parseScope,
|
|
5898
|
+
parseStreamEntries,
|
|
5671
5899
|
resolveTimeout,
|
|
5672
5900
|
schemas_exports as schemas,
|
|
5673
5901
|
security_exports as security,
|
|
@@ -5675,6 +5903,7 @@ export {
|
|
|
5675
5903
|
sensors_exports as sensors,
|
|
5676
5904
|
sha256,
|
|
5677
5905
|
signFrame,
|
|
5906
|
+
stableJsonStringify,
|
|
5678
5907
|
tlv,
|
|
5679
5908
|
u64be,
|
|
5680
5909
|
unpackPasskeyLoginOptionsReq,
|
|
@@ -5685,6 +5914,7 @@ export {
|
|
|
5685
5914
|
validateFrameShape,
|
|
5686
5915
|
varintLength,
|
|
5687
5916
|
varintU,
|
|
5688
|
-
verifyFrameSignature
|
|
5917
|
+
verifyFrameSignature,
|
|
5918
|
+
verifyResponse
|
|
5689
5919
|
};
|
|
5690
5920
|
//# sourceMappingURL=index.mjs.map
|