@nextera.one/axis-server-sdk 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -47,14 +47,21 @@ __export(index_exports, {
47
47
  AXIS_UPLOAD_SESSION_STORE: () => AXIS_UPLOAD_SESSION_STORE,
48
48
  AXIS_VERSION: () => import_axis_protocol2.AXIS_VERSION,
49
49
  Ats1Codec: () => ats1_exports,
50
+ AxisContext: () => AxisContext,
51
+ AxisDemoPubkey: () => AxisDemoPubkey,
52
+ AxisError: () => AxisError,
50
53
  AxisFilesDownloadHandler: () => AxisFilesDownloadHandler,
51
54
  AxisFilesFinalizeHandler: () => AxisFilesFinalizeHandler,
52
55
  AxisFrameZ: () => AxisFrameZ,
53
56
  AxisIdDto: () => AxisIdDto,
57
+ AxisIp: () => AxisIp,
54
58
  AxisPacketTags: () => T,
55
59
  AxisPartialType: () => AxisPartialType,
60
+ AxisRaw: () => AxisRaw,
56
61
  AxisResponseDto: () => AxisResponseDto,
62
+ AxisSensorChainService: () => AxisSensorChainService,
57
63
  AxisTlvDto: () => AxisTlvDto,
64
+ BAND: () => BAND,
58
65
  BodyProfile: () => import_axis_protocol2.BodyProfile,
59
66
  CAPABILITIES: () => CAPABILITIES,
60
67
  ContractViolationError: () => ContractViolationError,
@@ -72,7 +79,10 @@ __export(index_exports, {
72
79
  FLAG_CHAIN_REQ: () => import_axis_protocol2.FLAG_CHAIN_REQ,
73
80
  FLAG_HAS_WITNESS: () => import_axis_protocol2.FLAG_HAS_WITNESS,
74
81
  HANDLER_METADATA_KEY: () => HANDLER_METADATA_KEY,
82
+ HANDLER_SENSORS_KEY: () => HANDLER_SENSORS_KEY,
75
83
  Handler: () => Handler,
84
+ HandlerDiscoveryService: () => HandlerDiscoveryService,
85
+ HandlerSensors: () => HandlerSensors,
76
86
  INTENT_BODY_KEY: () => INTENT_BODY_KEY,
77
87
  INTENT_METADATA_KEY: () => INTENT_METADATA_KEY,
78
88
  INTENT_REQUIREMENTS: () => INTENT_REQUIREMENTS,
@@ -99,6 +109,7 @@ __export(index_exports, {
99
109
  NCERT_PUB: () => import_axis_protocol2.NCERT_PUB,
100
110
  NCERT_SCOPE: () => import_axis_protocol2.NCERT_SCOPE,
101
111
  NCERT_SIG: () => import_axis_protocol2.NCERT_SIG,
112
+ PRE_DECODE_BOUNDARY: () => PRE_DECODE_BOUNDARY,
102
113
  PROOF_CAPABILITIES: () => PROOF_CAPABILITIES,
103
114
  PROOF_CAPSULE: () => import_axis_protocol2.PROOF_CAPSULE,
104
115
  PROOF_JWT: () => import_axis_protocol2.PROOF_JWT,
@@ -113,11 +124,15 @@ __export(index_exports, {
113
124
  RESPONSE_TAG_UPDATED_AT: () => RESPONSE_TAG_UPDATED_AT,
114
125
  RESPONSE_TAG_UPDATED_BY: () => RESPONSE_TAG_UPDATED_BY,
115
126
  RiskDecision: () => RiskDecision,
127
+ SENSOR_METADATA_KEY: () => SENSOR_METADATA_KEY,
116
128
  Schema2002_PasskeyLoginOptionsRes: () => Schema2002_PasskeyLoginOptionsRes,
117
129
  Schema2011_PasskeyLoginVerifyReq: () => Schema2011_PasskeyLoginVerifyReq,
118
130
  Schema2012_PasskeyLoginVerifyRes: () => Schema2012_PasskeyLoginVerifyRes,
119
131
  Schema2021_PasskeyRegisterOptionsReq: () => Schema2021_PasskeyRegisterOptionsReq,
132
+ Sensor: () => Sensor,
120
133
  SensorDecisions: () => SensorDecisions,
134
+ SensorDiscoveryService: () => SensorDiscoveryService,
135
+ SensorRegistry: () => SensorRegistry,
121
136
  TLV: () => import_axis_protocol.TLV,
122
137
  TLV_ACTOR_ID: () => import_axis_protocol2.TLV_ACTOR_ID,
123
138
  TLV_AUD: () => import_axis_protocol2.TLV_AUD,
@@ -179,6 +194,7 @@ __export(index_exports, {
179
194
  computeReceiptHash: () => computeReceiptHash,
180
195
  computeSignaturePayload: () => computeSignaturePayload,
181
196
  core: () => core_exports,
197
+ createObservation: () => createObservation,
182
198
  crypto: () => crypto_exports,
183
199
  decodeArray: () => import_axis_protocol.decodeArray,
184
200
  decodeAxis1Frame: () => decodeAxis1Frame,
@@ -195,8 +211,10 @@ __export(index_exports, {
195
211
  encodeQueueMessage: () => encodeQueueMessage,
196
212
  encodeTLVs: () => import_axis_protocol.encodeTLVs,
197
213
  encodeVarint: () => import_axis_protocol3.encodeVarint,
214
+ endStage: () => endStage,
198
215
  engine: () => engine_exports,
199
216
  extractDtoSchema: () => extractDtoSchema,
217
+ finalizeObservation: () => finalizeObservation,
200
218
  generateEd25519KeyPair: () => generateEd25519KeyPair,
201
219
  getSignTarget: () => getSignTarget,
202
220
  hasScope: () => hasScope,
@@ -215,6 +233,7 @@ __export(index_exports, {
215
233
  parseAutoClaimEntries: () => parseAutoClaimEntries,
216
234
  parseScope: () => parseScope,
217
235
  parseStreamEntries: () => parseStreamEntries,
236
+ recordSensor: () => recordSensor,
218
237
  resolveTimeout: () => resolveTimeout,
219
238
  schemas: () => schemas_exports,
220
239
  security: () => security_exports,
@@ -223,6 +242,7 @@ __export(index_exports, {
223
242
  sha256: () => sha256,
224
243
  signFrame: () => signFrame,
225
244
  stableJsonStringify: () => stableJsonStringify,
245
+ startStage: () => startStage,
226
246
  tlv: () => tlv,
227
247
  u64be: () => u64be,
228
248
  unpackPasskeyLoginOptionsReq: () => unpackPasskeyLoginOptionsReq,
@@ -293,8 +313,24 @@ function IntentSensors(sensors) {
293
313
  };
294
314
  }
295
315
 
296
- // src/decorators/tlv-field.decorator.ts
316
+ // src/decorators/handler-sensors.decorator.ts
297
317
  var import_reflect_metadata4 = require("reflect-metadata");
318
+ var HANDLER_SENSORS_KEY = "axis:handler:sensors";
319
+ function HandlerSensors(sensors) {
320
+ return (target) => {
321
+ Reflect.defineMetadata(HANDLER_SENSORS_KEY, sensors, target);
322
+ };
323
+ }
324
+
325
+ // src/decorators/sensor.decorator.ts
326
+ var import_common2 = require("@nestjs/common");
327
+ var SENSOR_METADATA_KEY = "axis:sensor";
328
+ function Sensor(options) {
329
+ return (0, import_common2.SetMetadata)(SENSOR_METADATA_KEY, options ?? true);
330
+ }
331
+
332
+ // src/decorators/tlv-field.decorator.ts
333
+ var import_reflect_metadata5 = require("reflect-metadata");
298
334
  var TLV_FIELDS_KEY = "axis:tlv:fields";
299
335
  var TLV_VALIDATORS_KEY = "axis:tlv:validators";
300
336
  function TlvField(tag, options) {
@@ -352,7 +388,7 @@ function TlvRange(min, max, message) {
352
388
  }
353
389
 
354
390
  // src/decorators/dto-schema.util.ts
355
- var import_reflect_metadata5 = require("reflect-metadata");
391
+ var import_reflect_metadata6 = require("reflect-metadata");
356
392
 
357
393
  // src/core/tlv.ts
358
394
  var import_axis_protocol = require("@nextera.one/axis-protocol");
@@ -453,7 +489,7 @@ __decorateClass([
453
489
  ], AxisIdDto.prototype, "id", 2);
454
490
 
455
491
  // src/base/axis-partial-type.ts
456
- var import_reflect_metadata6 = require("reflect-metadata");
492
+ var import_reflect_metadata7 = require("reflect-metadata");
457
493
  function AxisPartialType(BaseDto) {
458
494
  class PartialDto extends BaseDto {
459
495
  }
@@ -499,7 +535,7 @@ __decorateClass([
499
535
  ], AxisResponseDto.prototype, "updated_by", 2);
500
536
 
501
537
  // src/engine/intent.router.ts
502
- var import_common2 = require("@nestjs/common");
538
+ var import_common3 = require("@nestjs/common");
503
539
 
504
540
  // src/sensor/axis-sensor.ts
505
541
  var Decision = /* @__PURE__ */ ((Decision2) => {
@@ -604,7 +640,7 @@ var SensorDecisions = {
604
640
  var IntentRouter = class {
605
641
  constructor(moduleRef) {
606
642
  this.moduleRef = moduleRef;
607
- this.logger = new import_common2.Logger(IntentRouter.name);
643
+ this.logger = new import_common3.Logger(IntentRouter.name);
608
644
  /** Internal registry of dynamic intent handlers */
609
645
  this.handlers = /* @__PURE__ */ new Map();
610
646
  /** Per-intent sensor classes (resolved at call time) */
@@ -666,6 +702,7 @@ var IntentRouter = class {
666
702
  );
667
703
  const prefix = handlerMeta?.intent || instance.name;
668
704
  const routes = Reflect.getMetadata(INTENT_ROUTES_KEY, instance.constructor) || [];
705
+ const handlerSensors = Reflect.getMetadata(HANDLER_SENSORS_KEY, instance.constructor) || [];
669
706
  for (const route of routes) {
670
707
  const intentName = route.absolute ? route.action : `${prefix}.${route.action}`;
671
708
  const fn = instance[route.methodName].bind(instance);
@@ -674,7 +711,12 @@ var IntentRouter = class {
674
711
  } else {
675
712
  this.register(intentName, fn);
676
713
  }
677
- this.registerIntentMeta(intentName, Object.getPrototypeOf(instance), String(route.methodName));
714
+ this.registerIntentMeta(
715
+ intentName,
716
+ Object.getPrototypeOf(instance),
717
+ String(route.methodName),
718
+ handlerSensors
719
+ );
678
720
  }
679
721
  const proto = Object.getPrototypeOf(instance);
680
722
  for (const key of Object.getOwnPropertyNames(proto)) {
@@ -683,7 +725,7 @@ var IntentRouter = class {
683
725
  if (!this.handlers.has(meta.intent)) {
684
726
  this.register(meta.intent, instance[key].bind(instance));
685
727
  }
686
- this.registerIntentMeta(meta.intent, proto, key);
728
+ this.registerIntentMeta(meta.intent, proto, key, handlerSensors);
687
729
  }
688
730
  }
689
731
  /**
@@ -819,14 +861,22 @@ var IntentRouter = class {
819
861
  this.logger.warn(`${intent} failed in ${ms}ms - ${error}`);
820
862
  }
821
863
  }
822
- registerIntentMeta(intent, proto, methodName) {
864
+ registerIntentMeta(intent, proto, methodName, handlerSensors) {
823
865
  const decoder = Reflect.getMetadata(INTENT_BODY_KEY, proto, methodName);
824
866
  if (decoder) {
825
867
  this.intentDecoders.set(intent, decoder);
826
868
  }
827
- const sensors = Reflect.getMetadata(INTENT_SENSORS_KEY, proto, methodName);
828
- if (sensors && Array.isArray(sensors) && sensors.length > 0) {
829
- this.intentSensors.set(intent, sensors);
869
+ const intentSensors = Reflect.getMetadata(
870
+ INTENT_SENSORS_KEY,
871
+ proto,
872
+ methodName
873
+ );
874
+ const combined = [
875
+ ...handlerSensors || [],
876
+ ...Array.isArray(intentSensors) ? intentSensors : []
877
+ ];
878
+ if (combined.length > 0) {
879
+ this.intentSensors.set(intent, combined);
830
880
  }
831
881
  const meta = Reflect.getMetadata(INTENT_METADATA_KEY, proto, methodName);
832
882
  if (meta) {
@@ -925,10 +975,27 @@ IntentRouter.BUILTIN_INTENTS = /* @__PURE__ */ new Set([
925
975
  "axis.intent.exec"
926
976
  ]);
927
977
  IntentRouter = __decorateClass([
928
- (0, import_common2.Injectable)(),
929
- __decorateParam(0, (0, import_common2.Optional)())
978
+ (0, import_common3.Injectable)(),
979
+ __decorateParam(0, (0, import_common3.Optional)())
930
980
  ], IntentRouter);
931
981
 
982
+ // src/engine/sensor-bands.ts
983
+ var BAND = {
984
+ /** Pre-decode: raw byte validation, geo, budget, magic */
985
+ WIRE: 0,
986
+ /** Post-decode: identity resolution, capsule, proof */
987
+ IDENTITY: 40,
988
+ /** Post-decode: authorization, signature, rate limiting */
989
+ POLICY: 90,
990
+ /** Post-decode: content validation, TLV, schema, files */
991
+ CONTENT: 140,
992
+ /** Post-decode: business logic sensors, streams, WS */
993
+ BUSINESS: 200,
994
+ /** Post-decode: audit, logging (always last) */
995
+ AUDIT: 900
996
+ };
997
+ var PRE_DECODE_BOUNDARY = 40;
998
+
932
999
  // src/engine/observation/stable-json.ts
933
1000
  function normalize(value) {
934
1001
  if (Array.isArray(value)) {
@@ -2805,7 +2872,7 @@ function isTimestampValid(ts, skewSeconds = 120) {
2805
2872
  }
2806
2873
 
2807
2874
  // src/upload/axis-files.handlers.ts
2808
- var import_common3 = require("@nestjs/common");
2875
+ var import_common4 = require("@nestjs/common");
2809
2876
  var crypto2 = __toESM(require("crypto"));
2810
2877
 
2811
2878
  // src/upload/upload.tokens.ts
@@ -2818,7 +2885,7 @@ var AxisFilesDownloadHandler = class {
2818
2885
  constructor(sessions, files) {
2819
2886
  this.sessions = sessions;
2820
2887
  this.files = files;
2821
- this.logger = new import_common3.Logger(AxisFilesDownloadHandler.name);
2888
+ this.logger = new import_common4.Logger(AxisFilesDownloadHandler.name);
2822
2889
  this.name = "axis.files.download";
2823
2890
  this.open = true;
2824
2891
  this.description = "File download handler";
@@ -2883,16 +2950,16 @@ __decorateClass([
2883
2950
  ], AxisFilesDownloadHandler.prototype, "execute", 1);
2884
2951
  AxisFilesDownloadHandler = __decorateClass([
2885
2952
  Handler("axis.files.download"),
2886
- (0, import_common3.Injectable)(),
2887
- __decorateParam(0, (0, import_common3.Inject)(AXIS_UPLOAD_SESSION_STORE)),
2888
- __decorateParam(1, (0, import_common3.Inject)(AXIS_UPLOAD_FILE_STORE))
2953
+ (0, import_common4.Injectable)(),
2954
+ __decorateParam(0, (0, import_common4.Inject)(AXIS_UPLOAD_SESSION_STORE)),
2955
+ __decorateParam(1, (0, import_common4.Inject)(AXIS_UPLOAD_FILE_STORE))
2889
2956
  ], AxisFilesDownloadHandler);
2890
2957
  var AxisFilesFinalizeHandler = class {
2891
2958
  constructor(sessions, files, keyring) {
2892
2959
  this.sessions = sessions;
2893
2960
  this.files = files;
2894
2961
  this.keyring = keyring;
2895
- this.logger = new import_common3.Logger(AxisFilesFinalizeHandler.name);
2962
+ this.logger = new import_common4.Logger(AxisFilesFinalizeHandler.name);
2896
2963
  this.name = "axis.files.finalize";
2897
2964
  this.open = false;
2898
2965
  this.description = "File upload finalization handler";
@@ -2968,11 +3035,11 @@ __decorateClass([
2968
3035
  ], AxisFilesFinalizeHandler.prototype, "execute", 1);
2969
3036
  AxisFilesFinalizeHandler = __decorateClass([
2970
3037
  Handler("axis.files.finalize"),
2971
- (0, import_common3.Injectable)(),
2972
- __decorateParam(0, (0, import_common3.Inject)(AXIS_UPLOAD_SESSION_STORE)),
2973
- __decorateParam(1, (0, import_common3.Inject)(AXIS_UPLOAD_FILE_STORE)),
2974
- __decorateParam(2, (0, import_common3.Optional)()),
2975
- __decorateParam(2, (0, import_common3.Inject)(AXIS_UPLOAD_RECEIPT_SIGNER))
3038
+ (0, import_common4.Injectable)(),
3039
+ __decorateParam(0, (0, import_common4.Inject)(AXIS_UPLOAD_SESSION_STORE)),
3040
+ __decorateParam(1, (0, import_common4.Inject)(AXIS_UPLOAD_FILE_STORE)),
3041
+ __decorateParam(2, (0, import_common4.Optional)()),
3042
+ __decorateParam(2, (0, import_common4.Inject)(AXIS_UPLOAD_RECEIPT_SIGNER))
2976
3043
  ], AxisFilesFinalizeHandler);
2977
3044
 
2978
3045
  // src/upload/disk-upload-file.store.ts
@@ -3031,92 +3098,54 @@ var DiskUploadFileStore = class {
3031
3098
  }
3032
3099
  };
3033
3100
 
3034
- // src/core/index.ts
3035
- var core_exports = {};
3036
- __export(core_exports, {
3037
- AXIS_MAGIC: () => import_axis_protocol2.AXIS_MAGIC,
3038
- AXIS_VERSION: () => import_axis_protocol2.AXIS_VERSION,
3039
- AxisError: () => AxisError,
3040
- AxisFrameZ: () => AxisFrameZ,
3041
- BodyProfile: () => import_axis_protocol2.BodyProfile,
3042
- ERR_BAD_SIGNATURE: () => import_axis_protocol2.ERR_BAD_SIGNATURE,
3043
- ERR_CONTRACT_VIOLATION: () => import_axis_protocol2.ERR_CONTRACT_VIOLATION,
3044
- ERR_INVALID_PACKET: () => import_axis_protocol2.ERR_INVALID_PACKET,
3045
- ERR_REPLAY_DETECTED: () => import_axis_protocol2.ERR_REPLAY_DETECTED,
3046
- FLAG_BODY_TLV: () => import_axis_protocol2.FLAG_BODY_TLV,
3047
- FLAG_CHAIN_REQ: () => import_axis_protocol2.FLAG_CHAIN_REQ,
3048
- FLAG_HAS_WITNESS: () => import_axis_protocol2.FLAG_HAS_WITNESS,
3049
- MAX_BODY_LEN: () => import_axis_protocol2.MAX_BODY_LEN,
3050
- MAX_FRAME_LEN: () => import_axis_protocol2.MAX_FRAME_LEN,
3051
- MAX_HDR_LEN: () => import_axis_protocol2.MAX_HDR_LEN,
3052
- MAX_SIG_LEN: () => import_axis_protocol2.MAX_SIG_LEN,
3053
- NCERT_ALG: () => import_axis_protocol2.NCERT_ALG,
3054
- NCERT_EXP: () => import_axis_protocol2.NCERT_EXP,
3055
- NCERT_ISSUER_KID: () => import_axis_protocol2.NCERT_ISSUER_KID,
3056
- NCERT_KID: () => import_axis_protocol2.NCERT_KID,
3057
- NCERT_NBF: () => import_axis_protocol2.NCERT_NBF,
3058
- NCERT_NODE_ID: () => import_axis_protocol2.NCERT_NODE_ID,
3059
- NCERT_PAYLOAD: () => import_axis_protocol2.NCERT_PAYLOAD,
3060
- NCERT_PUB: () => import_axis_protocol2.NCERT_PUB,
3061
- NCERT_SCOPE: () => import_axis_protocol2.NCERT_SCOPE,
3062
- NCERT_SIG: () => import_axis_protocol2.NCERT_SIG,
3063
- PROOF_CAPSULE: () => import_axis_protocol2.PROOF_CAPSULE,
3064
- PROOF_JWT: () => import_axis_protocol2.PROOF_JWT,
3065
- PROOF_LOOM: () => import_axis_protocol2.PROOF_LOOM,
3066
- PROOF_MTLS: () => import_axis_protocol2.PROOF_MTLS,
3067
- PROOF_NONE: () => import_axis_protocol2.PROOF_NONE,
3068
- PROOF_WITNESS: () => import_axis_protocol2.PROOF_WITNESS,
3069
- ProofType: () => import_axis_protocol2.ProofType,
3070
- TLV: () => import_axis_protocol.TLV,
3071
- TLV_ACTOR_ID: () => import_axis_protocol2.TLV_ACTOR_ID,
3072
- TLV_AUD: () => import_axis_protocol2.TLV_AUD,
3073
- TLV_BODY_ARR: () => import_axis_protocol2.TLV_BODY_ARR,
3074
- TLV_BODY_OBJ: () => import_axis_protocol2.TLV_BODY_OBJ,
3075
- TLV_CAPSULE: () => import_axis_protocol2.TLV_CAPSULE,
3076
- TLV_EFFECT: () => import_axis_protocol2.TLV_EFFECT,
3077
- TLV_ERROR_CODE: () => import_axis_protocol2.TLV_ERROR_CODE,
3078
- TLV_ERROR_MSG: () => import_axis_protocol2.TLV_ERROR_MSG,
3079
- TLV_INDEX: () => import_axis_protocol2.TLV_INDEX,
3080
- TLV_INTENT: () => import_axis_protocol2.TLV_INTENT,
3081
- TLV_KID: () => import_axis_protocol2.TLV_KID,
3082
- TLV_LOOM_PRESENCE_ID: () => import_axis_protocol2.TLV_LOOM_PRESENCE_ID,
3083
- TLV_LOOM_THREAD_HASH: () => import_axis_protocol2.TLV_LOOM_THREAD_HASH,
3084
- TLV_LOOM_WRIT: () => import_axis_protocol2.TLV_LOOM_WRIT,
3085
- TLV_NODE: () => import_axis_protocol2.TLV_NODE,
3086
- TLV_NODE_CERT_HASH: () => import_axis_protocol2.TLV_NODE_CERT_HASH,
3087
- TLV_NODE_KID: () => import_axis_protocol2.TLV_NODE_KID,
3088
- TLV_NONCE: () => import_axis_protocol2.TLV_NONCE,
3089
- TLV_OFFSET: () => import_axis_protocol2.TLV_OFFSET,
3090
- TLV_OK: () => import_axis_protocol2.TLV_OK,
3091
- TLV_PID: () => import_axis_protocol2.TLV_PID,
3092
- TLV_PREV_HASH: () => import_axis_protocol2.TLV_PREV_HASH,
3093
- TLV_PROOF_REF: () => import_axis_protocol2.TLV_PROOF_REF,
3094
- TLV_PROOF_TYPE: () => import_axis_protocol2.TLV_PROOF_TYPE,
3095
- TLV_REALM: () => import_axis_protocol2.TLV_REALM,
3096
- TLV_RECEIPT_HASH: () => import_axis_protocol2.TLV_RECEIPT_HASH,
3097
- TLV_RID: () => import_axis_protocol2.TLV_RID,
3098
- TLV_SHA256_CHUNK: () => import_axis_protocol2.TLV_SHA256_CHUNK,
3099
- TLV_TRACE_ID: () => import_axis_protocol2.TLV_TRACE_ID,
3100
- TLV_TS: () => import_axis_protocol2.TLV_TS,
3101
- TLV_UPLOAD_ID: () => import_axis_protocol2.TLV_UPLOAD_ID,
3102
- computeReceiptHash: () => computeReceiptHash,
3103
- computeSignaturePayload: () => computeSignaturePayload,
3104
- decodeArray: () => import_axis_protocol.decodeArray,
3105
- decodeFrame: () => decodeFrame,
3106
- decodeObject: () => import_axis_protocol.decodeObject,
3107
- decodeTLVs: () => import_axis_protocol.decodeTLVs,
3108
- decodeTLVsList: () => import_axis_protocol.decodeTLVsList,
3109
- decodeVarint: () => import_axis_protocol3.decodeVarint,
3110
- encodeFrame: () => encodeFrame,
3111
- encodeTLVs: () => import_axis_protocol.encodeTLVs,
3112
- encodeVarint: () => import_axis_protocol3.encodeVarint,
3113
- generateEd25519KeyPair: () => generateEd25519KeyPair,
3114
- getSignTarget: () => getSignTarget,
3115
- sha256: () => sha256,
3116
- signFrame: () => signFrame,
3117
- varintLength: () => import_axis_protocol3.varintLength,
3118
- verifyFrameSignature: () => verifyFrameSignature
3119
- });
3101
+ // src/decorators/axis-request.decorator.ts
3102
+ var import_common5 = require("@nestjs/common");
3103
+ function resolveIp(req) {
3104
+ return req.headers["x-forwarded-for"]?.split(",")[0]?.trim() || req.headers["x-real-ip"] || req.socket.remoteAddress || void 0;
3105
+ }
3106
+ var AxisRaw = (0, import_common5.createParamDecorator)(
3107
+ (_data, ctx) => {
3108
+ const req = ctx.switchToHttp().getRequest();
3109
+ return req.body;
3110
+ }
3111
+ );
3112
+ var AxisIp = (0, import_common5.createParamDecorator)(
3113
+ (_data, ctx) => {
3114
+ const req = ctx.switchToHttp().getRequest();
3115
+ return resolveIp(req);
3116
+ }
3117
+ );
3118
+ var AxisContext = (0, import_common5.createParamDecorator)(
3119
+ (_data, ctx) => {
3120
+ const req = ctx.switchToHttp().getRequest();
3121
+ const axisData = req.axis || {};
3122
+ return {
3123
+ raw: req.body,
3124
+ ip: resolveIp(req),
3125
+ preDecodeInput: axisData.preDecodeInput,
3126
+ frameBytesCount: axisData.frameBytesCount || 0
3127
+ };
3128
+ }
3129
+ );
3130
+ var AxisDemoPubkey = (0, import_common5.createParamDecorator)(
3131
+ (_data, ctx) => {
3132
+ if (process.env.NODE_ENV !== "development") return void 0;
3133
+ const req = ctx.switchToHttp().getRequest();
3134
+ return req.headers["x-demo-pubkey"];
3135
+ }
3136
+ );
3137
+ var AxisFrame3 = (0, import_common5.createParamDecorator)(
3138
+ (_data, ctx) => {
3139
+ const req = ctx.switchToHttp().getRequest();
3140
+ const decoded = req.axisDecoded;
3141
+ if (!decoded) {
3142
+ throw new Error(
3143
+ "@AxisFrame() requires AxisDecodeInterceptor on the route. Add @UseInterceptors(AxisDecodeInterceptor) to use this decorator."
3144
+ );
3145
+ }
3146
+ return decoded;
3147
+ }
3148
+ );
3120
3149
 
3121
3150
  // src/core/axis-error.ts
3122
3151
  var AxisError = class extends Error {
@@ -3129,342 +3158,240 @@ var AxisError = class extends Error {
3129
3158
  }
3130
3159
  };
3131
3160
 
3132
- // src/crypto/index.ts
3133
- var crypto_exports = {};
3134
- __export(crypto_exports, {
3135
- ProofVerificationService: () => ProofVerificationService,
3136
- b64urlDecode: () => b64urlDecode,
3137
- b64urlDecodeString: () => b64urlDecodeString,
3138
- b64urlEncode: () => b64urlEncode,
3139
- b64urlEncodeString: () => b64urlEncodeString,
3140
- canonicalJson: () => canonicalJson,
3141
- canonicalJsonExcluding: () => canonicalJsonExcluding
3142
- });
3143
-
3144
- // src/crypto/proof-verification.service.ts
3145
- var import_common4 = require("@nestjs/common");
3146
- var crypto3 = __toESM(require("crypto"));
3147
- var nacl = __toESM(require("tweetnacl"));
3148
- var ProofVerificationService = class {
3149
- constructor() {
3150
- this.logger = new import_common4.Logger(ProofVerificationService.name);
3151
- // Cache of registered device public keys (deviceId -> pubKey)
3152
- this.deviceKeys = /* @__PURE__ */ new Map();
3153
- // Cache of trusted mTLS certificate fingerprints
3154
- this.trustedCerts = /* @__PURE__ */ new Map();
3161
+ // src/engine/handler-discovery.service.ts
3162
+ var import_common6 = require("@nestjs/common");
3163
+ var HandlerDiscoveryService = class {
3164
+ constructor(discovery, scanner, router) {
3165
+ this.discovery = discovery;
3166
+ this.scanner = scanner;
3167
+ this.router = router;
3168
+ this.logger = new import_common6.Logger(HandlerDiscoveryService.name);
3155
3169
  }
3156
- /**
3157
- * Verifies an authentication proof based on its type.
3158
- *
3159
- * **Supported Types:**
3160
- * - 1 (CAPSULE): Delegated to `verifyCapsuleProof`
3161
- * - 2 (JWT): Verified by `verifyJWTProof`
3162
- * - 3 (MTLS_ID): Verified by `verifyMTLSProof`
3163
- * - 4 (DEVICE_SE): Verified by `verifyDeviceSEProof`
3164
- *
3165
- * @param {ProofType} proofType - The numeric AXIS proof type
3166
- * @param {Uint8Array} proofRef - The binary reference or token for the proof
3167
- * @param {Object} context - Additional metadata required for specific proof types
3168
- * @param {Uint8Array} [context.signTarget] - The canonical bytes that were signed (for Ed25519)
3169
- * @param {Uint8Array} [context.signature] - The signature to verify (for Ed25519)
3170
- * @param {MTLSContext} [context.mtls] - mTLS certificate data
3171
- * @param {DeviceSEContext} [context.deviceSE] - Device Secure Element information
3172
- * @returns {Promise<ProofVerificationResult>} The outcome of the verification
3173
- */
3174
- async verifyProof(proofType, proofRef, context) {
3175
- switch (proofType) {
3176
- case 1:
3177
- return this.verifyCapsuleProof(proofRef);
3178
- case 2:
3179
- return this.verifyJWTProof(proofRef);
3180
- case 3:
3181
- return this.verifyMTLSProof(context.mtls);
3182
- case 4:
3183
- return this.verifyDeviceSEProof(
3184
- context.signTarget,
3185
- context.signature,
3186
- context.deviceSE
3187
- );
3188
- default:
3189
- return { valid: false, error: `Unknown proof type: ${proofType}` };
3170
+ onModuleInit() {
3171
+ const providers = this.discovery.getProviders();
3172
+ let totalIntents = 0;
3173
+ for (const wrapper of providers) {
3174
+ const { instance, metatype } = wrapper;
3175
+ if (!instance || !metatype) continue;
3176
+ const handlerMeta = Reflect.getMetadata(HANDLER_METADATA_KEY, metatype);
3177
+ if (!handlerMeta) continue;
3178
+ const handlerName = handlerMeta.intent || metatype.name;
3179
+ const proto = Object.getPrototypeOf(instance);
3180
+ const methods = this.scanner.getAllMethodNames(proto);
3181
+ let registered = 0;
3182
+ const handlerSensors = Reflect.getMetadata(HANDLER_SENSORS_KEY, metatype) || [];
3183
+ for (const methodName of methods) {
3184
+ const meta = Reflect.getMetadata(
3185
+ INTENT_METADATA_KEY,
3186
+ proto,
3187
+ methodName
3188
+ );
3189
+ if (!meta?.intent) continue;
3190
+ if (!this.router.has(meta.intent)) {
3191
+ this.router.register(
3192
+ meta.intent,
3193
+ instance[methodName].bind(instance)
3194
+ );
3195
+ registered++;
3196
+ totalIntents++;
3197
+ }
3198
+ this.router.registerIntentMeta(
3199
+ meta.intent,
3200
+ proto,
3201
+ methodName,
3202
+ handlerSensors
3203
+ );
3204
+ }
3205
+ if (registered > 0) {
3206
+ this.logger.log(
3207
+ `Auto-registered ${registered} intents from ${handlerName}`
3208
+ );
3209
+ }
3190
3210
  }
3211
+ this.logger.log(
3212
+ `Handler discovery complete: ${totalIntents} intents auto-registered`
3213
+ );
3191
3214
  }
3192
- /**
3193
- * Verify CAPSULE proof (delegated to CapsuleService)
3194
- */
3195
- async verifyCapsuleProof(proofRef) {
3196
- const capsuleId = new TextDecoder().decode(proofRef);
3197
- return {
3198
- valid: true,
3199
- metadata: { capsuleId, requiresCapsuleValidation: true }
3200
- };
3215
+ };
3216
+ HandlerDiscoveryService = __decorateClass([
3217
+ (0, import_common6.Injectable)()
3218
+ ], HandlerDiscoveryService);
3219
+
3220
+ // src/engine/sensor-discovery.service.ts
3221
+ var import_common7 = require("@nestjs/common");
3222
+ var SensorDiscoveryService = class {
3223
+ constructor(discovery, reflector, registry) {
3224
+ this.discovery = discovery;
3225
+ this.reflector = reflector;
3226
+ this.registry = registry;
3227
+ this.logger = new import_common7.Logger(SensorDiscoveryService.name);
3201
3228
  }
3202
- /**
3203
- * Verifies a JSON Web Token (JWT) proof.
3204
- *
3205
- * **Validation Logic:**
3206
- * 1. Decodes the token string.
3207
- * 2. Checks for valid 3-part JWT structure.
3208
- * 3. Validates `exp` (expiration) and `nbf` (not before) claims.
3209
- * 4. Extracts `actor_id` or `sub` as the identity.
3210
- *
3211
- * @param {Uint8Array} proofRef - Binary representation of the JWT string
3212
- * @returns {Promise<ProofVerificationResult>} Result including the actor identifier
3213
- */
3214
- async verifyJWTProof(proofRef) {
3215
- try {
3216
- const token = new TextDecoder().decode(proofRef);
3217
- const parts = token.split(".");
3218
- if (parts.length !== 3) {
3219
- return { valid: false, error: "Invalid JWT format" };
3220
- }
3221
- const header = JSON.parse(Buffer.from(parts[0], "base64url").toString());
3222
- const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString());
3223
- if (payload.exp && Date.now() / 1e3 > payload.exp) {
3224
- return { valid: false, error: "JWT expired" };
3229
+ onApplicationBootstrap() {
3230
+ const providers = this.discovery.getProviders();
3231
+ let count = 0;
3232
+ for (const wrapper of providers) {
3233
+ const { instance } = wrapper;
3234
+ if (!instance || !instance.constructor) continue;
3235
+ const meta = this.reflector.get(
3236
+ SENSOR_METADATA_KEY,
3237
+ instance.constructor
3238
+ );
3239
+ if (!meta) continue;
3240
+ const sensor = instance;
3241
+ if (!sensor.name || sensor.order === void 0) {
3242
+ this.logger.warn(
3243
+ `@Sensor() on ${instance.constructor.name} missing name or order \u2014 skipped`
3244
+ );
3245
+ continue;
3225
3246
  }
3226
- if (payload.nbf && Date.now() / 1e3 < payload.nbf) {
3227
- return { valid: false, error: "JWT not yet valid" };
3247
+ if (!sensor.phase) {
3248
+ const decoratorPhase = meta !== true ? meta.phase : void 0;
3249
+ sensor.phase = decoratorPhase ?? (sensor.order < PRE_DECODE_BOUNDARY ? "PRE_DECODE" : "POST_DECODE");
3228
3250
  }
3229
- return {
3230
- valid: true,
3231
- actorId: payload.sub || payload.actor_id,
3232
- metadata: { iss: payload.iss, scope: payload.scope }
3233
- };
3234
- } catch (e) {
3235
- const message = e instanceof Error ? e.message : "Unknown error";
3236
- return { valid: false, error: `JWT parse error: ${message}` };
3251
+ this.registry.register(sensor);
3252
+ count++;
3237
3253
  }
3254
+ this.logger.log(`Auto-registered ${count} sensors via @Sensor()`);
3255
+ }
3256
+ };
3257
+ SensorDiscoveryService = __decorateClass([
3258
+ (0, import_common7.Injectable)()
3259
+ ], SensorDiscoveryService);
3260
+
3261
+ // src/engine/registry/sensor.registry.ts
3262
+ var import_common8 = require("@nestjs/common");
3263
+ var SensorRegistry = class {
3264
+ constructor(configService) {
3265
+ this.configService = configService;
3266
+ this.sensors = [];
3267
+ this.logger = new import_common8.Logger(SensorRegistry.name);
3238
3268
  }
3239
3269
  /**
3240
- * Verify mTLS client certificate proof
3270
+ * Registers a new sensor in the registry.
3271
+ *
3272
+ * Validates that:
3273
+ * - AxisSensor has a unique name
3274
+ * - AxisSensor has an order field
3275
+ * - Pre-decode sensors have order < 40
3276
+ * - Post-decode sensors have order >= 40
3277
+ *
3278
+ * @param {AxisSensor} sensor - The sensor instance to register
3279
+ * @throws Error if validation fails
3241
3280
  */
3242
- async verifyMTLSProof(mtls) {
3243
- if (!mtls) {
3244
- return { valid: false, error: "No mTLS context provided" };
3245
- }
3246
- if (!mtls.verified) {
3247
- return { valid: false, error: "mTLS not verified by TLS terminator" };
3248
- }
3249
- if (mtls.clientCertFingerprint) {
3250
- const trusted = this.trustedCerts.get(mtls.clientCertFingerprint);
3251
- if (trusted) {
3252
- return {
3253
- valid: true,
3254
- actorId: trusted.actorId,
3255
- metadata: {
3256
- fingerprint: mtls.clientCertFingerprint,
3257
- subject: mtls.clientCertSubject
3258
- }
3259
- };
3260
- }
3281
+ register(sensor) {
3282
+ if (!sensor.name) {
3283
+ throw new Error("AxisSensor must have a name");
3261
3284
  }
3262
- if (mtls.clientCertSubject) {
3263
- const cnMatch = mtls.clientCertSubject.match(/CN=([^,]+)/);
3264
- if (cnMatch) {
3265
- return {
3266
- valid: true,
3267
- actorId: cnMatch[1],
3268
- metadata: {
3269
- subject: mtls.clientCertSubject,
3270
- issuer: mtls.clientCertIssuer
3271
- }
3272
- };
3273
- }
3285
+ const enabledSensorsStr = this.configService.get("ENABLED_SENSORS");
3286
+ const disabledSensorsStr = this.configService.get("DISABLED_SENSORS");
3287
+ const enabledSensors = enabledSensorsStr ? enabledSensorsStr.split(",").map((s) => s.trim()) : null;
3288
+ const disabledSensors = disabledSensorsStr ? disabledSensorsStr.split(",").map((s) => s.trim()) : [];
3289
+ if (enabledSensors && !enabledSensors.includes(sensor.name)) {
3290
+ this.logger.log(`Skipping disabled sensor (not in ENABLED_SENSORS): ${sensor.name}`);
3291
+ return;
3274
3292
  }
3275
- return { valid: false, error: "Could not extract actor from certificate" };
3276
- }
3277
- /**
3278
- * Verify Device Secure Element signature
3279
- */
3280
- async verifyDeviceSEProof(signTarget, signature, deviceSE) {
3281
- if (!deviceSE || !signTarget || !signature) {
3282
- return { valid: false, error: "Missing Device SE context" };
3293
+ if (disabledSensors.includes(sensor.name)) {
3294
+ this.logger.log(`Skipping disabled sensor (in DISABLED_SENSORS): ${sensor.name}`);
3295
+ return;
3283
3296
  }
3284
- let publicKey = deviceSE.publicKey;
3285
- const registeredKey = this.deviceKeys.get(deviceSE.deviceId);
3286
- if (registeredKey) {
3287
- publicKey = registeredKey;
3297
+ if (sensor.order === void 0) {
3298
+ throw new Error(`AxisSensor "${sensor.name}" must have an order field`);
3288
3299
  }
3289
- if (!publicKey || publicKey.length !== 32) {
3290
- return {
3291
- valid: false,
3292
- error: "Invalid or unregistered device public key"
3293
- };
3300
+ const isPreDecodeSensor = this.isPreDecodeSensor(sensor);
3301
+ const isPostDecodeSensor = this.isPostDecodeSensor(sensor);
3302
+ if (isPreDecodeSensor && sensor.order >= 40) {
3303
+ this.logger.warn(
3304
+ `AxisSensor "${sensor.name}" is marked as PRE_DECODE but has order ${sensor.order} (should be < 40)`
3305
+ );
3294
3306
  }
3295
- try {
3296
- const valid = nacl.sign.detached.verify(signTarget, signature, publicKey);
3297
- if (!valid) {
3298
- return { valid: false, error: "Device signature verification failed" };
3299
- }
3300
- return {
3301
- valid: true,
3302
- actorId: deviceSE.deviceId,
3303
- metadata: { deviceId: deviceSE.deviceId, proofType: "DEVICE_SE" }
3304
- };
3305
- } catch (e) {
3306
- const message = e instanceof Error ? e.message : "Unknown error";
3307
- return {
3308
- valid: false,
3309
- error: `Signature verification error: ${message}`
3310
- };
3307
+ if (isPostDecodeSensor && sensor.order < 40) {
3308
+ this.logger.warn(
3309
+ `AxisSensor "${sensor.name}" is marked as POST_DECODE but has order ${sensor.order} (should be >= 40)`
3310
+ );
3311
3311
  }
3312
+ this.sensors.push(sensor);
3313
+ const phaseLabel = typeof sensor.phase === "string" ? sensor.phase : sensor.phase?.phase || "UNKNOWN";
3314
+ this.logger.debug(
3315
+ `Registered sensor: ${sensor.name} (order: ${sensor.order}, phase: ${phaseLabel})`
3316
+ );
3312
3317
  }
3313
3318
  /**
3314
- * Registers a public key for a trusted device.
3315
- * This key will be used for future `DEVICE_SE` proof verifications.
3319
+ * Returns all registered sensors, sorted by their execution order.
3316
3320
  *
3317
- * @param {string} deviceId - Unique identifier for the device
3318
- * @param {Uint8Array} publicKey - 32-byte Ed25519 public key
3319
- * @throws {Error} If the public key is not 32 bytes
3321
+ * @returns {AxisSensor[]} A sorted array of sensors
3320
3322
  */
3321
- registerDeviceKey(deviceId, publicKey) {
3322
- if (publicKey.length !== 32) {
3323
- throw new Error("Device public key must be 32 bytes (Ed25519)");
3324
- }
3325
- this.deviceKeys.set(deviceId, publicKey);
3326
- this.logger.log(`Registered device key for ${deviceId}`);
3323
+ list() {
3324
+ return [...this.sensors].sort(
3325
+ (a, b) => (a.order ?? 999) - (b.order ?? 999)
3326
+ );
3327
3327
  }
3328
3328
  /**
3329
- * Unregister a device
3329
+ * Returns only pre-decode sensors (order < 40).
3330
+ * These sensors run in middleware on raw bytes before frame decoding.
3331
+ *
3332
+ * @returns {AxisPreSensor[]} Pre-decode sensors sorted by order
3330
3333
  */
3331
- unregisterDevice(deviceId) {
3332
- return this.deviceKeys.delete(deviceId);
3333
- }
3334
+ getPreDecodeSensors() {
3335
+ return this.list().filter((s) => (s.order ?? 999) < 40);
3336
+ }
3334
3337
  /**
3335
- * Registers a trusted mTLS certificate fingerprint and associates it with an actor.
3338
+ * Returns only post-decode sensors (order >= 40).
3339
+ * These sensors run in the controller on fully decoded frames.
3336
3340
  *
3337
- * @param {string} fingerprint - SHA-256 fingerprint of the client certificate
3338
- * @param {string} actorId - The actor to associate with this certificate
3341
+ * @returns {AxisPostSensor[]} Post-decode sensors sorted by order
3339
3342
  */
3340
- registerMTLSCert(fingerprint, actorId) {
3341
- this.trustedCerts.set(fingerprint, { actorId, issuedAt: Date.now() });
3342
- this.logger.log(`Registered mTLS cert ${fingerprint} for actor ${actorId}`);
3343
+ getPostDecodeSensors() {
3344
+ return this.list().filter(
3345
+ (s) => (s.order ?? 999) >= 40
3346
+ );
3343
3347
  }
3344
3348
  /**
3345
- * Revoke an mTLS certificate
3349
+ * Helper: Check if a sensor is a pre-decode sensor.
3350
+ *
3351
+ * @private
3352
+ * @param {AxisSensor} sensor - The sensor to check
3353
+ * @returns {boolean} True if sensor is pre-decode
3346
3354
  */
3347
- revokeMTLSCert(fingerprint) {
3348
- return this.trustedCerts.delete(fingerprint);
3355
+ isPreDecodeSensor(sensor) {
3356
+ const phase = typeof sensor.phase === "string" ? sensor.phase : sensor.phase?.phase;
3357
+ return phase === "PRE_DECODE" || (sensor.order ?? 999) < 40;
3349
3358
  }
3350
3359
  /**
3351
- * Calculate certificate fingerprint (SHA-256)
3360
+ * Helper: Check if a sensor is a post-decode sensor.
3361
+ *
3362
+ * @private
3363
+ * @param {AxisSensor} sensor - The sensor to check
3364
+ * @returns {boolean} True if sensor is post-decode
3352
3365
  */
3353
- static calculateFingerprint(certPem) {
3354
- const der = Buffer.from(
3355
- certPem.replace(/-----BEGIN CERTIFICATE-----/, "").replace(/-----END CERTIFICATE-----/, "").replace(/\s/g, ""),
3356
- "base64"
3357
- );
3358
- return crypto3.createHash("sha256").update(der).digest("hex");
3359
- }
3360
- };
3361
- ProofVerificationService = __decorateClass([
3362
- (0, import_common4.Injectable)()
3363
- ], ProofVerificationService);
3364
-
3365
- // src/decorators/index.ts
3366
- var decorators_exports = {};
3367
- __export(decorators_exports, {
3368
- AxisContext: () => AxisContext,
3369
- AxisDemoPubkey: () => AxisDemoPubkey,
3370
- AxisFrame: () => AxisFrame3,
3371
- AxisIp: () => AxisIp,
3372
- AxisRaw: () => AxisRaw,
3373
- HANDLER_METADATA_KEY: () => HANDLER_METADATA_KEY,
3374
- Handler: () => Handler,
3375
- INTENT_BODY_KEY: () => INTENT_BODY_KEY,
3376
- INTENT_METADATA_KEY: () => INTENT_METADATA_KEY,
3377
- INTENT_ROUTES_KEY: () => INTENT_ROUTES_KEY,
3378
- INTENT_SENSORS_KEY: () => INTENT_SENSORS_KEY,
3379
- Intent: () => Intent,
3380
- IntentBody: () => IntentBody,
3381
- IntentSensors: () => IntentSensors,
3382
- SENSOR_METADATA_KEY: () => SENSOR_METADATA_KEY,
3383
- Sensor: () => Sensor,
3384
- TLV_FIELDS_KEY: () => TLV_FIELDS_KEY,
3385
- TLV_VALIDATORS_KEY: () => TLV_VALIDATORS_KEY,
3386
- TlvEnum: () => TlvEnum,
3387
- TlvField: () => TlvField,
3388
- TlvMinLen: () => TlvMinLen,
3389
- TlvRange: () => TlvRange,
3390
- TlvUtf8Pattern: () => TlvUtf8Pattern,
3391
- TlvValidate: () => TlvValidate,
3392
- buildDtoDecoder: () => buildDtoDecoder,
3393
- extractDtoSchema: () => extractDtoSchema
3394
- });
3395
-
3396
- // src/decorators/axis-request.decorator.ts
3397
- var import_common5 = require("@nestjs/common");
3398
- function resolveIp(req) {
3399
- return req.headers["x-forwarded-for"]?.split(",")[0]?.trim() || req.headers["x-real-ip"] || req.socket.remoteAddress || void 0;
3400
- }
3401
- var AxisRaw = (0, import_common5.createParamDecorator)(
3402
- (_data, ctx) => {
3403
- const req = ctx.switchToHttp().getRequest();
3404
- return req.body;
3405
- }
3406
- );
3407
- var AxisIp = (0, import_common5.createParamDecorator)(
3408
- (_data, ctx) => {
3409
- const req = ctx.switchToHttp().getRequest();
3410
- return resolveIp(req);
3366
+ isPostDecodeSensor(sensor) {
3367
+ const phase = typeof sensor.phase === "string" ? sensor.phase : sensor.phase?.phase;
3368
+ return phase === "POST_DECODE" || (sensor.order ?? 999) >= 40;
3411
3369
  }
3412
- );
3413
- var AxisContext = (0, import_common5.createParamDecorator)(
3414
- (_data, ctx) => {
3415
- const req = ctx.switchToHttp().getRequest();
3416
- const axisData = req.axis || {};
3370
+ /**
3371
+ * Returns sensor count by phase.
3372
+ * Useful for diagnostics and monitoring.
3373
+ *
3374
+ * @returns {{preDecodeCount: number, postDecodeCount: number}}
3375
+ */
3376
+ getSensorCountByPhase() {
3417
3377
  return {
3418
- raw: req.body,
3419
- ip: resolveIp(req),
3420
- preDecodeInput: axisData.preDecodeInput,
3421
- frameBytesCount: axisData.frameBytesCount || 0
3378
+ preDecodeCount: this.getPreDecodeSensors().length,
3379
+ postDecodeCount: this.getPostDecodeSensors().length
3422
3380
  };
3423
3381
  }
3424
- );
3425
- var AxisDemoPubkey = (0, import_common5.createParamDecorator)(
3426
- (_data, ctx) => {
3427
- if (process.env.NODE_ENV !== "development") return void 0;
3428
- const req = ctx.switchToHttp().getRequest();
3429
- return req.headers["x-demo-pubkey"];
3430
- }
3431
- );
3432
- var AxisFrame3 = (0, import_common5.createParamDecorator)(
3433
- (_data, ctx) => {
3434
- const req = ctx.switchToHttp().getRequest();
3435
- const decoded = req.axisDecoded;
3436
- if (!decoded) {
3437
- throw new Error(
3438
- "@AxisFrame() requires AxisDecodeInterceptor on the route. Add @UseInterceptors(AxisDecodeInterceptor) to use this decorator."
3439
- );
3440
- }
3441
- return decoded;
3382
+ /**
3383
+ * Clears all registered sensors.
3384
+ * Useful for testing.
3385
+ *
3386
+ * @internal
3387
+ */
3388
+ clear() {
3389
+ this.sensors = [];
3442
3390
  }
3443
- );
3444
-
3445
- // src/decorators/sensor.decorator.ts
3446
- var import_common6 = require("@nestjs/common");
3447
- var SENSOR_METADATA_KEY = "axis:sensor";
3448
- function Sensor(options) {
3449
- return (0, import_common6.SetMetadata)(SENSOR_METADATA_KEY, options ?? true);
3450
- }
3451
-
3452
- // src/engine/index.ts
3453
- var engine_exports = {};
3454
- __export(engine_exports, {
3455
- BAND: () => BAND,
3456
- HandlerDiscoveryService: () => HandlerDiscoveryService,
3457
- IntentRouter: () => IntentRouter,
3458
- PRE_DECODE_BOUNDARY: () => PRE_DECODE_BOUNDARY,
3459
- SensorDiscoveryService: () => SensorDiscoveryService,
3460
- SensorRegistry: () => SensorRegistry,
3461
- createObservation: () => createObservation,
3462
- endStage: () => endStage,
3463
- finalizeObservation: () => finalizeObservation,
3464
- observation: () => observation_exports,
3465
- recordSensor: () => recordSensor,
3466
- startStage: () => startStage
3467
- });
3391
+ };
3392
+ SensorRegistry = __decorateClass([
3393
+ (0, import_common8.Injectable)()
3394
+ ], SensorRegistry);
3468
3395
 
3469
3396
  // src/engine/axis-observation.ts
3470
3397
  var import_crypto5 = require("crypto");
@@ -3502,251 +3429,499 @@ function finalizeObservation(obs, decision, statusCode, resultCode) {
3502
3429
  if (resultCode) obs.resultCode = resultCode;
3503
3430
  }
3504
3431
 
3505
- // src/engine/handler-discovery.service.ts
3506
- var import_common7 = require("@nestjs/common");
3507
- var HandlerDiscoveryService = class {
3508
- constructor(discovery, scanner, router) {
3509
- this.discovery = discovery;
3510
- this.scanner = scanner;
3511
- this.router = router;
3512
- this.logger = new import_common7.Logger(HandlerDiscoveryService.name);
3432
+ // src/security/axis-sensor-chain.service.ts
3433
+ var import_common9 = require("@nestjs/common");
3434
+ var AxisSensorChainService = class {
3435
+ constructor(registry) {
3436
+ this.registry = registry;
3513
3437
  }
3514
- onModuleInit() {
3515
- const providers = this.discovery.getProviders();
3516
- let totalIntents = 0;
3517
- for (const wrapper of providers) {
3518
- const { instance, metatype } = wrapper;
3519
- if (!instance || !metatype) continue;
3520
- const handlerMeta = Reflect.getMetadata(HANDLER_METADATA_KEY, metatype);
3521
- if (!handlerMeta) continue;
3522
- const handlerName = handlerMeta.intent || metatype.name;
3523
- const proto = Object.getPrototypeOf(instance);
3524
- const methods = this.scanner.getAllMethodNames(proto);
3525
- let registered = 0;
3526
- for (const methodName of methods) {
3527
- const meta = Reflect.getMetadata(
3528
- INTENT_METADATA_KEY,
3529
- proto,
3530
- methodName
3531
- );
3532
- if (!meta?.intent) continue;
3533
- if (!this.router.has(meta.intent)) {
3534
- this.router.register(
3535
- meta.intent,
3536
- instance[methodName].bind(instance)
3438
+ /**
3439
+ * Evaluate all applicable sensors based on phase.
3440
+ */
3441
+ async evaluate(input, phase = "POST_DECODE", baseDecision) {
3442
+ if (phase === "PRE_DECODE") {
3443
+ return this.evaluateSensors(this.registry.getPreDecodeSensors(), input);
3444
+ }
3445
+ if (phase === "BOTH") {
3446
+ const rawPreResult = await this.evaluateSensors(
3447
+ this.registry.getPreDecodeSensors(),
3448
+ input
3449
+ );
3450
+ const preResult = normalizeSensorDecision(rawPreResult);
3451
+ if (!preResult.allow) return rawPreResult;
3452
+ return this.evaluateSensors(
3453
+ this.registry.getPostDecodeSensors(),
3454
+ input,
3455
+ rawPreResult
3456
+ );
3457
+ }
3458
+ return this.evaluateSensors(
3459
+ this.registry.getPostDecodeSensors(),
3460
+ input,
3461
+ baseDecision
3462
+ );
3463
+ }
3464
+ /** Run only pre-decode sensors. */
3465
+ async evaluatePre(input) {
3466
+ return this.evaluateSensors(this.registry.getPreDecodeSensors(), input);
3467
+ }
3468
+ /** Run only post-decode sensors. */
3469
+ async evaluatePost(input, baseDecision) {
3470
+ return this.evaluateSensors(
3471
+ this.registry.getPostDecodeSensors(),
3472
+ input,
3473
+ baseDecision
3474
+ );
3475
+ }
3476
+ async evaluateSensors(sensors, input, baseDecision) {
3477
+ const relevantSensors = sensors.filter(
3478
+ (s) => !s.supports || s.supports(input)
3479
+ );
3480
+ const normalizedBase = baseDecision ? normalizeSensorDecision(baseDecision) : void 0;
3481
+ let riskScore = normalizedBase?.riskScore ?? 0;
3482
+ const reasons = normalizedBase?.reasons ? [...normalizedBase.reasons] : [];
3483
+ const tags = normalizedBase?.tags ? { ...normalizedBase.tags } : {};
3484
+ let expSecondsMax = normalizedBase?.tighten?.expSecondsMax;
3485
+ let constraintsPatch = normalizedBase?.tighten?.constraintsPatch ? { ...normalizedBase.tighten.constraintsPatch } : {};
3486
+ for (const sensor of relevantSensors) {
3487
+ try {
3488
+ const t0 = Date.now();
3489
+ const rawDecision = await sensor.run(input);
3490
+ const elapsed = Date.now() - t0;
3491
+ const decision = normalizeSensorDecision(rawDecision);
3492
+ const obs = input.metadata?.observation;
3493
+ if (obs) {
3494
+ recordSensor(
3495
+ obs,
3496
+ sensor.name,
3497
+ decision.allow,
3498
+ decision.riskScore,
3499
+ elapsed,
3500
+ decision.reasons,
3501
+ decision.allow ? void 0 : decision.code
3537
3502
  );
3538
- registered++;
3539
- totalIntents++;
3540
3503
  }
3541
- this.router.registerIntentMeta(meta.intent, proto, methodName);
3542
- }
3543
- if (registered > 0) {
3544
- this.logger.log(
3545
- `Auto-registered ${registered} intents from ${handlerName}`
3546
- );
3504
+ if (!decision.allow) {
3505
+ return {
3506
+ allow: false,
3507
+ riskScore: Math.min(100, riskScore + decision.riskScore),
3508
+ reasons: [...reasons, ...decision.reasons],
3509
+ tags
3510
+ };
3511
+ }
3512
+ riskScore = Math.min(100, riskScore + decision.riskScore);
3513
+ reasons.push(...decision.reasons);
3514
+ if (decision.tags) {
3515
+ Object.assign(tags, decision.tags);
3516
+ }
3517
+ if (decision.tighten?.expSecondsMax !== void 0) {
3518
+ expSecondsMax = expSecondsMax === void 0 ? decision.tighten.expSecondsMax : Math.min(expSecondsMax, decision.tighten.expSecondsMax);
3519
+ }
3520
+ if (decision.tighten?.constraintsPatch) {
3521
+ constraintsPatch = {
3522
+ ...constraintsPatch,
3523
+ ...decision.tighten.constraintsPatch
3524
+ };
3525
+ }
3526
+ } catch (error) {
3527
+ console.error(`[AXIS][SENSOR] ${sensor.name} failed:`, error);
3528
+ const obs = input.metadata?.observation;
3529
+ if (obs) {
3530
+ recordSensor(obs, sensor.name, false, 100, 0, [
3531
+ `sensor_error:${sensor.name}`
3532
+ ]);
3533
+ }
3534
+ return {
3535
+ allow: false,
3536
+ riskScore: 100,
3537
+ reasons: [`sensor_error:${sensor.name}`]
3538
+ };
3547
3539
  }
3548
3540
  }
3549
- this.logger.log(
3550
- `Handler discovery complete: ${totalIntents} intents auto-registered`
3551
- );
3541
+ const tightenPatch = Object.keys(constraintsPatch).length > 0 ? constraintsPatch : void 0;
3542
+ return {
3543
+ allow: true,
3544
+ riskScore,
3545
+ reasons,
3546
+ tags,
3547
+ tighten: expSecondsMax !== void 0 || tightenPatch ? {
3548
+ expSecondsMax,
3549
+ constraintsPatch: tightenPatch
3550
+ } : void 0
3551
+ };
3552
3552
  }
3553
3553
  };
3554
- HandlerDiscoveryService = __decorateClass([
3555
- (0, import_common7.Injectable)()
3556
- ], HandlerDiscoveryService);
3554
+ AxisSensorChainService = __decorateClass([
3555
+ (0, import_common9.Injectable)()
3556
+ ], AxisSensorChainService);
3557
3557
 
3558
- // src/engine/sensor-bands.ts
3559
- var BAND = {
3560
- /** Pre-decode: raw byte validation, geo, budget, magic */
3561
- WIRE: 0,
3562
- /** Post-decode: identity resolution, capsule, proof */
3563
- IDENTITY: 40,
3564
- /** Post-decode: authorization, signature, rate limiting */
3565
- POLICY: 90,
3566
- /** Post-decode: content validation, TLV, schema, files */
3567
- CONTENT: 140,
3568
- /** Post-decode: business logic sensors, streams, WS */
3569
- BUSINESS: 200,
3570
- /** Post-decode: audit, logging (always last) */
3571
- AUDIT: 900
3572
- };
3573
- var PRE_DECODE_BOUNDARY = 40;
3558
+ // src/core/index.ts
3559
+ var core_exports = {};
3560
+ __export(core_exports, {
3561
+ AXIS_MAGIC: () => import_axis_protocol2.AXIS_MAGIC,
3562
+ AXIS_VERSION: () => import_axis_protocol2.AXIS_VERSION,
3563
+ AxisError: () => AxisError,
3564
+ AxisFrameZ: () => AxisFrameZ,
3565
+ BodyProfile: () => import_axis_protocol2.BodyProfile,
3566
+ ERR_BAD_SIGNATURE: () => import_axis_protocol2.ERR_BAD_SIGNATURE,
3567
+ ERR_CONTRACT_VIOLATION: () => import_axis_protocol2.ERR_CONTRACT_VIOLATION,
3568
+ ERR_INVALID_PACKET: () => import_axis_protocol2.ERR_INVALID_PACKET,
3569
+ ERR_REPLAY_DETECTED: () => import_axis_protocol2.ERR_REPLAY_DETECTED,
3570
+ FLAG_BODY_TLV: () => import_axis_protocol2.FLAG_BODY_TLV,
3571
+ FLAG_CHAIN_REQ: () => import_axis_protocol2.FLAG_CHAIN_REQ,
3572
+ FLAG_HAS_WITNESS: () => import_axis_protocol2.FLAG_HAS_WITNESS,
3573
+ MAX_BODY_LEN: () => import_axis_protocol2.MAX_BODY_LEN,
3574
+ MAX_FRAME_LEN: () => import_axis_protocol2.MAX_FRAME_LEN,
3575
+ MAX_HDR_LEN: () => import_axis_protocol2.MAX_HDR_LEN,
3576
+ MAX_SIG_LEN: () => import_axis_protocol2.MAX_SIG_LEN,
3577
+ NCERT_ALG: () => import_axis_protocol2.NCERT_ALG,
3578
+ NCERT_EXP: () => import_axis_protocol2.NCERT_EXP,
3579
+ NCERT_ISSUER_KID: () => import_axis_protocol2.NCERT_ISSUER_KID,
3580
+ NCERT_KID: () => import_axis_protocol2.NCERT_KID,
3581
+ NCERT_NBF: () => import_axis_protocol2.NCERT_NBF,
3582
+ NCERT_NODE_ID: () => import_axis_protocol2.NCERT_NODE_ID,
3583
+ NCERT_PAYLOAD: () => import_axis_protocol2.NCERT_PAYLOAD,
3584
+ NCERT_PUB: () => import_axis_protocol2.NCERT_PUB,
3585
+ NCERT_SCOPE: () => import_axis_protocol2.NCERT_SCOPE,
3586
+ NCERT_SIG: () => import_axis_protocol2.NCERT_SIG,
3587
+ PROOF_CAPSULE: () => import_axis_protocol2.PROOF_CAPSULE,
3588
+ PROOF_JWT: () => import_axis_protocol2.PROOF_JWT,
3589
+ PROOF_LOOM: () => import_axis_protocol2.PROOF_LOOM,
3590
+ PROOF_MTLS: () => import_axis_protocol2.PROOF_MTLS,
3591
+ PROOF_NONE: () => import_axis_protocol2.PROOF_NONE,
3592
+ PROOF_WITNESS: () => import_axis_protocol2.PROOF_WITNESS,
3593
+ ProofType: () => import_axis_protocol2.ProofType,
3594
+ TLV: () => import_axis_protocol.TLV,
3595
+ TLV_ACTOR_ID: () => import_axis_protocol2.TLV_ACTOR_ID,
3596
+ TLV_AUD: () => import_axis_protocol2.TLV_AUD,
3597
+ TLV_BODY_ARR: () => import_axis_protocol2.TLV_BODY_ARR,
3598
+ TLV_BODY_OBJ: () => import_axis_protocol2.TLV_BODY_OBJ,
3599
+ TLV_CAPSULE: () => import_axis_protocol2.TLV_CAPSULE,
3600
+ TLV_EFFECT: () => import_axis_protocol2.TLV_EFFECT,
3601
+ TLV_ERROR_CODE: () => import_axis_protocol2.TLV_ERROR_CODE,
3602
+ TLV_ERROR_MSG: () => import_axis_protocol2.TLV_ERROR_MSG,
3603
+ TLV_INDEX: () => import_axis_protocol2.TLV_INDEX,
3604
+ TLV_INTENT: () => import_axis_protocol2.TLV_INTENT,
3605
+ TLV_KID: () => import_axis_protocol2.TLV_KID,
3606
+ TLV_LOOM_PRESENCE_ID: () => import_axis_protocol2.TLV_LOOM_PRESENCE_ID,
3607
+ TLV_LOOM_THREAD_HASH: () => import_axis_protocol2.TLV_LOOM_THREAD_HASH,
3608
+ TLV_LOOM_WRIT: () => import_axis_protocol2.TLV_LOOM_WRIT,
3609
+ TLV_NODE: () => import_axis_protocol2.TLV_NODE,
3610
+ TLV_NODE_CERT_HASH: () => import_axis_protocol2.TLV_NODE_CERT_HASH,
3611
+ TLV_NODE_KID: () => import_axis_protocol2.TLV_NODE_KID,
3612
+ TLV_NONCE: () => import_axis_protocol2.TLV_NONCE,
3613
+ TLV_OFFSET: () => import_axis_protocol2.TLV_OFFSET,
3614
+ TLV_OK: () => import_axis_protocol2.TLV_OK,
3615
+ TLV_PID: () => import_axis_protocol2.TLV_PID,
3616
+ TLV_PREV_HASH: () => import_axis_protocol2.TLV_PREV_HASH,
3617
+ TLV_PROOF_REF: () => import_axis_protocol2.TLV_PROOF_REF,
3618
+ TLV_PROOF_TYPE: () => import_axis_protocol2.TLV_PROOF_TYPE,
3619
+ TLV_REALM: () => import_axis_protocol2.TLV_REALM,
3620
+ TLV_RECEIPT_HASH: () => import_axis_protocol2.TLV_RECEIPT_HASH,
3621
+ TLV_RID: () => import_axis_protocol2.TLV_RID,
3622
+ TLV_SHA256_CHUNK: () => import_axis_protocol2.TLV_SHA256_CHUNK,
3623
+ TLV_TRACE_ID: () => import_axis_protocol2.TLV_TRACE_ID,
3624
+ TLV_TS: () => import_axis_protocol2.TLV_TS,
3625
+ TLV_UPLOAD_ID: () => import_axis_protocol2.TLV_UPLOAD_ID,
3626
+ computeReceiptHash: () => computeReceiptHash,
3627
+ computeSignaturePayload: () => computeSignaturePayload,
3628
+ decodeArray: () => import_axis_protocol.decodeArray,
3629
+ decodeFrame: () => decodeFrame,
3630
+ decodeObject: () => import_axis_protocol.decodeObject,
3631
+ decodeTLVs: () => import_axis_protocol.decodeTLVs,
3632
+ decodeTLVsList: () => import_axis_protocol.decodeTLVsList,
3633
+ decodeVarint: () => import_axis_protocol3.decodeVarint,
3634
+ encodeFrame: () => encodeFrame,
3635
+ encodeTLVs: () => import_axis_protocol.encodeTLVs,
3636
+ encodeVarint: () => import_axis_protocol3.encodeVarint,
3637
+ generateEd25519KeyPair: () => generateEd25519KeyPair,
3638
+ getSignTarget: () => getSignTarget,
3639
+ sha256: () => sha256,
3640
+ signFrame: () => signFrame,
3641
+ varintLength: () => import_axis_protocol3.varintLength,
3642
+ verifyFrameSignature: () => verifyFrameSignature
3643
+ });
3574
3644
 
3575
- // src/engine/sensor-discovery.service.ts
3576
- var import_common8 = require("@nestjs/common");
3577
- var SensorDiscoveryService = class {
3578
- constructor(discovery, reflector, registry) {
3579
- this.discovery = discovery;
3580
- this.reflector = reflector;
3581
- this.registry = registry;
3582
- this.logger = new import_common8.Logger(SensorDiscoveryService.name);
3645
+ // src/crypto/index.ts
3646
+ var crypto_exports = {};
3647
+ __export(crypto_exports, {
3648
+ ProofVerificationService: () => ProofVerificationService,
3649
+ b64urlDecode: () => b64urlDecode,
3650
+ b64urlDecodeString: () => b64urlDecodeString,
3651
+ b64urlEncode: () => b64urlEncode,
3652
+ b64urlEncodeString: () => b64urlEncodeString,
3653
+ canonicalJson: () => canonicalJson,
3654
+ canonicalJsonExcluding: () => canonicalJsonExcluding
3655
+ });
3656
+
3657
+ // src/crypto/proof-verification.service.ts
3658
+ var import_common10 = require("@nestjs/common");
3659
+ var crypto3 = __toESM(require("crypto"));
3660
+ var nacl = __toESM(require("tweetnacl"));
3661
+ var ProofVerificationService = class {
3662
+ constructor() {
3663
+ this.logger = new import_common10.Logger(ProofVerificationService.name);
3664
+ // Cache of registered device public keys (deviceId -> pubKey)
3665
+ this.deviceKeys = /* @__PURE__ */ new Map();
3666
+ // Cache of trusted mTLS certificate fingerprints
3667
+ this.trustedCerts = /* @__PURE__ */ new Map();
3583
3668
  }
3584
- onApplicationBootstrap() {
3585
- const providers = this.discovery.getProviders();
3586
- let count = 0;
3587
- for (const wrapper of providers) {
3588
- const { instance } = wrapper;
3589
- if (!instance || !instance.constructor) continue;
3590
- const meta = this.reflector.get(
3591
- SENSOR_METADATA_KEY,
3592
- instance.constructor
3593
- );
3594
- if (!meta) continue;
3595
- const sensor = instance;
3596
- if (!sensor.name || sensor.order === void 0) {
3597
- this.logger.warn(
3598
- `@Sensor() on ${instance.constructor.name} missing name or order \u2014 skipped`
3669
+ /**
3670
+ * Verifies an authentication proof based on its type.
3671
+ *
3672
+ * **Supported Types:**
3673
+ * - 1 (CAPSULE): Delegated to `verifyCapsuleProof`
3674
+ * - 2 (JWT): Verified by `verifyJWTProof`
3675
+ * - 3 (MTLS_ID): Verified by `verifyMTLSProof`
3676
+ * - 4 (DEVICE_SE): Verified by `verifyDeviceSEProof`
3677
+ *
3678
+ * @param {ProofType} proofType - The numeric AXIS proof type
3679
+ * @param {Uint8Array} proofRef - The binary reference or token for the proof
3680
+ * @param {Object} context - Additional metadata required for specific proof types
3681
+ * @param {Uint8Array} [context.signTarget] - The canonical bytes that were signed (for Ed25519)
3682
+ * @param {Uint8Array} [context.signature] - The signature to verify (for Ed25519)
3683
+ * @param {MTLSContext} [context.mtls] - mTLS certificate data
3684
+ * @param {DeviceSEContext} [context.deviceSE] - Device Secure Element information
3685
+ * @returns {Promise<ProofVerificationResult>} The outcome of the verification
3686
+ */
3687
+ async verifyProof(proofType, proofRef, context) {
3688
+ switch (proofType) {
3689
+ case 1:
3690
+ return this.verifyCapsuleProof(proofRef);
3691
+ case 2:
3692
+ return this.verifyJWTProof(proofRef);
3693
+ case 3:
3694
+ return this.verifyMTLSProof(context.mtls);
3695
+ case 4:
3696
+ return this.verifyDeviceSEProof(
3697
+ context.signTarget,
3698
+ context.signature,
3699
+ context.deviceSE
3599
3700
  );
3600
- continue;
3601
- }
3602
- if (!sensor.phase) {
3603
- const decoratorPhase = meta !== true ? meta.phase : void 0;
3604
- sensor.phase = decoratorPhase ?? (sensor.order < PRE_DECODE_BOUNDARY ? "PRE_DECODE" : "POST_DECODE");
3605
- }
3606
- this.registry.register(sensor);
3607
- count++;
3701
+ default:
3702
+ return { valid: false, error: `Unknown proof type: ${proofType}` };
3608
3703
  }
3609
- this.logger.log(`Auto-registered ${count} sensors via @Sensor()`);
3610
3704
  }
3611
- };
3612
- SensorDiscoveryService = __decorateClass([
3613
- (0, import_common8.Injectable)()
3614
- ], SensorDiscoveryService);
3615
-
3616
- // src/engine/registry/sensor.registry.ts
3617
- var import_common9 = require("@nestjs/common");
3618
- var SensorRegistry = class {
3619
- constructor(configService) {
3620
- this.configService = configService;
3621
- this.sensors = [];
3622
- this.logger = new import_common9.Logger(SensorRegistry.name);
3705
+ /**
3706
+ * Verify CAPSULE proof (delegated to CapsuleService)
3707
+ */
3708
+ async verifyCapsuleProof(proofRef) {
3709
+ const capsuleId = new TextDecoder().decode(proofRef);
3710
+ return {
3711
+ valid: true,
3712
+ metadata: { capsuleId, requiresCapsuleValidation: true }
3713
+ };
3623
3714
  }
3624
3715
  /**
3625
- * Registers a new sensor in the registry.
3716
+ * Verifies a JSON Web Token (JWT) proof.
3626
3717
  *
3627
- * Validates that:
3628
- * - AxisSensor has a unique name
3629
- * - AxisSensor has an order field
3630
- * - Pre-decode sensors have order < 40
3631
- * - Post-decode sensors have order >= 40
3718
+ * **Validation Logic:**
3719
+ * 1. Decodes the token string.
3720
+ * 2. Checks for valid 3-part JWT structure.
3721
+ * 3. Validates `exp` (expiration) and `nbf` (not before) claims.
3722
+ * 4. Extracts `actor_id` or `sub` as the identity.
3632
3723
  *
3633
- * @param {AxisSensor} sensor - The sensor instance to register
3634
- * @throws Error if validation fails
3724
+ * @param {Uint8Array} proofRef - Binary representation of the JWT string
3725
+ * @returns {Promise<ProofVerificationResult>} Result including the actor identifier
3635
3726
  */
3636
- register(sensor) {
3637
- if (!sensor.name) {
3638
- throw new Error("AxisSensor must have a name");
3639
- }
3640
- const enabledSensorsStr = this.configService.get("ENABLED_SENSORS");
3641
- const disabledSensorsStr = this.configService.get("DISABLED_SENSORS");
3642
- const enabledSensors = enabledSensorsStr ? enabledSensorsStr.split(",").map((s) => s.trim()) : null;
3643
- const disabledSensors = disabledSensorsStr ? disabledSensorsStr.split(",").map((s) => s.trim()) : [];
3644
- if (enabledSensors && !enabledSensors.includes(sensor.name)) {
3645
- this.logger.log(`Skipping disabled sensor (not in ENABLED_SENSORS): ${sensor.name}`);
3646
- return;
3647
- }
3648
- if (disabledSensors.includes(sensor.name)) {
3649
- this.logger.log(`Skipping disabled sensor (in DISABLED_SENSORS): ${sensor.name}`);
3650
- return;
3727
+ async verifyJWTProof(proofRef) {
3728
+ try {
3729
+ const token = new TextDecoder().decode(proofRef);
3730
+ const parts = token.split(".");
3731
+ if (parts.length !== 3) {
3732
+ return { valid: false, error: "Invalid JWT format" };
3733
+ }
3734
+ const header = JSON.parse(Buffer.from(parts[0], "base64url").toString());
3735
+ const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString());
3736
+ if (payload.exp && Date.now() / 1e3 > payload.exp) {
3737
+ return { valid: false, error: "JWT expired" };
3738
+ }
3739
+ if (payload.nbf && Date.now() / 1e3 < payload.nbf) {
3740
+ return { valid: false, error: "JWT not yet valid" };
3741
+ }
3742
+ return {
3743
+ valid: true,
3744
+ actorId: payload.sub || payload.actor_id,
3745
+ metadata: { iss: payload.iss, scope: payload.scope }
3746
+ };
3747
+ } catch (e) {
3748
+ const message = e instanceof Error ? e.message : "Unknown error";
3749
+ return { valid: false, error: `JWT parse error: ${message}` };
3651
3750
  }
3652
- if (sensor.order === void 0) {
3653
- throw new Error(`AxisSensor "${sensor.name}" must have an order field`);
3751
+ }
3752
+ /**
3753
+ * Verify mTLS client certificate proof
3754
+ */
3755
+ async verifyMTLSProof(mtls) {
3756
+ if (!mtls) {
3757
+ return { valid: false, error: "No mTLS context provided" };
3654
3758
  }
3655
- const isPreDecodeSensor = this.isPreDecodeSensor(sensor);
3656
- const isPostDecodeSensor = this.isPostDecodeSensor(sensor);
3657
- if (isPreDecodeSensor && sensor.order >= 40) {
3658
- this.logger.warn(
3659
- `AxisSensor "${sensor.name}" is marked as PRE_DECODE but has order ${sensor.order} (should be < 40)`
3660
- );
3759
+ if (!mtls.verified) {
3760
+ return { valid: false, error: "mTLS not verified by TLS terminator" };
3661
3761
  }
3662
- if (isPostDecodeSensor && sensor.order < 40) {
3663
- this.logger.warn(
3664
- `AxisSensor "${sensor.name}" is marked as POST_DECODE but has order ${sensor.order} (should be >= 40)`
3665
- );
3762
+ if (mtls.clientCertFingerprint) {
3763
+ const trusted = this.trustedCerts.get(mtls.clientCertFingerprint);
3764
+ if (trusted) {
3765
+ return {
3766
+ valid: true,
3767
+ actorId: trusted.actorId,
3768
+ metadata: {
3769
+ fingerprint: mtls.clientCertFingerprint,
3770
+ subject: mtls.clientCertSubject
3771
+ }
3772
+ };
3773
+ }
3666
3774
  }
3667
- this.sensors.push(sensor);
3668
- const phaseLabel = typeof sensor.phase === "string" ? sensor.phase : sensor.phase?.phase || "UNKNOWN";
3669
- this.logger.debug(
3670
- `Registered sensor: ${sensor.name} (order: ${sensor.order}, phase: ${phaseLabel})`
3671
- );
3672
- }
3673
- /**
3674
- * Returns all registered sensors, sorted by their execution order.
3675
- *
3676
- * @returns {AxisSensor[]} A sorted array of sensors
3677
- */
3678
- list() {
3679
- return [...this.sensors].sort(
3680
- (a, b) => (a.order ?? 999) - (b.order ?? 999)
3681
- );
3775
+ if (mtls.clientCertSubject) {
3776
+ const cnMatch = mtls.clientCertSubject.match(/CN=([^,]+)/);
3777
+ if (cnMatch) {
3778
+ return {
3779
+ valid: true,
3780
+ actorId: cnMatch[1],
3781
+ metadata: {
3782
+ subject: mtls.clientCertSubject,
3783
+ issuer: mtls.clientCertIssuer
3784
+ }
3785
+ };
3786
+ }
3787
+ }
3788
+ return { valid: false, error: "Could not extract actor from certificate" };
3682
3789
  }
3683
3790
  /**
3684
- * Returns only pre-decode sensors (order < 40).
3685
- * These sensors run in middleware on raw bytes before frame decoding.
3686
- *
3687
- * @returns {AxisPreSensor[]} Pre-decode sensors sorted by order
3791
+ * Verify Device Secure Element signature
3688
3792
  */
3689
- getPreDecodeSensors() {
3690
- return this.list().filter((s) => (s.order ?? 999) < 40);
3793
+ async verifyDeviceSEProof(signTarget, signature, deviceSE) {
3794
+ if (!deviceSE || !signTarget || !signature) {
3795
+ return { valid: false, error: "Missing Device SE context" };
3796
+ }
3797
+ let publicKey = deviceSE.publicKey;
3798
+ const registeredKey = this.deviceKeys.get(deviceSE.deviceId);
3799
+ if (registeredKey) {
3800
+ publicKey = registeredKey;
3801
+ }
3802
+ if (!publicKey || publicKey.length !== 32) {
3803
+ return {
3804
+ valid: false,
3805
+ error: "Invalid or unregistered device public key"
3806
+ };
3807
+ }
3808
+ try {
3809
+ const valid = nacl.sign.detached.verify(signTarget, signature, publicKey);
3810
+ if (!valid) {
3811
+ return { valid: false, error: "Device signature verification failed" };
3812
+ }
3813
+ return {
3814
+ valid: true,
3815
+ actorId: deviceSE.deviceId,
3816
+ metadata: { deviceId: deviceSE.deviceId, proofType: "DEVICE_SE" }
3817
+ };
3818
+ } catch (e) {
3819
+ const message = e instanceof Error ? e.message : "Unknown error";
3820
+ return {
3821
+ valid: false,
3822
+ error: `Signature verification error: ${message}`
3823
+ };
3824
+ }
3691
3825
  }
3692
3826
  /**
3693
- * Returns only post-decode sensors (order >= 40).
3694
- * These sensors run in the controller on fully decoded frames.
3827
+ * Registers a public key for a trusted device.
3828
+ * This key will be used for future `DEVICE_SE` proof verifications.
3695
3829
  *
3696
- * @returns {AxisPostSensor[]} Post-decode sensors sorted by order
3830
+ * @param {string} deviceId - Unique identifier for the device
3831
+ * @param {Uint8Array} publicKey - 32-byte Ed25519 public key
3832
+ * @throws {Error} If the public key is not 32 bytes
3697
3833
  */
3698
- getPostDecodeSensors() {
3699
- return this.list().filter(
3700
- (s) => (s.order ?? 999) >= 40
3701
- );
3834
+ registerDeviceKey(deviceId, publicKey) {
3835
+ if (publicKey.length !== 32) {
3836
+ throw new Error("Device public key must be 32 bytes (Ed25519)");
3837
+ }
3838
+ this.deviceKeys.set(deviceId, publicKey);
3839
+ this.logger.log(`Registered device key for ${deviceId}`);
3702
3840
  }
3703
3841
  /**
3704
- * Helper: Check if a sensor is a pre-decode sensor.
3705
- *
3706
- * @private
3707
- * @param {AxisSensor} sensor - The sensor to check
3708
- * @returns {boolean} True if sensor is pre-decode
3842
+ * Unregister a device
3709
3843
  */
3710
- isPreDecodeSensor(sensor) {
3711
- const phase = typeof sensor.phase === "string" ? sensor.phase : sensor.phase?.phase;
3712
- return phase === "PRE_DECODE" || (sensor.order ?? 999) < 40;
3844
+ unregisterDevice(deviceId) {
3845
+ return this.deviceKeys.delete(deviceId);
3713
3846
  }
3714
3847
  /**
3715
- * Helper: Check if a sensor is a post-decode sensor.
3848
+ * Registers a trusted mTLS certificate fingerprint and associates it with an actor.
3716
3849
  *
3717
- * @private
3718
- * @param {AxisSensor} sensor - The sensor to check
3719
- * @returns {boolean} True if sensor is post-decode
3850
+ * @param {string} fingerprint - SHA-256 fingerprint of the client certificate
3851
+ * @param {string} actorId - The actor to associate with this certificate
3720
3852
  */
3721
- isPostDecodeSensor(sensor) {
3722
- const phase = typeof sensor.phase === "string" ? sensor.phase : sensor.phase?.phase;
3723
- return phase === "POST_DECODE" || (sensor.order ?? 999) >= 40;
3853
+ registerMTLSCert(fingerprint, actorId) {
3854
+ this.trustedCerts.set(fingerprint, { actorId, issuedAt: Date.now() });
3855
+ this.logger.log(`Registered mTLS cert ${fingerprint} for actor ${actorId}`);
3724
3856
  }
3725
3857
  /**
3726
- * Returns sensor count by phase.
3727
- * Useful for diagnostics and monitoring.
3728
- *
3729
- * @returns {{preDecodeCount: number, postDecodeCount: number}}
3858
+ * Revoke an mTLS certificate
3730
3859
  */
3731
- getSensorCountByPhase() {
3732
- return {
3733
- preDecodeCount: this.getPreDecodeSensors().length,
3734
- postDecodeCount: this.getPostDecodeSensors().length
3735
- };
3860
+ revokeMTLSCert(fingerprint) {
3861
+ return this.trustedCerts.delete(fingerprint);
3736
3862
  }
3737
3863
  /**
3738
- * Clears all registered sensors.
3739
- * Useful for testing.
3740
- *
3741
- * @internal
3864
+ * Calculate certificate fingerprint (SHA-256)
3742
3865
  */
3743
- clear() {
3744
- this.sensors = [];
3866
+ static calculateFingerprint(certPem) {
3867
+ const der = Buffer.from(
3868
+ certPem.replace(/-----BEGIN CERTIFICATE-----/, "").replace(/-----END CERTIFICATE-----/, "").replace(/\s/g, ""),
3869
+ "base64"
3870
+ );
3871
+ return crypto3.createHash("sha256").update(der).digest("hex");
3745
3872
  }
3746
3873
  };
3747
- SensorRegistry = __decorateClass([
3748
- (0, import_common9.Injectable)()
3749
- ], SensorRegistry);
3874
+ ProofVerificationService = __decorateClass([
3875
+ (0, import_common10.Injectable)()
3876
+ ], ProofVerificationService);
3877
+
3878
+ // src/decorators/index.ts
3879
+ var decorators_exports = {};
3880
+ __export(decorators_exports, {
3881
+ AxisContext: () => AxisContext,
3882
+ AxisDemoPubkey: () => AxisDemoPubkey,
3883
+ AxisFrame: () => AxisFrame3,
3884
+ AxisIp: () => AxisIp,
3885
+ AxisRaw: () => AxisRaw,
3886
+ HANDLER_METADATA_KEY: () => HANDLER_METADATA_KEY,
3887
+ Handler: () => Handler,
3888
+ INTENT_BODY_KEY: () => INTENT_BODY_KEY,
3889
+ INTENT_METADATA_KEY: () => INTENT_METADATA_KEY,
3890
+ INTENT_ROUTES_KEY: () => INTENT_ROUTES_KEY,
3891
+ INTENT_SENSORS_KEY: () => INTENT_SENSORS_KEY,
3892
+ Intent: () => Intent,
3893
+ IntentBody: () => IntentBody,
3894
+ IntentSensors: () => IntentSensors,
3895
+ SENSOR_METADATA_KEY: () => SENSOR_METADATA_KEY,
3896
+ Sensor: () => Sensor,
3897
+ TLV_FIELDS_KEY: () => TLV_FIELDS_KEY,
3898
+ TLV_VALIDATORS_KEY: () => TLV_VALIDATORS_KEY,
3899
+ TlvEnum: () => TlvEnum,
3900
+ TlvField: () => TlvField,
3901
+ TlvMinLen: () => TlvMinLen,
3902
+ TlvRange: () => TlvRange,
3903
+ TlvUtf8Pattern: () => TlvUtf8Pattern,
3904
+ TlvValidate: () => TlvValidate,
3905
+ buildDtoDecoder: () => buildDtoDecoder,
3906
+ extractDtoSchema: () => extractDtoSchema
3907
+ });
3908
+
3909
+ // src/engine/index.ts
3910
+ var engine_exports = {};
3911
+ __export(engine_exports, {
3912
+ BAND: () => BAND,
3913
+ HandlerDiscoveryService: () => HandlerDiscoveryService,
3914
+ IntentRouter: () => IntentRouter,
3915
+ PRE_DECODE_BOUNDARY: () => PRE_DECODE_BOUNDARY,
3916
+ SensorDiscoveryService: () => SensorDiscoveryService,
3917
+ SensorRegistry: () => SensorRegistry,
3918
+ createObservation: () => createObservation,
3919
+ endStage: () => endStage,
3920
+ finalizeObservation: () => finalizeObservation,
3921
+ observation: () => observation_exports,
3922
+ recordSensor: () => recordSensor,
3923
+ startStage: () => startStage
3924
+ });
3750
3925
 
3751
3926
  // src/engine/observation/index.ts
3752
3927
  var observation_exports = {};
@@ -4131,7 +4306,7 @@ var AxisErrorZ = z2.object({
4131
4306
  });
4132
4307
 
4133
4308
  // src/schemas/body-profile.validator.ts
4134
- var import_common10 = require("@nestjs/common");
4309
+ var import_common11 = require("@nestjs/common");
4135
4310
  var BodyProfile2 = /* @__PURE__ */ ((BodyProfile3) => {
4136
4311
  BodyProfile3[BodyProfile3["RAW"] = 0] = "RAW";
4137
4312
  BodyProfile3[BodyProfile3["TLV_MAP"] = 1] = "TLV_MAP";
@@ -4141,7 +4316,7 @@ var BodyProfile2 = /* @__PURE__ */ ((BodyProfile3) => {
4141
4316
  })(BodyProfile2 || {});
4142
4317
  var BodyProfileValidator = class {
4143
4318
  constructor() {
4144
- this.logger = new import_common10.Logger(BodyProfileValidator.name);
4319
+ this.logger = new import_common11.Logger(BodyProfileValidator.name);
4145
4320
  }
4146
4321
  /**
4147
4322
  * Validate body matches declared profile
@@ -4257,12 +4432,13 @@ var BodyProfileValidator = class {
4257
4432
  }
4258
4433
  };
4259
4434
  BodyProfileValidator = __decorateClass([
4260
- (0, import_common10.Injectable)()
4435
+ (0, import_common11.Injectable)()
4261
4436
  ], BodyProfileValidator);
4262
4437
 
4263
4438
  // src/security/index.ts
4264
4439
  var security_exports = {};
4265
4440
  __export(security_exports, {
4441
+ AxisSensorChainService: () => AxisSensorChainService,
4266
4442
  CAPABILITIES: () => CAPABILITIES,
4267
4443
  INTENT_REQUIREMENTS: () => INTENT_REQUIREMENTS,
4268
4444
  PROOF_CAPABILITIES: () => PROOF_CAPABILITIES,
@@ -4295,7 +4471,7 @@ __export(sensors_exports, {
4295
4471
  });
4296
4472
 
4297
4473
  // src/sensors/access-profile-resolver.sensor.ts
4298
- var import_common11 = require("@nestjs/common");
4474
+ var import_common12 = require("@nestjs/common");
4299
4475
  var AccessProfileResolverSensor = class {
4300
4476
  constructor() {
4301
4477
  /** AxisSensor identifier */
@@ -4321,11 +4497,11 @@ var AccessProfileResolverSensor = class {
4321
4497
  };
4322
4498
  AccessProfileResolverSensor = __decorateClass([
4323
4499
  Sensor(),
4324
- (0, import_common11.Injectable)()
4500
+ (0, import_common12.Injectable)()
4325
4501
  ], AccessProfileResolverSensor);
4326
4502
 
4327
4503
  // src/sensors/body-budget.sensor.ts
4328
- var import_common12 = require("@nestjs/common");
4504
+ var import_common13 = require("@nestjs/common");
4329
4505
  var BodyBudgetSensor = class {
4330
4506
  constructor() {
4331
4507
  /** AxisSensor identifier */
@@ -4399,14 +4575,14 @@ var BodyBudgetSensor = class {
4399
4575
  };
4400
4576
  BodyBudgetSensor = __decorateClass([
4401
4577
  Sensor(),
4402
- (0, import_common12.Injectable)()
4578
+ (0, import_common13.Injectable)()
4403
4579
  ], BodyBudgetSensor);
4404
4580
 
4405
4581
  // src/sensors/capability-enforcement.sensor.ts
4406
- var import_common13 = require("@nestjs/common");
4582
+ var import_common14 = require("@nestjs/common");
4407
4583
  var CapabilityEnforcementSensor = class {
4408
4584
  constructor() {
4409
- this.logger = new import_common13.Logger(CapabilityEnforcementSensor.name);
4585
+ this.logger = new import_common14.Logger(CapabilityEnforcementSensor.name);
4410
4586
  /** AxisSensor identifier for logging and registry */
4411
4587
  this.name = "CapabilityEnforcementSensor";
4412
4588
  /**
@@ -4500,11 +4676,11 @@ var CapabilityEnforcementSensor = class {
4500
4676
  };
4501
4677
  CapabilityEnforcementSensor = __decorateClass([
4502
4678
  Sensor(),
4503
- (0, import_common13.Injectable)()
4679
+ (0, import_common14.Injectable)()
4504
4680
  ], CapabilityEnforcementSensor);
4505
4681
 
4506
4682
  // src/sensors/chunk-hash.sensor.ts
4507
- var import_common14 = require("@nestjs/common");
4683
+ var import_common15 = require("@nestjs/common");
4508
4684
  var import_crypto6 = require("crypto");
4509
4685
  var ChunkHashSensor = class {
4510
4686
  constructor() {
@@ -4577,15 +4753,15 @@ var ChunkHashSensor = class {
4577
4753
  };
4578
4754
  ChunkHashSensor = __decorateClass([
4579
4755
  Sensor(),
4580
- (0, import_common14.Injectable)()
4756
+ (0, import_common15.Injectable)()
4581
4757
  ], ChunkHashSensor);
4582
4758
 
4583
4759
  // src/sensors/entropy.sensor.ts
4584
- var import_common15 = require("@nestjs/common");
4760
+ var import_common16 = require("@nestjs/common");
4585
4761
  var crypto4 = __toESM(require("crypto"));
4586
4762
  var EntropySensor = class {
4587
4763
  constructor() {
4588
- this.logger = new import_common15.Logger(EntropySensor.name);
4764
+ this.logger = new import_common16.Logger(EntropySensor.name);
4589
4765
  /**
4590
4766
  * Minimum acceptable entropy in bits per byte.
4591
4767
  *
@@ -4755,14 +4931,14 @@ var EntropySensor = class {
4755
4931
  };
4756
4932
  EntropySensor = __decorateClass([
4757
4933
  Sensor(),
4758
- (0, import_common15.Injectable)()
4934
+ (0, import_common16.Injectable)()
4759
4935
  ], EntropySensor);
4760
4936
 
4761
4937
  // src/sensors/execution-timeout.sensor.ts
4762
- var import_common16 = require("@nestjs/common");
4938
+ var import_common17 = require("@nestjs/common");
4763
4939
  var ExecutionTimeoutSensor = class {
4764
4940
  constructor() {
4765
- this.logger = new import_common16.Logger(ExecutionTimeoutSensor.name);
4941
+ this.logger = new import_common17.Logger(ExecutionTimeoutSensor.name);
4766
4942
  /** AxisSensor identifier */
4767
4943
  this.name = "ExecutionTimeoutSensor";
4768
4944
  /**
@@ -4840,11 +5016,11 @@ var ExecutionTimeoutSensor = class {
4840
5016
  };
4841
5017
  ExecutionTimeoutSensor = __decorateClass([
4842
5018
  Sensor(),
4843
- (0, import_common16.Injectable)()
5019
+ (0, import_common17.Injectable)()
4844
5020
  ], ExecutionTimeoutSensor);
4845
5021
 
4846
5022
  // src/sensors/frame-budget.sensor.ts
4847
- var import_common17 = require("@nestjs/common");
5023
+ var import_common18 = require("@nestjs/common");
4848
5024
  var FrameBudgetSensor = class {
4849
5025
  constructor(config) {
4850
5026
  this.config = config;
@@ -4903,11 +5079,11 @@ var FrameBudgetSensor = class {
4903
5079
  };
4904
5080
  FrameBudgetSensor = __decorateClass([
4905
5081
  Sensor({ phase: "PRE_DECODE" }),
4906
- (0, import_common17.Injectable)()
5082
+ (0, import_common18.Injectable)()
4907
5083
  ], FrameBudgetSensor);
4908
5084
 
4909
5085
  // src/sensors/frame-header-sanity.sensor.ts
4910
- var import_common18 = require("@nestjs/common");
5086
+ var import_common19 = require("@nestjs/common");
4911
5087
  var FrameHeaderSanitySensor = class {
4912
5088
  constructor() {
4913
5089
  this.name = "FrameHeaderSanitySensor";
@@ -4951,12 +5127,12 @@ var FrameHeaderSanitySensor = class {
4951
5127
  }
4952
5128
  };
4953
5129
  FrameHeaderSanitySensor = __decorateClass([
4954
- (0, import_common18.Injectable)(),
5130
+ (0, import_common19.Injectable)(),
4955
5131
  Sensor({ phase: "PRE_DECODE" })
4956
5132
  ], FrameHeaderSanitySensor);
4957
5133
 
4958
5134
  // src/sensors/header-tlv-limit.sensor.ts
4959
- var import_common19 = require("@nestjs/common");
5135
+ var import_common20 = require("@nestjs/common");
4960
5136
  var HeaderTLVLimitSensor = class {
4961
5137
  constructor() {
4962
5138
  this.name = "HeaderTLVLimitSensor";
@@ -4988,12 +5164,12 @@ var HeaderTLVLimitSensor = class {
4988
5164
  }
4989
5165
  };
4990
5166
  HeaderTLVLimitSensor = __decorateClass([
4991
- (0, import_common19.Injectable)(),
5167
+ (0, import_common20.Injectable)(),
4992
5168
  Sensor()
4993
5169
  ], HeaderTLVLimitSensor);
4994
5170
 
4995
5171
  // src/sensors/intent-allowlist.sensor.ts
4996
- var import_common20 = require("@nestjs/common");
5172
+ var import_common21 = require("@nestjs/common");
4997
5173
  var PUBLIC_INTENT_ALLOWLIST = [
4998
5174
  "public.",
4999
5175
  "schema.",
@@ -5028,12 +5204,12 @@ var IntentAllowlistSensor = class {
5028
5204
  }
5029
5205
  };
5030
5206
  IntentAllowlistSensor = __decorateClass([
5031
- (0, import_common20.Injectable)(),
5207
+ (0, import_common21.Injectable)(),
5032
5208
  Sensor()
5033
5209
  ], IntentAllowlistSensor);
5034
5210
 
5035
5211
  // src/sensors/intent-registry.sensor.ts
5036
- var import_common21 = require("@nestjs/common");
5212
+ var import_common22 = require("@nestjs/common");
5037
5213
  var IntentRegistrySensor = class {
5038
5214
  constructor(router) {
5039
5215
  this.router = router;
@@ -5056,12 +5232,12 @@ var IntentRegistrySensor = class {
5056
5232
  }
5057
5233
  };
5058
5234
  IntentRegistrySensor = __decorateClass([
5059
- (0, import_common21.Injectable)(),
5235
+ (0, import_common22.Injectable)(),
5060
5236
  Sensor({ phase: "POST_DECODE" })
5061
5237
  ], IntentRegistrySensor);
5062
5238
 
5063
5239
  // src/sensors/proof-presence.sensor.ts
5064
- var import_common22 = require("@nestjs/common");
5240
+ var import_common23 = require("@nestjs/common");
5065
5241
  var ProofPresenceSensor = class {
5066
5242
  constructor() {
5067
5243
  this.name = "ProofPresenceSensor";
@@ -5109,11 +5285,11 @@ var ProofPresenceSensor = class {
5109
5285
  };
5110
5286
  ProofPresenceSensor = __decorateClass([
5111
5287
  Sensor(),
5112
- (0, import_common22.Injectable)()
5288
+ (0, import_common23.Injectable)()
5113
5289
  ], ProofPresenceSensor);
5114
5290
 
5115
5291
  // src/sensors/protocol-strict.sensor.ts
5116
- var import_common23 = require("@nestjs/common");
5292
+ var import_common24 = require("@nestjs/common");
5117
5293
  var VALID_FLAGS = [
5118
5294
  0,
5119
5295
  // No flags
@@ -5131,7 +5307,7 @@ var VALID_FLAGS = [
5131
5307
  var ProtocolStrictSensor = class {
5132
5308
  constructor(config) {
5133
5309
  this.config = config;
5134
- this.logger = new import_common23.Logger(ProtocolStrictSensor.name);
5310
+ this.logger = new import_common24.Logger(ProtocolStrictSensor.name);
5135
5311
  /** Sensor identifier for logging and registry */
5136
5312
  this.name = "ProtocolStrictSensor";
5137
5313
  /**
@@ -5384,11 +5560,11 @@ var ProtocolStrictSensor = class {
5384
5560
  };
5385
5561
  ProtocolStrictSensor = __decorateClass([
5386
5562
  Sensor({ phase: "PRE_DECODE" }),
5387
- (0, import_common23.Injectable)()
5563
+ (0, import_common24.Injectable)()
5388
5564
  ], ProtocolStrictSensor);
5389
5565
 
5390
5566
  // src/sensors/receipt-policy.sensor.ts
5391
- var import_common24 = require("@nestjs/common");
5567
+ var import_common25 = require("@nestjs/common");
5392
5568
  var ReceiptPolicySensor = class {
5393
5569
  constructor() {
5394
5570
  this.name = "ReceiptPolicySensor";
@@ -5402,12 +5578,12 @@ var ReceiptPolicySensor = class {
5402
5578
  }
5403
5579
  };
5404
5580
  ReceiptPolicySensor = __decorateClass([
5405
- (0, import_common24.Injectable)(),
5581
+ (0, import_common25.Injectable)(),
5406
5582
  Sensor()
5407
5583
  ], ReceiptPolicySensor);
5408
5584
 
5409
5585
  // src/sensors/schema-validation.sensor.ts
5410
- var import_common25 = require("@nestjs/common");
5586
+ var import_common26 = require("@nestjs/common");
5411
5587
  function readU64be(b) {
5412
5588
  if (b.length !== 8)
5413
5589
  throw new AxisError("SCHEMA_TYPE_MISMATCH", "u64 must be 8 bytes", 400);
@@ -5582,11 +5758,11 @@ var SchemaValidationSensor = class {
5582
5758
  };
5583
5759
  SchemaValidationSensor = __decorateClass([
5584
5760
  Sensor(),
5585
- (0, import_common25.Injectable)()
5761
+ (0, import_common26.Injectable)()
5586
5762
  ], SchemaValidationSensor);
5587
5763
 
5588
5764
  // src/sensors/stream-scope.sensor.ts
5589
- var import_common26 = require("@nestjs/common");
5765
+ var import_common27 = require("@nestjs/common");
5590
5766
  var StreamScopeSensor = class {
5591
5767
  constructor() {
5592
5768
  /** Sensor identifier */
@@ -5632,11 +5808,11 @@ var StreamScopeSensor = class {
5632
5808
  };
5633
5809
  StreamScopeSensor = __decorateClass([
5634
5810
  Sensor(),
5635
- (0, import_common26.Injectable)()
5811
+ (0, import_common27.Injectable)()
5636
5812
  ], StreamScopeSensor);
5637
5813
 
5638
5814
  // src/sensors/tlv-parse.sensor.ts
5639
- var import_common27 = require("@nestjs/common");
5815
+ var import_common28 = require("@nestjs/common");
5640
5816
  var TLVParseSensor = class {
5641
5817
  constructor() {
5642
5818
  this.name = "TLVParseSensor";
@@ -5738,11 +5914,11 @@ var TLVParseSensor = class {
5738
5914
  };
5739
5915
  TLVParseSensor = __decorateClass([
5740
5916
  Sensor(),
5741
- (0, import_common27.Injectable)()
5917
+ (0, import_common28.Injectable)()
5742
5918
  ], TLVParseSensor);
5743
5919
 
5744
5920
  // src/sensors/varint-hardening.sensor.ts
5745
- var import_common28 = require("@nestjs/common");
5921
+ var import_common29 = require("@nestjs/common");
5746
5922
  var VarintHardeningSensor = class {
5747
5923
  constructor() {
5748
5924
  /** Sensor identifier */
@@ -5805,7 +5981,7 @@ var VarintHardeningSensor = class {
5805
5981
  };
5806
5982
  VarintHardeningSensor = __decorateClass([
5807
5983
  Sensor({ phase: "PRE_DECODE" }),
5808
- (0, import_common28.Injectable)()
5984
+ (0, import_common29.Injectable)()
5809
5985
  ], VarintHardeningSensor);
5810
5986
 
5811
5987
  // src/utils/index.ts
@@ -5877,14 +6053,21 @@ function toBuffer(value) {
5877
6053
  AXIS_UPLOAD_SESSION_STORE,
5878
6054
  AXIS_VERSION,
5879
6055
  Ats1Codec,
6056
+ AxisContext,
6057
+ AxisDemoPubkey,
6058
+ AxisError,
5880
6059
  AxisFilesDownloadHandler,
5881
6060
  AxisFilesFinalizeHandler,
5882
6061
  AxisFrameZ,
5883
6062
  AxisIdDto,
6063
+ AxisIp,
5884
6064
  AxisPacketTags,
5885
6065
  AxisPartialType,
6066
+ AxisRaw,
5886
6067
  AxisResponseDto,
6068
+ AxisSensorChainService,
5887
6069
  AxisTlvDto,
6070
+ BAND,
5888
6071
  BodyProfile,
5889
6072
  CAPABILITIES,
5890
6073
  ContractViolationError,
@@ -5902,7 +6085,10 @@ function toBuffer(value) {
5902
6085
  FLAG_CHAIN_REQ,
5903
6086
  FLAG_HAS_WITNESS,
5904
6087
  HANDLER_METADATA_KEY,
6088
+ HANDLER_SENSORS_KEY,
5905
6089
  Handler,
6090
+ HandlerDiscoveryService,
6091
+ HandlerSensors,
5906
6092
  INTENT_BODY_KEY,
5907
6093
  INTENT_METADATA_KEY,
5908
6094
  INTENT_REQUIREMENTS,
@@ -5929,6 +6115,7 @@ function toBuffer(value) {
5929
6115
  NCERT_PUB,
5930
6116
  NCERT_SCOPE,
5931
6117
  NCERT_SIG,
6118
+ PRE_DECODE_BOUNDARY,
5932
6119
  PROOF_CAPABILITIES,
5933
6120
  PROOF_CAPSULE,
5934
6121
  PROOF_JWT,
@@ -5943,11 +6130,15 @@ function toBuffer(value) {
5943
6130
  RESPONSE_TAG_UPDATED_AT,
5944
6131
  RESPONSE_TAG_UPDATED_BY,
5945
6132
  RiskDecision,
6133
+ SENSOR_METADATA_KEY,
5946
6134
  Schema2002_PasskeyLoginOptionsRes,
5947
6135
  Schema2011_PasskeyLoginVerifyReq,
5948
6136
  Schema2012_PasskeyLoginVerifyRes,
5949
6137
  Schema2021_PasskeyRegisterOptionsReq,
6138
+ Sensor,
5950
6139
  SensorDecisions,
6140
+ SensorDiscoveryService,
6141
+ SensorRegistry,
5951
6142
  TLV,
5952
6143
  TLV_ACTOR_ID,
5953
6144
  TLV_AUD,
@@ -6009,6 +6200,7 @@ function toBuffer(value) {
6009
6200
  computeReceiptHash,
6010
6201
  computeSignaturePayload,
6011
6202
  core,
6203
+ createObservation,
6012
6204
  crypto,
6013
6205
  decodeArray,
6014
6206
  decodeAxis1Frame,
@@ -6025,8 +6217,10 @@ function toBuffer(value) {
6025
6217
  encodeQueueMessage,
6026
6218
  encodeTLVs,
6027
6219
  encodeVarint,
6220
+ endStage,
6028
6221
  engine,
6029
6222
  extractDtoSchema,
6223
+ finalizeObservation,
6030
6224
  generateEd25519KeyPair,
6031
6225
  getSignTarget,
6032
6226
  hasScope,
@@ -6045,6 +6239,7 @@ function toBuffer(value) {
6045
6239
  parseAutoClaimEntries,
6046
6240
  parseScope,
6047
6241
  parseStreamEntries,
6242
+ recordSensor,
6048
6243
  resolveTimeout,
6049
6244
  schemas,
6050
6245
  security,
@@ -6053,6 +6248,7 @@ function toBuffer(value) {
6053
6248
  sha256,
6054
6249
  signFrame,
6055
6250
  stableJsonStringify,
6251
+ startStage,
6056
6252
  tlv,
6057
6253
  u64be,
6058
6254
  unpackPasskeyLoginOptionsReq,