Skip to content

feat(policy): Phase 2 scaffolding - Wasm interpreter + pooled runtime#23

Draft
srdjan wants to merge 1 commit into
mainfrom
policy/phase2-scaffolding
Draft

feat(policy): Phase 2 scaffolding - Wasm interpreter + pooled runtime#23
srdjan wants to merge 1 commit into
mainfrom
policy/phase2-scaffolding

Conversation

@srdjan
Copy link
Copy Markdown
Owner

@srdjan srdjan commented May 9, 2026

Summary

Phase 2 scaffolding for the Wasm-backed policy capability gating system described in docs/zigttp_zigts_policy_wasm_spec.md. This PR locks in the Phase 2 contract so the implementation PR has clear, compilable targets. No Wasm interpreter is implemented here.

Spec reference: docs/zigttp_zigts_policy_wasm_spec.md — relevant sections:

  • Section 6: Wasm component interface / WIT ABI — implemented as WasmInterpreter.callPolicyCheck stub in packages/zigts/src/wasm/interpreter.zig
  • Section 10: Performance — never instantiate per request, strict timeout, fail-closed — the WasmPool skeleton in packages/zigts/src/wasm/pool.zig encodes this contract in its doc comment
  • Section 11: Fail-closed semantics — trap, timeout, malformed input, and unknown action all deny; referenced in interpreter.zig and in the Phase 2 checklist below
  • Section 14: Sign/checksum step — wasm_policy_hash field in HandlerContract (packages/zigts/src/contract_types.zig) and round-tripped through the contract JSON writer/parser

What's in this PR

packages/zigts/src/wasm/ (new directory)

File Purpose
interpreter.zig WasmInterpreter struct — init, deinit, callPolicyCheck stubs (spec sections 6, 10)
pool.zig WasmPool skeleton wrapping the LockFreePool pattern — acquire/release stubs (spec section 10)
loader.zig loadWasmArtifact stub — returns raw bytes; later phases add WIT validation
root.zig Re-exports for the wasm sub-package

packages/zigts/src/policy.zig

  • WasmPolicyChecker struct added alongside LocalPolicyChecker; both expose check(input: PolicyInput) PolicyResult so call sites are unchanged at Phase 2 rollout
  • WasmPolicyChecker.init(pool_ptr) stub mirrors LocalPolicyChecker.init — makes the startup-time checker selection point explicit
  • Failing integration test "WasmPolicyChecker matches LocalPolicyChecker for known fixtures" added with error.SkipZigTest — see note below

packages/zigts/src/contract_types.zig

  • wasm_policy_hash: [32]u8 field added to HandlerContract (all-zeros = no Wasm policy present)
  • Serialized as "wasmPolicyHash" in contract_json_writer.zig and round-tripped in contract_json_parser.zig using the existing writeJsonHex / hexToBytes conventions

Failing test — intentional

The test "WasmPolicyChecker matches LocalPolicyChecker for known fixtures" returns error.SkipZigTest and does not break CI. It locks in the equivalence contract: the Wasm-backed checker must produce byte-identical results to the in-process checker for every fixture in packages/zigts/src/fixtures/policy/. The implementation PR will convert it to a real fixture loop by removing the return error.SkipZigTest line.

Phase 2 implementation checklist

  • Implement minimal Wasm 1.0 decoder (load, validate, instantiate)
  • Implement WasmInterpreter.callPolicyCheck with strict timeout per spec section 10
  • Pool of pre-instantiated runtimes via WasmPool (spec section 10: never instantiate per request)
  • Compile a Phase 1 in-process equivalent policy as Wasm and embed it for fixtures
  • Wire wasm_policy_hash field through currentPolicyHashRaw (reuse rule_registry.policyHash conventions)
  • Convert the skeleton equivalence test to a real fixture loop
  • Fail-closed handling: trap, timeout, malformed input, unknown action all deny per spec section 11

Generated by Claude Code

Adds an `init(pool_ptr)` function to `WasmPolicyChecker` that mirrors
`LocalPolicyChecker.init`, making the startup-time checker selection
point explicit. Uses `*anyopaque` to avoid a circular import with the
wasm package; the Phase 2 implementation PR will introduce the proper
module boundary once `wasm.WasmPool` is live.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant