omnibase_infra 0.2.9__py3-none-any.whl → 0.3.0__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.
- omnibase_infra/__init__.py +1 -1
- omnibase_infra/errors/__init__.py +18 -0
- omnibase_infra/errors/repository/__init__.py +78 -0
- omnibase_infra/errors/repository/errors_repository.py +424 -0
- omnibase_infra/nodes/contract_registry_reducer/reducer.py +12 -2
- omnibase_infra/runtime/db/__init__.py +73 -0
- omnibase_infra/runtime/db/models/__init__.py +41 -0
- omnibase_infra/runtime/db/models/model_repository_runtime_config.py +211 -0
- omnibase_infra/runtime/db/postgres_repository_runtime.py +545 -0
- omnibase_infra/validation/infra_validators.py +4 -1
- omnibase_infra/validation/validation_exemptions.yaml +18 -0
- {omnibase_infra-0.2.9.dist-info → omnibase_infra-0.3.0.dist-info}/METADATA +2 -2
- {omnibase_infra-0.2.9.dist-info → omnibase_infra-0.3.0.dist-info}/RECORD +16 -10
- {omnibase_infra-0.2.9.dist-info → omnibase_infra-0.3.0.dist-info}/WHEEL +0 -0
- {omnibase_infra-0.2.9.dist-info → omnibase_infra-0.3.0.dist-info}/entry_points.txt +0 -0
- {omnibase_infra-0.2.9.dist-info → omnibase_infra-0.3.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
"""Database Runtime Models Module.
|
|
4
|
+
|
|
5
|
+
This module exports Pydantic models for database runtime configuration.
|
|
6
|
+
Contract models (ModelDbRepositoryContract, ModelDbOperation, ModelDbReturn)
|
|
7
|
+
are imported from omnibase_core.models.contracts.
|
|
8
|
+
|
|
9
|
+
Exports:
|
|
10
|
+
ModelRepositoryRuntimeConfig: Configuration for PostgresRepositoryRuntime
|
|
11
|
+
- Safety constraints (max_row_limit, timeout_ms)
|
|
12
|
+
- Operation allowlisting (select, insert, update, upsert)
|
|
13
|
+
- Feature flags (allow_raw_operations, allow_delete_operations)
|
|
14
|
+
- Determinism controls (primary_key_column, default_order_by)
|
|
15
|
+
- Metrics emission configuration
|
|
16
|
+
|
|
17
|
+
ModelDbRepositoryContract: (re-export from omnibase_core)
|
|
18
|
+
ModelDbOperation: (re-export from omnibase_core)
|
|
19
|
+
ModelDbReturn: (re-export from omnibase_core)
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
# Contract models from omnibase_core (canonical source)
|
|
25
|
+
from omnibase_core.models.contracts import (
|
|
26
|
+
ModelDbOperation,
|
|
27
|
+
ModelDbRepositoryContract,
|
|
28
|
+
ModelDbReturn,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Runtime config is local to omnibase_infra
|
|
32
|
+
from omnibase_infra.runtime.db.models.model_repository_runtime_config import (
|
|
33
|
+
ModelRepositoryRuntimeConfig,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
__all__: list[str] = [
|
|
37
|
+
"ModelDbOperation",
|
|
38
|
+
"ModelDbRepositoryContract",
|
|
39
|
+
"ModelDbReturn",
|
|
40
|
+
"ModelRepositoryRuntimeConfig",
|
|
41
|
+
]
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
"""Repository Runtime Configuration Model.
|
|
4
|
+
|
|
5
|
+
This module provides the configuration model for PostgresRepositoryRuntime.
|
|
6
|
+
All fields are strongly typed to eliminate Any usage and enable proper validation.
|
|
7
|
+
|
|
8
|
+
Safety Constraints:
|
|
9
|
+
- max_row_limit: Prevents unbounded SELECT queries
|
|
10
|
+
- timeout_ms: Prevents long-running queries from blocking resources
|
|
11
|
+
- allowed_modes: Allowlist of permitted operation modes (read, write)
|
|
12
|
+
- allow_write_operations: Explicit opt-in for write operations
|
|
13
|
+
|
|
14
|
+
Determinism:
|
|
15
|
+
- primary_key_column: Enables ORDER BY injection for stable pagination
|
|
16
|
+
- default_order_by: Default ordering clause when PK is declared
|
|
17
|
+
|
|
18
|
+
Metrics:
|
|
19
|
+
- emit_metrics: Controls whether duration_ms and rows_returned are emitted
|
|
20
|
+
|
|
21
|
+
SQL Identifier Validation:
|
|
22
|
+
- primary_key_column and default_order_by are validated against safe SQL
|
|
23
|
+
identifier patterns to prevent SQL injection from misconfiguration.
|
|
24
|
+
- Pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ for column names
|
|
25
|
+
- ORDER BY allows: column [ASC|DESC] [, column [ASC|DESC]]*
|
|
26
|
+
|
|
27
|
+
Example:
|
|
28
|
+
>>> config = ModelRepositoryRuntimeConfig(
|
|
29
|
+
... max_row_limit=100,
|
|
30
|
+
... timeout_ms=5000,
|
|
31
|
+
... allowed_ops={"select", "insert"},
|
|
32
|
+
... )
|
|
33
|
+
>>> print(config.allow_raw_operations)
|
|
34
|
+
False
|
|
35
|
+
>>> print("delete" in config.allowed_ops)
|
|
36
|
+
False
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
from __future__ import annotations
|
|
40
|
+
|
|
41
|
+
import re
|
|
42
|
+
from typing import Literal
|
|
43
|
+
|
|
44
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
45
|
+
|
|
46
|
+
# Safe SQL identifier pattern: starts with letter or underscore,
|
|
47
|
+
# followed by letters, digits, or underscores
|
|
48
|
+
_SQL_IDENTIFIER_PATTERN = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*$")
|
|
49
|
+
|
|
50
|
+
# ORDER BY clause pattern: column [ASC|DESC]
|
|
51
|
+
# Allows whitespace around components
|
|
52
|
+
_ORDER_BY_COMPONENT_PATTERN = re.compile(
|
|
53
|
+
r"^\s*[a-zA-Z_][a-zA-Z0-9_]*\s*(?:ASC|DESC)?\s*$", re.IGNORECASE
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class ModelRepositoryRuntimeConfig(BaseModel):
|
|
58
|
+
"""Configuration for PostgresRepositoryRuntime.
|
|
59
|
+
|
|
60
|
+
This model controls safety constraints, allowed operations, determinism
|
|
61
|
+
behavior, and metrics emission for the PostgresRepositoryRuntime.
|
|
62
|
+
|
|
63
|
+
Attributes:
|
|
64
|
+
max_row_limit: Maximum rows for multi-row selects (1-1000, default: 10).
|
|
65
|
+
Prevents unbounded SELECT queries that could return massive result sets.
|
|
66
|
+
timeout_ms: Query timeout in milliseconds (1000-300000, default: 30000).
|
|
67
|
+
Queries exceeding this timeout are cancelled to prevent resource exhaustion.
|
|
68
|
+
allowed_modes: Set of allowed operation modes (read, write).
|
|
69
|
+
Both modes enabled by default. SQL safety is validated by
|
|
70
|
+
omnibase_core validators at contract load time.
|
|
71
|
+
allow_write_operations: Enable 'write' mode operations.
|
|
72
|
+
Default: True. Set to False for read-only configurations.
|
|
73
|
+
primary_key_column: Column name for ORDER BY injection.
|
|
74
|
+
When set, ensures deterministic query results for pagination.
|
|
75
|
+
default_order_by: Default ORDER BY clause when primary_key_column is set.
|
|
76
|
+
Applied when no explicit ORDER BY is provided.
|
|
77
|
+
emit_metrics: Whether to emit duration_ms and rows_returned metrics.
|
|
78
|
+
Enable for observability integration. Default: True.
|
|
79
|
+
|
|
80
|
+
Example:
|
|
81
|
+
>>> from omnibase_infra.runtime.db.models import ModelRepositoryRuntimeConfig
|
|
82
|
+
>>> # Restrictive config for read-only operations
|
|
83
|
+
>>> readonly_config = ModelRepositoryRuntimeConfig(
|
|
84
|
+
... allowed_modes=frozenset({"read"}),
|
|
85
|
+
... allow_write_operations=False,
|
|
86
|
+
... max_row_limit=50,
|
|
87
|
+
... )
|
|
88
|
+
>>> # Permissive config with higher limits
|
|
89
|
+
>>> admin_config = ModelRepositoryRuntimeConfig(
|
|
90
|
+
... max_row_limit=500,
|
|
91
|
+
... )
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
model_config = ConfigDict(
|
|
95
|
+
strict=True,
|
|
96
|
+
frozen=True,
|
|
97
|
+
extra="forbid",
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# Safety constraints
|
|
101
|
+
max_row_limit: int = Field(
|
|
102
|
+
default=10,
|
|
103
|
+
ge=1,
|
|
104
|
+
le=1000,
|
|
105
|
+
description="Maximum rows for multi-row selects",
|
|
106
|
+
)
|
|
107
|
+
timeout_ms: int = Field(
|
|
108
|
+
default=30000,
|
|
109
|
+
ge=1000,
|
|
110
|
+
le=300000,
|
|
111
|
+
description="Query timeout in milliseconds",
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# Allowed operation modes (from omnibase_core contract schema)
|
|
115
|
+
# Note: Specific SQL safety is validated by omnibase_core validators at contract load
|
|
116
|
+
allowed_modes: frozenset[Literal["read", "write"]] = Field(
|
|
117
|
+
default=frozenset({"read", "write"}),
|
|
118
|
+
description="Allowed operation modes from contract (read=SELECT, write=INSERT/UPDATE/etc)",
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# Feature flag for write operations (additional safety layer)
|
|
122
|
+
allow_write_operations: bool = Field(
|
|
123
|
+
default=True,
|
|
124
|
+
description="Enable 'write' mode operations (INSERT, UPDATE, UPSERT)",
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
# Determinism controls
|
|
128
|
+
primary_key_column: str | None = Field(
|
|
129
|
+
default=None,
|
|
130
|
+
description="Primary key column for ORDER BY injection to ensure deterministic results",
|
|
131
|
+
)
|
|
132
|
+
default_order_by: str | None = Field(
|
|
133
|
+
default=None,
|
|
134
|
+
description="Default ORDER BY clause when primary_key_column is declared",
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
# Metrics emission
|
|
138
|
+
emit_metrics: bool = Field(
|
|
139
|
+
default=True,
|
|
140
|
+
description="Emit duration_ms and rows_returned metrics for observability",
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
@field_validator("primary_key_column")
|
|
144
|
+
@classmethod
|
|
145
|
+
def validate_primary_key_column(cls, v: str | None) -> str | None:
|
|
146
|
+
"""Validate primary_key_column is a safe SQL identifier.
|
|
147
|
+
|
|
148
|
+
Prevents SQL injection from misconfigured column names.
|
|
149
|
+
Pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
v: The column name to validate, or None.
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
The validated column name, or None if not set.
|
|
156
|
+
|
|
157
|
+
Raises:
|
|
158
|
+
ValueError: If the column name contains unsafe characters.
|
|
159
|
+
"""
|
|
160
|
+
if v is None:
|
|
161
|
+
return v
|
|
162
|
+
if not _SQL_IDENTIFIER_PATTERN.match(v):
|
|
163
|
+
raise ValueError(
|
|
164
|
+
f"Invalid SQL identifier for primary_key_column: '{v}'. "
|
|
165
|
+
"Must start with a letter or underscore, followed by letters, "
|
|
166
|
+
"digits, or underscores only (pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$)."
|
|
167
|
+
)
|
|
168
|
+
return v
|
|
169
|
+
|
|
170
|
+
@field_validator("default_order_by")
|
|
171
|
+
@classmethod
|
|
172
|
+
def validate_default_order_by(cls, v: str | None) -> str | None:
|
|
173
|
+
"""Validate default_order_by contains only safe SQL identifiers.
|
|
174
|
+
|
|
175
|
+
Allows format: column [ASC|DESC] [, column [ASC|DESC]]*
|
|
176
|
+
Prevents SQL injection from misconfigured ORDER BY clauses.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
v: The ORDER BY clause to validate, or None.
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
The validated ORDER BY clause, or None if not set.
|
|
183
|
+
|
|
184
|
+
Raises:
|
|
185
|
+
ValueError: If any column reference contains unsafe characters.
|
|
186
|
+
"""
|
|
187
|
+
if v is None:
|
|
188
|
+
return v
|
|
189
|
+
|
|
190
|
+
# Split by comma to get individual column specifications
|
|
191
|
+
components = v.split(",")
|
|
192
|
+
|
|
193
|
+
for component in components:
|
|
194
|
+
component = component.strip()
|
|
195
|
+
if not component:
|
|
196
|
+
raise ValueError(
|
|
197
|
+
f"Invalid ORDER BY clause: '{v}'. "
|
|
198
|
+
"Empty component found after splitting by comma."
|
|
199
|
+
)
|
|
200
|
+
if not _ORDER_BY_COMPONENT_PATTERN.match(component):
|
|
201
|
+
raise ValueError(
|
|
202
|
+
f"Invalid ORDER BY component: '{component}' in '{v}'. "
|
|
203
|
+
"Each component must be a valid SQL identifier optionally "
|
|
204
|
+
"followed by ASC or DESC. Column names must start with a "
|
|
205
|
+
"letter or underscore, followed by letters, digits, or "
|
|
206
|
+
"underscores only."
|
|
207
|
+
)
|
|
208
|
+
return v
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
__all__: list[str] = ["ModelRepositoryRuntimeConfig"]
|