arkgate 2.8.0 → 2.8.2

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.
@@ -80,7 +80,7 @@ __export(runtime_exports, {
80
80
  module.exports = __toCommonJS(runtime_exports);
81
81
 
82
82
  // src/version.ts
83
- var version = "2.8.0";
83
+ var version = "2.8.2";
84
84
 
85
85
  // src/kernel/intent/IntentRegistry.ts
86
86
  var IntentRegistry = class {
@@ -548,12 +548,39 @@ var ObservedLayerFlowViolationError = class extends Error {
548
548
  }
549
549
  };
550
550
 
551
- // src/kernel/event-bus/EventBus.ts
552
- var interceptorSequence = 0;
553
- function nextInterceptorRegistrationId() {
554
- interceptorSequence += 1;
555
- return `interceptor-${Date.now()}-${interceptorSequence}`;
551
+ // src/kernel/event-bus/publishGuards.ts
552
+ function assertIntentAllowed(intentName, options) {
553
+ if (!options.strictRegistry && !options.validateIntentNaming) {
554
+ return;
555
+ }
556
+ if (options.validateIntentNaming) {
557
+ const validation = validateIntentName(intentName);
558
+ if (!validation.valid) {
559
+ throw new InvalidIntentNameError(intentName, validation.reason);
560
+ }
561
+ }
562
+ if (options.strictRegistry && options.intentRegistry && !options.intentRegistry.has(intentName)) {
563
+ throw new UnregisteredIntentError(intentName);
564
+ }
565
+ }
566
+ function assertSourceAllowed(event, options) {
567
+ if (!options.requireKnownSource) return;
568
+ if (!event.metadata.source || event.metadata.source === "unknown") {
569
+ throw new UnknownEventSourceError(event.intent);
570
+ }
571
+ if (options.intentRegistry && !options.intentRegistry.has(event.metadata.source)) {
572
+ throw new UnknownEventSourceError(event.intent, event.metadata.source);
573
+ }
556
574
  }
575
+ function assertContractAllowed(event, options) {
576
+ if (!options.eventContracts) return;
577
+ const result = options.eventContracts.validate(event);
578
+ if (!result.ok && (options.strictEventContracts || result.contract)) {
579
+ throw new EventContractViolationError(event.intent, result.issues);
580
+ }
581
+ }
582
+
583
+ // src/kernel/event-bus/payloadPatch.ts
557
584
  function isPlainRecord(value) {
558
585
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
559
586
  return false;
@@ -624,29 +651,318 @@ function applyPayloadPatch(payload, patch) {
624
651
  }
625
652
  return mergeRecordPatch(payload, patch);
626
653
  }
654
+
655
+ // src/kernel/event-bus/publishInterceptors.ts
656
+ async function applyInterceptors(event, deps) {
657
+ if (event.metadata.allowInterception === false) {
658
+ return event;
659
+ }
660
+ const matching = [...deps.interceptorsForIntent(event.intent)];
661
+ let current = event;
662
+ for (const registration of matching) {
663
+ const patches = [];
664
+ try {
665
+ await Promise.resolve(
666
+ registration.interceptor({
667
+ event: current,
668
+ intercept: (patch) => {
669
+ patches.push(patch);
670
+ }
671
+ })
672
+ );
673
+ if (patches.length === 0) {
674
+ continue;
675
+ }
676
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
677
+ let candidate = {
678
+ ...current,
679
+ metadata: {
680
+ ...current.metadata,
681
+ interceptions: [
682
+ ...current.metadata.interceptions ?? [],
683
+ { interceptorId: registration.interceptorId, timestamp }
684
+ ]
685
+ }
686
+ };
687
+ for (const patch of patches) {
688
+ candidate = {
689
+ ...candidate,
690
+ payload: applyPayloadPatch(candidate.payload, patch),
691
+ metadata: { ...candidate.metadata }
692
+ };
693
+ }
694
+ assertContractAllowed(candidate, {
695
+ eventContracts: deps.eventContracts,
696
+ strictEventContracts: deps.strictEventContracts
697
+ });
698
+ current = candidate;
699
+ registration.lastInterceptedAt = timestamp;
700
+ deps.appendTrace({
701
+ type: "event.intercepted",
702
+ timestamp,
703
+ intent: current.intent,
704
+ correlationId: current.metadata.correlationId,
705
+ traceId: current.metadata.traceId,
706
+ spanId: current.metadata.spanId,
707
+ details: {
708
+ registrationId: registration.registrationId,
709
+ interceptorId: registration.interceptorId,
710
+ patchesApplied: patches.length
711
+ }
712
+ });
713
+ await deps.recordAudit("event.intercepted", current, {
714
+ registrationId: registration.registrationId,
715
+ interceptorId: registration.interceptorId,
716
+ patchesApplied: patches.length
717
+ });
718
+ } catch (err) {
719
+ await recordInterceptorError(registration, current, err, deps);
720
+ }
721
+ }
722
+ return current;
723
+ }
724
+ async function recordInterceptorError(interceptor, event, error, deps) {
725
+ const message = error instanceof Error ? error.message : String(error);
726
+ deps.appendTrace({
727
+ type: "interceptor.error",
728
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
729
+ intent: event.intent,
730
+ correlationId: event.metadata.correlationId,
731
+ traceId: event.metadata.traceId,
732
+ spanId: event.metadata.spanId,
733
+ details: {
734
+ registrationId: interceptor.registrationId,
735
+ interceptorId: interceptor.interceptorId,
736
+ error: message
737
+ }
738
+ });
739
+ await deps.recordAudit("interceptor.error", event, {
740
+ registrationId: interceptor.registrationId,
741
+ interceptorId: interceptor.interceptorId,
742
+ error: message
743
+ });
744
+ }
745
+
746
+ // src/kernel/event-bus/observedLayerFlow.ts
747
+ async function assertObservedLayerFlowAllowed(event, deps) {
748
+ if (deps.mode === "off" || !deps.architectureProfile) {
749
+ return;
750
+ }
751
+ const source = event.metadata.source;
752
+ if (!source || source === "unknown") return;
753
+ const profile = deps.architectureProfile;
754
+ const fromLayer = profile.resolveLayer(source);
755
+ const toLayer = profile.resolveLayer(event.intent);
756
+ if (!fromLayer || !toLayer) return;
757
+ const blocked = profile.rules.find(
758
+ (rule) => !rule.allowed && rule.from === fromLayer && rule.to === toLayer
759
+ );
760
+ if (!blocked) return;
761
+ const severity = deps.mode;
762
+ const message = blocked.message ?? `Observed layer violation: "${source}" (${fromLayer}) must not produce "${event.intent}" (${toLayer}).`;
763
+ const details = {
764
+ source,
765
+ intent: event.intent,
766
+ fromLayer,
767
+ toLayer,
768
+ severity,
769
+ message,
770
+ rule: blocked
771
+ };
772
+ deps.appendTrace({
773
+ type: "layer.observedViolation",
774
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
775
+ intent: event.intent,
776
+ correlationId: event.metadata.correlationId,
777
+ traceId: event.metadata.traceId,
778
+ spanId: event.metadata.spanId,
779
+ details
780
+ });
781
+ await deps.recordAudit("layer.observedViolation", event, details);
782
+ if (severity === "hard") {
783
+ throw new ObservedLayerFlowViolationError(
784
+ source,
785
+ event.intent,
786
+ fromLayer,
787
+ toLayer,
788
+ message
789
+ );
790
+ }
791
+ }
792
+
793
+ // src/kernel/event-bus/publishPolicy.ts
794
+ async function enforcePublishPolicy(event, deps) {
795
+ const ctx = deps.getPolicyContext(event);
796
+ let policyResult;
797
+ try {
798
+ policyResult = deps.policyEngine.enforce(ctx);
799
+ } catch (err) {
800
+ if (err instanceof PolicyViolationError) {
801
+ deps.appendTrace({
802
+ type: "policy.hardViolation",
803
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
804
+ intent: event.intent,
805
+ correlationId: event.metadata.correlationId,
806
+ traceId: event.metadata.traceId,
807
+ spanId: event.metadata.spanId,
808
+ details: { violations: err.violations }
809
+ });
810
+ await deps.recordAudit("policy.hardViolation", event, {
811
+ violations: err.violations
812
+ });
813
+ }
814
+ throw err;
815
+ }
816
+ if (policyResult.softViolations.length > 0) {
817
+ deps.appendTrace({
818
+ type: "policy.softViolation",
819
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
820
+ intent: event.intent,
821
+ correlationId: event.metadata.correlationId,
822
+ traceId: event.metadata.traceId,
823
+ spanId: event.metadata.spanId,
824
+ details: { violations: policyResult.softViolations }
825
+ });
826
+ await deps.recordAudit("policy.softViolation", event, {
827
+ violations: policyResult.softViolations
828
+ });
829
+ if (deps.onSoftViolation) {
830
+ await deps.safeHook(
831
+ () => deps.onSoftViolation(policyResult, event),
832
+ "onSoftViolation",
833
+ event
834
+ );
835
+ }
836
+ }
837
+ }
838
+
839
+ // src/kernel/event-bus/publishRecording.ts
840
+ function appendHistory(buffers, record) {
841
+ buffers.history.push(record);
842
+ if (buffers.maxHistorySize !== void 0 && buffers.history.length > buffers.maxHistorySize) {
843
+ buffers.history.splice(0, buffers.history.length - buffers.maxHistorySize);
844
+ }
845
+ }
846
+ function appendTrace(buffers, record) {
847
+ buffers.trace.push(record);
848
+ if (buffers.maxHistorySize !== void 0 && buffers.trace.length > buffers.maxHistorySize) {
849
+ buffers.trace.splice(0, buffers.trace.length - buffers.maxHistorySize);
850
+ }
851
+ for (const sink of buffers.traceSinks) {
852
+ try {
853
+ sink(record);
854
+ } catch {
855
+ }
856
+ }
857
+ }
858
+ async function recordAudit(buffers, type, event, details) {
859
+ if (!buffers.auditTrail) return;
860
+ try {
861
+ await buffers.auditTrail.record({
862
+ type,
863
+ source: event.metadata.source,
864
+ intent: event.intent,
865
+ correlationId: event.metadata.correlationId,
866
+ causationId: event.metadata.causationId,
867
+ subject: event.intent,
868
+ details
869
+ });
870
+ } catch (err) {
871
+ appendTrace(buffers, {
872
+ type: "hook.error",
873
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
874
+ intent: event.intent,
875
+ correlationId: event.metadata.correlationId,
876
+ traceId: event.metadata.traceId,
877
+ spanId: event.metadata.spanId,
878
+ details: {
879
+ hook: "auditTrail",
880
+ error: err instanceof Error ? err.message : String(err)
881
+ }
882
+ });
883
+ }
884
+ }
885
+ async function recordRawPublishDiagnostic(buffers, event) {
886
+ const details = {
887
+ intent: event.intent,
888
+ source: event.metadata.source,
889
+ suggestion: "Publish through a registered intent creator so strict registry, contracts, and agent tooling share one source of truth."
890
+ };
891
+ appendTrace(buffers, {
892
+ type: "event.rawPublish",
893
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
894
+ intent: event.intent,
895
+ correlationId: event.metadata.correlationId,
896
+ traceId: event.metadata.traceId,
897
+ spanId: event.metadata.spanId,
898
+ details
899
+ });
900
+ await recordAudit(buffers, "event.rawPublish", event, details);
901
+ }
902
+ async function recordSuccessfulPublish(buffers, event, subscribersNotified) {
903
+ const record = {
904
+ event,
905
+ publishedAt: (/* @__PURE__ */ new Date()).toISOString(),
906
+ subscribersNotified
907
+ };
908
+ appendHistory(buffers, record);
909
+ await buffers.outbox?.enqueue(event);
910
+ appendTrace(buffers, {
911
+ type: "event.published",
912
+ timestamp: record.publishedAt,
913
+ intent: event.intent,
914
+ correlationId: event.metadata.correlationId,
915
+ traceId: event.metadata.traceId,
916
+ spanId: event.metadata.spanId,
917
+ details: { subscribersNotified }
918
+ });
919
+ await recordAudit(buffers, "event.published", event, {
920
+ subscribersNotified
921
+ });
922
+ return record;
923
+ }
924
+ function enrichMetadata(base, extra, instanceId) {
925
+ return {
926
+ ...base,
927
+ ...extra,
928
+ occurredAt: extra.occurredAt || base.occurredAt || (/* @__PURE__ */ new Date()).toISOString(),
929
+ source: extra.source || base.source || "unknown",
930
+ kernelInstanceId: extra.kernelInstanceId ?? base.kernelInstanceId ?? instanceId,
931
+ eventVersion: extra.eventVersion ?? base.eventVersion,
932
+ schemaVersion: extra.schemaVersion ?? base.schemaVersion,
933
+ allowInterception: extra.allowInterception ?? base.allowInterception,
934
+ interceptions: extra.interceptions ?? base.interceptions,
935
+ correlationId: extra.correlationId ?? base.correlationId,
936
+ causationId: extra.causationId ?? base.causationId,
937
+ traceId: extra.traceId ?? base.traceId,
938
+ spanId: extra.spanId ?? base.spanId,
939
+ parentSpanId: extra.parentSpanId ?? base.parentSpanId
940
+ };
941
+ }
942
+
943
+ // src/kernel/event-bus/EventBus.ts
944
+ var interceptorSequence = 0;
945
+ function nextInterceptorRegistrationId() {
946
+ interceptorSequence += 1;
947
+ return `interceptor-${Date.now()}-${interceptorSequence}`;
948
+ }
627
949
  var EventBusImpl = class {
628
950
  subscriptions = [];
629
951
  subscriptionsByIntent = /* @__PURE__ */ new Map();
630
952
  interceptors = [];
631
953
  interceptorsByIntent = /* @__PURE__ */ new Map();
632
- history = [];
633
- trace = [];
954
+ recording;
634
955
  onPublish;
635
956
  onSoftViolation;
636
957
  onHandlerError;
637
- auditTrail;
638
958
  eventContracts;
639
959
  strictEventContracts;
640
960
  requireKnownSource;
641
961
  architectureProfile;
642
962
  enforceObservedLayerFlowMode;
643
- outbox;
644
- instanceId;
645
- traceSinks;
646
963
  rethrowHandlerErrors;
647
964
  policyEngine;
648
965
  getPolicyContext;
649
- maxHistorySize;
650
966
  intentRegistry;
651
967
  dependencyGraph;
652
968
  strictRegistry;
@@ -655,21 +971,25 @@ var EventBusImpl = class {
655
971
  this.onPublish = options.onPublish;
656
972
  this.onSoftViolation = options.onSoftViolation;
657
973
  this.onHandlerError = options.onHandlerError;
658
- this.auditTrail = options.auditTrail;
659
974
  this.eventContracts = options.eventContracts;
660
975
  this.strictEventContracts = options.strictEventContracts ?? false;
661
976
  this.requireKnownSource = options.requireKnownSource ?? false;
662
977
  this.architectureProfile = options.architectureProfile;
663
978
  this.enforceObservedLayerFlowMode = options.enforceObservedLayerFlow ?? "off";
664
- this.outbox = options.outbox;
665
- this.instanceId = options.instanceId;
666
- this.traceSinks = [...options.traceSinks ?? []];
667
979
  this.rethrowHandlerErrors = options.rethrowHandlerErrors ?? false;
668
- this.maxHistorySize = options.maxHistorySize;
669
980
  this.intentRegistry = options.intentRegistry;
670
981
  this.dependencyGraph = options.dependencyGraph;
671
982
  this.strictRegistry = options.strictRegistry ?? options.intentRegistry !== void 0;
672
983
  this.validateIntentNaming = options.validateIntentNaming ?? this.strictRegistry;
984
+ this.recording = {
985
+ history: [],
986
+ trace: [],
987
+ maxHistorySize: options.maxHistorySize,
988
+ traceSinks: [...options.traceSinks ?? []],
989
+ auditTrail: options.auditTrail,
990
+ outbox: options.outbox,
991
+ instanceId: options.instanceId
992
+ };
673
993
  if (options.policyEngine) {
674
994
  this.policyEngine = options.policyEngine;
675
995
  } else if (options.policies && options.policies.length > 0) {
@@ -700,94 +1020,77 @@ var EventBusImpl = class {
700
1020
  const created = creator(payload);
701
1021
  event = {
702
1022
  ...created,
703
- metadata: this.enrichMetadata(created.metadata, extraMeta)
1023
+ metadata: enrichMetadata(
1024
+ created.metadata,
1025
+ extraMeta,
1026
+ this.recording.instanceId
1027
+ )
704
1028
  };
705
1029
  } else {
706
1030
  const rawEvent = eventOrCreator;
707
1031
  const extraMeta = metadata ?? payloadOrMeta ?? {};
708
1032
  event = {
709
1033
  ...rawEvent,
710
- metadata: this.enrichMetadata(rawEvent.metadata, extraMeta)
1034
+ metadata: enrichMetadata(
1035
+ rawEvent.metadata,
1036
+ extraMeta,
1037
+ this.recording.instanceId
1038
+ )
711
1039
  };
712
1040
  }
713
1041
  if (rawPublish && this.strictRegistry) {
714
- await this.recordRawPublishDiagnostic(event);
715
- }
716
- this.assertIntentAllowed(event.intent);
717
- this.assertSourceAllowed(event);
718
- this.assertContractAllowed(event);
719
- event = await this.applyInterceptors(event);
720
- this.assertContractAllowed(event);
721
- await this.assertObservedLayerFlowAllowed(event);
1042
+ await recordRawPublishDiagnostic(this.recording, event);
1043
+ }
1044
+ assertIntentAllowed(event.intent, {
1045
+ strictRegistry: this.strictRegistry,
1046
+ validateIntentNaming: this.validateIntentNaming,
1047
+ intentRegistry: this.intentRegistry
1048
+ });
1049
+ assertSourceAllowed(event, {
1050
+ requireKnownSource: this.requireKnownSource,
1051
+ intentRegistry: this.intentRegistry
1052
+ });
1053
+ assertContractAllowed(event, {
1054
+ eventContracts: this.eventContracts,
1055
+ strictEventContracts: this.strictEventContracts
1056
+ });
1057
+ event = await applyInterceptors(event, {
1058
+ interceptorsForIntent: (intent) => this.interceptorsByIntent.get(intent) ?? [],
1059
+ eventContracts: this.eventContracts,
1060
+ strictEventContracts: this.strictEventContracts,
1061
+ appendTrace: (r) => this.appendTrace(r),
1062
+ recordAudit: (type, e, details) => this.recordAudit(type, e, details)
1063
+ });
1064
+ assertContractAllowed(event, {
1065
+ eventContracts: this.eventContracts,
1066
+ strictEventContracts: this.strictEventContracts
1067
+ });
1068
+ await assertObservedLayerFlowAllowed(event, {
1069
+ mode: this.enforceObservedLayerFlowMode,
1070
+ architectureProfile: this.architectureProfile,
1071
+ appendTrace: (r) => this.appendTrace(r),
1072
+ recordAudit: (type, e, details) => this.recordAudit(type, e, details)
1073
+ });
722
1074
  this.dependencyGraph?.registerEventFlow(event.metadata.source, event.intent);
723
1075
  const matching = [...this.subscriptionsByIntent.get(event.intent) ?? []];
724
1076
  if (this.policyEngine) {
725
- const ctx = this.getPolicyContext(event);
726
- let policyResult;
727
- try {
728
- policyResult = this.policyEngine.enforce(ctx);
729
- } catch (err) {
730
- if (err instanceof PolicyViolationError) {
731
- this.appendTrace({
732
- type: "policy.hardViolation",
733
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
734
- intent: event.intent,
735
- correlationId: event.metadata.correlationId,
736
- traceId: event.metadata.traceId,
737
- spanId: event.metadata.spanId,
738
- details: { violations: err.violations }
739
- });
740
- await this.recordAudit("policy.hardViolation", event, {
741
- violations: err.violations
742
- });
743
- }
744
- throw err;
745
- }
746
- if (policyResult.softViolations.length > 0) {
747
- this.appendTrace({
748
- type: "policy.softViolation",
749
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
750
- intent: event.intent,
751
- correlationId: event.metadata.correlationId,
752
- traceId: event.metadata.traceId,
753
- spanId: event.metadata.spanId,
754
- details: { violations: policyResult.softViolations }
755
- });
756
- await this.recordAudit("policy.softViolation", event, {
757
- violations: policyResult.softViolations
758
- });
759
- if (this.onSoftViolation) {
760
- await this.safeHook(
761
- () => this.onSoftViolation(policyResult, event),
762
- "onSoftViolation",
763
- event
764
- );
765
- }
766
- }
1077
+ await enforcePublishPolicy(event, {
1078
+ policyEngine: this.policyEngine,
1079
+ getPolicyContext: this.getPolicyContext,
1080
+ appendTrace: (r) => this.appendTrace(r),
1081
+ recordAudit: (type, e, details) => this.recordAudit(type, e, details),
1082
+ onSoftViolation: this.onSoftViolation,
1083
+ safeHook: (fn, name, e) => this.safeHook(fn, name, e)
1084
+ });
767
1085
  }
768
- const record = {
1086
+ await recordSuccessfulPublish(
1087
+ this.recording,
769
1088
  event,
770
- publishedAt: (/* @__PURE__ */ new Date()).toISOString(),
771
- subscribersNotified: matching.length
772
- };
773
- this.appendHistory(record);
774
- await this.outbox?.enqueue(event);
775
- this.appendTrace({
776
- type: "event.published",
777
- timestamp: record.publishedAt,
778
- intent: event.intent,
779
- correlationId: event.metadata.correlationId,
780
- traceId: event.metadata.traceId,
781
- spanId: event.metadata.spanId,
782
- details: { subscribersNotified: matching.length }
783
- });
784
- await this.recordAudit("event.published", event, {
785
- subscribersNotified: matching.length
786
- });
787
- const notifications = matching.map(
788
- (sub) => this.invokeHandler(sub, event)
1089
+ matching.length
1090
+ );
1091
+ await Promise.all(
1092
+ matching.map((sub) => this.invokeHandler(sub, event))
789
1093
  );
790
- await Promise.all(notifications);
791
1094
  if (this.onPublish) {
792
1095
  await this.safeHook(
793
1096
  () => this.onPublish(event),
@@ -798,7 +1101,11 @@ var EventBusImpl = class {
798
1101
  }
799
1102
  createPublisher(source) {
800
1103
  const sourceName = typeof source === "string" ? source : source.name;
801
- this.assertIntentAllowed(sourceName);
1104
+ assertIntentAllowed(sourceName, {
1105
+ strictRegistry: this.strictRegistry,
1106
+ validateIntentNaming: this.validateIntentNaming,
1107
+ intentRegistry: this.intentRegistry
1108
+ });
802
1109
  return {
803
1110
  source: sourceName,
804
1111
  publish: async (intent, payload, metadata = {}) => {
@@ -814,7 +1121,11 @@ var EventBusImpl = class {
814
1121
  }
815
1122
  subscribe(intent, handler) {
816
1123
  const intentName = typeof intent === "string" ? intent : intent.name;
817
- this.assertIntentAllowed(intentName);
1124
+ assertIntentAllowed(intentName, {
1125
+ strictRegistry: this.strictRegistry,
1126
+ validateIntentNaming: this.validateIntentNaming,
1127
+ intentRegistry: this.intentRegistry
1128
+ });
818
1129
  const sub = {
819
1130
  intentName,
820
1131
  handler
@@ -835,7 +1146,11 @@ var EventBusImpl = class {
835
1146
  }
836
1147
  registerInterceptor(intent, interceptor, interceptorId) {
837
1148
  const intentName = typeof intent === "string" ? intent : intent.name;
838
- this.assertIntentAllowed(intentName);
1149
+ assertIntentAllowed(intentName, {
1150
+ strictRegistry: this.strictRegistry,
1151
+ validateIntentNaming: this.validateIntentNaming,
1152
+ intentRegistry: this.intentRegistry
1153
+ });
839
1154
  const registration = {
840
1155
  registrationId: nextInterceptorRegistrationId(),
841
1156
  interceptorId: interceptorId ?? intentName,
@@ -874,174 +1189,22 @@ var EventBusImpl = class {
874
1189
  }));
875
1190
  }
876
1191
  getHistory() {
877
- return [...this.history];
1192
+ return [...this.recording.history];
878
1193
  }
879
1194
  clearHistory() {
880
- this.history.length = 0;
1195
+ this.recording.history.length = 0;
881
1196
  }
882
1197
  getTrace() {
883
- return [...this.trace];
1198
+ return [...this.recording.trace];
884
1199
  }
885
1200
  clearTrace() {
886
- this.trace.length = 0;
887
- }
888
- assertIntentAllowed(intentName) {
889
- if (!this.strictRegistry && !this.validateIntentNaming) {
890
- return;
891
- }
892
- if (this.validateIntentNaming) {
893
- const validation = validateIntentName(intentName);
894
- if (!validation.valid) {
895
- throw new InvalidIntentNameError(intentName, validation.reason);
896
- }
897
- }
898
- if (this.strictRegistry && this.intentRegistry && !this.intentRegistry.has(intentName)) {
899
- throw new UnregisteredIntentError(intentName);
900
- }
901
- }
902
- assertSourceAllowed(event) {
903
- if (!this.requireKnownSource) return;
904
- if (!event.metadata.source || event.metadata.source === "unknown") {
905
- throw new UnknownEventSourceError(event.intent);
906
- }
907
- if (this.intentRegistry && !this.intentRegistry.has(event.metadata.source)) {
908
- throw new UnknownEventSourceError(event.intent, event.metadata.source);
909
- }
910
- }
911
- assertContractAllowed(event) {
912
- if (!this.eventContracts) return;
913
- const result = this.eventContracts.validate(event);
914
- if (!result.ok && (this.strictEventContracts || result.contract)) {
915
- throw new EventContractViolationError(event.intent, result.issues);
916
- }
917
- }
918
- /**
919
- * Enforce the OBSERVED producer→event flow (metadata.source → intent) against the
920
- * architecture profile's layer rules. This is the runtime counterpart to the
921
- * declared-model layer policy: it checks what the system actually did, resolving both
922
- * layers directly from the profile. It runs BEFORE the flow is recorded via
923
- * registerEventFlow, so in hard mode a rejected flow leaves no edge in the graph.
924
- */
925
- async assertObservedLayerFlowAllowed(event) {
926
- if (this.enforceObservedLayerFlowMode === "off" || !this.architectureProfile) {
927
- return;
928
- }
929
- const source = event.metadata.source;
930
- if (!source || source === "unknown") return;
931
- const profile = this.architectureProfile;
932
- const fromLayer = profile.resolveLayer(source);
933
- const toLayer = profile.resolveLayer(event.intent);
934
- if (!fromLayer || !toLayer) return;
935
- const blocked = profile.rules.find(
936
- (rule) => !rule.allowed && rule.from === fromLayer && rule.to === toLayer
937
- );
938
- if (!blocked) return;
939
- const severity = this.enforceObservedLayerFlowMode;
940
- const message = blocked.message ?? `Observed layer violation: "${source}" (${fromLayer}) must not produce "${event.intent}" (${toLayer}).`;
941
- const details = {
942
- source,
943
- intent: event.intent,
944
- fromLayer,
945
- toLayer,
946
- severity,
947
- message,
948
- rule: blocked
949
- };
950
- this.appendTrace({
951
- type: "layer.observedViolation",
952
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
953
- intent: event.intent,
954
- correlationId: event.metadata.correlationId,
955
- traceId: event.metadata.traceId,
956
- spanId: event.metadata.spanId,
957
- details
958
- });
959
- await this.recordAudit("layer.observedViolation", event, details);
960
- if (severity === "hard") {
961
- throw new ObservedLayerFlowViolationError(source, event.intent, fromLayer, toLayer, message);
962
- }
1201
+ this.recording.trace.length = 0;
963
1202
  }
964
- async recordRawPublishDiagnostic(event) {
965
- const details = {
966
- intent: event.intent,
967
- source: event.metadata.source,
968
- suggestion: "Publish through a registered intent creator so strict registry, contracts, and agent tooling share one source of truth."
969
- };
970
- this.appendTrace({
971
- type: "event.rawPublish",
972
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
973
- intent: event.intent,
974
- correlationId: event.metadata.correlationId,
975
- traceId: event.metadata.traceId,
976
- spanId: event.metadata.spanId,
977
- details
978
- });
979
- await this.recordAudit("event.rawPublish", event, details);
1203
+ appendTrace(record) {
1204
+ appendTrace(this.recording, record);
980
1205
  }
981
- async applyInterceptors(event) {
982
- if (event.metadata.allowInterception === false) {
983
- return event;
984
- }
985
- const matching = [...this.interceptorsByIntent.get(event.intent) ?? []];
986
- let current = event;
987
- for (const registration of matching) {
988
- const patches = [];
989
- try {
990
- await Promise.resolve(
991
- registration.interceptor({
992
- event: current,
993
- intercept: (patch) => {
994
- patches.push(patch);
995
- }
996
- })
997
- );
998
- if (patches.length === 0) {
999
- continue;
1000
- }
1001
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
1002
- let candidate = {
1003
- ...current,
1004
- metadata: {
1005
- ...current.metadata,
1006
- interceptions: [
1007
- ...current.metadata.interceptions ?? [],
1008
- { interceptorId: registration.interceptorId, timestamp }
1009
- ]
1010
- }
1011
- };
1012
- for (const patch of patches) {
1013
- candidate = {
1014
- ...candidate,
1015
- payload: applyPayloadPatch(candidate.payload, patch),
1016
- metadata: { ...candidate.metadata }
1017
- };
1018
- }
1019
- this.assertContractAllowed(candidate);
1020
- current = candidate;
1021
- registration.lastInterceptedAt = timestamp;
1022
- this.appendTrace({
1023
- type: "event.intercepted",
1024
- timestamp,
1025
- intent: current.intent,
1026
- correlationId: current.metadata.correlationId,
1027
- traceId: current.metadata.traceId,
1028
- spanId: current.metadata.spanId,
1029
- details: {
1030
- registrationId: registration.registrationId,
1031
- interceptorId: registration.interceptorId,
1032
- patchesApplied: patches.length
1033
- }
1034
- });
1035
- await this.recordAudit("event.intercepted", current, {
1036
- registrationId: registration.registrationId,
1037
- interceptorId: registration.interceptorId,
1038
- patchesApplied: patches.length
1039
- });
1040
- } catch (err) {
1041
- await this.recordInterceptorError(registration, current, err);
1042
- }
1043
- }
1044
- return current;
1206
+ async recordAudit(type, event, details) {
1207
+ await recordAudit(this.recording, type, event, details);
1045
1208
  }
1046
1209
  async invokeHandler(sub, event) {
1047
1210
  try {
@@ -1094,90 +1257,6 @@ var EventBusImpl = class {
1094
1257
  });
1095
1258
  }
1096
1259
  }
1097
- async recordInterceptorError(interceptor, event, error) {
1098
- const message = error instanceof Error ? error.message : String(error);
1099
- this.appendTrace({
1100
- type: "interceptor.error",
1101
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1102
- intent: event.intent,
1103
- correlationId: event.metadata.correlationId,
1104
- traceId: event.metadata.traceId,
1105
- spanId: event.metadata.spanId,
1106
- details: {
1107
- registrationId: interceptor.registrationId,
1108
- interceptorId: interceptor.interceptorId,
1109
- error: message
1110
- }
1111
- });
1112
- await this.recordAudit("interceptor.error", event, {
1113
- registrationId: interceptor.registrationId,
1114
- interceptorId: interceptor.interceptorId,
1115
- error: message
1116
- });
1117
- }
1118
- appendHistory(record) {
1119
- this.history.push(record);
1120
- if (this.maxHistorySize !== void 0 && this.history.length > this.maxHistorySize) {
1121
- this.history.splice(0, this.history.length - this.maxHistorySize);
1122
- }
1123
- }
1124
- appendTrace(record) {
1125
- this.trace.push(record);
1126
- if (this.maxHistorySize !== void 0 && this.trace.length > this.maxHistorySize) {
1127
- this.trace.splice(0, this.trace.length - this.maxHistorySize);
1128
- }
1129
- for (const sink of this.traceSinks) {
1130
- try {
1131
- sink(record);
1132
- } catch {
1133
- }
1134
- }
1135
- }
1136
- async recordAudit(type, event, details) {
1137
- if (!this.auditTrail) return;
1138
- try {
1139
- await this.auditTrail.record({
1140
- type,
1141
- source: event.metadata.source,
1142
- intent: event.intent,
1143
- correlationId: event.metadata.correlationId,
1144
- causationId: event.metadata.causationId,
1145
- subject: event.intent,
1146
- details
1147
- });
1148
- } catch (err) {
1149
- this.appendTrace({
1150
- type: "hook.error",
1151
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1152
- intent: event.intent,
1153
- correlationId: event.metadata.correlationId,
1154
- traceId: event.metadata.traceId,
1155
- spanId: event.metadata.spanId,
1156
- details: {
1157
- hook: "auditTrail",
1158
- error: err instanceof Error ? err.message : String(err)
1159
- }
1160
- });
1161
- }
1162
- }
1163
- enrichMetadata(base, extra) {
1164
- return {
1165
- ...base,
1166
- ...extra,
1167
- occurredAt: extra.occurredAt || base.occurredAt || (/* @__PURE__ */ new Date()).toISOString(),
1168
- source: extra.source || base.source || "unknown",
1169
- kernelInstanceId: extra.kernelInstanceId ?? base.kernelInstanceId ?? this.instanceId,
1170
- eventVersion: extra.eventVersion ?? base.eventVersion,
1171
- schemaVersion: extra.schemaVersion ?? base.schemaVersion,
1172
- allowInterception: extra.allowInterception ?? base.allowInterception,
1173
- interceptions: extra.interceptions ?? base.interceptions,
1174
- correlationId: extra.correlationId ?? base.correlationId,
1175
- causationId: extra.causationId ?? base.causationId,
1176
- traceId: extra.traceId ?? base.traceId,
1177
- spanId: extra.spanId ?? base.spanId,
1178
- parentSpanId: extra.parentSpanId ?? base.parentSpanId
1179
- };
1180
- }
1181
1260
  };
1182
1261
  function createEventBus(options) {
1183
1262
  return new EventBusImpl(options);