Python SDK
PyHall is the Python reference implementation of WCP. It implements WCP-Full — the complete compliance tier including blast radius scoring, privilege envelopes, policy gate evaluation, and evidence receipts.
Version: 0.3.0 | PyPI: pyhall-wcp | WCP spec: 0.1
Install
pip install pyhall-wcpQuick Start
import uuidfrom pyhall import make_decision, RouteInput, Registry, load_rules
# Load routing rules and enrolled workersrules = load_rules("rules.json")registry = Registry(registry_dir="enrolled/")
# Build a capability requestinp = RouteInput( capability_id="cap.doc.summarize", env="dev", data_label="INTERNAL", tenant_risk="low", qos_class="P2", tenant_id="acme-corp", correlation_id=str(uuid.uuid4()),)
# Ask the Halldecision = make_decision( inp=inp, rules=rules, registry_controls_present=registry.controls_present(), registry_worker_available=registry.worker_available,)
if decision.denied: print(f"Denied: {decision.deny_reason_if_denied}")else: print(f"Dispatch to: {decision.selected_worker_species_id}") # -> "wrk.doc.summarizer"pyhall.models
All models are Pydantic v2 BaseModel classes.
Type Aliases
Env = Literal["dev", "stage", "prod", "edge"]DataLabel = Literal["PUBLIC", "INTERNAL", "RESTRICTED"]QoSClass = Literal["P0", "P1", "P2", "P3"]TenantRisk = Literal["low", "medium", "high"]RouteInput
The capability request envelope sent to the Hall. Maps to WCP spec section 4.1.
| Field | Type | Required | Description |
|---|---|---|---|
capability_id | str | yes | WCP capability ID, e.g. cap.doc.summarize |
env | Env | yes | Deployment environment: dev | stage | prod | edge |
data_label | DataLabel | yes | Data sensitivity: PUBLIC | INTERNAL | RESTRICTED |
tenant_risk | TenantRisk | yes | Tenant risk tier: low | medium | high |
qos_class | QoSClass | yes | QoS priority: P0 (highest) through P3 (background) |
tenant_id | str | yes | Identifier of the requesting tenant. Must not be empty or whitespace. |
correlation_id | str | yes | UUID v4. Must be propagated through all downstream calls. |
request | Dict[str, Any] | no | Arbitrary payload for the target worker. Default: {} |
blast_radius | Optional[Dict[str, Any]] | no | Pre-computed blast radius dimensions. |
blast_score | Optional[int] | no | Pre-computed blast score (0–100). Router computes if None. Must not be bool. |
privilege_context | Optional[Dict[str, Any]] | no | Privilege context for envelope enforcement. |
dry_run | bool | no | If True, decision is made but no worker is dispatched. Default: False |
tenant_credential | Optional[str] | no | Signed WCP credential. Optional in v0.1; required when HallConfig.require_credential=True (v0.2+). |
RouteDecision
The routing decision returned by the Hall. On success: denied=False, selected_worker_species_id is set. On denial: denied=True, deny_reason_if_denied is set.
| Field | Type | Description |
|---|---|---|
decision_id | str | UUID v4 identifying this routing decision. |
timestamp | str | ISO 8601 UTC timestamp of the decision. |
correlation_id | str | Propagated from RouteInput.correlation_id. |
tenant_id | str | Propagated from RouteInput.tenant_id. |
capability_id | str | The capability that was requested. |
matched_rule_id | str | The routing rule that matched. "NO_MATCH" if none matched. |
env | Env | Propagated from input. |
data_label | DataLabel | Propagated from input. |
tenant_risk | TenantRisk | Propagated from input. |
qos_class | QoSClass | Propagated from input. |
denied | bool | True if the request was denied. |
deny_reason_if_denied | Optional[Dict[str, Any]] | Denial reason dict. None on allow. |
selected_worker_species_id | Optional[str] | The dispatched worker species. None on denial. |
candidate_workers_ranked | List[CandidateWorker] | All candidates considered, in rank order. |
required_controls_effective | List[str] | Controls that were enforced. |
recommended_profiles_effective | List[Dict[str, Any]] | Recommended profiles from the matched rule. |
escalation_effective | Escalation | Escalation policy applied. |
preconditions_checked | PreconditionsChecked | Precondition flags. |
artifact_hash | Optional[str] | SHA-256 of the serialized RouteInput. Proves what was routed. |
worker_attestation_checked | bool | True when the Hall verified the worker’s code hash. |
worker_attestation_valid | Optional[bool] | True = hash matched. False = TAMPERED. None = not checked. |
dry_run | bool | True when this was a dry-run decision. |
telemetry_envelopes | List[Dict[str, Any]] | Mandatory WCP telemetry events (always 3+). |
CandidateWorker
A worker species candidate considered during routing.
| Field | Type | Description |
|---|---|---|
worker_species_id | str | WCP worker species ID, e.g. wrk.doc.summarizer. |
score_hint | Optional[float] | Pre-ranked score from the rules engine. |
requires_controls_minimum | Optional[List[str]] | Minimum controls this candidate requires. |
skip_reason | Optional[str] | Why this candidate was not selected. |
Escalation
Escalation policy from the matched routing rule.
| Field | Type | Default | Description |
|---|---|---|---|
policy_gate | bool | False | Whether the policy gate must be evaluated. |
msavx_step_up | bool | False | Whether MSAVX step-up approval is required. |
human_required_default | bool | False | Whether human review is required by default. |
human_required_if | List[Dict[str, Any]] | [] | Conditional human review triggers. |
rationale | Optional[str] | None | Reason for escalation requirement. |
HallConfig
Hall-level governance configuration. Sets floors that individual routing rules cannot lower.
| Field | Type | Default | Description |
|---|---|---|---|
require_signatory | bool | False | Deny requests from tenants not in allowed_tenants. |
allowed_tenants | List[str] | [] | Registered signatory tenant IDs. |
require_credential | bool | False | Not enforced in v0.1. Planned for v0.2. |
require_worker_attestation | bool | False | Verify worker code hash before dispatch (WCP §5.10). |
enforce_correlation_id | bool | True | Require correlation_id on every request. |
enforce_required_controls | bool | True | Enforce controls check regardless of rule. |
enforce_blast_scoring_in_prod | bool | True | Enforce blast scoring in prod/edge. |
enforce_privilege_envelopes | bool | False | Privilege envelope enforcement (opt-in per rule in v0.1). |
PreconditionsChecked
Precondition flags applied during routing.
| Field | Type | Default |
|---|---|---|
must_have_correlation_id | bool | True |
must_attach_policy_version | bool | True |
must_record_artifact_hash_if_executes | bool | True |
deny_if_missing_required_controls | bool | True |
deny_if_unsigned_artifact_in_prod | bool | False |
deny_if_no_attestation_in_prod | bool | False |
pyhall.router
make_decision()
The Hall’s core routing function. Never raises in normal operation — all failures are expressed as denied RouteDecision objects.
from pyhall.router import make_decision
def make_decision( inp: RouteInput, rules: List[Rule], registry_controls_present: set[str], registry_worker_available: Callable[[str], bool], registry_get_privilege_envelope: Optional[Callable[[str], Optional[dict]]] = None, registry_policy_allows_privilege: Optional[Callable[[str, str, dict], tuple[bool, str]]] = None, policy_gate_eval: Optional[Callable[[dict], tuple[str, str, str]]] = None, conformance_spec: Optional[Dict[str, Any]] = None, task_id: str = "task_default", hall_config: Optional[HallConfig] = None, registry_get_worker_hash: Optional[Callable[[str], Optional[str]]] = None, get_current_worker_hash: Optional[Callable[[str], Optional[str]]] = None,) -> RouteDecision:Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
inp | RouteInput | yes | The capability request. |
rules | List[Rule] | yes | Ordered routing rules from load_rules(). |
registry_controls_present | set[str] | yes | Controls declared present. From Registry.controls_present(). |
registry_worker_available | Callable[[str], bool] | yes | Returns True if the species is enrolled. From Registry.worker_available. |
registry_get_privilege_envelope | Optional[Callable] | no | Returns privilege envelope for a species. |
registry_policy_allows_privilege | Optional[Callable] | no | Returns (allowed, reason) for privilege enforcement. |
policy_gate_eval | Optional[Callable] | no | Required when a matched rule has escalation.policy_gate=True. Returns (decision, policy_version, reason) where decision is "ALLOW", "DENY", or "REQUIRE_HUMAN". |
conformance_spec | Optional[Dict] | no | Conformance spec for CI/test mode only. Raises RuntimeError on failure. Do not use in production. |
task_id | str | no | Identifier for this routing task. Included in telemetry. Default: "task_default". |
hall_config | Optional[HallConfig] | no | Hall-level governance floors. |
registry_get_worker_hash | Optional[Callable] | no | Returns registered code hash for a species. Required when hall_config.require_worker_attestation=True. |
get_current_worker_hash | Optional[Callable] | no | Returns current live code hash for a species. Required when hall_config.require_worker_attestation=True. |
Returns: RouteDecision
Routing pipeline (WCP-Full):
- Match first routing rule (fail-closed on no match)
- Verify preconditions (
correlation_id, etc.) - Verify required controls against registry
- Blast radius scoring and gating
- Policy gate evaluation
- Select first available worker candidate
- Emit mandatory telemetry
- Optional conformance check
- Return
RouteDecision
pyhall.registry
Registry
The Hall’s source of truth for enrolled workers. Loads enrollment records from a directory of JSON files.
from pyhall.registry import Registry
# Load from directoryregistry = Registry(registry_dir="/path/to/enrolled/")
# Or build programmaticallyregistry = Registry()registry.enroll(record_dict)Constructor:
Registry(registry_dir: Optional[str] = None)Enrollment:
| Method | Signature | Description |
|---|---|---|
enroll | (record: Dict[str, Any]) -> None | Enroll a single worker from a registry record dict. |
Controls:
| Method | Signature | Description |
|---|---|---|
controls_present | () -> set[str] | Return the set of currently declared controls. |
set_controls_present | (controls: List[str]) -> None | Override the full set of present controls. |
add_controls_present | (controls: List[str]) -> None | Add controls to the existing set. |
Worker availability:
| Method | Signature | Description |
|---|---|---|
worker_available | (worker_species_id: str) -> bool | Return True if the species is enrolled and available. |
workers_for_capability | (capability_id: str) -> List[str] | Return all enrolled species that handle this capability. |
set_workers_available | (worker_species_ids: List[str]) -> None | Override the full set of available species. |
add_workers_available | (worker_species_ids: List[str]) -> None | Mark additional species as available. |
Privilege envelopes:
| Method | Signature | Description |
|---|---|---|
get_privilege_envelope | (worker_species_id: str) -> Optional[dict] | Return the privilege envelope for a species. |
set_privilege_envelopes | (envelopes: Dict[str, dict]) -> None | Map worker_species_id -> privilege envelope. |
set_egress_allowlist | (env: str, allowlist: List[str]) -> None | Configure the egress allowlist for an environment. |
policy_allows_privilege | (env: str, data_label: str, envelope: Optional[dict]) -> Tuple[bool, str] | Evaluate whether the privilege envelope is permitted. Returns (allowed, reason). |
Worker code attestation (WCP §5.10):
| Method | Signature | Description |
|---|---|---|
register_attestation | (species_id: str, source_file: str) -> str | Hash the worker’s source file and register as known-good. Returns SHA-256 hex digest. |
get_worker_hash | (species_id: str) -> Optional[str] | Return the registered (known-good) SHA-256 hash. |
compute_current_hash | (species_id: str) -> Optional[str] | Read the worker source file from disk and compute its current hash. |
attestation_callables | () -> Tuple[Callable, Callable] | Return (get_worker_hash, compute_current_hash) for use in make_decision(). |
Path allowlist:
| Method | Signature | Description |
|---|---|---|
set_allowed_worker_dirs | (dirs: List[str]) -> None | Restrict worker source_file paths to these directories. Prevents path traversal. |
Introspection:
| Method | Signature | Description |
|---|---|---|
enrolled_count | () -> int | Return the number of enrolled workers. |
enrolled_workers | () -> List[dict] | Return all enrolled worker records. |
summary | () -> dict | Return a status summary dict for display or health checks. |
Worker registry record format:
{ "worker_id": "org.example.my-summarizer", "worker_species_id": "wrk.doc.summarizer", "capabilities": ["cap.doc.summarize"], "risk_tier": "low", "required_controls": ["ctrl.obs.audit-log-append-only"], "currently_implements": ["ctrl.obs.audit-log-append-only"], "allowed_environments": ["dev", "stage", "prod"], "blast_radius": {"data": 1, "network": 0, "financial": 0, "time": 1}, "privilege_envelope": { "secrets_access": [], "network_egress": "none", "filesystem_writes": ["/tmp/"], "tools": [] }, "owner": "org.example", "contact": "team@example.com"}pyhall.rules
Rule
A single WCP routing rule (frozen dataclass).
from pyhall.rules import Rule
@dataclass(frozen=True)class Rule: rule_id: str # Unique rule identifier, e.g. "rr_doc_summarize_dev_001" match: Dict[str, Any] # Match conditions decision: Dict[str, Any] # Decision payloadMatch conditions support:
- Exact:
"data_label": "INTERNAL" - Membership:
"env": {"in": ["dev", "stage"]} - Wildcard:
"capability_id": {"any": true}
load_rules()
from pyhall.rules import load_rules
def load_rules(seed_path: str | Path) -> List[Rule]:Load routing rules from a JSON file. The file must have a top-level "rules" array.
Raises FileNotFoundError, KeyError (missing "rules" key), or json.JSONDecodeError.
load_rules_from_dict()
def load_rules_from_dict(doc: Dict[str, Any]) -> List[Rule]:Load routing rules from an already-parsed dict. Useful for testing.
route_first_match()
def route_first_match(rules: List[Rule], inp: Dict[str, Any]) -> Optional[Rule]:Return the first rule that matches inp, or None. Per WCP §5.1, None MUST produce a denied routing decision.
Example rules.json:
{ "rules": [ { "rule_id": "rr_doc_summarize_dev_001", "match": { "capability_id": "cap.doc.summarize", "env": {"in": ["dev", "stage"]}, "data_label": "INTERNAL" }, "decision": { "candidate_workers_ranked": [ {"worker_species_id": "wrk.doc.summarizer", "score_hint": 1.0} ], "required_controls_suggested": ["ctrl.obs.audit-log-append-only"], "escalation": {"policy_gate": false, "human_required_default": false}, "preconditions": {} } } ]}pyhall.policy_gate
PolicyGate
Evaluates a capability request context and returns a (decision, policy_version, reason) triple. The default implementation allows everything. Subclass to implement real governance.
from pyhall.policy_gate import PolicyGate
class PolicyGate: def evaluate(self, context: Dict[str, Any]) -> Tuple[str, str, str]: ...evaluate() parameters:
context dict contains:
capability_idtenant_idenvdata_labeltenant_riskqos_classpolicy_version
Returns: Tuple[str, str, str] — (decision, policy_version, reason)
decision:"ALLOW"|"DENY"|"REQUIRE_HUMAN"policy_version: the policy version string evaluatedreason: human-readable reason string
Custom policy gate example:
class MyPolicyGate(PolicyGate): def evaluate(self, context): if context["env"] == "prod" and context["data_label"] == "RESTRICTED": return ("REQUIRE_HUMAN", "policy.v1", "restricted_data_in_prod") return ("ALLOW", "policy.v1", "default_allow")
gate = MyPolicyGate()decision = make_decision(inp, rules, ..., policy_gate_eval=gate.evaluate)Hall API Server
The Hall API is an HTTP interface to the Hall registry and routing decision log. Each organization runs their own instance.
Start the server:
pip install pyhall-wcp flaskpython -m hall_api.serverEnvironment variables:
| Variable | Default | Description |
|---|---|---|
HALL_API_PORT | 8765 | Port to listen on. |
HALL_API_HOST | 127.0.0.1 | Host to bind. |
HALL_DB_PATH | hall.db | Path to the SQLite database. |
CLI
The pyhall CLI ships with pip install pyhall-wcp.
# Route a capability requestpyhall route --capability cap.doc.summarize --env dev --tenant-id demo
# Validate all test fixtures against routing rulespyhall validate --rules rules.json --tests tests.json
# Show registry statuspyhall status --registry-dir enrolled/
# Enroll a workerpyhall enroll my_worker/registry_record.json
# Interactive wizard to scaffold a complete WCP worker packagepyhall build
# Fuzzy search across taxonomy catalog entitiespyhall search "summarize documents"
# Detailed lookup for a specific catalog entitypyhall explain cap.doc.summarize
# Browse the taxonomy catalog (interactive)pyhall browsepyhall browse --type cap
# Simulate routing a capability requestpyhall dispatch cap.doc.summarize --env prod
# Show PyHall and WCP spec versionspyhall versionpyhall.registry_client
RegistryClient
HTTP client for the pyhall.dev registry API. Zero external dependencies — stdlib urllib only.
from pyhall import RegistryClient, RegistryRateLimitError
client = RegistryClient() # default: https://api.pyhall.devr = client.verify("org.example.my-worker")print(r.status) # 'active' | 'revoked' | 'banned' | 'unknown'Constructor:
RegistryClient( base_url: Optional[str] = None, # override via PYHALL_REGISTRY_URL env var session_token: Optional[str] = None, # pyhall_session JWT for authenticated calls bearer_token: Optional[str] = None, # JWT bearer token for authenticated calls timeout: int = 10, # request timeout in seconds cache_ttl: float = 60.0, # verify() cache TTL in seconds)Public endpoints (no auth required):
| Method | Signature | Description |
|---|---|---|
verify | (worker_id: str) -> VerifyResponse | Get a worker’s attestation status. Returns status='unknown' on 404 (IDOR-safe). |
is_hash_banned | (sha256: str) -> bool | Returns True if the hash appears in confirmed ban-list entries. |
get_ban_list | (limit: int = 500) -> list[BanEntry] | Fetch all confirmed ban-list entries. |
health | () -> dict | Returns {'ok': bool, 'version': str}. |
prefetch | (worker_ids: list[str]) -> None | Pre-populate the verify cache. Non-fatal on 404 or rate limit. |
get_worker_hash | (worker_id: str) -> Optional[str] | Returns current_hash for active workers; None otherwise. Suitable as registry_get_worker_hash callback in make_decision(). |
Authenticated endpoints (require session_token or bearer_token):
| Method | Signature | Description |
|---|---|---|
report_hash | (sha256: str, reason: str, evidence_url: Optional[str]) -> None | Submit a community hash report. Written as confirmed=0 pending admin review. |
submit_attestation | (worker_id, package_hash, *, label, ai_generated, ai_service, ai_model, ai_session_id, bearer_token) -> AttestationResponse | Submit a full-package attestation to the registry. |
Data models:
@dataclassclass VerifyResponse: worker_id: str status: str # 'active' | 'revoked' | 'banned' | 'unknown' current_hash: Optional[str] banned: bool ban_reason: Optional[str] attested_at: Optional[str] ai_generated: bool ai_service: Optional[str] ai_model: Optional[str] ai_session_fingerprint: Optional[str]
@dataclassclass BanEntry: sha256: str reason: str reported_at: str source: str review_status: Optional[str] = None
@dataclassclass AttestationResponse: id: str worker_id: str sha256: strRegistry + make_decision() integration:
from pyhall import make_decision, RegistryClient, Registry, load_rules
client = RegistryClient()
# Pre-populate cache so the synchronous callback has dataclient.prefetch(["org.example.my-worker"])
rules = load_rules("rules.json")registry = Registry(registry_dir="enrolled/")
decision = make_decision( inp=inp, rules=rules, registry_controls_present=registry.controls_present(), registry_worker_available=registry.worker_available, registry_get_worker_hash=client.get_worker_hash,)pyhall.attestation
Full-package attestation for WCP workers. The unit of attestation is the complete worker package directory — code, dependencies, and config all hashed together.
Signing model: HMAC-SHA256. Signing secret is read from the WCP_ATTEST_HMAC_KEY environment variable.
Deny codes (fail-closed — no silent fallback):
| Constant | Meaning |
|---|---|
ATTEST_MANIFEST_MISSING | manifest.json absent or unreadable |
ATTEST_MANIFEST_ID_MISMATCH | Manifest identity doesn’t match declared worker |
ATTEST_HASH_MISMATCH | Recomputed package hash doesn’t match manifest |
ATTEST_SIGNATURE_MISSING | No signature in manifest or WCP_ATTEST_HMAC_KEY not set |
ATTEST_SIG_INVALID | HMAC-SHA256 signature verification failed |
ATTEST_BANNED_HASH | Package hash matches a banned hash in the registry’s banned_hashes set |
scaffold_package()
Create a minimal worker package directory layout.
from pathlib import Pathfrom pyhall import scaffold_package
scaffold_package( package_root=Path("my-worker/"), worker_logic_file=Path("my_logic.py"), # optional; writes stub if None overwrite=False,)# Creates:# my-worker/code/bootstrap.py# my-worker/code/worker_logic.py# my-worker/requirements.lock# my-worker/config.schema.jsoncanonical_package_hash()
Compute a deterministic SHA-256 hash over all files in a worker package directory. Excludes manifest.json, .git/, __pycache__/, .pyc files.
from pathlib import Pathfrom pyhall import canonical_package_hash
pkg_hash = canonical_package_hash(Path("my-worker/"))# → 64-character lowercase hex SHA-256build_manifest()
Build and HMAC-sign a worker package manifest. Does not write to disk.
from pathlib import Pathfrom pyhall import build_manifest
manifest = build_manifest( package_root=Path("my-worker/"), worker_id="org.example.my-worker.instance-1", worker_species_id="wrk.example.my-worker", worker_version="1.0.0", signing_secret="your-secret", # or set WCP_ATTEST_HMAC_KEY build_source="local", # 'local' | 'ci' | 'agent')# Returns a signed manifest dict with 'signature_hmac_sha256' fieldwrite_manifest()
Write a signed manifest dict to disk as formatted JSON.
from pathlib import Pathfrom pyhall import write_manifest
write_manifest(manifest, Path("my-worker/manifest.json"))PackageAttestationVerifier
Verifies that a worker package is attested and unchanged at runtime. Fail-closed — any mismatch returns a deny code and ok=False.
from pathlib import Pathfrom pyhall import PackageAttestationVerifier
verifier = PackageAttestationVerifier( package_root=Path("/opt/workers/my-worker"), manifest_path=Path("/opt/workers/my-worker/manifest.json"), worker_id="org.example.my-worker.instance-1", worker_species_id="wrk.example.my-worker", # secret_env defaults to "WCP_ATTEST_HMAC_KEY")ok, deny_code, meta = verifier.verify()if not ok: raise SystemExit(f"Attestation denied: {deny_code}")
# meta["trust_statement"] — canonical namespace-key trust claim# meta["package_hash"] — verified hash for evidence receipts# meta["verified_at_utc"] — UTC ISO 8601Worker package workflow
from pathlib import Pathfrom pyhall import scaffold_package, build_manifest, write_manifest, PackageAttestationVerifierimport os
pkg = Path("my-worker/")
# 1. Scaffold the package layoutscaffold_package(pkg, worker_logic_file=Path("my_logic.py"))
# 2. Build and sign the manifest (at build/CI time)manifest = build_manifest( package_root=pkg, worker_id="org.example.my-worker.instance-1", worker_species_id="wrk.example.my-worker", worker_version="1.0.0", signing_secret=os.environ["WCP_ATTEST_HMAC_KEY"], build_source="ci",)
# 3. Write manifest alongside the packagewrite_manifest(manifest, pkg / "manifest.json")
# 4. At runtime — verify before executionverifier = PackageAttestationVerifier( package_root=pkg, manifest_path=pkg / "manifest.json", worker_id="org.example.my-worker.instance-1", worker_species_id="wrk.example.my-worker",)ok, deny_code, meta = verifier.verify()if not ok: raise SystemExit(f"Worker tampered: {deny_code}")Additional exports
detect_shadow_rules()
Detect rules that may shadow later, more specific rules in a rule list.
from pyhall import detect_shadow_rules, load_rules
rules = load_rules("rules.json")shadows = detect_shadow_rules(rules)for s in shadows: print(f"Rule {s['shadowing_rule_id']} shadows {s['shadowed_rule_id']}")A rule A shadows rule B when A appears before B and A’s match conditions are a semantic superset of B’s — meaning B never fires. Useful for validating rule sets in CI.
Public exports summary
from pyhall import ( # Core routing make_decision, detect_shadow_rules,
# Models RouteInput, RouteDecision, HallConfig,
# Registry Registry, PolicyGate,
# Rules Rule, load_rules, load_rules_from_dict,
# Registry client RegistryClient, RegistryRateLimitError, VerifyResponse, BanEntry, AttestationResponse,
# Package attestation PackageAttestationVerifier, canonical_package_hash, build_manifest, write_manifest, scaffold_package, ATTEST_MANIFEST_MISSING, ATTEST_MANIFEST_ID_MISMATCH, ATTEST_HASH_MISMATCH, ATTEST_SIGNATURE_MISSING, ATTEST_SIG_INVALID, ATTEST_BANNED_HASH,)