openframe-core 3.0.1__tar.gz → 3.2.0__tar.gz

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 (151) hide show
  1. {openframe_core-3.0.1 → openframe_core-3.2.0}/.github/CHANGELOG.md +71 -6
  2. {openframe_core-3.0.1 → openframe_core-3.2.0}/PKG-INFO +8 -18
  3. {openframe_core-3.0.1 → openframe_core-3.2.0}/README.md +6 -16
  4. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/code/getting-started/index.md +5 -3
  5. openframe_core-3.2.0/docs/code/modules/health.md +46 -0
  6. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/code/modules/index.md +4 -5
  7. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/code/modules/plugins.md +3 -3
  8. openframe_core-3.2.0/docs/code/modules/ports.md +428 -0
  9. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/code/modules/runtime.md +1 -1
  10. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/developer-guide/explore.md +7 -9
  11. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/developer-guide/how-it-works.md +6 -6
  12. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/developer-guide/local-dev.md +1 -1
  13. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/developer-guide/quick-start/index.md +5 -5
  14. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/index.md +1 -1
  15. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/architecture/adrs/adr-006-unified-port-lifecycle.md +83 -1
  16. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/architecture/capability-taxonomy.md +19 -3
  17. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/architecture/design-decisions.md +41 -17
  18. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/architecture/package-journey/adapter-lifecycle.md +1 -1
  19. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/architecture/package-journey/template-wiring.md +2 -2
  20. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/architecture/system-architecture.md +44 -28
  21. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/infrastructure/networking.md +1 -1
  22. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/operations/runbooks/adapter-connection-failure.md +2 -2
  23. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/operations/runbooks/queue-consumer-stuck.md +1 -1
  24. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/overview/glossary.md +6 -6
  25. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/overview/roadmap.md +13 -3
  26. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/overview/system-overview.md +20 -21
  27. {openframe_core-3.0.1 → openframe_core-3.2.0}/mkdocs.yml +0 -1
  28. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/exceptions/base.py +1 -1
  29. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/inbound/command.py +1 -1
  30. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/inbound/context.py +4 -4
  31. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/inbound/query.py +1 -1
  32. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/inbound/usecase.py +2 -2
  33. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/plugins/__init__.py +3 -3
  34. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/plugins/registry.py +12 -12
  35. openframe_core-3.2.0/openframe/core/ports/__init__.py +64 -0
  36. {openframe_core-3.0.1/openframe/core/contracts → openframe_core-3.2.0/openframe/core/ports}/capability.py +2 -2
  37. {openframe_core-3.0.1/openframe/core/contracts → openframe_core-3.2.0/openframe/core/ports}/context.py +6 -6
  38. {openframe_core-3.0.1/openframe/core/contracts → openframe_core-3.2.0/openframe/core/ports}/health.py +6 -6
  39. {openframe_core-3.0.1/openframe/core/contracts → openframe_core-3.2.0/openframe/core/ports}/identity.py +7 -7
  40. {openframe_core-3.0.1/openframe/core/contracts → openframe_core-3.2.0/openframe/core/ports}/lifecycle.py +7 -7
  41. openframe_core-3.2.0/openframe/core/ports/outbound/__init__.py +40 -0
  42. {openframe_core-3.0.1/openframe/core/ports → openframe_core-3.2.0/openframe/core/ports/outbound}/consumer.py +6 -6
  43. {openframe_core-3.0.1/openframe/core/ports → openframe_core-3.2.0/openframe/core/ports/outbound}/producer.py +6 -6
  44. {openframe_core-3.0.1/openframe/core/ports → openframe_core-3.2.0/openframe/core/ports/outbound}/repository.py +6 -6
  45. {openframe_core-3.0.1/openframe/core/contracts → openframe_core-3.2.0/openframe/core/ports}/port.py +8 -8
  46. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/runtime/bootstrap.py +7 -7
  47. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/testing/__init__.py +26 -2
  48. openframe_core-3.2.0/openframe/core/testing/contracts/__init__.py +44 -0
  49. openframe_core-3.2.0/openframe/core/testing/contracts/inbound.py +221 -0
  50. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/testing/contracts/lifecycle.py +8 -8
  51. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/testing/contracts/port.py +6 -6
  52. openframe_core-3.2.0/openframe/core/testing/fakes/__init__.py +36 -0
  53. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/testing/fakes/consumer.py +2 -2
  54. openframe_core-3.2.0/openframe/core/testing/fakes/inbound.py +256 -0
  55. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/testing/fakes/producer.py +2 -2
  56. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/testing/fakes/repository.py +3 -3
  57. {openframe_core-3.0.1 → openframe_core-3.2.0}/pyproject.toml +2 -2
  58. {openframe_core-3.0.1 → openframe_core-3.2.0}/tests/test_inbound.py +1 -1
  59. openframe_core-3.2.0/tests/test_inbound_contracts.py +164 -0
  60. {openframe_core-3.0.1 → openframe_core-3.2.0}/tests/test_plugins.py +1 -1
  61. {openframe_core-3.0.1 → openframe_core-3.2.0}/tests/test_ports.py +11 -3
  62. openframe_core-3.0.1/tests/test_contracts.py → openframe_core-3.2.0/tests/test_ports_primitives.py +6 -4
  63. {openframe_core-3.0.1 → openframe_core-3.2.0}/tests/test_runtime.py +1 -1
  64. {openframe_core-3.0.1 → openframe_core-3.2.0}/tests/test_testing_fakes.py +2 -2
  65. openframe_core-3.0.1/docs/code/modules/contracts.md +0 -219
  66. openframe_core-3.0.1/docs/code/modules/health.md +0 -41
  67. openframe_core-3.0.1/docs/code/modules/ports.md +0 -224
  68. openframe_core-3.0.1/openframe/core/contracts/__init__.py +0 -61
  69. openframe_core-3.0.1/openframe/core/ports/__init__.py +0 -32
  70. openframe_core-3.0.1/openframe/core/testing/contracts/__init__.py +0 -25
  71. openframe_core-3.0.1/openframe/core/testing/fakes/__init__.py +0 -22
  72. {openframe_core-3.0.1 → openframe_core-3.2.0}/.github/requirements/docs.txt +0 -0
  73. {openframe_core-3.0.1 → openframe_core-3.2.0}/.github/requirements/test.txt +0 -0
  74. {openframe_core-3.0.1 → openframe_core-3.2.0}/.github/workflows/app-test.yml +0 -0
  75. {openframe_core-3.0.1 → openframe_core-3.2.0}/.github/workflows/auto-docs.yml +0 -0
  76. {openframe_core-3.0.1 → openframe_core-3.2.0}/.github/workflows/python-build.yml +0 -0
  77. {openframe_core-3.0.1 → openframe_core-3.2.0}/.gitignore +0 -0
  78. {openframe_core-3.0.1 → openframe_core-3.2.0}/.vscode/settings.json +0 -0
  79. {openframe_core-3.0.1 → openframe_core-3.2.0}/LICENSE +0 -0
  80. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/assets/images/banner.png +0 -0
  81. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/assets/images/favicon.png +0 -0
  82. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/assets/images/logo-dark.png +0 -0
  83. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/assets/images/logo-light.png +0 -0
  84. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/assets/javascripts/extra.js +0 -0
  85. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/assets/stylesheets/extra.css +0 -0
  86. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/code/cicd/pipeline.md +0 -0
  87. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/code/modules/config.md +0 -0
  88. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/code/modules/exceptions.md +0 -0
  89. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/code/modules/inbound.md +0 -0
  90. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/code/modules/middleware.md +0 -0
  91. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/code/modules/telemetry.md +0 -0
  92. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/code/modules/testing.md +0 -0
  93. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/code/modules/tracing.md +0 -0
  94. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/developer-guide/debugging.md +0 -0
  95. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/developer-guide/first-change.md +0 -0
  96. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/architecture/adrs/adr-001-namespace.md +0 -0
  97. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/architecture/adrs/adr-002-hexagonal.md +0 -0
  98. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/architecture/adrs/adr-003-async.md +0 -0
  99. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/architecture/adrs/adr-004-pydantic.md +0 -0
  100. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/architecture/adrs/adr-005-middleware.md +0 -0
  101. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/architecture/adrs/index.md +0 -0
  102. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/architecture/component-lifecycle.md +0 -0
  103. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/architecture/data-flows.md +0 -0
  104. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/architecture/error-taxonomy.md +0 -0
  105. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/architecture/package-journey/error-propagation.md +0 -0
  106. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/architecture/package-journey/index.md +0 -0
  107. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/architecture/package-journey/tracing-flow.md +0 -0
  108. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/deployment/cicd.md +0 -0
  109. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/deployment/environments.md +0 -0
  110. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/deployment/secrets-and-config.md +0 -0
  111. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/infrastructure/platform.md +0 -0
  112. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/infrastructure/storage.md +0 -0
  113. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/operations/index.md +0 -0
  114. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/operations/monitoring.md +0 -0
  115. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/operations/runbooks/modal-cold-start-spike.md +0 -0
  116. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/operations/runbooks/postgres-pool-exhausted.md +0 -0
  117. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/operations/runbooks/redis-connection-lost.md +0 -0
  118. {openframe_core-3.0.1 → openframe_core-3.2.0}/docs/technical/operations/runbooks/telemetry-export-failing.md +0 -0
  119. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/__init__.py +0 -0
  120. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/__init__.py +0 -0
  121. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/config/__init__.py +0 -0
  122. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/config/settings.py +0 -0
  123. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/exceptions/__init__.py +0 -0
  124. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/exceptions/adapter.py +0 -0
  125. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/exceptions/codes.py +0 -0
  126. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/exceptions/plugin.py +0 -0
  127. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/inbound/__init__.py +0 -0
  128. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/middleware/__init__.py +0 -0
  129. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/middleware/telemetry.py +0 -0
  130. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/middleware/types.py +0 -0
  131. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/runtime/__init__.py +0 -0
  132. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/telemetry/__init__.py +0 -0
  133. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/telemetry/setup.py +0 -0
  134. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/testing/contracts/consumer.py +0 -0
  135. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/testing/contracts/producer.py +0 -0
  136. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/testing/contracts/repository.py +0 -0
  137. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/testing/fixtures.py +0 -0
  138. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/tracing/__init__.py +0 -0
  139. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/tracing/propagation.py +0 -0
  140. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/core/tracing/proxy.py +0 -0
  141. {openframe_core-3.0.1 → openframe_core-3.2.0}/openframe/py.typed +0 -0
  142. {openframe_core-3.0.1 → openframe_core-3.2.0}/tests/conftest.py +0 -0
  143. {openframe_core-3.0.1 → openframe_core-3.2.0}/tests/test_config.py +0 -0
  144. {openframe_core-3.0.1 → openframe_core-3.2.0}/tests/test_exceptions.py +0 -0
  145. {openframe_core-3.0.1 → openframe_core-3.2.0}/tests/test_middleware.py +0 -0
  146. {openframe_core-3.0.1 → openframe_core-3.2.0}/tests/test_middleware_types.py +0 -0
  147. {openframe_core-3.0.1 → openframe_core-3.2.0}/tests/test_record_error.py +0 -0
  148. {openframe_core-3.0.1 → openframe_core-3.2.0}/tests/test_shutdown_telemetry.py +0 -0
  149. {openframe_core-3.0.1 → openframe_core-3.2.0}/tests/test_telemetry_sidecar.py +0 -0
  150. {openframe_core-3.0.1 → openframe_core-3.2.0}/tests/test_tracing.py +0 -0
  151. {openframe_core-3.0.1 → openframe_core-3.2.0}/tests/test_tracing_propagation.py +0 -0
@@ -18,12 +18,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
18
18
  as the default starting point and frame the other two as explicit alternatives
19
19
  with stated conditions. Tracked in the roadmap.
20
20
 
21
- - **`contracts/` five-module depth** — the `capability → context → health →
22
- identity → lifecycle → port` chain is clean today. The risk is a sixth or
23
- seventh module that doesn't stay within the single-concept-per-file rule or
24
- that imports from non-adjacent layers. Consolidate before expanding if either
25
- signal appears.
26
-
27
21
  ### Added
28
22
 
29
23
  - **`openframe.core.telemetry.shutdown_telemetry()`** — flushes and shuts
@@ -64,6 +58,77 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
64
58
 
65
59
  ---
66
60
 
61
+ ## v3.2.0
62
+
63
+ ### Added
64
+
65
+ - `openframe.core.testing.fakes.inbound` — three in-memory test
66
+ doubles for the inbound contracts: `EchoUseCase`,
67
+ `SpyCommandHandler`, `SpyQueryHandler`. Mirror of the outbound
68
+ fakes (`InMemoryRepository`, `FakeProducer`, `FakeConsumer`).
69
+ - `openframe.core.testing.contracts.inbound` — three inheritable
70
+ pytest base classes: `UseCaseContractTests`,
71
+ `CommandHandlerContractTests`, `QueryHandlerContractTests`.
72
+ Any application service or validation-framework service
73
+ implementing these protocols can prove conformance by inheriting
74
+ the relevant class.
75
+ - All six new names exported from `openframe.core.testing`
76
+ top-level for consistent import ergonomics.
77
+
78
+ ---
79
+
80
+ ## v3.1.0
81
+
82
+ ### Breaking changes
83
+
84
+ #### openframe.core.contracts → openframe.core.ports
85
+
86
+ The openframe.core.contracts module has been merged into
87
+ openframe.core.ports and no longer exists. All names previously
88
+ importable from openframe.core.contracts are now importable from
89
+ openframe.core.ports:
90
+
91
+ ```python
92
+ # Before (< v3.1.0)
93
+ from openframe.core.contracts import BasePort, Capability, PluginHealth
94
+
95
+ # After (v3.1.0+)
96
+ from openframe.core.ports import BasePort, Capability, PluginHealth
97
+ ```
98
+
99
+ No compatibility shim is provided at the old path.
100
+
101
+ `openframe.core.ports` now exports both the port primitives
102
+ (BasePort, Capability, Identity, Lifecycle, PluginStatus,
103
+ PluginHealth, PluginContext, PrincipalContext, TenantContext)
104
+ and the outbound protocols (BaseRepository, BaseProducer,
105
+ BaseConsumer) from a single unified module.
106
+
107
+ #### BaseRepository, BaseProducer, BaseConsumer moved to ports/outbound/
108
+
109
+ The three capability-specific outbound port protocols have moved
110
+ into the ports/outbound/ sub-module to mirror the existing
111
+ inbound/ sub-module on the driven side of the hexagon.
112
+ The public API is unchanged — import from openframe.core.ports
113
+ as before:
114
+
115
+ ```python
116
+ from openframe.core.ports import BaseRepository # unchanged
117
+ ```
118
+
119
+ The explicit sub-module path is now:
120
+
121
+ ```python
122
+ from openframe.core.ports.outbound import BaseRepository
123
+ ```
124
+
125
+ Future outbound capability protocols (BaseSecretsProvider,
126
+ BaseObjectStore, BaseFeatureFlagProvider from openframe-infra)
127
+ will be added to openframe/core/ports/outbound/ as the
128
+ ecosystem grows.
129
+
130
+ ---
131
+
67
132
  ## [3.0.0] — 2026-07-07
68
133
 
69
134
  ### Architecture scorecard
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openframe-core
3
- Version: 3.0.1
4
- Summary: OpenFrame Microservice Suite - platform kernel. Contracts, testing utilities, plugin registry, and composition root.
3
+ Version: 3.2.0
4
+ Summary: OpenFrame Microservice Suite - platform kernel. Port contracts, testing utilities, plugin registry, and composition root.
5
5
  Project-URL: Homepage, https://github.com/Furious-Meteors/openframe-core
6
6
  Project-URL: Documentation, https://furious-meteors.github.io/openframe-core/
7
7
  Project-URL: Repository, https://github.com/Furious-Meteors/openframe-core
@@ -73,24 +73,15 @@ Description-Content-Type: text/markdown
73
73
  <a href="https://github.com/Furious-Meteors/openframe-core/blob/production/.github/CHANGELOG.md">Changelog</a>
74
74
  </p>
75
75
 
76
- ---
77
-
78
76
  `openframe-core` is the foundation package of the OpenFrame Microservice Development Suite. It defines the structural contracts, telemetry primitives, and shared utilities that every other package in the ecosystem depends on.
79
77
 
80
- Every package in the OpenFrame ecosystem pins `openframe-core>=3.0,<4`. The major version is the stability contract for the entire ecosystem.
81
-
82
- > **v3.0.0 is a breaking redesign.** The old hardcoded, lifecycle-free ports, the standalone `HealthCheck` protocol, and the separate `OpenFramePlugin` protocol are gone. They are replaced by a single unified contract layer built on `BasePort` (`Identity` + `Lifecycle`), and the error hierarchy is consolidated under a single `OpenFrameError` root. See [ADR-006](https://furious-meteors.github.io/openframe-core/technical/architecture/adrs/adr-006-unified-port-lifecycle/) and the [Changelog](.github/CHANGELOG.md) for the full migration guide.
83
-
84
- ---
85
-
86
78
  ## What's inside
87
79
 
88
80
  | Module | Exports |
89
81
  |---|---|
90
- | `openframe.core.contracts` | `BasePort` · `Identity` · `Lifecycle` · `Capability` · `PluginStatus` · `PluginHealth` · `PluginContext` · `PrincipalContext` · `TenantContext` |
82
+ | `openframe.core.ports` | `BasePort` · `Identity` · `Lifecycle` · `Capability` · `PluginStatus` · `PluginHealth` · `PluginContext` · `PrincipalContext` · `TenantContext` · `BaseRepository[T]` · `BaseProducer[T]` · `BaseConsumer[T]` |
91
83
  | `openframe.core.exceptions` | `OpenFrameError` (root) · `ErrorCode` · `Severity` · `AdapterError` (+5) · `PluginError` (+4, incl. `AmbiguousCapabilityError`) |
92
84
  | `openframe.core.config` | `BaseAdapterSettings` — Pydantic `BaseSettings` subclass all adapters inherit |
93
- | `openframe.core.ports` | `BaseRepository[T]` · `BaseProducer[T]` · `BaseConsumer[T]` — `BasePort` + domain methods (outbound side) |
94
85
  | `openframe.core.inbound` | `UseCase[TIn, TOut]` · `CommandHandler[TIn]` · `QueryHandler[TIn, TOut]` · `RequestContext` (driving side) |
95
86
  | `openframe.core.plugins` | `PluginRegistry` — explicit registration, ordered init, LIFO shutdown, capability lookup |
96
87
  | `openframe.core.runtime` | `ApplicationBootstrap` — optional composition-root base class |
@@ -169,8 +160,7 @@ settings = PostgresSettings()
169
160
  Every port is a `BasePort`: `Identity` (`name`/`version`/`capability`) + `Lifecycle` (`initialize`/`shutdown`/`health`) plus its own domain methods. Adapters satisfy it structurally — no inheritance required.
170
161
 
171
162
  ```python
172
- from openframe.core.contracts import Capability, PluginContext, PluginHealth, PluginStatus
173
- from openframe.core.ports import BaseRepository
163
+ from openframe.core.ports import Capability, PluginContext, PluginHealth, PluginStatus, BaseRepository
174
164
 
175
165
  class PostgresItemRepository:
176
166
  # Identity
@@ -200,7 +190,7 @@ assert isinstance(PostgresItemRepository(), BaseRepository) # True
200
190
  A "plugin" is just a registered `BasePort`. The registry initializes in order, shuts down LIFO, and looks up by the typed `Capability` enum:
201
191
 
202
192
  ```python
203
- from openframe.core.contracts import Capability
193
+ from openframe.core.ports import Capability
204
194
  from openframe.core.plugins import PluginRegistry
205
195
 
206
196
  registry = PluginRegistry()
@@ -218,7 +208,7 @@ await registry.shutdown_all() # reverse order; never raises
218
208
  ### Runtime — optional composition root
219
209
 
220
210
  ```python
221
- from openframe.core.contracts import Capability
211
+ from openframe.core.ports import Capability
222
212
  from openframe.core.runtime import ApplicationBootstrap
223
213
 
224
214
  class MyServiceBootstrap(ApplicationBootstrap):
@@ -356,11 +346,11 @@ pip install -e ".[dev]"
356
346
  pytest tests/ -v
357
347
  ```
358
348
 
359
- 284 tests. All run in under 1 second — no network calls, no external services.
349
+ 301 tests. All run in under 1 second — no network calls, no external services.
360
350
 
361
351
  ```bash
362
352
  # Smoke test
363
- python -c "from openframe.core.contracts import BasePort; print('openframe-core OK')"
353
+ python -c "from openframe.core.ports import BasePort; print('openframe-core OK')"
364
354
  ```
365
355
 
366
356
  ---
@@ -17,24 +17,15 @@
17
17
  <a href="https://github.com/Furious-Meteors/openframe-core/blob/production/.github/CHANGELOG.md">Changelog</a>
18
18
  </p>
19
19
 
20
- ---
21
-
22
20
  `openframe-core` is the foundation package of the OpenFrame Microservice Development Suite. It defines the structural contracts, telemetry primitives, and shared utilities that every other package in the ecosystem depends on.
23
21
 
24
- Every package in the OpenFrame ecosystem pins `openframe-core>=3.0,<4`. The major version is the stability contract for the entire ecosystem.
25
-
26
- > **v3.0.0 is a breaking redesign.** The old hardcoded, lifecycle-free ports, the standalone `HealthCheck` protocol, and the separate `OpenFramePlugin` protocol are gone. They are replaced by a single unified contract layer built on `BasePort` (`Identity` + `Lifecycle`), and the error hierarchy is consolidated under a single `OpenFrameError` root. See [ADR-006](https://furious-meteors.github.io/openframe-core/technical/architecture/adrs/adr-006-unified-port-lifecycle/) and the [Changelog](.github/CHANGELOG.md) for the full migration guide.
27
-
28
- ---
29
-
30
22
  ## What's inside
31
23
 
32
24
  | Module | Exports |
33
25
  |---|---|
34
- | `openframe.core.contracts` | `BasePort` · `Identity` · `Lifecycle` · `Capability` · `PluginStatus` · `PluginHealth` · `PluginContext` · `PrincipalContext` · `TenantContext` |
26
+ | `openframe.core.ports` | `BasePort` · `Identity` · `Lifecycle` · `Capability` · `PluginStatus` · `PluginHealth` · `PluginContext` · `PrincipalContext` · `TenantContext` · `BaseRepository[T]` · `BaseProducer[T]` · `BaseConsumer[T]` |
35
27
  | `openframe.core.exceptions` | `OpenFrameError` (root) · `ErrorCode` · `Severity` · `AdapterError` (+5) · `PluginError` (+4, incl. `AmbiguousCapabilityError`) |
36
28
  | `openframe.core.config` | `BaseAdapterSettings` — Pydantic `BaseSettings` subclass all adapters inherit |
37
- | `openframe.core.ports` | `BaseRepository[T]` · `BaseProducer[T]` · `BaseConsumer[T]` — `BasePort` + domain methods (outbound side) |
38
29
  | `openframe.core.inbound` | `UseCase[TIn, TOut]` · `CommandHandler[TIn]` · `QueryHandler[TIn, TOut]` · `RequestContext` (driving side) |
39
30
  | `openframe.core.plugins` | `PluginRegistry` — explicit registration, ordered init, LIFO shutdown, capability lookup |
40
31
  | `openframe.core.runtime` | `ApplicationBootstrap` — optional composition-root base class |
@@ -113,8 +104,7 @@ settings = PostgresSettings()
113
104
  Every port is a `BasePort`: `Identity` (`name`/`version`/`capability`) + `Lifecycle` (`initialize`/`shutdown`/`health`) plus its own domain methods. Adapters satisfy it structurally — no inheritance required.
114
105
 
115
106
  ```python
116
- from openframe.core.contracts import Capability, PluginContext, PluginHealth, PluginStatus
117
- from openframe.core.ports import BaseRepository
107
+ from openframe.core.ports import Capability, PluginContext, PluginHealth, PluginStatus, BaseRepository
118
108
 
119
109
  class PostgresItemRepository:
120
110
  # Identity
@@ -144,7 +134,7 @@ assert isinstance(PostgresItemRepository(), BaseRepository) # True
144
134
  A "plugin" is just a registered `BasePort`. The registry initializes in order, shuts down LIFO, and looks up by the typed `Capability` enum:
145
135
 
146
136
  ```python
147
- from openframe.core.contracts import Capability
137
+ from openframe.core.ports import Capability
148
138
  from openframe.core.plugins import PluginRegistry
149
139
 
150
140
  registry = PluginRegistry()
@@ -162,7 +152,7 @@ await registry.shutdown_all() # reverse order; never raises
162
152
  ### Runtime — optional composition root
163
153
 
164
154
  ```python
165
- from openframe.core.contracts import Capability
155
+ from openframe.core.ports import Capability
166
156
  from openframe.core.runtime import ApplicationBootstrap
167
157
 
168
158
  class MyServiceBootstrap(ApplicationBootstrap):
@@ -300,11 +290,11 @@ pip install -e ".[dev]"
300
290
  pytest tests/ -v
301
291
  ```
302
292
 
303
- 284 tests. All run in under 1 second — no network calls, no external services.
293
+ 301 tests. All run in under 1 second — no network calls, no external services.
304
294
 
305
295
  ```bash
306
296
  # Smoke test
307
- python -c "from openframe.core.contracts import BasePort; print('openframe-core OK')"
297
+ python -c "from openframe.core.ports import BasePort; print('openframe-core OK')"
308
298
  ```
309
299
 
310
300
  ---
@@ -23,8 +23,10 @@ pip install openframe-core
23
23
 
24
24
  ```bash
25
25
  python -c "
26
- from openframe.core.contracts import BasePort, Capability, PluginHealth, PluginStatus
27
- from openframe.core.ports import BaseRepository, BaseProducer, BaseConsumer
26
+ from openframe.core.ports import (
27
+ BasePort, Capability, PluginHealth, PluginStatus,
28
+ BaseRepository, BaseProducer, BaseConsumer,
29
+ )
28
30
  from openframe.core.exceptions import OpenFrameError, AdapterError
29
31
  from openframe.core.inbound import UseCase, RequestContext
30
32
  from openframe.core.plugins import PluginRegistry
@@ -67,7 +69,7 @@ export OPENFRAME_ENV="dev"
67
69
  ```python
68
70
  from contextlib import asynccontextmanager
69
71
  from fastapi import FastAPI
70
- from openframe.core.contracts import Capability
72
+ from openframe.core.ports import Capability
71
73
  from openframe.core.plugins import PluginRegistry
72
74
  from openframe.core.telemetry import setup_telemetry, record_lifecycle_event
73
75
  from openframe.core.middleware import TelemetryMiddleware
@@ -0,0 +1,46 @@
1
+ # Health
2
+
3
+ Health is part of the unified `Lifecycle` contract in `openframe.core.ports`. Every `BasePort` implements a single `health()` method that returns a rich `PluginHealth` snapshot — there is no separate health protocol.
4
+
5
+ ```python
6
+ from openframe.core.ports import Lifecycle, PluginHealth, PluginStatus
7
+
8
+ async def health(self) -> PluginHealth:
9
+ try:
10
+ await self._pool.fetchval("SELECT 1")
11
+ return PluginHealth(status=PluginStatus.READY)
12
+ except Exception as exc:
13
+ return PluginHealth(
14
+ status=PluginStatus.UNAVAILABLE,
15
+ message=str(exc),
16
+ )
17
+ ```
18
+
19
+ `Lifecycle.health()` is the single canonical health primitive. Liveness vs. readiness granularity — or any other reporting distinction an adapter needs — is expressed through `PluginStatus` and `PluginHealth.details`, not through separate methods:
20
+
21
+ ```python
22
+ # Minimal
23
+ PluginHealth(status=PluginStatus.READY)
24
+
25
+ # With detail
26
+ PluginHealth(
27
+ status=PluginStatus.READY,
28
+ details={"ping_ms": 2.1, "schema_ok": True},
29
+ )
30
+
31
+ # Degraded
32
+ PluginHealth(
33
+ status=PluginStatus.DEGRADED,
34
+ message="replica lag 5s",
35
+ details={"lag_s": 5},
36
+ )
37
+ ```
38
+
39
+ `PluginRegistry` calls `health()` on every registered port to build a live snapshot — see [`PluginRegistry.health_all()`](plugins.md).
40
+
41
+ ---
42
+
43
+ ## See Also
44
+
45
+ - [ports module](ports.md) — `Lifecycle`, `PluginHealth`, `PluginStatus`, `BasePort`
46
+ - [ADR-006](../../technical/architecture/adrs/adr-006-unified-port-lifecycle.md) — full design rationale
@@ -1,13 +1,12 @@
1
1
  # Modules
2
2
 
3
- `openframe-core` v3.0.0 contains eleven modules, organised into three tiers: foundation, contract layer, and application modules. Each page documents every public class, method, and function with parameters, return types, and what it raises.
3
+ `openframe-core` v3.1.0 contains ten modules, organised into three tiers: foundation, contract layer, and application modules. Each page documents every public class, method, and function with parameters, return types, and what it raises.
4
4
 
5
5
  | Module | Import path | What it provides |
6
6
  |---|---|---|
7
7
  | [exceptions](exceptions.md) | `openframe.core.exceptions` | `OpenFrameError` (root) · `ErrorCode` · `Severity` · `AdapterError` (+5) · `PluginError` (+4, incl. `AmbiguousCapabilityError`) |
8
8
  | [config](config.md) | `openframe.core.config` | `BaseAdapterSettings` |
9
- | [contracts](contracts.md) | `openframe.core.contracts` | `Identity` · `Lifecycle` · `BasePort` · `Capability` · `PluginStatus` · `PluginHealth` · `PluginContext` · `PrincipalContext` · `TenantContext` |
10
- | [ports](ports.md) | `openframe.core.ports` | `BaseRepository[T]` · `BaseProducer[T]` · `BaseConsumer[T]` — `BasePort` + domain methods |
9
+ | [ports](ports.md) | `openframe.core.ports` | `Identity` · `Lifecycle` · `BasePort` · `Capability` · `PluginStatus` · `PluginHealth` · `PluginContext` · `PrincipalContext` · `TenantContext` · `BaseRepository[T]` · `BaseProducer[T]` · `BaseConsumer[T]` |
11
10
  | [inbound](inbound.md) | `openframe.core.inbound` | `UseCase[TIn, TOut]` · `CommandHandler[TIn]` · `QueryHandler[TIn, TOut]` · `RequestContext` |
12
11
  | [telemetry](telemetry.md) | `openframe.core.telemetry` | `setup_telemetry` · `get_tracer` · `get_meter` · `record_lifecycle_event` · `record_error` |
13
12
  | [tracing](tracing.md) | `openframe.core.tracing` | `TracingProxy` |
@@ -16,5 +15,5 @@
16
15
  | [runtime](runtime.md) | `openframe.core.runtime` | `ApplicationBootstrap` |
17
16
  | [testing](testing.md) | `openframe.core.testing` | `InMemoryRepository` · `FakeProducer` · `FakeConsumer` · contract test base classes |
18
17
 
19
- !!! note "health module removed in v3.0.0"
20
- The `openframe.core.health` module and `HealthCheck` protocol were removed in v3.0.0. Health is now part of the unified `Lifecycle` contract in `openframe.core.contracts` (`Lifecycle.health() -> PluginHealth`). See the [contracts module](contracts.md) and [ADR-006](../../technical/architecture/adrs/adr-006-unified-port-lifecycle.md).
18
+ !!! note "health module removed in v3.0.0; contracts merged into ports in v3.1.0"
19
+ The `openframe.core.health` module and `HealthCheck` protocol were removed in v3.0.0. Health is now part of the unified `Lifecycle` contract in `openframe.core.ports` (`Lifecycle.health() -> PluginHealth`). In v3.1.0, `openframe.core.contracts` was merged into `openframe.core.ports`, and the outbound protocols (`BaseRepository`, `BaseProducer`, `BaseConsumer`) moved into an internal `ports/outbound/` sub-module mirroring `openframe.core.inbound` on the driving side — the public import path (`from openframe.core.ports import ...`) is unaffected. No compatibility shim exists at the old `openframe.core.contracts` path. See the [ports module](ports.md) and [ADR-006](../../technical/architecture/adrs/adr-006-unified-port-lifecycle.md).
@@ -10,7 +10,7 @@
10
10
 
11
11
  ```python
12
12
  from openframe.core.plugins import PluginRegistry
13
- from openframe.core.contracts import Capability
13
+ from openframe.core.ports import Capability
14
14
  ```
15
15
 
16
16
  ---
@@ -119,7 +119,7 @@ Return all registered ports for the given `Capability`. Returns an empty list wh
119
119
 
120
120
  ```python
121
121
  from openframe.core.plugins import PluginRegistry
122
- from openframe.core.contracts import Capability
122
+ from openframe.core.ports import Capability
123
123
 
124
124
  registry = PluginRegistry()
125
125
 
@@ -154,7 +154,7 @@ primary, replica = registry.get_all(Capability.PERSISTENCE)
154
154
 
155
155
  ```python
156
156
  from openframe.core.runtime import ApplicationBootstrap
157
- from openframe.core.contracts import Capability
157
+ from openframe.core.ports import Capability
158
158
 
159
159
  class MyApp(ApplicationBootstrap):
160
160
  def configure(self) -> None: