Skip to content

Security & Governance

The pyhall Skills & Tools system is built on the same WCP governance chain that governs all workers. Skills are not raw functions — they are governed artifacts with mandatory attestation, certification, and audit trails.

Core security model

Deny-by-default everywhere.

A skill can only execute when all of the following are satisfied:

  1. The canonical manifest is valid (hash verified)
  2. The adapter artifact is signed and its certification is present in the registry
  3. The worker is registered and passes attestation
  4. All required WCP controls are satisfied for the policy tier
  5. The namespace is authorized for the calling organization
  6. The skill is not on the ban list (org-level or global)

If any condition fails: execution is denied, a structured error is returned, and an audit event is written. There is no silent fallback.

Lifecycle controls

Every skill lifecycle event is auditable:

EventAudit record written
skill initManifest created, author identity recorded
skill buildAdapter generated, manifest hash recorded
skill certifyCertification issued, signature attached
skill publishRegistry entry created, artifact hash stored
skill installInstallation recorded (if analytics enabled)
skill executeExecution decision recorded (ALLOW or DENY)
skill denyDenial reason, worker identity, timestamp

Registry enforcement

The pyhall registry is consulted at enrollment, publish time, and every tool execution. There is no cached-trust path that skips governance.

When a skill is published:

  • The manifest hash is stored immutably
  • The adapter artifact hash is stored with its signature
  • The certification timestamp and signer identity are recorded
  • The revocation status is initialized to active

When a skill executes:

  • The registry is queried to verify the certification is still active
  • The ban list is checked
  • The attestation check is performed
  • The governance gate decision is recorded

Kill switch

Every skill and every adapter supports an independent kill switch:

  • Org-level revocation: an org admin can revoke a skill; all workers using it are denied immediately
  • Global ban: the registry operator can ban a skill at the global level
  • Adapter-level degradation: if a platform API breaks compatibility, the specific adapter is marked degraded and denied

Kill switches take effect on the next execution gate call — there is no grace period for unauthorized execution.

Input validation

The pyhall compiler generates strict JSON Schema validators for all skill inputs. Manifests that produce malformed adapter output are rejected at build time — they cannot be published or installed.

Preventing silent bypass

pyhall is designed to fail loudly, not silently:

  • Missing attestation callables → explicit deny + structured error
  • Registry unreachable → fail closed (no execution allowed for uncertified installs)
  • Missing controls → explicit deny
  • Malformed adapter output → build fails, nothing is published

There is no “try anyway” path.

PolicyGate enforcement

Every skill invocation routed through make_decision() can require a policy gate evaluation. The gate returns one of three decisions:

DecisionEffect
ALLOWExecution proceeds
DENYExecution denied, audit record written
REQUIRE_HUMANExecution paused pending human review

When escalation.policy_gate=True in a routing rule, a policy_gate_eval callable must be provided to make_decision(). Missing the callable on a gate-required rule produces a denial — there is no default-allow fallback.

from pyhall import make_decision, PolicyGate
class MyGate(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 = MyGate()
decision = make_decision(inp, rules, ..., policy_gate_eval=gate.evaluate)

Fail-closed behavior

pyhall is designed to fail loudly, not silently. Failure modes and their outcomes:

FailureResult
No routing rule matchesDenied (matched_rule_id = "NO_MATCH")
Required controls missing from registryDenied
policy_gate=True but no policy_gate_eval providedDenied
Worker not enrolled in registryDenied
Attestation hash mismatchDenied (worker_attestation_valid = False)
Manifest missing or unreadableATTEST_MANIFEST_MISSING deny code
Package tampered (hash mismatch)ATTEST_HASH_MISMATCH deny code
HMAC signature invalidATTEST_SIG_INVALID deny code

There is no silent fallback path. Every denial emits a structured audit event.

WCP_ATTEST_HMAC_KEY for production

Worker package attestation is signed with HMAC-SHA256 using a secret read from the WCP_ATTEST_HMAC_KEY environment variable.

Terminal window
export WCP_ATTEST_HMAC_KEY="your-namespace-signing-secret"

Set this in your CI/CD environment at build time (for build_manifest()) and on your production worker host (for PackageAttestationVerifier.verify()). The same key must be present at both points — build and runtime.

If the env var is not set at verify time, PackageAttestationVerifier.verify() returns ATTEST_SIGNATURE_MISSING and denies execution.

For hardened production deployments, rotate this key periodically and re-attest all worker packages. The asymmetric (Ed25519) signing path is planned for a future release.

WCP alignment

The Skills governance model maps directly to WCP control model fields:

Manifest fieldWCP control
namespaceOrg-level authority scope
policy_tierRisk tier enforcement
capabilitiesCapability declaration
attestation_requiredWorker attestation gate
audit_eventsImmutable audit trail

See the WCP specification for the full control model.