What a cap actually is
A cap is a two-sided artifact. Neither side works alone.
Python side — cpython-ext/_<name>_cap/
Lives in this repo under cpython-ext/. Contains:
_<name>_capmodule.c— a CPython C extension. Calls generated wit-bindgen bindings to route Python calls through the cap's WIT interface. This gets statically linked intopython.wasmat CPython build time.wit/*.wit— a smallworlddeclaringimportof the WIT interface(s) this extension consumes. This is what wit-bindgen sees at binding-generation time.gen/— wit-bindgen-c output:_import.c,_import.h,_import_component_type.o. Regenerate via thegentarget in each cap's makefile pattern; checked in so the CPython cross-build does not need wit-bindgen on the host.pyforge-pkg.toml— the manifest. Names the module, its C file, its WIT dir, its[[capabilities.required]]block (interface- version), and optional
[[provides]]blocks that ship user-facing Python shim modules intoLib/.
- version), and optional
- Optional Python facade — e.g.
duckdb.pybeside_duckdb_capability_module.c. Ships toLib/duckdb.py. Presents the DB-API surface a user expects (import duckdb), routes it through the underscored C ext (_duckdb_cap). See naming conventions.
Wasm side — ~/git/<name>-wasm/
A separate sibling repo, one per cap. Owns:
- The vendor library (miniz, OpenSSL, SQLite, DuckDB, Zstandard, ...)
built for
wasm32-wasip2orwasm32-wasip1. - The Rust (or C, or wit-bindgen-guest for any component-model language) implementation wrapping that vendor library and exporting the WIT interface.
- The WIT source (or a copy synced from
wit/in this repo — the interface is the contract).
The contract between them
The WIT interface is the entire contract. As long as the sibling
repo's component exports openssl:component/tls@0.2.0 (or whatever)
and this repo's _ssl_capability imports the same, wac plug
composes them and the runtime sees a satisfied import graph.
This is why the capability layer is consumer-agnostic:
MicroPython's _ssl_cap imports the same openssl:component/tls.
The same openssl-component.wasm satisfies both consumers.