Add guide-board pilot ingestion

This commit is contained in:
2026-05-17 00:09:11 +02:00
parent 1f379ba321
commit 91bb08c8e5
22 changed files with 1074 additions and 12 deletions

View File

@@ -33,6 +33,7 @@ from artifactstore.dataplane.spi import DataPlane, IngestHints
from artifactstore.db.schema import (
artifact_files,
artifact_packages,
metadata_schemas,
retention_classes,
retention_state,
storage_locations,
@@ -70,6 +71,7 @@ __all__ = [
"FileNotFoundError",
"FileRecord",
"IllegalPackageStateError",
"MetadataSchemaRecord",
"PackageNotFoundError",
"PackageRecord",
"Registry",
@@ -100,6 +102,16 @@ class RetentionStateError(ValueError):
"""Raised when a retention lifecycle operation is invalid."""
@dataclass(frozen=True, slots=True)
class MetadataSchemaRecord:
"""Registered package metadata schema."""
id: UUID
slug: str
json_schema: dict[str, Any]
created_at: datetime | None
@dataclass(frozen=True, slots=True)
class PackageRecord:
"""Materialised package row projected into the registry API."""
@@ -208,9 +220,15 @@ class Registry:
retention_class: str,
actor: str,
metadata: dict[str, Any] | None = None,
metadata_schema_slug: str | None = None,
) -> UUID:
"""Create a new package; returns its ``UUID``."""
retention_class_row = await self._get_retention_class(retention_class)
package_metadata = metadata or {}
metadata_schema_id = await self._validate_metadata_schema(
metadata_schema_slug,
package_metadata,
)
package_id = uuid.uuid4()
payload = cbor2.dumps(
{
@@ -218,7 +236,8 @@ class Registry:
"producer": producer,
"subject": subject,
"retention_class": retention_class,
"metadata": metadata or {},
"metadata": package_metadata,
"metadata_schema_id": str(metadata_schema_id) if metadata_schema_id else None,
},
canonical=True,
)
@@ -513,6 +532,48 @@ class Registry:
for r in rows
]
async def register_metadata_schema(
self,
*,
slug: str,
json_schema: dict[str, Any],
) -> UUID:
"""Register a package metadata JSON Schema, idempotent by slug."""
schema_id = uuid.uuid4()
async with self._engine.begin() as conn:
existing = (
await conn.execute(
select(metadata_schemas.c.id).where(metadata_schemas.c.slug == slug)
)
).first()
if existing is not None:
return UUID(str(existing.id))
await conn.execute(
metadata_schemas.insert().values(
id=schema_id,
slug=slug,
json_schema=json_schema,
)
)
return schema_id
async def get_metadata_schema(self, slug: str) -> MetadataSchemaRecord:
"""Return one registered metadata schema by slug."""
async with self._engine.connect() as conn:
row = (
await conn.execute(
select(metadata_schemas).where(metadata_schemas.c.slug == slug)
)
).first()
if row is None:
raise KeyError(f"metadata schema not found: {slug}")
return MetadataSchemaRecord(
id=row.id,
slug=row.slug,
json_schema=dict(row.json_schema),
created_at=row.created_at,
)
async def get_retention_state(self, package_id: UUID) -> RetentionStateRecord:
"""Return the retention materialised view for one package."""
async with self._engine.connect() as conn:
@@ -902,6 +963,25 @@ class Registry:
deletion_strategy=row.deletion_strategy,
)
async def _validate_metadata_schema(
self,
slug: str | None,
metadata: dict[str, Any],
) -> UUID | None:
if slug is None:
return None
try:
schema = await self.get_metadata_schema(slug)
except KeyError as exc:
raise ValueError(str(exc)) from exc
required = schema.json_schema.get("required", [])
if not isinstance(required, list):
raise ValueError(f"metadata schema {slug!r} has invalid required list")
missing = [key for key in required if isinstance(key, str) and key not in metadata]
if missing:
raise ValueError(f"metadata missing required schema keys: {', '.join(missing)}")
return schema.id
def _iso(value: datetime | None) -> str | None:
if value is None: