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-repo docs-check drift-check standards-check topology-check chronos-evidence-loop-readout-validate lattice-surfaces-check lattice-surface-ingestor-smoke lattice-studio-smoke validate-ops-fabric validate-search-academy-deploy validate-search-image-release validate-lampstand-lifecycle validate-zone-stack-audit policy-fabric-endpoint-client-smoke policy-fabric-guarded-workflow-smoke zone-router-publication-local-publish-smoke zone-router-publication-failure-evidence-smoke zone-router-publication-retry-state-smoke zone-router-publication-remote-broker-seam-smoke validate-workroom-update-contract validate-professional-intelligence-manifest validate-svf-agent-contract validate-environment-validate-change-v2 validate-channel-runtime-gates test-go test-python-apps test-tools smoke smoke-health smoke-eval-fabric smoke-evidence-receipts smoke-evidence-console validate-phase3 lampstand-smoke validate-phase4 lampstand-vertical-slice-smoke lampstand-zone-smoke zone-router-publication-smoke zone-router-publication-enqueue-smoke semantic-bridge-zone-validation-smoke validate-fogstack validate-storage-suite trustops-art-runner-smoke
.PHONY: validate validate-repo docs-check drift-check standards-check topology-check chronos-evidence-loop-readout-validate lattice-surfaces-check lattice-surface-ingestor-smoke lattice-studio-smoke validate-ops-fabric validate-search-academy-deploy validate-search-image-release validate-lampstand-lifecycle validate-zone-stack-audit policy-fabric-endpoint-client-smoke policy-fabric-guarded-workflow-smoke zone-router-publication-local-publish-smoke zone-router-publication-failure-evidence-smoke zone-router-publication-retry-state-smoke zone-router-publication-remote-broker-seam-smoke validate-workroom-update-contract validate-professional-intelligence-manifest validate-wallguard-professional-workroom validate-svf-agent-contract validate-environment-validate-change-v2 validate-channel-runtime-gates test-go test-python-apps test-tools smoke smoke-health smoke-eval-fabric smoke-evidence-receipts smoke-evidence-console validate-phase3 lampstand-smoke validate-phase4 lampstand-vertical-slice-smoke lampstand-zone-smoke zone-router-publication-smoke zone-router-publication-enqueue-smoke semantic-bridge-zone-validation-smoke validate-fogstack validate-storage-suite trustops-art-runner-smoke

validate: validate-repo drift-check standards-check topology-check chronos-evidence-loop-readout-validate lattice-surfaces-check lattice-surface-ingestor-smoke lattice-studio-smoke validate-ops-fabric validate-search-academy-deploy validate-search-image-release validate-lampstand-lifecycle validate-zone-stack-audit policy-fabric-endpoint-client-smoke policy-fabric-guarded-workflow-smoke zone-router-publication-local-publish-smoke zone-router-publication-failure-evidence-smoke zone-router-publication-retry-state-smoke zone-router-publication-remote-broker-seam-smoke validate-workroom-update-contract validate-professional-intelligence-manifest validate-svf-agent-contract validate-environment-validate-change-v2 validate-channel-runtime-gates test-go validate-phase4 test-python-apps test-tools validate-fogstack validate-storage-suite trustops-art-runner-smoke
validate: validate-repo drift-check standards-check topology-check chronos-evidence-loop-readout-validate lattice-surfaces-check lattice-surface-ingestor-smoke lattice-studio-smoke validate-ops-fabric validate-search-academy-deploy validate-search-image-release validate-lampstand-lifecycle validate-zone-stack-audit policy-fabric-endpoint-client-smoke policy-fabric-guarded-workflow-smoke zone-router-publication-local-publish-smoke zone-router-publication-failure-evidence-smoke zone-router-publication-retry-state-smoke zone-router-publication-remote-broker-seam-smoke validate-workroom-update-contract validate-professional-intelligence-manifest validate-wallguard-professional-workroom validate-svf-agent-contract validate-environment-validate-change-v2 validate-channel-runtime-gates test-go validate-phase4 test-python-apps test-tools validate-fogstack validate-storage-suite trustops-art-runner-smoke

validate-repo:
python3 tools/validate_repo.py
Expand Down Expand Up @@ -93,6 +93,9 @@ validate-workroom-update-contract:
validate-professional-intelligence-manifest:
python3 tools/validate_professional_intelligence_manifest.py

validate-wallguard-professional-workroom:
python3 tools/validate_wallguard_professional_workroom.py

validate-svf-agent-contract:
python3 tools/validate_svf_agent_contract.py

Expand Down
50 changes: 50 additions & 0 deletions contracts/wallguard/professional-workroom.example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"schemaVersion": "prophet-platform.wallguard-professional-workroom.v0.1",
"recordType": "WallGuardProfessionalWorkroom",
"workroomRef": "workroom://client-a/matter-x",
"clientRef": "client://client-a",
"matterRef": "matter://client-a/matter-x",
"wallRef": "wall://client-a/matter-x",
"policyRefs": [
"policy-fabric://wallguard.professional-workroom.v0"
],
"participants": [
{
"subjectRef": "user://operator-alpha",
"subjectType": "human",
"wallContextRef": "ack://wall/client-a/matter-x/operator-alpha"
},
{
"subjectRef": "agent-registry://agent-alpha",
"subjectType": "agent",
"wallContextRef": "agent-wall-context://agent-alpha/client-a/matter-x"
}
],
"resourceRefs": [
"resource://client-a/matter-x/doc-001"
],
"enforcementRefs": {
"agentContext": "SocioProphet/agent-registry#45",
"agentCollaboration": "SocioProphet/agentplane#252",
"guardrailBinding": "SocioProphet/guardrail-fabric#32",
"memoryGate": "SocioProphet/memory-mesh#33",
"retrievalFilter": "SocioProphet/sherlock-search#61",
"cleanRoomSynthesis": "SocioProphet/holmes#13"
},
"requiredProductStates": [
"wall_state_visible",
"policy_version_visible",
"participant_membership_visible",
"blocked_attempts_visible",
"receipt_refs_visible",
"clean_room_release_requestable"
],
"receiptRefs": [
"wallguard-receipt://workroom-create-client-a-matter-x-001"
],
"runtimeBoundary": {
"policyAuthority": "SocioProphet/policy-fabric",
"productSurfaceOwner": "SocioProphet/prophet-platform",
"runtimeEnforcementImplemented": false
}
}
141 changes: 141 additions & 0 deletions tools/validate_wallguard_professional_workroom.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#!/usr/bin/env python3
"""Validate WallGuard Professional Workroom product contract fixture."""

from __future__ import annotations

import json
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
FIXTURE = ROOT / "contracts" / "wallguard" / "professional-workroom.example.json"

REQUIRED_TOP = {
"schemaVersion",
"recordType",
"workroomRef",
"clientRef",
"matterRef",
"wallRef",
"policyRefs",
"participants",
"resourceRefs",
"enforcementRefs",
"requiredProductStates",
"receiptRefs",
"runtimeBoundary",
}

REQUIRED_PRODUCT_STATES = {
"wall_state_visible",
"policy_version_visible",
"participant_membership_visible",
"blocked_attempts_visible",
"receipt_refs_visible",
"clean_room_release_requestable",
}

REQUIRED_ENFORCEMENT_REFS = {
"agentContext",
"agentCollaboration",
"guardrailBinding",
"memoryGate",
"retrievalFilter",
"cleanRoomSynthesis",
}


class ValidationError(Exception):
pass


def fail(message: str) -> None:
raise ValidationError(message)


def load_json(path: Path) -> dict:
try:
data = json.loads(path.read_text(encoding="utf-8"))
except FileNotFoundError as exc:
raise ValidationError(f"missing fixture: {path.relative_to(ROOT)}") from exc
except json.JSONDecodeError as exc:
raise ValidationError(f"invalid JSON: {path.relative_to(ROOT)}: {exc}") from exc
if not isinstance(data, dict):
fail("fixture root must be an object")
return data


def require_list(data: dict, key: str) -> list:
value = data.get(key)
if not isinstance(value, list) or not value:
fail(f"{key} must be a non-empty list")
return value


def validate(data: dict) -> None:
missing = sorted(REQUIRED_TOP - set(data))
if missing:
fail(f"missing top-level fields: {missing}")
if data["schemaVersion"] != "prophet-platform.wallguard-professional-workroom.v0.1":
fail("schemaVersion mismatch")
if data["recordType"] != "WallGuardProfessionalWorkroom":
fail("recordType mismatch")
if not data["workroomRef"].startswith("workroom://"):
fail("workroomRef must use workroom://")
if not data["wallRef"].startswith("wall://"):
fail("wallRef must use wall://")

policy_refs = require_list(data, "policyRefs")
if not any(ref.startswith("policy-fabric://") for ref in policy_refs):
fail("policyRefs must include a Policy Fabric reference")

participants = require_list(data, "participants")
subject_types = {participant.get("subjectType") for participant in participants if isinstance(participant, dict)}
if {"human", "agent"} - subject_types:
fail("fixture must include at least one human and one agent participant")
for participant in participants:
if not isinstance(participant, dict):
fail("participants must be objects")
for key in ("subjectRef", "subjectType", "wallContextRef"):
if not participant.get(key):
fail(f"participant missing {key}")

enforcement_refs = data["enforcementRefs"]
if not isinstance(enforcement_refs, dict):
fail("enforcementRefs must be an object")
missing_refs = sorted(REQUIRED_ENFORCEMENT_REFS - set(enforcement_refs))
if missing_refs:
fail(f"missing enforcement refs: {missing_refs}")

product_states = set(require_list(data, "requiredProductStates"))
missing_states = sorted(REQUIRED_PRODUCT_STATES - product_states)
if missing_states:
fail(f"missing product states: {missing_states}")

receipt_refs = require_list(data, "receiptRefs")
if not all(str(ref).startswith("wallguard-receipt://") for ref in receipt_refs):
fail("all receiptRefs must be wallguard-receipt:// refs")

runtime = data["runtimeBoundary"]
if not isinstance(runtime, dict):
fail("runtimeBoundary must be an object")
if runtime.get("policyAuthority") != "SocioProphet/policy-fabric":
fail("policy authority must remain Policy Fabric")
if runtime.get("productSurfaceOwner") != "SocioProphet/prophet-platform":
fail("product surface owner must be Prophet Platform")
if runtime.get("runtimeEnforcementImplemented") is not False:
fail("this tranche must not claim runtime enforcement")


def main() -> int:
try:
validate(load_json(FIXTURE))
except ValidationError as exc:
print(f"ERROR: {exc}", file=sys.stderr)
return 1
print("OK: WallGuard Professional Workroom fixture validates")
return 0


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