feat(db): repository writes uuid + returns payload_hash on every row

This commit is contained in:
DumiFlex
2026-04-28 12:22:18 +03:00
parent c6b1feb156
commit b14b1c297c
2 changed files with 43 additions and 7 deletions
+13 -7
View File
@@ -13,6 +13,7 @@ import sqlite3
from typing import Any
from engine._utils import now_iso as _now
from engine.modules.snapshot import payload_hash
_TYPE_PREFIX = {
"wildcard": "wc",
@@ -49,15 +50,18 @@ def _slug(name: str) -> str:
def _row_to_module(row: sqlite3.Row) -> dict[str, Any]:
payload = json.loads(row["payload"])
return {
"id": row["id"],
"uuid": row["uuid"],
"type": row["type"],
"name": row["name"],
"description": row["description"],
"category_id": row["category_id"],
"tags": json.loads(row["tags"]),
"is_favorite": bool(row["is_favorite"]),
"payload": json.loads(row["payload"]),
"payload": payload,
"payload_hash": payload_hash(payload),
"version": row["version"],
"created_at": row["created_at"],
"updated_at": row["updated_at"],
@@ -68,9 +72,11 @@ class ModuleRepository:
def __init__(self, conn: sqlite3.Connection) -> None:
self._conn = conn
def _gen_id(self, type: str, name: str) -> str:
def _gen_id(self, type: str, name: str) -> tuple[str, str]:
"""Generate `(id, uuid)` for a new row. id = `<prefix>_<slug>_<uuid>`."""
prefix = _TYPE_PREFIX.get(type, "mod")
return f"{prefix}_{_slug(name)}_{secrets.token_hex(4)}"
uuid = secrets.token_hex(4)
return f"{prefix}_{_slug(name)}_{uuid}", uuid
def create(
self,
@@ -87,16 +93,16 @@ class ModuleRepository:
raise ValueError(
f"unknown module type {type!r}; expected one of {sorted(_VALID_TYPES)}"
)
mid = self._gen_id(type, name)
mid, uuid = self._gen_id(type, name)
now = _now()
with self._conn:
self._conn.execute(
"INSERT INTO modules("
"id, type, name, description, category_id, tags, "
"id, uuid, type, name, description, category_id, tags, "
"is_favorite, payload, version, created_at, updated_at"
") VALUES(?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?);",
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?);",
(
mid, type, name, description, category_id,
mid, uuid, type, name, description, category_id,
json.dumps(tags), int(is_favorite),
json.dumps(payload), now, now,
),
+30
View File
@@ -215,3 +215,33 @@ def test_create_rejects_unknown_type(wp_db):
type="bogus", name="x", description="",
category_id=None, tags=[], payload={},
)
def test_create_writes_uuid_column_matching_id_suffix(wp_db):
"""create() must persist the uuid column. The value equals the trailing
8 hex chars of the generated id so existing rows (backfilled) and new
rows share one identity convention."""
repo = ModuleRepository(wp_db)
row = repo.create(
type="wildcard", name="color", description="",
category_id=None, tags=[], payload={"options": []},
)
assert "uuid" in row
assert len(row["uuid"]) == 8
assert all(c in "0123456789abcdef" for c in row["uuid"])
assert row["id"].endswith(f"_{row['uuid']}")
def test_row_to_module_includes_payload_hash(wp_db):
"""API responses (and drift detection) need payload_hash on every row.
Sourced from engine.modules.snapshot.payload_hash so drift comparison
is bit-identical to embedded snapshot hashes."""
repo = ModuleRepository(wp_db)
row = repo.create(
type="wildcard", name="x", description="",
category_id=None, tags=[], payload={"options": [{"value": "a"}]},
)
assert "payload_hash" in row
# 64-char SHA-256 hex
assert len(row["payload_hash"]) == 64
assert all(c in "0123456789abcdef" for c in row["payload_hash"])