generated from coulomb/repo-seed
Markitect schema-validation integration use case and fixture for Markdown proxy documents
This commit is contained in:
@@ -16,6 +16,7 @@ from kontextual_engine import (
|
||||
MetadataFieldDefinition,
|
||||
MetadataRecord,
|
||||
MetadataSchema,
|
||||
MetadataSchemaAssignment,
|
||||
MetadataValueType,
|
||||
OperationContext,
|
||||
PolicyDecision,
|
||||
@@ -224,6 +225,60 @@ def test_asset_registry_validates_metadata_schema_before_writes() -> None:
|
||||
assert [record.key for record in repo.list_metadata_records(created.asset.id)] == ["owner"]
|
||||
|
||||
|
||||
def test_asset_registry_applies_persisted_metadata_schema_assignments() -> None:
|
||||
repo = InMemoryAssetRegistryRepository()
|
||||
service = AssetRegistryService(repo)
|
||||
context = operation_context()
|
||||
schema = MetadataSchema(
|
||||
schema_id="schema-policy-note-v1",
|
||||
name="Policy Note Metadata",
|
||||
allow_unknown=False,
|
||||
fields=(
|
||||
MetadataFieldDefinition("owner", MetadataValueType.STRING, required=True, require_confirmed=True),
|
||||
MetadataFieldDefinition("state", MetadataValueType.STRING, allowed_values=("draft", "approved")),
|
||||
),
|
||||
)
|
||||
assignment = MetadataSchemaAssignment(
|
||||
assignment_id="assignment-policy-note",
|
||||
schema_id=schema.schema_id,
|
||||
asset_types=("policy-note",),
|
||||
sensitivities=(Sensitivity.INTERNAL,),
|
||||
policy_ref="local://metadata-policy/policy-note",
|
||||
)
|
||||
|
||||
service.register_metadata_schema(schema, context)
|
||||
service.assign_metadata_schema(assignment, context)
|
||||
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
service.create_asset(
|
||||
"Policy Note",
|
||||
Classification(asset_type="policy-note", sensitivity=Sensitivity.INTERNAL),
|
||||
context,
|
||||
asset_id="asset-policy-note-invalid",
|
||||
metadata_records=[MetadataRecord("state", "published")],
|
||||
)
|
||||
|
||||
assert {issue["code"] for issue in exc_info.value.details["issues"]} == {
|
||||
"metadata.required_missing",
|
||||
"metadata.value_not_allowed",
|
||||
}
|
||||
assert repo.list_assets() == []
|
||||
|
||||
created = service.create_asset(
|
||||
"Policy Note",
|
||||
Classification(asset_type="policy-note", sensitivity=Sensitivity.INTERNAL),
|
||||
context,
|
||||
asset_id="asset-policy-note",
|
||||
metadata_records=[
|
||||
MetadataRecord("owner", "Platform Knowledge", confirmed=True),
|
||||
MetadataRecord("state", "approved", confirmed=True),
|
||||
],
|
||||
)
|
||||
|
||||
assert created.asset.id == "asset-policy-note"
|
||||
assert service.list_metadata_schema_assignments()[0].policy_ref == "local://metadata-policy/policy-note"
|
||||
|
||||
|
||||
def test_sqlite_asset_registry_survives_reinstantiation(tmp_path: Path) -> None:
|
||||
db_path = tmp_path / "registry.sqlite"
|
||||
repo = SQLiteAssetRegistryRepository(db_path)
|
||||
@@ -305,6 +360,67 @@ def test_sqlite_registry_persists_context_entities_relationships_and_idempotency
|
||||
]
|
||||
|
||||
|
||||
def test_sqlite_registry_persists_metadata_schemas_and_assignments(tmp_path: Path) -> None:
|
||||
db_path = tmp_path / "registry.sqlite"
|
||||
repo = SQLiteAssetRegistryRepository(db_path)
|
||||
service = AssetRegistryService(repo)
|
||||
context = operation_context()
|
||||
schema = MetadataSchema(
|
||||
schema_id="schema-review-v1",
|
||||
name="Review Metadata",
|
||||
allow_unknown=False,
|
||||
fields=(
|
||||
MetadataFieldDefinition("reviewer", MetadataValueType.STRING, required=True, require_confirmed=True),
|
||||
MetadataFieldDefinition("score", MetadataValueType.NUMBER, min_value=0, max_value=1),
|
||||
),
|
||||
)
|
||||
|
||||
service.register_metadata_schema(schema, context)
|
||||
service.assign_metadata_schema(
|
||||
MetadataSchemaAssignment(
|
||||
assignment_id="assignment-review-documents",
|
||||
schema_id=schema.schema_id,
|
||||
asset_types=("review",),
|
||||
),
|
||||
context,
|
||||
)
|
||||
|
||||
reloaded_service = AssetRegistryService(SQLiteAssetRegistryRepository(db_path))
|
||||
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
reloaded_service.create_asset(
|
||||
"Review",
|
||||
Classification(asset_type="review", sensitivity=Sensitivity.INTERNAL),
|
||||
context,
|
||||
asset_id="asset-review-invalid",
|
||||
metadata_records=[
|
||||
MetadataRecord("reviewer", "Ada", confirmed=False),
|
||||
MetadataRecord("score", 1.7),
|
||||
],
|
||||
)
|
||||
|
||||
assert {issue["code"] for issue in exc_info.value.details["issues"]} == {
|
||||
"metadata.confirmation_required",
|
||||
"metadata.value_too_large",
|
||||
}
|
||||
|
||||
created = reloaded_service.create_asset(
|
||||
"Review",
|
||||
Classification(asset_type="review", sensitivity=Sensitivity.INTERNAL),
|
||||
context,
|
||||
asset_id="asset-review",
|
||||
metadata_records=[
|
||||
MetadataRecord("reviewer", "Ada", confirmed=True),
|
||||
MetadataRecord("score", 0.92),
|
||||
],
|
||||
)
|
||||
|
||||
reloaded_repo = SQLiteAssetRegistryRepository(db_path)
|
||||
assert created.asset.id == "asset-review"
|
||||
assert reloaded_repo.get_metadata_schema("schema-review-v1").name == "Review Metadata"
|
||||
assert reloaded_repo.get_metadata_schema_assignment("assignment-review-documents").schema_id == "schema-review-v1"
|
||||
|
||||
|
||||
def test_sqlite_registry_enforces_representation_asset_reference(tmp_path: Path) -> None:
|
||||
repo = SQLiteAssetRegistryRepository(tmp_path / "registry.sqlite")
|
||||
representation = AssetRepresentation.from_content(
|
||||
|
||||
@@ -12,6 +12,7 @@ from kontextual_engine.core import (
|
||||
MetadataFieldDefinition,
|
||||
MetadataRecord,
|
||||
MetadataSchema,
|
||||
MetadataSchemaAssignment,
|
||||
MetadataValueType,
|
||||
OperationContext,
|
||||
PolicyDecision,
|
||||
@@ -210,3 +211,25 @@ def test_metadata_schema_reports_structured_validation_issues() -> None:
|
||||
assert schema.applies_to(Classification(asset_type="document")) is True
|
||||
assert schema.applies_to(Classification(asset_type="dataset")) is False
|
||||
assert MetadataSchema.from_dict(schema.to_dict()).fields[0].value_type == MetadataValueType.STRING
|
||||
|
||||
|
||||
def test_metadata_schema_assignment_matches_classification_and_roundtrips() -> None:
|
||||
assignment = MetadataSchemaAssignment(
|
||||
assignment_id="assignment-documents",
|
||||
schema_id="schema-document-v1",
|
||||
asset_types=("document",),
|
||||
sensitivities=(Sensitivity.INTERNAL,),
|
||||
lifecycle_states=(LifecycleState.ACTIVE,),
|
||||
policy_ref="local://policy/document-metadata",
|
||||
)
|
||||
|
||||
assert assignment.applies_to(
|
||||
Classification(asset_type="document", sensitivity=Sensitivity.INTERNAL)
|
||||
) is True
|
||||
assert assignment.applies_to(
|
||||
Classification(asset_type="document", sensitivity=Sensitivity.CONFIDENTIAL)
|
||||
) is False
|
||||
assert (
|
||||
MetadataSchemaAssignment.from_dict(assignment.to_dict()).policy_ref
|
||||
== "local://policy/document-metadata"
|
||||
)
|
||||
|
||||
@@ -23,6 +23,7 @@ INTERNAL = EXAMPLE_ROOT / "corpus" / "internal-risk-note.md"
|
||||
BUNDLE = EXAMPLE_ROOT / "composition" / "context-bundle.md"
|
||||
MANIFEST = EXAMPLE_ROOT / "manifests" / "agent-context.yaml"
|
||||
CONTRACT = EXAMPLE_ROOT / "contracts" / "decision-record.contract.md"
|
||||
SCHEMA = EXAMPLE_ROOT / "schemas" / "adr-proxy.schema.md"
|
||||
|
||||
|
||||
def test_markitect_parser_returns_structured_markdown_document() -> None:
|
||||
@@ -170,3 +171,16 @@ def test_markitect_document_contracts_accept_valid_and_report_invalid_documents(
|
||||
assert invalid.valid is False
|
||||
assert "contract.section.missing" in invalid_codes
|
||||
assert "contract.section.forbidden" in invalid_codes
|
||||
|
||||
|
||||
def test_markitect_schema_validation_accepts_markdown_proxy_documents() -> None:
|
||||
loaded_schema = mkt.load_schema_file(SCHEMA)
|
||||
schema_check = mkt.validate_schema(loaded_schema.schema)
|
||||
valid = mkt.validate_markdown_file(ADR, SCHEMA)
|
||||
invalid = mkt.validate_markdown_file(INVALID_ADR, SCHEMA)
|
||||
|
||||
assert loaded_schema.metadata["schema-id"] == "kontextual-engine.markdown-proxy.adr.v1"
|
||||
assert schema_check.valid is True
|
||||
assert valid.valid is True
|
||||
assert invalid.valid is False
|
||||
assert any("Decision" in violation.message for violation in invalid.violations)
|
||||
|
||||
Reference in New Issue
Block a user