fix(identifiers): reject unproven assignments

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a023c0-a0a3-7c03-b395-5a0d2757214d
This commit is contained in:
tegwick 2026-08-22 23:54:24 +02:00
parent 055c6971ab
commit 4398167580
3 changed files with 26 additions and 2 deletions

View file

@ -80,7 +80,8 @@ the cutover: each replacement must resolve its current UUID with HTTP 200 and
its derived target with HTTP 404 on every named projection, or the manifest is
not ready for approval. Saved projection endpoints are rechecked by
`migration-batch-verify`; omitting the option retains the offline source/Git-only
planning mode.
planning mode. A projection-aware batch containing UUID assignments fails
closed until an assignment-specific projection identity check is implemented.
Activation and applying a bulk migration remain separate governed steps.
Publishing or planning this function does not retroactively rewrite existing

View file

@ -365,7 +365,14 @@ def _projection_migration_preflight(
) -> dict[str, Any]:
"""Require every replacement source and no replacement target per projection."""
projections: list[dict[str, Any]] = []
errors: list[dict[str, str]] = []
errors: list[dict[str, str]] = [
{
"scope": str(mapping.get("record_id") or "unknown"),
"reason": "projection-aware approval does not yet support UUID assignments",
}
for mapping in mappings
if mapping.get("action") == "assign"
]
for raw_base in api_bases:
api_base = raw_base.strip().rstrip("/")
try:

View file

@ -7,6 +7,7 @@ import httpx
import pytest
from repo_manager.identifiers import (
_projection_migration_preflight,
derive_work_record_uuid,
load_fleet_namespace,
migrate_repository_identifier_files,
@ -22,6 +23,21 @@ def test_declared_fleet_namespace_is_helixforge() -> None:
assert load_fleet_namespace() == "helixforge"
def test_projection_preflight_rejects_unproven_assignment() -> None:
result = _projection_migration_preflight(
[{"action": "assign", "record_id": "ONE-WP-0001"}],
["http://hub.test"],
)
assert result["ok"] is False
assert result["errors"] == [
{
"scope": "ONE-WP-0001",
"reason": "projection-aware approval does not yet support UUID assignments",
}
]
def _workplan(path: Path, identifier: str, status: str, task_status: str = "todo") -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(