Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.PHONY: validate validate-json validate-schemas validate-control-plane validate-eventctl validate-event-store validate-events validate-identity validate-process-provenance validate-policy-normalizer validate-service-graph install-dev
.PHONY: validate validate-json validate-schemas validate-control-plane validate-eventctl validate-event-store validate-events validate-identity validate-process-provenance validate-policy-normalizer validate-service-graph validate-semantic-enterprise-state-integrity install-dev

validate: validate-json validate-schemas validate-control-plane validate-eventctl validate-event-store validate-events validate-identity validate-process-provenance validate-policy-normalizer validate-service-graph
validate: validate-json validate-schemas validate-control-plane validate-eventctl validate-event-store validate-events validate-identity validate-process-provenance validate-policy-normalizer validate-service-graph validate-semantic-enterprise-state-integrity

install-dev:
python3 -m pip install -r requirements-dev.txt
Expand Down Expand Up @@ -57,3 +57,6 @@ validate-policy-normalizer:
validate-service-graph:
python3 tools/sourceos_service_graph.py validate examples/services/*.json
python3 tools/sourceos_service_graph.py graph examples/services/*.json --json >/dev/null

validate-semantic-enterprise-state-integrity:
python3 tools/validate_semantic_enterprise_state_integrity.py
68 changes: 68 additions & 0 deletions docs/semantic-enterprise-state-integrity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Semantic Enterprise State Integrity Mapping v0.1

`sourceos-syncd` consumes `semantic-enterprise-v0.1.0` from `SocioProphet/ontogenesis` as a state-integrity mapping surface.

The local fixture is:

- `examples/semantic-enterprise/v0.1/state-integrity-mapping.example.json`

The validator is:

- `tools/validate_semantic_enterprise_state_integrity.py`

## Source release

- Repository: `SocioProphet/ontogenesis`
- Release/tag: `semantic-enterprise-v0.1.0`
- Manifest: `manifests/semantic_enterprise_v0_1_manifest.json`
- Rollup registry: `catalog/semantic_enterprise_v0_1_registry.ttl`
- Supply-chain module: `Domains/supply-chain.ttl`
- Named graph fixture: `examples/named-graphs/semantic_sector_named_graphs.ttl`

## State integrity surfaces

The v0.1 mapping covers:

- artifact lineage
- release provenance
- repair lineage
- rollback evidence
- local-first state context
- named graph governance

## Semantic bindings

The fixture maps SourceOS state surfaces to Semantic Enterprise concepts:

- `release_artifact` -> `supply-chain:Component`
- `state_integrity_report` -> `named-graph-governance:CuratedGraph`
- `repair_plan` -> `supply-chain:MitigationAction`
- `rollback_evidence` -> `supply-chain:AlternateSource`

## Closure boundary

The mapping distinguishes:

- `inside_source`: Ontogenesis authors semantic source modules and supply-chain scenarios.
- `outside_state_runtime`: SourceOS syncd maps semantic provenance into local-first state integrity evidence.
- `boundary_membrane`: release tag, source path, graph URI, trust level, access class, retention policy, and lifecycle phase survive translation.
- `feedback_surface`: SourceOS repair, rollback, and state reports remain downstream evidence.

## Validation

Run:

```bash
make validate
```

or:

```bash
python3 tools/validate_semantic_enterprise_state_integrity.py
```

## Parent work

- `SourceOS-Linux/sourceos-syncd#22`
- `SocioProphet/delivery-excellence#21`
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
{
"contract": "sourceos-syncd.semantic-enterprise.state-integrity",
"version": "0.1.0",
"source": {
"repository": "SocioProphet/ontogenesis",
"release": "semantic-enterprise-v0.1.0",
"manifest_path": "manifests/semantic_enterprise_v0_1_manifest.json",
"rollup_registry_path": "catalog/semantic_enterprise_v0_1_registry.ttl",
"supply_chain_module_path": "Domains/supply-chain.ttl",
"named_graph_fixture_path": "examples/named-graphs/semantic_sector_named_graphs.ttl"
},
"state_integrity_surfaces": [
"artifact_lineage",
"release_provenance",
"repair_lineage",
"rollback_evidence",
"local_first_state_context",
"named_graph_governance"
],
"provenance_requirements": [
"source_path",
"graph_uri",
"source_system",
"trust_level",
"access_class",
"retention_policy",
"lifecycle_phase",
"release_tag"
],
"semantic_bindings": [
{
"sourceos_surface": "release_artifact",
"semantic_enterprise_class": "supply-chain:Component",
"evidence_role": "software-artifact-component",
"required_fields": ["artifact_id", "source_path", "release_tag", "trust_level"]
},
{
"sourceos_surface": "state_integrity_report",
"semantic_enterprise_class": "named-graph-governance:CuratedGraph",
"evidence_role": "curated-state-perspective",
"required_fields": ["graph_uri", "source_system", "access_class", "retention_policy"]
},
{
"sourceos_surface": "repair_plan",
"semantic_enterprise_class": "supply-chain:MitigationAction",
"evidence_role": "non-destructive-repair-mitigation",
"required_fields": ["plan_id", "source_path", "affected_component", "approval_state"]
},
{
"sourceos_surface": "rollback_evidence",
"semantic_enterprise_class": "supply-chain:AlternateSource",
"evidence_role": "alternate-source-or-rollback-reference",
"required_fields": ["rollback_id", "source_path", "previous_state_ref", "trust_level"]
}
],
"named_graph_contexts": [
{
"sector": "supply-chain",
"source_path": "examples/scenarios/supply_chain_resilience_demo.ttl",
"graph_uri_fragment": "graphs/scenarios/supply-chain-resilience",
"source_system": "Ontogenesis semantic-enterprise scenario fixture",
"access_class": "internal",
"trust_level": "curated-demo",
"retention_policy": "retain-current-plus-audit-history",
"lifecycle_phase": "KnowledgeCuration"
}
],
"sourceos_fixture": {
"artifact_id": "sourceos-demo-release-component",
"release_tag": "semantic-enterprise-v0.1.0",
"state_context": "local-first-state-integrity-demo",
"graph_uri_fragment": "graphs/scenarios/supply-chain-resilience",
"trust_level": "curated-demo",
"access_class": "internal",
"operator_narrative": "Semantic Enterprise supply-chain provenance is mapped into SourceOS state integrity evidence without mutating Ontogenesis source semantics."
},
"closure_model": {
"inside_source": "Ontogenesis authors the semantic source modules and supply-chain scenario.",
"outside_state_runtime": "SourceOS syncd maps semantic provenance into local-first state integrity evidence.",
"boundary_membrane": "Release tag, source path, graph URI, trust level, access class, retention policy, and lifecycle phase must survive translation.",
"feedback_surface": "SourceOS repair, rollback, and state reports remain downstream evidence and do not mutate Ontogenesis source semantics."
}
}
154 changes: 154 additions & 0 deletions tools/validate_semantic_enterprise_state_integrity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#!/usr/bin/env python3
"""Validate SourceOS syncd's Semantic Enterprise v0.1 state-integrity mapping fixture."""
from __future__ import annotations

import json
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
FIXTURE = ROOT / "examples/semantic-enterprise/v0.1/state-integrity-mapping.example.json"

REQUIRED_SURFACES = {
"artifact_lineage",
"release_provenance",
"repair_lineage",
"rollback_evidence",
"local_first_state_context",
"named_graph_governance",
}
REQUIRED_PROVENANCE = {
"source_path",
"graph_uri",
"source_system",
"trust_level",
"access_class",
"retention_policy",
"lifecycle_phase",
"release_tag",
}
REQUIRED_BINDINGS = {
"release_artifact",
"state_integrity_report",
"repair_plan",
"rollback_evidence",
}
REQUIRED_CLOSURE_KEYS = {
"inside_source",
"outside_state_runtime",
"boundary_membrane",
"feedback_surface",
}


def main() -> int:
errors: list[str] = []
if not FIXTURE.is_file():
print(f"missing fixture: {FIXTURE}")
return 1

try:
data = json.loads(FIXTURE.read_text(encoding="utf-8"))
except json.JSONDecodeError as exc:
print(f"invalid JSON: {exc}")
return 1

if data.get("contract") != "sourceos-syncd.semantic-enterprise.state-integrity":
errors.append("unexpected contract identifier")
if data.get("version") != "0.1.0":
errors.append("unexpected contract version")

source = data.get("source")
if not isinstance(source, dict):
errors.append("source must be an object")
else:
expected = {
"repository": "SocioProphet/ontogenesis",
"release": "semantic-enterprise-v0.1.0",
"manifest_path": "manifests/semantic_enterprise_v0_1_manifest.json",
"rollup_registry_path": "catalog/semantic_enterprise_v0_1_registry.ttl",
"supply_chain_module_path": "Domains/supply-chain.ttl",
"named_graph_fixture_path": "examples/named-graphs/semantic_sector_named_graphs.ttl",
}
for key, value in expected.items():
if source.get(key) != value:
errors.append(f"source.{key} expected {value!r}, got {source.get(key)!r}")

surfaces = set(data.get("state_integrity_surfaces") or [])
if not REQUIRED_SURFACES.issubset(surfaces):
errors.append(f"state_integrity_surfaces missing: {sorted(REQUIRED_SURFACES.difference(surfaces))}")

provenance = set(data.get("provenance_requirements") or [])
if not REQUIRED_PROVENANCE.issubset(provenance):
errors.append(f"provenance_requirements missing: {sorted(REQUIRED_PROVENANCE.difference(provenance))}")

bindings = data.get("semantic_bindings")
if not isinstance(bindings, list):
errors.append("semantic_bindings must be a list")
else:
binding_surfaces = {binding.get("sourceos_surface") for binding in bindings if isinstance(binding, dict)}
if binding_surfaces != REQUIRED_BINDINGS:
errors.append(f"expected sourceos surfaces {sorted(REQUIRED_BINDINGS)}, got {sorted(binding_surfaces)}")
for binding in bindings:
if not isinstance(binding, dict):
errors.append("semantic binding must be an object")
continue
surface = binding.get("sourceos_surface")
if not binding.get("semantic_enterprise_class"):
errors.append(f"{surface} missing semantic_enterprise_class")
if not binding.get("evidence_role"):
errors.append(f"{surface} missing evidence_role")
required_fields = binding.get("required_fields")
if not isinstance(required_fields, list) or not required_fields:
errors.append(f"{surface} must include required_fields")

contexts = data.get("named_graph_contexts")
if not isinstance(contexts, list) or not contexts:
errors.append("named_graph_contexts must be a non-empty list")
else:
for context in contexts:
if not isinstance(context, dict):
errors.append("named graph context must be an object")
continue
if context.get("sector") != "supply-chain":
errors.append("SourceOS v0.1 mapping should bind the supply-chain sector first")
if not str(context.get("source_path", "")).startswith("examples/scenarios/"):
errors.append("named graph context source_path must point to examples/scenarios")
if not str(context.get("graph_uri_fragment", "")).startswith("graphs/scenarios/"):
errors.append("named graph context graph_uri_fragment must point to graphs/scenarios")
for key in ["source_system", "access_class", "trust_level", "retention_policy", "lifecycle_phase"]:
if not context.get(key):
errors.append(f"named graph context missing {key}")

fixture = data.get("sourceos_fixture")
if not isinstance(fixture, dict):
errors.append("sourceos_fixture must be an object")
else:
for key in ["artifact_id", "release_tag", "state_context", "graph_uri_fragment", "trust_level", "access_class", "operator_narrative"]:
if not fixture.get(key):
errors.append(f"sourceos_fixture missing {key}")
if fixture.get("release_tag") != "semantic-enterprise-v0.1.0":
errors.append("sourceos_fixture release_tag mismatch")

closure = data.get("closure_model")
if not isinstance(closure, dict):
errors.append("closure_model must be an object")
else:
missing = REQUIRED_CLOSURE_KEYS.difference(closure)
if missing:
errors.append(f"closure_model missing keys: {sorted(missing)}")
for key in REQUIRED_CLOSURE_KEYS.intersection(closure):
if not isinstance(closure.get(key), str) or not closure[key].strip():
errors.append(f"closure_model.{key} must be a non-empty string")

if errors:
print("Semantic Enterprise state-integrity validation failed:")
for error in errors:
print(f"- {error}")
return 1

print("Semantic Enterprise state-integrity validation passed.")
return 0


if __name__ == "__main__":
raise SystemExit(main())
Loading