An honest inventory
What works, what is coming, and what is explicitly out of scope. Capa is released at v1.15.1: the surface is stable under SemVer, the test suite of over 4,000 tests is green on three operating systems, the discipline and information-flow control are enforced end-to-end, the package manager ships, all five audit artefacts are emitted by the compiler, and the Wasm Component Model backend is fully functional for real programs.
The boundary between real and roadmap is sharp
Capa compiles, type-checks, transpiles to Python, lowers to WebAssembly (core and Component Model), and runs. Every example on this site is executable.
Language core shipped
- Lexer + parser + analyzer + transpiler: 4 stages, ~5K lines of Python.
- Full type system: primitives, tuples, List/Map/Set, Option/Result, structs, sum types, generics with inference, pattern matching, closures, the ? operator.
- Built-in capabilities (Stdio, Fs, Net, Env, Clock, Random, Db, Proc, Unsafe) plus user-defined ones, with monotonic restrict_to attenuation and the consume qualifier.
- Module system (import, cycle detection, pub visibility, CAPA_PATH) and a package manager (capa.toml + capa install + capa.lock).
Information-flow control shipped
- Two-point lattice (@public below @secret) on types, parameters and fields, with automatic label propagation by join.
- env.get is a secret-by-default source; secret-to-public sinks are warn-then-enforce, hard errors under @strict_ifc().
- declassify(value, reason) as the single auditable bridge, recorded in the SBOM as declassification_sites.
- Flagship example: capa_paymentguard.
Tooling shipped
- A 12-feature language server (diagnostics, hover, definition, references, outline, rename, type-aware completion, semantic tokens, folding, formatting).
- AST round-trip formatter with comment preservation, watch mode, doc-comment HTML generator, capa init scaffolding, the capa test runner, and a REPL with persistent history.
- VSCode extension on the Marketplace with a bundled LSP client.
Supply-chain artefacts shipped
- Five emitters: --manifest, --cyclonedx 1.5, --spdx 2.3, --vex (per-function exploitability), --provenance (SLSA L1).
- Product composition. --compose-sbom rolls the per-function facts up the dependency tree into a per-product capability SBOM over a lattice with a distinguished authority-unknown top: an unanalyzable subtree (native, unvendored, or Unsafe-crossing) composes as authority-unknown and fails closed, never reads as clean. --check-capabilities is the per-package ceiling CI gate against capa.toml [capabilities].
- Signed authority diffs. --capability-diff old.json new.json with --fail-on-widening: a canonical, signable release-over-release changelog that flags capability widening (the node-ipc 2022 signal, a build step holding Fs that silently gains Net).
- Compliance policies. An organization capa-policy.toml over the composed graph (exclusion, product-subset, purity, forbid-capability, forbid-dependency, no-unresolved-dependencies), fail-closed on authority-unknown: --check-policies gates and --conformance-report emits signable evidence.
- --manifest-digest emits the canonical, content-addressable manifest wrapped in a content-integrity envelope: a byte-stable sha256 over the canonical bytes with an empty detached-signature slot (SLSA L1; the compiler holds no keys and never signs in-band).
- Eight signed seed libraries with three-layer hardening: lockfile SHA pin + GPG tag signatures + SLSA L2 via Sigstore Rekor.
- SBOM tooling written in Capa: diff, capability audit, SPDX and CycloneDX parsers.
Wasm backend shipped
- Component Model backend: capa --wasm --component --output app.wasm produces a standalone artifact with the WIT spec embedded, output bit-identical to the Python pipeline.
- Full generics and trait-dispatch parity; all capabilities run on Wasm with sound cross-function attenuation enforced at the host boundary.
- --prefer-wasm tries Wasm first with silent fallback. Unsafe is loudly rejected at emit time.
- Typed foreign components. extern component <Name> from "x.wasm" runs an untrusted, separately-compiled Wasm component confined by the sandbox to exactly its declared capabilities: for the capability subset it can carry, static-declared equals runtime-permitted (a child importing an ungranted interface is refused at instantiation, before its code runs). A resource ceiling bounds it too, --foreign-fuel (CPU) and --foreign-memory-cap (memory). Unsafe stays Python-only and composes as authority-unknown.
- Experimental --wasi mode. Compiles to a component that runs on stock WASI Preview 2 runtimes (for example wasmtime), instead of the default --component, which targets the dedicated capa:host. It provides mitigation Levels 1 and 2 (a runtime ceiling via --preopen and environment, plus the guest-side proof) but not Level 3, which needs capa:host: a slightly weaker guarantee tier in exchange for running on any stock WASI runtime. Literal filesystem paths pass the static ceiling; dynamic paths (for example from argv) require an operator grant --preopen <dir>, recorded in the SBOM as operator_declared_grants. capa --wasi-surface <file> shows which argv arguments reach Fs or Net sinks. Networking goes through wasi:http; note that wasmtime's wasi:http is allow-all at the host level (its C-API exposes no per-host allowed-hosts control), so the defence (fail-closed on non-2xx responses, anti-SSRF) is done guest-side. A dynamic (argv-derived) URL likewise needs an operator grant --allow-host <host> (append :get or :post to grant read or write only), the Net analogue of --preopen, recorded in the SBOM as an operator-declared grant. Example: capa --wasm --component --wasi --run programa.capa --preopen . -- <args>.
Quality & proofs shipped
- Agda mechanisation of all four λcap soundness theorems in proofs/.
- Property-based testing through Phase 4 (50k+ generated programs) lifting wasm_runtime_classes ⊆ manifest_classes through the Wasm backend.
- Over 4,000 unit + end-to-end tests, green across three OSes and three Python versions; a published soundness-hardening advisory (1.2.0).
What is still open
Most of the original design promises have shipped: generic attenuation, the native module system, the package manager, selective import, doc comments, raw strings, named arguments, the LSP, the formatter, and the full SBOM/VEX/provenance triangle are all done. What remains is deliberately small.
- Refinement types P3. A way to express properties like "this string is non-empty" or "this list is sorted" in the type system. Research-grade; explicitly not in scope for 1.x.
- A full hosted registry with search and a web publish flow. The signed index covers name resolution and supply-chain anchoring today; the hosted experience is future.
- Package-manager polish: --frozen and richer transitive resolution remain for future iterations.
- LSP v2 polish (deferred until a real-user session surfaces a need): signatureHelp, inlayHint, workspace/symbol, codeLens, selectionRange.
- A dedicated native/LLVM backend is deliberately deferred, with no date: the Wasm Component Model backend emits a component that the runtime (for example wasmtime) can AOT-compile, which is distinct from a dedicated native backend.
Help shape the next milestone
Capa is a personal project, and an open one. The fastest way to influence the roadmap is to show up with a real use case.