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.
@@ -104,41 +104,6 @@ function createAuditTrail(options = {}) {
104
104
  );
105
105
  }
106
106
 
107
- // src/kernel/intent/validateIntentName.ts
108
- var ALLOWED_PREFIXES = [
109
- "Domain.",
110
- "Application.",
111
- "Adapter.",
112
- "Workflow.",
113
- "Job.",
114
- "Presentation.",
115
- "Reporting.",
116
- "Metadata.",
117
- "Security.",
118
- "Audit.",
119
- "Observability.",
120
- "Kernel."
121
- ];
122
- function validateIntentName(name) {
123
- if (!name || typeof name !== "string") {
124
- return { valid: false, reason: "Intent name must be a non-empty string" };
125
- }
126
- if (!ALLOWED_PREFIXES.some((p) => name.startsWith(p))) {
127
- return {
128
- valid: false,
129
- reason: `Intent "${name}" must start with one of: ${ALLOWED_PREFIXES.join(", ")}`
130
- };
131
- }
132
- const rest = name.slice(name.indexOf(".") + 1);
133
- if (!rest || !/^[A-Za-z][A-Za-z0-9_.]*$/.test(rest)) {
134
- return {
135
- valid: false,
136
- reason: `Intent "${name}" has an invalid segment after the layer prefix`
137
- };
138
- }
139
- return { valid: true };
140
- }
141
-
142
107
  // src/kernel/policy/PolicyViolationError.ts
143
108
  var PolicyViolationError = class extends Error {
144
109
  violations;
@@ -405,12 +370,74 @@ var ObservedLayerFlowViolationError = class extends Error {
405
370
  }
406
371
  };
407
372
 
408
- // src/kernel/event-bus/EventBus.ts
409
- var interceptorSequence = 0;
410
- function nextInterceptorRegistrationId() {
411
- interceptorSequence += 1;
412
- return `interceptor-${Date.now()}-${interceptorSequence}`;
373
+ // src/kernel/intent/validateIntentName.ts
374
+ var ALLOWED_PREFIXES = [
375
+ "Domain.",
376
+ "Application.",
377
+ "Adapter.",
378
+ "Workflow.",
379
+ "Job.",
380
+ "Presentation.",
381
+ "Reporting.",
382
+ "Metadata.",
383
+ "Security.",
384
+ "Audit.",
385
+ "Observability.",
386
+ "Kernel."
387
+ ];
388
+ function validateIntentName(name) {
389
+ if (!name || typeof name !== "string") {
390
+ return { valid: false, reason: "Intent name must be a non-empty string" };
391
+ }
392
+ if (!ALLOWED_PREFIXES.some((p) => name.startsWith(p))) {
393
+ return {
394
+ valid: false,
395
+ reason: `Intent "${name}" must start with one of: ${ALLOWED_PREFIXES.join(", ")}`
396
+ };
397
+ }
398
+ const rest = name.slice(name.indexOf(".") + 1);
399
+ if (!rest || !/^[A-Za-z][A-Za-z0-9_.]*$/.test(rest)) {
400
+ return {
401
+ valid: false,
402
+ reason: `Intent "${name}" has an invalid segment after the layer prefix`
403
+ };
404
+ }
405
+ return { valid: true };
406
+ }
407
+
408
+ // src/kernel/event-bus/publishGuards.ts
409
+ function assertIntentAllowed(intentName, options) {
410
+ if (!options.strictRegistry && !options.validateIntentNaming) {
411
+ return;
412
+ }
413
+ if (options.validateIntentNaming) {
414
+ const validation = validateIntentName(intentName);
415
+ if (!validation.valid) {
416
+ throw new InvalidIntentNameError(intentName, validation.reason);
417
+ }
418
+ }
419
+ if (options.strictRegistry && options.intentRegistry && !options.intentRegistry.has(intentName)) {
420
+ throw new UnregisteredIntentError(intentName);
421
+ }
422
+ }
423
+ function assertSourceAllowed(event, options) {
424
+ if (!options.requireKnownSource) return;
425
+ if (!event.metadata.source || event.metadata.source === "unknown") {
426
+ throw new UnknownEventSourceError(event.intent);
427
+ }
428
+ if (options.intentRegistry && !options.intentRegistry.has(event.metadata.source)) {
429
+ throw new UnknownEventSourceError(event.intent, event.metadata.source);
430
+ }
431
+ }
432
+ function assertContractAllowed(event, options) {
433
+ if (!options.eventContracts) return;
434
+ const result = options.eventContracts.validate(event);
435
+ if (!result.ok && (options.strictEventContracts || result.contract)) {
436
+ throw new EventContractViolationError(event.intent, result.issues);
437
+ }
413
438
  }
439
+
440
+ // src/kernel/event-bus/payloadPatch.ts
414
441
  function isPlainRecord(value) {
415
442
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
416
443
  return false;
@@ -481,29 +508,318 @@ function applyPayloadPatch(payload, patch) {
481
508
  }
482
509
  return mergeRecordPatch(payload, patch);
483
510
  }
511
+
512
+ // src/kernel/event-bus/publishInterceptors.ts
513
+ async function applyInterceptors(event, deps) {
514
+ if (event.metadata.allowInterception === false) {
515
+ return event;
516
+ }
517
+ const matching = [...deps.interceptorsForIntent(event.intent)];
518
+ let current = event;
519
+ for (const registration of matching) {
520
+ const patches = [];
521
+ try {
522
+ await Promise.resolve(
523
+ registration.interceptor({
524
+ event: current,
525
+ intercept: (patch) => {
526
+ patches.push(patch);
527
+ }
528
+ })
529
+ );
530
+ if (patches.length === 0) {
531
+ continue;
532
+ }
533
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
534
+ let candidate = {
535
+ ...current,
536
+ metadata: {
537
+ ...current.metadata,
538
+ interceptions: [
539
+ ...current.metadata.interceptions ?? [],
540
+ { interceptorId: registration.interceptorId, timestamp }
541
+ ]
542
+ }
543
+ };
544
+ for (const patch of patches) {
545
+ candidate = {
546
+ ...candidate,
547
+ payload: applyPayloadPatch(candidate.payload, patch),
548
+ metadata: { ...candidate.metadata }
549
+ };
550
+ }
551
+ assertContractAllowed(candidate, {
552
+ eventContracts: deps.eventContracts,
553
+ strictEventContracts: deps.strictEventContracts
554
+ });
555
+ current = candidate;
556
+ registration.lastInterceptedAt = timestamp;
557
+ deps.appendTrace({
558
+ type: "event.intercepted",
559
+ timestamp,
560
+ intent: current.intent,
561
+ correlationId: current.metadata.correlationId,
562
+ traceId: current.metadata.traceId,
563
+ spanId: current.metadata.spanId,
564
+ details: {
565
+ registrationId: registration.registrationId,
566
+ interceptorId: registration.interceptorId,
567
+ patchesApplied: patches.length
568
+ }
569
+ });
570
+ await deps.recordAudit("event.intercepted", current, {
571
+ registrationId: registration.registrationId,
572
+ interceptorId: registration.interceptorId,
573
+ patchesApplied: patches.length
574
+ });
575
+ } catch (err) {
576
+ await recordInterceptorError(registration, current, err, deps);
577
+ }
578
+ }
579
+ return current;
580
+ }
581
+ async function recordInterceptorError(interceptor, event, error, deps) {
582
+ const message = error instanceof Error ? error.message : String(error);
583
+ deps.appendTrace({
584
+ type: "interceptor.error",
585
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
586
+ intent: event.intent,
587
+ correlationId: event.metadata.correlationId,
588
+ traceId: event.metadata.traceId,
589
+ spanId: event.metadata.spanId,
590
+ details: {
591
+ registrationId: interceptor.registrationId,
592
+ interceptorId: interceptor.interceptorId,
593
+ error: message
594
+ }
595
+ });
596
+ await deps.recordAudit("interceptor.error", event, {
597
+ registrationId: interceptor.registrationId,
598
+ interceptorId: interceptor.interceptorId,
599
+ error: message
600
+ });
601
+ }
602
+
603
+ // src/kernel/event-bus/observedLayerFlow.ts
604
+ async function assertObservedLayerFlowAllowed(event, deps) {
605
+ if (deps.mode === "off" || !deps.architectureProfile) {
606
+ return;
607
+ }
608
+ const source = event.metadata.source;
609
+ if (!source || source === "unknown") return;
610
+ const profile = deps.architectureProfile;
611
+ const fromLayer = profile.resolveLayer(source);
612
+ const toLayer = profile.resolveLayer(event.intent);
613
+ if (!fromLayer || !toLayer) return;
614
+ const blocked = profile.rules.find(
615
+ (rule) => !rule.allowed && rule.from === fromLayer && rule.to === toLayer
616
+ );
617
+ if (!blocked) return;
618
+ const severity = deps.mode;
619
+ const message = blocked.message ?? `Observed layer violation: "${source}" (${fromLayer}) must not produce "${event.intent}" (${toLayer}).`;
620
+ const details = {
621
+ source,
622
+ intent: event.intent,
623
+ fromLayer,
624
+ toLayer,
625
+ severity,
626
+ message,
627
+ rule: blocked
628
+ };
629
+ deps.appendTrace({
630
+ type: "layer.observedViolation",
631
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
632
+ intent: event.intent,
633
+ correlationId: event.metadata.correlationId,
634
+ traceId: event.metadata.traceId,
635
+ spanId: event.metadata.spanId,
636
+ details
637
+ });
638
+ await deps.recordAudit("layer.observedViolation", event, details);
639
+ if (severity === "hard") {
640
+ throw new ObservedLayerFlowViolationError(
641
+ source,
642
+ event.intent,
643
+ fromLayer,
644
+ toLayer,
645
+ message
646
+ );
647
+ }
648
+ }
649
+
650
+ // src/kernel/event-bus/publishPolicy.ts
651
+ async function enforcePublishPolicy(event, deps) {
652
+ const ctx = deps.getPolicyContext(event);
653
+ let policyResult;
654
+ try {
655
+ policyResult = deps.policyEngine.enforce(ctx);
656
+ } catch (err) {
657
+ if (err instanceof PolicyViolationError) {
658
+ deps.appendTrace({
659
+ type: "policy.hardViolation",
660
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
661
+ intent: event.intent,
662
+ correlationId: event.metadata.correlationId,
663
+ traceId: event.metadata.traceId,
664
+ spanId: event.metadata.spanId,
665
+ details: { violations: err.violations }
666
+ });
667
+ await deps.recordAudit("policy.hardViolation", event, {
668
+ violations: err.violations
669
+ });
670
+ }
671
+ throw err;
672
+ }
673
+ if (policyResult.softViolations.length > 0) {
674
+ deps.appendTrace({
675
+ type: "policy.softViolation",
676
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
677
+ intent: event.intent,
678
+ correlationId: event.metadata.correlationId,
679
+ traceId: event.metadata.traceId,
680
+ spanId: event.metadata.spanId,
681
+ details: { violations: policyResult.softViolations }
682
+ });
683
+ await deps.recordAudit("policy.softViolation", event, {
684
+ violations: policyResult.softViolations
685
+ });
686
+ if (deps.onSoftViolation) {
687
+ await deps.safeHook(
688
+ () => deps.onSoftViolation(policyResult, event),
689
+ "onSoftViolation",
690
+ event
691
+ );
692
+ }
693
+ }
694
+ }
695
+
696
+ // src/kernel/event-bus/publishRecording.ts
697
+ function appendHistory(buffers, record) {
698
+ buffers.history.push(record);
699
+ if (buffers.maxHistorySize !== void 0 && buffers.history.length > buffers.maxHistorySize) {
700
+ buffers.history.splice(0, buffers.history.length - buffers.maxHistorySize);
701
+ }
702
+ }
703
+ function appendTrace(buffers, record) {
704
+ buffers.trace.push(record);
705
+ if (buffers.maxHistorySize !== void 0 && buffers.trace.length > buffers.maxHistorySize) {
706
+ buffers.trace.splice(0, buffers.trace.length - buffers.maxHistorySize);
707
+ }
708
+ for (const sink of buffers.traceSinks) {
709
+ try {
710
+ sink(record);
711
+ } catch {
712
+ }
713
+ }
714
+ }
715
+ async function recordAudit(buffers, type, event, details) {
716
+ if (!buffers.auditTrail) return;
717
+ try {
718
+ await buffers.auditTrail.record({
719
+ type,
720
+ source: event.metadata.source,
721
+ intent: event.intent,
722
+ correlationId: event.metadata.correlationId,
723
+ causationId: event.metadata.causationId,
724
+ subject: event.intent,
725
+ details
726
+ });
727
+ } catch (err) {
728
+ appendTrace(buffers, {
729
+ type: "hook.error",
730
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
731
+ intent: event.intent,
732
+ correlationId: event.metadata.correlationId,
733
+ traceId: event.metadata.traceId,
734
+ spanId: event.metadata.spanId,
735
+ details: {
736
+ hook: "auditTrail",
737
+ error: err instanceof Error ? err.message : String(err)
738
+ }
739
+ });
740
+ }
741
+ }
742
+ async function recordRawPublishDiagnostic(buffers, event) {
743
+ const details = {
744
+ intent: event.intent,
745
+ source: event.metadata.source,
746
+ suggestion: "Publish through a registered intent creator so strict registry, contracts, and agent tooling share one source of truth."
747
+ };
748
+ appendTrace(buffers, {
749
+ type: "event.rawPublish",
750
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
751
+ intent: event.intent,
752
+ correlationId: event.metadata.correlationId,
753
+ traceId: event.metadata.traceId,
754
+ spanId: event.metadata.spanId,
755
+ details
756
+ });
757
+ await recordAudit(buffers, "event.rawPublish", event, details);
758
+ }
759
+ async function recordSuccessfulPublish(buffers, event, subscribersNotified) {
760
+ const record = {
761
+ event,
762
+ publishedAt: (/* @__PURE__ */ new Date()).toISOString(),
763
+ subscribersNotified
764
+ };
765
+ appendHistory(buffers, record);
766
+ await buffers.outbox?.enqueue(event);
767
+ appendTrace(buffers, {
768
+ type: "event.published",
769
+ timestamp: record.publishedAt,
770
+ intent: event.intent,
771
+ correlationId: event.metadata.correlationId,
772
+ traceId: event.metadata.traceId,
773
+ spanId: event.metadata.spanId,
774
+ details: { subscribersNotified }
775
+ });
776
+ await recordAudit(buffers, "event.published", event, {
777
+ subscribersNotified
778
+ });
779
+ return record;
780
+ }
781
+ function enrichMetadata(base, extra, instanceId) {
782
+ return {
783
+ ...base,
784
+ ...extra,
785
+ occurredAt: extra.occurredAt || base.occurredAt || (/* @__PURE__ */ new Date()).toISOString(),
786
+ source: extra.source || base.source || "unknown",
787
+ kernelInstanceId: extra.kernelInstanceId ?? base.kernelInstanceId ?? instanceId,
788
+ eventVersion: extra.eventVersion ?? base.eventVersion,
789
+ schemaVersion: extra.schemaVersion ?? base.schemaVersion,
790
+ allowInterception: extra.allowInterception ?? base.allowInterception,
791
+ interceptions: extra.interceptions ?? base.interceptions,
792
+ correlationId: extra.correlationId ?? base.correlationId,
793
+ causationId: extra.causationId ?? base.causationId,
794
+ traceId: extra.traceId ?? base.traceId,
795
+ spanId: extra.spanId ?? base.spanId,
796
+ parentSpanId: extra.parentSpanId ?? base.parentSpanId
797
+ };
798
+ }
799
+
800
+ // src/kernel/event-bus/EventBus.ts
801
+ var interceptorSequence = 0;
802
+ function nextInterceptorRegistrationId() {
803
+ interceptorSequence += 1;
804
+ return `interceptor-${Date.now()}-${interceptorSequence}`;
805
+ }
484
806
  var EventBusImpl = class {
485
807
  subscriptions = [];
486
808
  subscriptionsByIntent = /* @__PURE__ */ new Map();
487
809
  interceptors = [];
488
810
  interceptorsByIntent = /* @__PURE__ */ new Map();
489
- history = [];
490
- trace = [];
811
+ recording;
491
812
  onPublish;
492
813
  onSoftViolation;
493
814
  onHandlerError;
494
- auditTrail;
495
815
  eventContracts;
496
816
  strictEventContracts;
497
817
  requireKnownSource;
498
818
  architectureProfile;
499
819
  enforceObservedLayerFlowMode;
500
- outbox;
501
- instanceId;
502
- traceSinks;
503
820
  rethrowHandlerErrors;
504
821
  policyEngine;
505
822
  getPolicyContext;
506
- maxHistorySize;
507
823
  intentRegistry;
508
824
  dependencyGraph;
509
825
  strictRegistry;
@@ -512,21 +828,25 @@ var EventBusImpl = class {
512
828
  this.onPublish = options.onPublish;
513
829
  this.onSoftViolation = options.onSoftViolation;
514
830
  this.onHandlerError = options.onHandlerError;
515
- this.auditTrail = options.auditTrail;
516
831
  this.eventContracts = options.eventContracts;
517
832
  this.strictEventContracts = options.strictEventContracts ?? false;
518
833
  this.requireKnownSource = options.requireKnownSource ?? false;
519
834
  this.architectureProfile = options.architectureProfile;
520
835
  this.enforceObservedLayerFlowMode = options.enforceObservedLayerFlow ?? "off";
521
- this.outbox = options.outbox;
522
- this.instanceId = options.instanceId;
523
- this.traceSinks = [...options.traceSinks ?? []];
524
836
  this.rethrowHandlerErrors = options.rethrowHandlerErrors ?? false;
525
- this.maxHistorySize = options.maxHistorySize;
526
837
  this.intentRegistry = options.intentRegistry;
527
838
  this.dependencyGraph = options.dependencyGraph;
528
839
  this.strictRegistry = options.strictRegistry ?? options.intentRegistry !== void 0;
529
840
  this.validateIntentNaming = options.validateIntentNaming ?? this.strictRegistry;
841
+ this.recording = {
842
+ history: [],
843
+ trace: [],
844
+ maxHistorySize: options.maxHistorySize,
845
+ traceSinks: [...options.traceSinks ?? []],
846
+ auditTrail: options.auditTrail,
847
+ outbox: options.outbox,
848
+ instanceId: options.instanceId
849
+ };
530
850
  if (options.policyEngine) {
531
851
  this.policyEngine = options.policyEngine;
532
852
  } else if (options.policies && options.policies.length > 0) {
@@ -557,94 +877,77 @@ var EventBusImpl = class {
557
877
  const created = creator(payload);
558
878
  event = {
559
879
  ...created,
560
- metadata: this.enrichMetadata(created.metadata, extraMeta)
880
+ metadata: enrichMetadata(
881
+ created.metadata,
882
+ extraMeta,
883
+ this.recording.instanceId
884
+ )
561
885
  };
562
886
  } else {
563
887
  const rawEvent = eventOrCreator;
564
888
  const extraMeta = metadata ?? payloadOrMeta ?? {};
565
889
  event = {
566
890
  ...rawEvent,
567
- metadata: this.enrichMetadata(rawEvent.metadata, extraMeta)
891
+ metadata: enrichMetadata(
892
+ rawEvent.metadata,
893
+ extraMeta,
894
+ this.recording.instanceId
895
+ )
568
896
  };
569
897
  }
570
898
  if (rawPublish && this.strictRegistry) {
571
- await this.recordRawPublishDiagnostic(event);
572
- }
573
- this.assertIntentAllowed(event.intent);
574
- this.assertSourceAllowed(event);
575
- this.assertContractAllowed(event);
576
- event = await this.applyInterceptors(event);
577
- this.assertContractAllowed(event);
578
- await this.assertObservedLayerFlowAllowed(event);
899
+ await recordRawPublishDiagnostic(this.recording, event);
900
+ }
901
+ assertIntentAllowed(event.intent, {
902
+ strictRegistry: this.strictRegistry,
903
+ validateIntentNaming: this.validateIntentNaming,
904
+ intentRegistry: this.intentRegistry
905
+ });
906
+ assertSourceAllowed(event, {
907
+ requireKnownSource: this.requireKnownSource,
908
+ intentRegistry: this.intentRegistry
909
+ });
910
+ assertContractAllowed(event, {
911
+ eventContracts: this.eventContracts,
912
+ strictEventContracts: this.strictEventContracts
913
+ });
914
+ event = await applyInterceptors(event, {
915
+ interceptorsForIntent: (intent) => this.interceptorsByIntent.get(intent) ?? [],
916
+ eventContracts: this.eventContracts,
917
+ strictEventContracts: this.strictEventContracts,
918
+ appendTrace: (r) => this.appendTrace(r),
919
+ recordAudit: (type, e, details) => this.recordAudit(type, e, details)
920
+ });
921
+ assertContractAllowed(event, {
922
+ eventContracts: this.eventContracts,
923
+ strictEventContracts: this.strictEventContracts
924
+ });
925
+ await assertObservedLayerFlowAllowed(event, {
926
+ mode: this.enforceObservedLayerFlowMode,
927
+ architectureProfile: this.architectureProfile,
928
+ appendTrace: (r) => this.appendTrace(r),
929
+ recordAudit: (type, e, details) => this.recordAudit(type, e, details)
930
+ });
579
931
  this.dependencyGraph?.registerEventFlow(event.metadata.source, event.intent);
580
932
  const matching = [...this.subscriptionsByIntent.get(event.intent) ?? []];
581
933
  if (this.policyEngine) {
582
- const ctx = this.getPolicyContext(event);
583
- let policyResult;
584
- try {
585
- policyResult = this.policyEngine.enforce(ctx);
586
- } catch (err) {
587
- if (err instanceof PolicyViolationError) {
588
- this.appendTrace({
589
- type: "policy.hardViolation",
590
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
591
- intent: event.intent,
592
- correlationId: event.metadata.correlationId,
593
- traceId: event.metadata.traceId,
594
- spanId: event.metadata.spanId,
595
- details: { violations: err.violations }
596
- });
597
- await this.recordAudit("policy.hardViolation", event, {
598
- violations: err.violations
599
- });
600
- }
601
- throw err;
602
- }
603
- if (policyResult.softViolations.length > 0) {
604
- this.appendTrace({
605
- type: "policy.softViolation",
606
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
607
- intent: event.intent,
608
- correlationId: event.metadata.correlationId,
609
- traceId: event.metadata.traceId,
610
- spanId: event.metadata.spanId,
611
- details: { violations: policyResult.softViolations }
612
- });
613
- await this.recordAudit("policy.softViolation", event, {
614
- violations: policyResult.softViolations
615
- });
616
- if (this.onSoftViolation) {
617
- await this.safeHook(
618
- () => this.onSoftViolation(policyResult, event),
619
- "onSoftViolation",
620
- event
621
- );
622
- }
623
- }
934
+ await enforcePublishPolicy(event, {
935
+ policyEngine: this.policyEngine,
936
+ getPolicyContext: this.getPolicyContext,
937
+ appendTrace: (r) => this.appendTrace(r),
938
+ recordAudit: (type, e, details) => this.recordAudit(type, e, details),
939
+ onSoftViolation: this.onSoftViolation,
940
+ safeHook: (fn, name, e) => this.safeHook(fn, name, e)
941
+ });
624
942
  }
625
- const record = {
943
+ await recordSuccessfulPublish(
944
+ this.recording,
626
945
  event,
627
- publishedAt: (/* @__PURE__ */ new Date()).toISOString(),
628
- subscribersNotified: matching.length
629
- };
630
- this.appendHistory(record);
631
- await this.outbox?.enqueue(event);
632
- this.appendTrace({
633
- type: "event.published",
634
- timestamp: record.publishedAt,
635
- intent: event.intent,
636
- correlationId: event.metadata.correlationId,
637
- traceId: event.metadata.traceId,
638
- spanId: event.metadata.spanId,
639
- details: { subscribersNotified: matching.length }
640
- });
641
- await this.recordAudit("event.published", event, {
642
- subscribersNotified: matching.length
643
- });
644
- const notifications = matching.map(
645
- (sub) => this.invokeHandler(sub, event)
946
+ matching.length
947
+ );
948
+ await Promise.all(
949
+ matching.map((sub) => this.invokeHandler(sub, event))
646
950
  );
647
- await Promise.all(notifications);
648
951
  if (this.onPublish) {
649
952
  await this.safeHook(
650
953
  () => this.onPublish(event),
@@ -655,7 +958,11 @@ var EventBusImpl = class {
655
958
  }
656
959
  createPublisher(source) {
657
960
  const sourceName = typeof source === "string" ? source : source.name;
658
- this.assertIntentAllowed(sourceName);
961
+ assertIntentAllowed(sourceName, {
962
+ strictRegistry: this.strictRegistry,
963
+ validateIntentNaming: this.validateIntentNaming,
964
+ intentRegistry: this.intentRegistry
965
+ });
659
966
  return {
660
967
  source: sourceName,
661
968
  publish: async (intent, payload, metadata = {}) => {
@@ -671,7 +978,11 @@ var EventBusImpl = class {
671
978
  }
672
979
  subscribe(intent, handler) {
673
980
  const intentName = typeof intent === "string" ? intent : intent.name;
674
- this.assertIntentAllowed(intentName);
981
+ assertIntentAllowed(intentName, {
982
+ strictRegistry: this.strictRegistry,
983
+ validateIntentNaming: this.validateIntentNaming,
984
+ intentRegistry: this.intentRegistry
985
+ });
675
986
  const sub = {
676
987
  intentName,
677
988
  handler
@@ -692,7 +1003,11 @@ var EventBusImpl = class {
692
1003
  }
693
1004
  registerInterceptor(intent, interceptor, interceptorId) {
694
1005
  const intentName = typeof intent === "string" ? intent : intent.name;
695
- this.assertIntentAllowed(intentName);
1006
+ assertIntentAllowed(intentName, {
1007
+ strictRegistry: this.strictRegistry,
1008
+ validateIntentNaming: this.validateIntentNaming,
1009
+ intentRegistry: this.intentRegistry
1010
+ });
696
1011
  const registration = {
697
1012
  registrationId: nextInterceptorRegistrationId(),
698
1013
  interceptorId: interceptorId ?? intentName,
@@ -731,174 +1046,22 @@ var EventBusImpl = class {
731
1046
  }));
732
1047
  }
733
1048
  getHistory() {
734
- return [...this.history];
1049
+ return [...this.recording.history];
735
1050
  }
736
1051
  clearHistory() {
737
- this.history.length = 0;
1052
+ this.recording.history.length = 0;
738
1053
  }
739
1054
  getTrace() {
740
- return [...this.trace];
1055
+ return [...this.recording.trace];
741
1056
  }
742
1057
  clearTrace() {
743
- this.trace.length = 0;
744
- }
745
- assertIntentAllowed(intentName) {
746
- if (!this.strictRegistry && !this.validateIntentNaming) {
747
- return;
748
- }
749
- if (this.validateIntentNaming) {
750
- const validation = validateIntentName(intentName);
751
- if (!validation.valid) {
752
- throw new InvalidIntentNameError(intentName, validation.reason);
753
- }
754
- }
755
- if (this.strictRegistry && this.intentRegistry && !this.intentRegistry.has(intentName)) {
756
- throw new UnregisteredIntentError(intentName);
757
- }
758
- }
759
- assertSourceAllowed(event) {
760
- if (!this.requireKnownSource) return;
761
- if (!event.metadata.source || event.metadata.source === "unknown") {
762
- throw new UnknownEventSourceError(event.intent);
763
- }
764
- if (this.intentRegistry && !this.intentRegistry.has(event.metadata.source)) {
765
- throw new UnknownEventSourceError(event.intent, event.metadata.source);
766
- }
767
- }
768
- assertContractAllowed(event) {
769
- if (!this.eventContracts) return;
770
- const result = this.eventContracts.validate(event);
771
- if (!result.ok && (this.strictEventContracts || result.contract)) {
772
- throw new EventContractViolationError(event.intent, result.issues);
773
- }
774
- }
775
- /**
776
- * Enforce the OBSERVED producer→event flow (metadata.source → intent) against the
777
- * architecture profile's layer rules. This is the runtime counterpart to the
778
- * declared-model layer policy: it checks what the system actually did, resolving both
779
- * layers directly from the profile. It runs BEFORE the flow is recorded via
780
- * registerEventFlow, so in hard mode a rejected flow leaves no edge in the graph.
781
- */
782
- async assertObservedLayerFlowAllowed(event) {
783
- if (this.enforceObservedLayerFlowMode === "off" || !this.architectureProfile) {
784
- return;
785
- }
786
- const source = event.metadata.source;
787
- if (!source || source === "unknown") return;
788
- const profile = this.architectureProfile;
789
- const fromLayer = profile.resolveLayer(source);
790
- const toLayer = profile.resolveLayer(event.intent);
791
- if (!fromLayer || !toLayer) return;
792
- const blocked = profile.rules.find(
793
- (rule) => !rule.allowed && rule.from === fromLayer && rule.to === toLayer
794
- );
795
- if (!blocked) return;
796
- const severity = this.enforceObservedLayerFlowMode;
797
- const message = blocked.message ?? `Observed layer violation: "${source}" (${fromLayer}) must not produce "${event.intent}" (${toLayer}).`;
798
- const details = {
799
- source,
800
- intent: event.intent,
801
- fromLayer,
802
- toLayer,
803
- severity,
804
- message,
805
- rule: blocked
806
- };
807
- this.appendTrace({
808
- type: "layer.observedViolation",
809
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
810
- intent: event.intent,
811
- correlationId: event.metadata.correlationId,
812
- traceId: event.metadata.traceId,
813
- spanId: event.metadata.spanId,
814
- details
815
- });
816
- await this.recordAudit("layer.observedViolation", event, details);
817
- if (severity === "hard") {
818
- throw new ObservedLayerFlowViolationError(source, event.intent, fromLayer, toLayer, message);
819
- }
1058
+ this.recording.trace.length = 0;
820
1059
  }
821
- async recordRawPublishDiagnostic(event) {
822
- const details = {
823
- intent: event.intent,
824
- source: event.metadata.source,
825
- suggestion: "Publish through a registered intent creator so strict registry, contracts, and agent tooling share one source of truth."
826
- };
827
- this.appendTrace({
828
- type: "event.rawPublish",
829
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
830
- intent: event.intent,
831
- correlationId: event.metadata.correlationId,
832
- traceId: event.metadata.traceId,
833
- spanId: event.metadata.spanId,
834
- details
835
- });
836
- await this.recordAudit("event.rawPublish", event, details);
1060
+ appendTrace(record) {
1061
+ appendTrace(this.recording, record);
837
1062
  }
838
- async applyInterceptors(event) {
839
- if (event.metadata.allowInterception === false) {
840
- return event;
841
- }
842
- const matching = [...this.interceptorsByIntent.get(event.intent) ?? []];
843
- let current = event;
844
- for (const registration of matching) {
845
- const patches = [];
846
- try {
847
- await Promise.resolve(
848
- registration.interceptor({
849
- event: current,
850
- intercept: (patch) => {
851
- patches.push(patch);
852
- }
853
- })
854
- );
855
- if (patches.length === 0) {
856
- continue;
857
- }
858
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
859
- let candidate = {
860
- ...current,
861
- metadata: {
862
- ...current.metadata,
863
- interceptions: [
864
- ...current.metadata.interceptions ?? [],
865
- { interceptorId: registration.interceptorId, timestamp }
866
- ]
867
- }
868
- };
869
- for (const patch of patches) {
870
- candidate = {
871
- ...candidate,
872
- payload: applyPayloadPatch(candidate.payload, patch),
873
- metadata: { ...candidate.metadata }
874
- };
875
- }
876
- this.assertContractAllowed(candidate);
877
- current = candidate;
878
- registration.lastInterceptedAt = timestamp;
879
- this.appendTrace({
880
- type: "event.intercepted",
881
- timestamp,
882
- intent: current.intent,
883
- correlationId: current.metadata.correlationId,
884
- traceId: current.metadata.traceId,
885
- spanId: current.metadata.spanId,
886
- details: {
887
- registrationId: registration.registrationId,
888
- interceptorId: registration.interceptorId,
889
- patchesApplied: patches.length
890
- }
891
- });
892
- await this.recordAudit("event.intercepted", current, {
893
- registrationId: registration.registrationId,
894
- interceptorId: registration.interceptorId,
895
- patchesApplied: patches.length
896
- });
897
- } catch (err) {
898
- await this.recordInterceptorError(registration, current, err);
899
- }
900
- }
901
- return current;
1063
+ async recordAudit(type, event, details) {
1064
+ await recordAudit(this.recording, type, event, details);
902
1065
  }
903
1066
  async invokeHandler(sub, event) {
904
1067
  try {
@@ -951,90 +1114,6 @@ var EventBusImpl = class {
951
1114
  });
952
1115
  }
953
1116
  }
954
- async recordInterceptorError(interceptor, event, error) {
955
- const message = error instanceof Error ? error.message : String(error);
956
- this.appendTrace({
957
- type: "interceptor.error",
958
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
959
- intent: event.intent,
960
- correlationId: event.metadata.correlationId,
961
- traceId: event.metadata.traceId,
962
- spanId: event.metadata.spanId,
963
- details: {
964
- registrationId: interceptor.registrationId,
965
- interceptorId: interceptor.interceptorId,
966
- error: message
967
- }
968
- });
969
- await this.recordAudit("interceptor.error", event, {
970
- registrationId: interceptor.registrationId,
971
- interceptorId: interceptor.interceptorId,
972
- error: message
973
- });
974
- }
975
- appendHistory(record) {
976
- this.history.push(record);
977
- if (this.maxHistorySize !== void 0 && this.history.length > this.maxHistorySize) {
978
- this.history.splice(0, this.history.length - this.maxHistorySize);
979
- }
980
- }
981
- appendTrace(record) {
982
- this.trace.push(record);
983
- if (this.maxHistorySize !== void 0 && this.trace.length > this.maxHistorySize) {
984
- this.trace.splice(0, this.trace.length - this.maxHistorySize);
985
- }
986
- for (const sink of this.traceSinks) {
987
- try {
988
- sink(record);
989
- } catch {
990
- }
991
- }
992
- }
993
- async recordAudit(type, event, details) {
994
- if (!this.auditTrail) return;
995
- try {
996
- await this.auditTrail.record({
997
- type,
998
- source: event.metadata.source,
999
- intent: event.intent,
1000
- correlationId: event.metadata.correlationId,
1001
- causationId: event.metadata.causationId,
1002
- subject: event.intent,
1003
- details
1004
- });
1005
- } catch (err) {
1006
- this.appendTrace({
1007
- type: "hook.error",
1008
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1009
- intent: event.intent,
1010
- correlationId: event.metadata.correlationId,
1011
- traceId: event.metadata.traceId,
1012
- spanId: event.metadata.spanId,
1013
- details: {
1014
- hook: "auditTrail",
1015
- error: err instanceof Error ? err.message : String(err)
1016
- }
1017
- });
1018
- }
1019
- }
1020
- enrichMetadata(base, extra) {
1021
- return {
1022
- ...base,
1023
- ...extra,
1024
- occurredAt: extra.occurredAt || base.occurredAt || (/* @__PURE__ */ new Date()).toISOString(),
1025
- source: extra.source || base.source || "unknown",
1026
- kernelInstanceId: extra.kernelInstanceId ?? base.kernelInstanceId ?? this.instanceId,
1027
- eventVersion: extra.eventVersion ?? base.eventVersion,
1028
- schemaVersion: extra.schemaVersion ?? base.schemaVersion,
1029
- allowInterception: extra.allowInterception ?? base.allowInterception,
1030
- interceptions: extra.interceptions ?? base.interceptions,
1031
- correlationId: extra.correlationId ?? base.correlationId,
1032
- causationId: extra.causationId ?? base.causationId,
1033
- traceId: extra.traceId ?? base.traceId,
1034
- spanId: extra.spanId ?? base.spanId,
1035
- parentSpanId: extra.parentSpanId ?? base.parentSpanId
1036
- };
1037
- }
1038
1117
  };
1039
1118
  function createEventBus(options) {
1040
1119
  return new EventBusImpl(options);
@@ -1648,7 +1727,7 @@ var elevenLayerProfile = createArchitectureProfile({
1648
1727
  var MANIFEST_SCHEMA_VERSION = "1.0";
1649
1728
 
1650
1729
  // src/version.ts
1651
- var version = "2.8.0";
1730
+ var version = "2.8.2";
1652
1731
 
1653
1732
  // src/kernel/manifest/createArkManifest.ts
1654
1733
  function policyId(name) {