tigrbl_kms 0.3.2.dev7__tar.gz → 0.3.2.dev8__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tigrbl_kms
3
- Version: 0.3.2.dev7
3
+ Version: 0.3.2.dev8
4
4
  Summary: A Tigrbl key management service for Swarmauri.
5
5
  License-Expression: Apache-2.0
6
6
  License-File: LICENSE
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tigrbl_kms"
3
- version = "0.3.2.dev7"
3
+ version = "0.3.2.dev8"
4
4
  description = "A Tigrbl key management service for Swarmauri."
5
5
  license = "Apache-2.0"
6
6
  readme = "README.md"
@@ -41,6 +41,11 @@ app = TigrblApp(
41
41
  # Custom ops return raw dicts so no finalize hook needed
42
42
  app.include_tables([Key, KeyVersion], base_prefix="/kms")
43
43
  app.attach_diagnostics(prefix="/system")
44
+
45
+ # Keep package-level contract focused on domain models only.
46
+ for _system_model in ("__tigrbl_system_docs__", "__tigrbl_system_routes__"):
47
+ app.tables.pop(_system_model, None)
48
+
44
49
  # Backward-compatible alias used by tests and older integrations.
45
50
  app.routes = app.router.routes
46
51
 
@@ -1,6 +1,7 @@
1
1
  # tigrbl_kms/orm/key.py
2
2
  from __future__ import annotations
3
3
  import base64
4
+ import inspect
4
5
  from enum import Enum
5
6
  from uuid import UUID, uuid4
6
7
  from typing import List, Optional, TYPE_CHECKING
@@ -11,10 +12,10 @@ from tigrbl.orm.mixins import BulkCapable, Replaceable
11
12
 
12
13
  from tigrbl.orm.tables import Base
13
14
  from tigrbl.specs import acol, vcol, S, F, IO
14
- from tigrbl.hook import hook_ctx
15
- from tigrbl.op import op_ctx
15
+ from tigrbl.decorators.hook import hook_ctx
16
+ from tigrbl.decorators import op_ctx
16
17
  from tigrbl.runtime.status.exceptions import HTTPException
17
- from tigrbl.responses import Response
18
+ from tigrbl import Response
18
19
 
19
20
  if TYPE_CHECKING:
20
21
  from .key_version import KeyVersion
@@ -253,7 +254,22 @@ class Key(Base, BulkCapable, Replaceable):
253
254
  )
254
255
  async def _ensure_key_enabled(cls, ctx):
255
256
  pp = ctx.get("path_params") or {}
256
- ident = pp.get("id") or pp.get("item_id")
257
+ temp = ctx.get("temp") or {}
258
+ route = temp.get("route") if isinstance(temp, dict) else {}
259
+ route_pp = route.get("path_params") if isinstance(route, dict) else {}
260
+ if not isinstance(route_pp, dict):
261
+ route_pp = {}
262
+
263
+ # Runtime route metadata may stage member identifiers in temp.route.
264
+ # Support both current and legacy parameter names.
265
+ ident = (
266
+ pp.get("id")
267
+ or pp.get("item_id")
268
+ or pp.get("key_id")
269
+ or route_pp.get("id")
270
+ or route_pp.get("item_id")
271
+ or route_pp.get("key_id")
272
+ )
257
273
  if not ident:
258
274
  raise HTTPException(status_code=400, detail="Missing key identifier")
259
275
  try:
@@ -263,16 +279,26 @@ class Key(Base, BulkCapable, Replaceable):
263
279
 
264
280
  db = ctx.get("db")
265
281
  if db is None:
266
- raise HTTPException(status_code=500, detail="DB session missing")
267
- # works with sync or async session
282
+ try:
283
+ db, _release_db = cls.acquire(op_alias="read")
284
+ # Keep acquired session available for downstream ops in this request.
285
+ ctx["db"] = db
286
+ temp = ctx.get("temp")
287
+ if not isinstance(temp, dict):
288
+ temp = {}
289
+ ctx["temp"] = temp
290
+ temp.setdefault("__sys_db_release__", _release_db)
291
+ except Exception as exc:
292
+ raise HTTPException(
293
+ status_code=500, detail="DB session missing"
294
+ ) from exc
295
+
268
296
  getter = getattr(db, "get", None)
269
- obj = (
270
- await getter(cls, ident)
271
- if callable(getter)
272
- and getattr(getter, "__code__", None)
273
- and getter.__code__.co_flags & 0x80
274
- else db.get(cls, ident)
275
- )
297
+ if not callable(getter):
298
+ raise HTTPException(status_code=500, detail="DB session missing get()")
299
+ obj = getter(cls, ident)
300
+ if inspect.isawaitable(obj):
301
+ obj = await obj
276
302
  if obj is None:
277
303
  raise HTTPException(status_code=404, detail="Key not found")
278
304
  if obj.status == KeyStatus.disabled:
@@ -4,11 +4,9 @@ from uuid import UUID, uuid4
4
4
 
5
5
  from tigrbl.runtime.status.exceptions import HTTPException
6
6
 
7
- from tigrbl.hook import hook_ctx
8
- from tigrbl.specs import IO, F, S, acol
7
+ from tigrbl.decorators.hook import hook_ctx
8
+ from tigrbl.specs import IO, F, S, Pair, ForeignKeySpec, acol
9
9
  from tigrbl.orm.mixins import BulkCapable, Replaceable
10
- from tigrbl.column.io_spec import Pair
11
- from tigrbl.column.storage_spec import ForeignKeySpec
12
10
  from tigrbl.orm.tables import Base
13
11
  from tigrbl.types import (
14
12
  Integer,
@@ -98,6 +96,35 @@ class KeyVersion(Base, BulkCapable, Replaceable):
98
96
 
99
97
  key = relationship("Key", back_populates="versions", lazy="joined")
100
98
 
99
+ @hook_ctx(ops=("create", "bulk_create"), phase="PRE_HANDLER")
100
+ async def _coerce_key_id_uuid(cls, ctx):
101
+ payload = ctx.get("payload")
102
+ if payload is None:
103
+ return
104
+
105
+ def _coerce_item(item):
106
+ if not isinstance(item, dict):
107
+ return
108
+ key_id = item.get("key_id")
109
+ if key_id is None or isinstance(key_id, UUID):
110
+ return
111
+ try:
112
+ item["key_id"] = UUID(str(key_id))
113
+ except Exception as exc:
114
+ raise HTTPException(status_code=400, detail="Invalid key_id") from exc
115
+
116
+ if isinstance(payload, list):
117
+ for item in payload:
118
+ _coerce_item(item)
119
+ return
120
+
121
+ if isinstance(payload, dict):
122
+ _coerce_item(payload)
123
+ items = payload.get("items")
124
+ if isinstance(items, list):
125
+ for item in items:
126
+ _coerce_item(item)
127
+
101
128
  @hook_ctx(ops="create", phase="POST_HANDLER")
102
129
  async def _generate_material(cls, ctx):
103
130
  obj = ctx.get("result")
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  import base64
4
4
  from typing import Any, Mapping, Optional
5
5
 
6
- from tigrbl.requests import Request
6
+ from tigrbl import Request
7
7
 
8
8
  from swarmauri_core.crypto.types import ExportPolicy, KeyType, KeyUse
9
9
 
File without changes