omnibase_infra 0.2.8__py3-none-any.whl → 0.2.9__py3-none-any.whl

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.
Files changed (79) hide show
  1. omnibase_infra/__init__.py +1 -1
  2. omnibase_infra/enums/__init__.py +4 -0
  3. omnibase_infra/enums/enum_declarative_node_violation.py +102 -0
  4. omnibase_infra/event_bus/adapters/__init__.py +31 -0
  5. omnibase_infra/event_bus/adapters/adapter_protocol_event_publisher_kafka.py +517 -0
  6. omnibase_infra/mixins/mixin_async_circuit_breaker.py +113 -1
  7. omnibase_infra/models/__init__.py +9 -0
  8. omnibase_infra/models/event_bus/__init__.py +22 -0
  9. omnibase_infra/models/event_bus/model_consumer_retry_config.py +367 -0
  10. omnibase_infra/models/event_bus/model_dlq_config.py +177 -0
  11. omnibase_infra/models/event_bus/model_idempotency_config.py +131 -0
  12. omnibase_infra/models/event_bus/model_offset_policy_config.py +107 -0
  13. omnibase_infra/models/resilience/model_circuit_breaker_config.py +15 -0
  14. omnibase_infra/models/validation/__init__.py +8 -0
  15. omnibase_infra/models/validation/model_declarative_node_validation_result.py +139 -0
  16. omnibase_infra/models/validation/model_declarative_node_violation.py +169 -0
  17. omnibase_infra/nodes/architecture_validator/__init__.py +28 -7
  18. omnibase_infra/nodes/architecture_validator/constants.py +36 -0
  19. omnibase_infra/nodes/architecture_validator/handlers/__init__.py +28 -0
  20. omnibase_infra/nodes/architecture_validator/handlers/contract.yaml +120 -0
  21. omnibase_infra/nodes/architecture_validator/handlers/handler_architecture_validation.py +359 -0
  22. omnibase_infra/nodes/architecture_validator/node.py +1 -0
  23. omnibase_infra/nodes/architecture_validator/node_architecture_validator.py +48 -336
  24. omnibase_infra/nodes/node_ledger_projection_compute/__init__.py +16 -2
  25. omnibase_infra/nodes/node_ledger_projection_compute/contract.yaml +14 -4
  26. omnibase_infra/nodes/node_ledger_projection_compute/handlers/__init__.py +18 -0
  27. omnibase_infra/nodes/node_ledger_projection_compute/handlers/contract.yaml +53 -0
  28. omnibase_infra/nodes/node_ledger_projection_compute/handlers/handler_ledger_projection.py +354 -0
  29. omnibase_infra/nodes/node_ledger_projection_compute/node.py +20 -256
  30. omnibase_infra/nodes/node_registry_effect/node.py +20 -73
  31. omnibase_infra/protocols/protocol_dispatch_engine.py +90 -0
  32. omnibase_infra/runtime/__init__.py +11 -0
  33. omnibase_infra/runtime/baseline_subscriptions.py +150 -0
  34. omnibase_infra/runtime/event_bus_subcontract_wiring.py +455 -24
  35. omnibase_infra/runtime/kafka_contract_source.py +13 -5
  36. omnibase_infra/runtime/service_message_dispatch_engine.py +112 -0
  37. omnibase_infra/runtime/service_runtime_host_process.py +6 -11
  38. omnibase_infra/services/__init__.py +36 -0
  39. omnibase_infra/services/contract_publisher/__init__.py +95 -0
  40. omnibase_infra/services/contract_publisher/config.py +199 -0
  41. omnibase_infra/services/contract_publisher/errors.py +243 -0
  42. omnibase_infra/services/contract_publisher/models/__init__.py +28 -0
  43. omnibase_infra/services/contract_publisher/models/model_contract_error.py +67 -0
  44. omnibase_infra/services/contract_publisher/models/model_infra_error.py +62 -0
  45. omnibase_infra/services/contract_publisher/models/model_publish_result.py +112 -0
  46. omnibase_infra/services/contract_publisher/models/model_publish_stats.py +79 -0
  47. omnibase_infra/services/contract_publisher/service.py +617 -0
  48. omnibase_infra/services/contract_publisher/sources/__init__.py +52 -0
  49. omnibase_infra/services/contract_publisher/sources/model_discovered.py +155 -0
  50. omnibase_infra/services/contract_publisher/sources/protocol.py +101 -0
  51. omnibase_infra/services/contract_publisher/sources/source_composite.py +309 -0
  52. omnibase_infra/services/contract_publisher/sources/source_filesystem.py +174 -0
  53. omnibase_infra/services/contract_publisher/sources/source_package.py +221 -0
  54. omnibase_infra/services/observability/__init__.py +40 -0
  55. omnibase_infra/services/observability/agent_actions/__init__.py +64 -0
  56. omnibase_infra/services/observability/agent_actions/config.py +209 -0
  57. omnibase_infra/services/observability/agent_actions/consumer.py +1320 -0
  58. omnibase_infra/services/observability/agent_actions/models/__init__.py +87 -0
  59. omnibase_infra/services/observability/agent_actions/models/model_agent_action.py +142 -0
  60. omnibase_infra/services/observability/agent_actions/models/model_detection_failure.py +125 -0
  61. omnibase_infra/services/observability/agent_actions/models/model_envelope.py +85 -0
  62. omnibase_infra/services/observability/agent_actions/models/model_execution_log.py +159 -0
  63. omnibase_infra/services/observability/agent_actions/models/model_performance_metric.py +130 -0
  64. omnibase_infra/services/observability/agent_actions/models/model_routing_decision.py +138 -0
  65. omnibase_infra/services/observability/agent_actions/models/model_transformation_event.py +124 -0
  66. omnibase_infra/services/observability/agent_actions/tests/__init__.py +20 -0
  67. omnibase_infra/services/observability/agent_actions/tests/test_consumer.py +1154 -0
  68. omnibase_infra/services/observability/agent_actions/tests/test_models.py +645 -0
  69. omnibase_infra/services/observability/agent_actions/tests/test_writer.py +709 -0
  70. omnibase_infra/services/observability/agent_actions/writer_postgres.py +926 -0
  71. omnibase_infra/validation/__init__.py +12 -0
  72. omnibase_infra/validation/contracts/declarative_node.validation.yaml +143 -0
  73. omnibase_infra/validation/validation_exemptions.yaml +93 -0
  74. omnibase_infra/validation/validator_declarative_node.py +850 -0
  75. {omnibase_infra-0.2.8.dist-info → omnibase_infra-0.2.9.dist-info}/METADATA +2 -2
  76. {omnibase_infra-0.2.8.dist-info → omnibase_infra-0.2.9.dist-info}/RECORD +79 -27
  77. {omnibase_infra-0.2.8.dist-info → omnibase_infra-0.2.9.dist-info}/WHEEL +0 -0
  78. {omnibase_infra-0.2.8.dist-info → omnibase_infra-0.2.9.dist-info}/entry_points.txt +0 -0
  79. {omnibase_infra-0.2.8.dist-info → omnibase_infra-0.2.9.dist-info}/licenses/LICENSE +0 -0
@@ -22,17 +22,21 @@ Design Decisions:
22
22
  - 100% Contract-Driven: All routing logic in YAML, not Python
23
23
  - Zero Custom Routing: Base class handles handler dispatch via contract
24
24
  - Declarative Handlers: handler_routing section defines dispatch rules
25
- - External Wiring: Handlers resolved via container dependency injection
25
+ - Container DI: Backend adapters resolved via container, not setter methods
26
26
 
27
27
  Node Responsibilities:
28
28
  - Define I/O model contract (ModelRegistryRequest -> ModelRegistryResponse)
29
- - Provide dependency injection points for backend clients
30
29
  - Delegate all execution to handlers via base class
30
+ - NO custom logic - pure declarative shell
31
31
 
32
32
  The actual handler execution and routing is performed by:
33
33
  - NodeOrchestrator (for workflow coordination)
34
34
  - Or direct handler invocation by callers
35
35
 
36
+ Handlers receive their dependencies directly via constructor injection:
37
+ - HandlerConsulRegister(consul_client)
38
+ - HandlerPostgresUpsert(postgres_adapter)
39
+
36
40
  Coroutine Safety:
37
41
  This node is async-safe. Handler coordination is performed by the
38
42
  orchestrator layer, not by this effect node.
@@ -43,32 +47,24 @@ Related Modules:
43
47
  - models/: Node-specific input/output models
44
48
  - NodeRegistrationOrchestrator: Coordinates handler execution
45
49
 
46
- Migration Notes (OMN-1103):
47
- This declarative node replaces the imperative implementation.
48
- All routing logic has been moved to contract.yaml handler_routing.
49
- Callers should use handlers directly or via the orchestrator.
50
+ Migration Notes (OMN-1726):
51
+ Refactored from setter-based dependency injection to pure declarative shell.
52
+ Backend adapters are now resolved via container, not via set_* methods.
53
+ Handlers receive dependencies directly via their constructors.
50
54
  """
51
55
 
52
56
  from __future__ import annotations
53
57
 
54
- from typing import TYPE_CHECKING
55
-
56
58
  from omnibase_core.nodes.node_effect import NodeEffect
57
59
 
58
- if TYPE_CHECKING:
59
- from omnibase_core.models.container.model_onex_container import ModelONEXContainer
60
- from omnibase_infra.nodes.effects.protocol_consul_client import ProtocolConsulClient
61
- from omnibase_infra.nodes.effects.protocol_postgres_adapter import (
62
- ProtocolPostgresAdapter,
63
- )
64
-
65
60
 
61
+ # ONEX_EXCLUDE: declarative_node - legacy effect node with direct adapter access (OMN-1725)
66
62
  class NodeRegistryEffect(NodeEffect):
67
63
  """Declarative effect node for dual-backend node registration.
68
64
 
69
65
  This effect node is a lightweight shell that defines the I/O contract
70
66
  for registration operations. All routing and execution logic is driven
71
- by contract.yaml - this class contains no custom routing code.
67
+ by contract.yaml - this class contains NO custom routing code.
72
68
 
73
69
  Handler coordination is performed by:
74
70
  - NodeRegistrationOrchestrator for workflow-based execution
@@ -80,8 +76,9 @@ class NodeRegistryEffect(NodeEffect):
80
76
  - retry_partial_failure: Retry a specific backend after partial failure
81
77
 
82
78
  Dependency Injection:
83
- Backend clients are injected via setter methods. The orchestrator
84
- or caller is responsible for wiring these dependencies.
79
+ Backend adapters (Consul, PostgreSQL) are resolved via container.
80
+ Handlers receive their dependencies directly via constructor injection.
81
+ This node contains NO instance variables for backend clients.
85
82
 
86
83
  Example:
87
84
  ```python
@@ -92,15 +89,14 @@ class NodeRegistryEffect(NodeEffect):
92
89
  HandlerPostgresUpsert,
93
90
  )
94
91
 
95
- # Create effect node
92
+ # Create effect node via container
96
93
  container = ModelONEXContainer()
97
94
  effect = NodeRegistryEffect(container)
98
95
 
99
- # Wire backend clients
100
- effect.set_consul_client(consul_client)
101
- effect.set_postgres_adapter(postgres_adapter)
96
+ # Handlers receive dependencies directly via constructor
97
+ consul_client = container.resolve(ProtocolConsulClient)
98
+ postgres_adapter = container.resolve(ProtocolPostgresAdapter)
102
99
 
103
- # Execute via handlers directly
104
100
  consul_handler = HandlerConsulRegister(consul_client)
105
101
  postgres_handler = HandlerPostgresUpsert(postgres_adapter)
106
102
 
@@ -110,56 +106,7 @@ class NodeRegistryEffect(NodeEffect):
110
106
  ```
111
107
  """
112
108
 
113
- def __init__(self, container: ModelONEXContainer) -> None:
114
- """Initialize the effect node.
115
-
116
- Args:
117
- container: ONEX dependency injection container providing:
118
- - Backend adapters (Consul client, PostgreSQL adapter)
119
- - Handler instances
120
- - Configuration
121
- """
122
- super().__init__(container)
123
-
124
- # Backend adapters (injected via setter methods)
125
- self._consul_client: ProtocolConsulClient | None = None
126
- self._postgres_adapter: ProtocolPostgresAdapter | None = None
127
-
128
- def set_consul_client(self, client: ProtocolConsulClient) -> None:
129
- """Set the Consul client for service registration.
130
-
131
- Args:
132
- client: Protocol-compliant Consul client implementation.
133
- """
134
- self._consul_client = client
135
-
136
- def set_postgres_adapter(self, adapter: ProtocolPostgresAdapter) -> None:
137
- """Set the PostgreSQL adapter for registration persistence.
138
-
139
- Args:
140
- adapter: Protocol-compliant PostgreSQL adapter implementation.
141
- """
142
- self._postgres_adapter = adapter
143
-
144
- @property
145
- def consul_client(self) -> ProtocolConsulClient | None:
146
- """Get the Consul client if configured."""
147
- return self._consul_client
148
-
149
- @property
150
- def postgres_adapter(self) -> ProtocolPostgresAdapter | None:
151
- """Get the PostgreSQL adapter if configured."""
152
- return self._postgres_adapter
153
-
154
- @property
155
- def has_consul_client(self) -> bool:
156
- """Check if Consul client is configured."""
157
- return self._consul_client is not None
158
-
159
- @property
160
- def has_postgres_adapter(self) -> bool:
161
- """Check if PostgreSQL adapter is configured."""
162
- return self._postgres_adapter is not None
109
+ # Pure declarative shell - all behavior defined in contract.yaml
163
110
 
164
111
 
165
112
  __all__ = ["NodeRegistryEffect"]
@@ -150,3 +150,93 @@ class ProtocolDispatchEngine(Protocol):
150
150
  await dispatch_engine.dispatch(topic, envelope)
151
151
  """
152
152
  ...
153
+
154
+ async def dispatch_with_transaction(
155
+ self,
156
+ *,
157
+ topic: str,
158
+ envelope: ModelEventEnvelope[object],
159
+ tx: object,
160
+ ) -> ModelDispatchResult | None:
161
+ """Dispatch an event envelope with database transaction context.
162
+
163
+ This method enables transaction-scoped dispatch for correct idempotency
164
+ semantics. The transaction parameter allows handlers to participate in
165
+ the same database transaction as the idempotency insert, ensuring
166
+ exactly-once processing.
167
+
168
+ Design Decision:
169
+ The ``tx`` parameter is typed as ``object`` rather than a specific
170
+ database type (e.g., ``asyncpg.Connection``) to avoid leaking
171
+ infrastructure types into the protocol. This keeps the protocol
172
+ generic and allows future flexibility for different database backends.
173
+
174
+ Implementers should type-narrow ``tx`` via duck-typing (checking for
175
+ required methods) rather than isinstance checks, per ONEX conventions:
176
+
177
+ .. code-block:: python
178
+
179
+ from omnibase_core.errors import OnexError
180
+
181
+ async def dispatch_with_transaction(
182
+ self,
183
+ *,
184
+ topic: str,
185
+ envelope: ModelEventEnvelope[object],
186
+ tx: object,
187
+ ) -> ModelDispatchResult | None:
188
+ # Duck-type check for required database connection methods
189
+ if not (hasattr(tx, 'execute') and callable(tx.execute)):
190
+ raise OnexError(
191
+ "Transaction object must implement execute() method"
192
+ )
193
+ # Use tx with duck-typed interface...
194
+
195
+ Thread Safety:
196
+ This method MUST be safe for concurrent calls from multiple
197
+ coroutines. The transaction context (``tx``) is typically
198
+ connection-scoped and should not be shared across coroutines.
199
+
200
+ Args:
201
+ topic: The full topic name from which the envelope was consumed.
202
+ Used for routing and logging context.
203
+ Example: "dev.onex.evt.node.introspected.v1"
204
+ envelope: The deserialized event envelope containing the payload.
205
+ The payload type varies by topic/event type.
206
+ tx: Database transaction/connection context. Typed as ``object``
207
+ to avoid infrastructure type leakage; implementations should
208
+ type-narrow based on their database backend (e.g.,
209
+ ``asyncpg.Connection``, ``aiosqlite.Connection``).
210
+
211
+ Returns:
212
+ ModelDispatchResult if the implementation returns dispatch metrics/results,
213
+ None if the implementation does not track results. Callers should not
214
+ depend on the return value for correctness.
215
+
216
+ Raises:
217
+ InfraDispatchError: If no handler is registered for the topic/message type.
218
+ OnexError: For handler execution failures or if ``tx`` does not implement
219
+ the required database connection interface (duck-type validation).
220
+
221
+ Example:
222
+ .. code-block:: python
223
+
224
+ # Idempotency consumer with transaction context
225
+ async with pool.acquire() as conn:
226
+ async with conn.transaction():
227
+ # Insert idempotency record and dispatch in same transaction
228
+ await insert_idempotency_record(conn, message_id)
229
+ await dispatch_engine.dispatch_with_transaction(
230
+ topic=topic,
231
+ envelope=envelope,
232
+ tx=conn,
233
+ )
234
+ # Both committed atomically
235
+
236
+ Related:
237
+ - OMN-1740: Transaction-scoped dispatch for idempotency
238
+ - dispatch(): Non-transactional dispatch method
239
+
240
+ .. versionadded:: 0.2.9
241
+ """
242
+ ...
@@ -272,6 +272,13 @@ from omnibase_infra.runtime.registry_contract_source import (
272
272
  # Kafka contract source (OMN-1654)
273
273
  from omnibase_infra.runtime.kafka_contract_source import KafkaContractSource
274
274
 
275
+ # Baseline subscriptions (OMN-1696)
276
+ from omnibase_infra.runtime.baseline_subscriptions import (
277
+ BASELINE_CONTRACT_TOPICS,
278
+ BASELINE_PLATFORM_TOPICS,
279
+ get_baseline_topics,
280
+ )
281
+
275
282
  # Chain-aware dispatch (OMN-951) - must be imported LAST to avoid circular import
276
283
  from omnibase_infra.runtime.chain_aware_dispatch import (
277
284
  ChainAwareDispatcher,
@@ -442,4 +449,8 @@ __all__: list[str] = [
442
449
  "store_contract_in_consul",
443
450
  # Kafka contract source (OMN-1654)
444
451
  "KafkaContractSource",
452
+ # Baseline subscriptions (OMN-1696)
453
+ "BASELINE_CONTRACT_TOPICS",
454
+ "BASELINE_PLATFORM_TOPICS",
455
+ "get_baseline_topics",
445
456
  ]
@@ -0,0 +1,150 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2025 OmniNode Team
3
+ """Baseline Subscriptions Assembly Module.
4
+
5
+ Aggregates platform baseline topic constants from omnibase_core for use
6
+ by the ONEX runtime when wiring Kafka subscriptions.
7
+
8
+ Part of OMN-1696: Wire baseline topic constants from omnibase_core into
9
+ omnibase_infra runtime subscription assembly.
10
+
11
+ Platform Baseline Topics:
12
+ These topics are automatically subscribed to by the runtime during
13
+ initialization, providing core platform functionality:
14
+
15
+ - **Contract Registered**: Notifies when a new handler contract is registered.
16
+ Used by KafkaContractSource for dynamic contract discovery.
17
+
18
+ - **Contract Deregistered**: Notifies when a handler contract is removed.
19
+ Used by KafkaContractSource for cache invalidation.
20
+
21
+ - **Node Heartbeat**: Periodic health signals from running nodes.
22
+ Used for liveness monitoring and service discovery.
23
+
24
+ Usage:
25
+ >>> from omnibase_infra.runtime.baseline_subscriptions import (
26
+ ... BASELINE_CONTRACT_TOPICS,
27
+ ... BASELINE_PLATFORM_TOPICS,
28
+ ... get_baseline_topics,
29
+ ... )
30
+ >>>
31
+ >>> # Get contract-only topics (registration/deregistration)
32
+ >>> contract_topics = get_baseline_topics(include_heartbeat=False)
33
+ >>>
34
+ >>> # Get all platform baseline topics (including heartbeat)
35
+ >>> all_topics = get_baseline_topics(include_heartbeat=True)
36
+
37
+ Related:
38
+ - KafkaContractSource: Consumes contract registration events
39
+ - RuntimeHostProcess: Wires baseline subscriptions on startup
40
+ - omnibase_core.constants: Source of truth for topic suffix constants
41
+
42
+ Related Tickets:
43
+ - OMN-1696: Wire baseline topic constants from omnibase_core
44
+ - OMN-1652: Define platform baseline topic suffixes in omnibase_core
45
+ - OMN-1654: KafkaContractSource (cache + discovery)
46
+
47
+ .. versionadded:: 0.2.9
48
+ Created as part of OMN-1696 baseline subscription wiring.
49
+ """
50
+
51
+ from __future__ import annotations
52
+
53
+ from omnibase_core.constants import (
54
+ PLATFORM_BASELINE_TOPIC_SUFFIXES,
55
+ TOPIC_SUFFIX_CONTRACT_DEREGISTERED,
56
+ TOPIC_SUFFIX_CONTRACT_REGISTERED,
57
+ TOPIC_SUFFIX_NODE_HEARTBEAT,
58
+ )
59
+
60
+ # Contract registration/deregistration topics only.
61
+ # Use when you need to track contract lifecycle events but not node health.
62
+ BASELINE_CONTRACT_TOPICS: frozenset[str] = frozenset(
63
+ {
64
+ TOPIC_SUFFIX_CONTRACT_REGISTERED,
65
+ TOPIC_SUFFIX_CONTRACT_DEREGISTERED,
66
+ }
67
+ )
68
+ """Contract lifecycle topics (registration and deregistration).
69
+
70
+ This subset excludes heartbeat topics and is appropriate when:
71
+ - You only need to track contract changes
72
+ - Heartbeat processing is handled separately
73
+ - You want to minimize subscription overhead
74
+
75
+ Example:
76
+ >>> for topic_suffix in BASELINE_CONTRACT_TOPICS:
77
+ ... full_topic = f"{environment}.{topic_suffix}"
78
+ ... subscribe(full_topic)
79
+ """
80
+
81
+ # All platform baseline topics including heartbeat.
82
+ # Use when you need complete platform observability.
83
+ BASELINE_PLATFORM_TOPICS: frozenset[str] = frozenset(PLATFORM_BASELINE_TOPIC_SUFFIXES)
84
+ """All platform baseline topics including heartbeat.
85
+
86
+ This is the full set of platform-reserved topics that the runtime
87
+ subscribes to automatically during initialization.
88
+
89
+ Includes:
90
+ - Contract registered events
91
+ - Contract deregistered events
92
+ - Node heartbeat events
93
+
94
+ Example:
95
+ >>> for topic_suffix in BASELINE_PLATFORM_TOPICS:
96
+ ... full_topic = f"{environment}.{topic_suffix}"
97
+ ... subscribe(full_topic)
98
+ """
99
+
100
+
101
+ def get_baseline_topics(*, include_heartbeat: bool = True) -> frozenset[str]:
102
+ """Return the appropriate set of baseline topic suffixes.
103
+
104
+ This helper function provides a convenient way to select between
105
+ the full platform topic set or contract-only topics based on
106
+ runtime requirements.
107
+
108
+ Args:
109
+ include_heartbeat: If True (default), returns all platform baseline
110
+ topics including node heartbeat. If False, returns only contract
111
+ registration/deregistration topics.
112
+
113
+ Returns:
114
+ A frozenset of topic suffix strings. These are suffixes that should
115
+ be prefixed with the environment name to form complete topic names.
116
+
117
+ Example:
118
+ >>> # For full platform observability
119
+ >>> topics = get_baseline_topics(include_heartbeat=True)
120
+ >>> assert TOPIC_SUFFIX_NODE_HEARTBEAT in topics
121
+ >>>
122
+ >>> # For contract-only tracking
123
+ >>> topics = get_baseline_topics(include_heartbeat=False)
124
+ >>> assert TOPIC_SUFFIX_NODE_HEARTBEAT not in topics
125
+ >>> assert TOPIC_SUFFIX_CONTRACT_REGISTERED in topics
126
+
127
+ Note:
128
+ The returned frozenset is immutable and can be safely shared
129
+ across threads without synchronization.
130
+
131
+ .. versionadded:: 0.2.9
132
+ Created as part of OMN-1696.
133
+ """
134
+ if include_heartbeat:
135
+ return BASELINE_PLATFORM_TOPICS
136
+ return BASELINE_CONTRACT_TOPICS
137
+
138
+
139
+ __all__: list[str] = [
140
+ # Topic sets
141
+ "BASELINE_CONTRACT_TOPICS",
142
+ "BASELINE_PLATFORM_TOPICS",
143
+ # Helper function
144
+ "get_baseline_topics",
145
+ # Re-exported constants from omnibase_core for convenience
146
+ "PLATFORM_BASELINE_TOPIC_SUFFIXES",
147
+ "TOPIC_SUFFIX_CONTRACT_DEREGISTERED",
148
+ "TOPIC_SUFFIX_CONTRACT_REGISTERED",
149
+ "TOPIC_SUFFIX_NODE_HEARTBEAT",
150
+ ]