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