MetaSpace Membrane
A deterministic safety membrane for machine-generated software.
MetaSpace Membrane turns an undecidable question — "is this AI doing the right thing?" —
into a decidable one — "is this effect inside the declared boundary?" — and enforces the
answer deny-by-default. One .bio constitution, three membranes, two products.
Part of the MetaSpace.Bio Engine Project — Szőke László-Ferenc (admin@metaspace.bio). Patent pending.
Watch the 60-second explainer
Containment, not correctness — the idea in one minute. ▶ click to play
Screenshots
The Warden control panel (metaspace ui) — a localhost web UI to configure the membrane
per working directory. No config files to hand-edit; every project shows its mode
(observe / dry-run / enforcing) at a glance.
The one-line pitch — the agent can be completely deceived; the harmful effect still cannot occur.
Why
You cannot prove that a generated program does the right thing (Rice's theorem — undecidable). So we stop verifying intent and contain effects instead. A membrane sits at a chokepoint, reads the constitution, and blocks anything not explicitly granted. A bug becomes a deviation from the constitution — machine-measurable and enforceable.
The guarantee is only as hard as the chokepoint is unbypassable — each tier's exact strength and
condition is recorded in docs/CLAIMS.md:
heuristic -> language guard -> harness hook -> WebAssembly
(advisory) (bypassable) (hard on agent) (unbypassable)
Case study — "Friendly Fire" (AI Now Institute, 2026): a prompt-injected coding agent is steered by a malicious repo into running a payload → RCE. We assume the model is fully deceived and still make the effect unreachable. A real functional payload fires without the membrane and never with it. See
docs/THREAT_FRIENDLY_FIRE.md· reproduce withpython evidence/run_friendly_fire_proof.py.
Install & try (60 seconds)
pip install metaspace-membrane
metaspace install # user-level, starts in dry-run (observe, no blocking)
metaspace demo # live self-test: watch it block the attack, then `metaspace enforce`
metaspace demo running the real hook: the agent is assumed fully deceived, yet every attack effect is blocked while normal work still runs.
Requires Python 3.10+ (the hook has zero third-party dependencies — nothing else to install).
The membrane installs outside any project's write scope, so a prompt-injected agent cannot
disable it. Full guide + honest scope: docs/INSTALL.md.
Two products, one engine
| Product A — App membrane | Product B — Agent membrane | |
|---|---|---|
| Contains | any application ⊂ its .bio |
the coding assistant ⊂ its limits |
| Chokepoint | WebAssembly capability import | Claude Code PreToolUse hook |
| Guarantee | unbypassable (hard, WebAssembly only) | hard on the agent (sits outside it) |
| Status | WebAssembly/WASI or OS-sandbox (Landlock): real native programs, kernel-contained | Warden MVP — install → enforce → report loop, proven end-to-end |
Both are built on the same core/ decision engine (guard.py) and the same .bio file.
Status & maturity
This is a research prototype / reference implementation (TRL ~3–4). The mechanisms are real,
falsifiable, and enforced by real substrates — run python evidence/run_falsification.py to make
the repo try (and fail) to prove itself hollow, and python evidence/run_fuzz.py for 5000
adversarial cases. They are demonstrated on real programs and fuzzed inputs, but at lab scale,
by a single author, without a third-party security audit or production users. "Patent pending"
refers to the underlying method; the two "products" are working proofs-of-concept, not shipped
software. See SECURITY.md for the threat model and how to
try to break it. Every claim above is tracked with its proof in
docs/CLAIMS.md.
The metaspace CLI
pip install . # installs the `metaspace` command
metaspace init . # synthesize a draft constitution from your code
metaspace ratify metaspace.bio # review + justify + stamp RATIFIED
metaspace gate metaspace.bio # exit 0 only if RATIFIED (use in CI)
metaspace report path/to/audit.jsonl # human-readable session safety report
One entry point over the engine: synthesize, ratify, gate, report, init. Cross-platform
by construction, and verified on Linux: run_proofs.py is green on Debian (kernel 6.1,
Python 3.11) and on Windows — the full suite passes on both, with the Landlock proof skipped on
Windows (it runs only where the OS provides it). The runs also surfaced and
fixed real bugs (a path-portability bug, a shared-parser bug). macOS is not yet verified (no host
available) — see SECURITY.md.
Exact per-release counts live in
CHANGELOG.md; the ledger of every claim and the proof backing it isdocs/CLAIMS.md.
Run the proofs (the evidence is a reproducible run)
pip install wasmtime
python run_proofs.py # runs every proof; exit 0 if all pass
Or run them individually:
python products/app_membrane/run_wasm_demo.py # every capability kind mediated (FS/NET/ENV/SUBPROCESS): 4 ALLOW / 5 DENY
python products/app_membrane/bypass_proof.py # ungranted gate -> unknown import (blocked)
python products/app_membrane/wasi/run_wasi_demo.py # real Rust program contained by WASI capabilities
python evidence/run_landlock_demo.py # real native program OS-confined by .bio (Linux/Landlock, M3)
python evidence/demos/run_synth_demo.py # code -> constitution -> enforcement (closed loop)
python evidence/demos/run_ratify_demo.py # ratification is content-bound (tamper detected)
python evidence/demos/run_gate_demo.py # production gate: only RATIFIED runs
python evidence/demos/run_knowledge_demo.py # 2 ALLOW / 5 DENY (hallucination blocked)
python evidence/demos/run_entailment_demo.py # soft tier flags faithfulness (never blocks)
python products/ai_membrane/test_hook.py # 17/17
python evidence/run_product_e2e.py # Warden loop: real hook -> audit -> report (M1)
python evidence/run_mcp_e2e.py # one core, second harness: MCP broker parity (M2)
python evidence/run_team_gate_e2e.py # team/CI gate: only a ratified, unbroadened .bio passes (M4)
python evidence/run_falsification.py # self-falsification: proofs are real, not slop
The last one is a self-falsification audit: it mutates a constitution (the decision flips),
sabotages guard.check() (a proof then fails), and has WebAssembly itself refuse an ungranted
syscall — so the evidence is measuring real behaviour, not printing PASS.
No hosted CI required — the proof is a command anyone can run.
MetaSpace Warden — the agent membrane (Product B)
Warden is the shipping product: a deny-by-default membrane for a Claude Code session. You
install it, it enforces a hardened default constitution from outside the agent, and it leaves
a session safety report. The whole loop is a reproducible proof
(python evidence/run_product_e2e.py), driving the real hook over a realistic session:
install the membrane -> the agent acts (writes, shell, fetches)
-> the hook enforces the shipped constitution (deny-by-default)
-> it logs a project-local audit (.metaspace/session_audit.jsonl)
-> `metaspace report` summarizes what was blocked, by capability
In the proof, of a realistic 11-step session the membrane allows 6 legitimate actions and blocks
5 (a write outside the project, git push, rm -rf /, a curl … | bash, and a beacon to an
unlisted host) — then metaspace report shows the block breakdown (FILESYSTEM / SHELL / NETWORK).
As a Claude Code plugin (one command):
/plugin marketplace add LemonScripter/metaspace-membrane
/plugin install metaspace-membrane@metaspace
Restart the session and run /hooks to confirm the PreToolUse membrane is active. The plugin
ships a hardened default constitution (project-only writes, host allowlist, dangerous-command
block); ${CLAUDE_PROJECT_DIR} is used as the project boundary automatically.
Or as a portable installer (writes .claude/settings.json directly, with an editable
constitution in .claude/metaspace/):
python products/ai_membrane/install.py /path/to/your/project
Restart the Claude Code session, then run /hooks to confirm it is active. Removing the hook
block reverts either method.
The session constitution is deny-by-default: writes are limited to the project directory,
outbound network to an allowlist, and dangerous shell patterns are blocked. The membrane logs
every decision to .metaspace/session_audit.jsonl in the project; after a session, see what it
blocked with:
metaspace report # reads ./.metaspace/session_audit.jsonl by default
Other harnesses: the generic MCP broker
The membrane's decision lives in one harness-independent core (core/agent_adapter.py); the
Claude Code hook is just one thin adapter over it. A second adapter — a generic MCP
capability-broker (products/mcp_membrane/server.py, a minimal JSON-RPC stdio server) —
exposes mediated effect tools (fs_write, fs_read, net_fetch) to any MCP-capable agent,
each gated by the same core, deny-by-default. python evidence/run_mcp_e2e.py drives both the
hook and the broker over their real interfaces and shows they reach identical verdicts.
Honest condition (the hard-vs-advisory line): an MCP tool the agent may voluntarily call is only advisory — back to self-discipline, which does not contain a misaligned agent. The broker is hard only when the agent is deployed with its ambient authority removed, so the broker's tools are its only path to the filesystem/network. Under that condition the guarantee equals the hook's; the broker cannot constrain effects reached through some other unmediated tool.
Team / CI: gate the constitution at merge time
Commit a ratified metaspace.bio to your repo, and make "the effect boundary here is
human-ratified and hasn't been silently broadened" a build-breaking check — the same
content-bound ratification as the runtime gate, now enforced in CI and pre-commit:
# .github/workflows/metaspace-gate.yml (ships in this repo as a template)
- run: pip install "metaspace-membrane @ git+https://github.com/LemonScripter/metaspace-membrane"
- run: metaspace gate metaspace.bio # exit 0 only if RATIFIED and unbroadened
# .pre-commit-config.yaml
repos:
- repo: https://github.com/LemonScripter/metaspace-membrane
rev: main
hooks: [{ id: metaspace-gate }]
An unratified constitution, or one widened after ratifying (→ TAMPERED), fails the build.
python evidence/run_team_gate_e2e.py proves the whole flow with the real CLI. (Honest note:
there is no hosted-CI badge — GitHub Actions is disabled on this repo — so the gate logic is
proven locally and cross-OS instead, on Windows and real Linux.)
The .bio constitution
One file, three lenses:
CAPABILITIES {
FILESYSTEM write "out/**"
NETWORK out "api.allowed.com"
}
KNOWLEDGE {
ENTITY order FROM "kb/orders.json"
FIELD order.status IN pending, shipped, delivered, refunded
ACTUATE refund PROVENANCE verified_db
CITATION REQUIRED
SOURCE verified_db
}
- Capability — mediates effects on the world (deny-by-default).
- Value invariant — guards safety bounds.
- Knowledge — grounded facts only: no invented entities, no ungrounded actuation.
Synthesize a constitution from code
Point the synthesizer at a file or directory; it detects the code's real effects
(filesystem, network, env, subprocess, hardware, import-path) and drafts a .bio — marked
SYNTHESIZED, since a human ratifies before it is trusted:
python synthesize.py path/to/app --out app.constitution.bio
evidence/demos/run_synth_demo.py runs the loop end-to-end: it synthesizes a constitution
from a sample app, feeds it straight into the membrane, and shows the app can then only do
what it declared — an effect it never had (a subprocess) is denied by default.
This is a static heuristic; the runtime membrane, not the synthesis, is the
guarantee.
Ratify a reviewed constitution (SYNTHESIZED 🟡 → RATIFIED 🟢):
python ratify.py app.constitution.bio --yes
Ratification is content-bound: the stamp carries a fingerprint of the enforced policy, so a later edit that widens a scope or adds a capability is detected as TAMPERED 🔴 — you cannot ratify a policy and then quietly broaden it.
In production, gate the membrane on ratification — Guard(..., require_ratified=True) (or
core.gate) runs only a RATIFIED constitution; a SYNTHESIZED or TAMPERED one is refused,
fail-closed. A policy is enforceable only after human ratification.
Capabilities the dry-run learned are marked provisional: ratification is refused until each
carries a written JUSTIFY reason — a per-item, read-gated justification that defeats
rubber-stamping (--yes cannot bypass it). The code enforces the justification's presence,
not its truth, so the human's judgement on the reason still matters.
Layout
core/ shared decision engine (guard, knowledge, analyzer, agent_adapter)
products/ app_membrane (WebAssembly + Landlock) · ai_membrane (hook + installer) · mcp_membrane (broker)
evidence/ runnable proofs + decisions
docs/ ARCHITECTURE.md
See docs/ARCHITECTURE.md for the full technical background, or the
technical whitepaper docs/MetaSpace_Membrane_Whitepaper_EN.pdf
(LaTeX source alongside; every claim is a reproducible run or true by construction).
Honest limits
- Product A's hard guarantee requires a real substrate: the WebAssembly capability model, or an
OS sandbox (Landlock,
products/app_membrane/sandbox_enforcer.py) that confines a stock native program's filesystem writes to its.biofrom the kernel. A language-level guard is bypassable and is not shipped as a product. The Landlock MVP confines writes (read/execute unrestricted so any binary runs); it is Linux-only and fail-closed if unavailable. - The code→constitution synthesis is a static heuristic; a dry-run learning mode
(
core/dryrun.py) observes concrete runtime effects and augments the constitution before ratification, so it does not false-positive-block legitimate dynamic behaviour. - The agent membrane affects tool effects, not the model's prose; its shell check is a
structural allowlist (
core/shell_policy.py) — obfuscation-resistant and fail-closed. - The shell allowlist is defence-in-depth, not the boundary. Shell interpreters are hardened
(
bash -c CMDis re-checked recursively, piped stdin refused), but an allowlisted language runtime is not an allowlist-shaped question:python -c "…"andnode -e "…"execute code no entry describes. Measured, not theorised — an agent refusedwhoamiread the username throughpython -c. A development agent needs those runtimes, so on shell-mediated hosts the guarantee rests on the FILESYSTEM write-scope and the NETWORK out-scope, which mediate what such code can actually do. - A constitution's allowlist is parsed by one quote-aware parser, so a comment can never silently empty it; an allowlist that is declared but unreadable denies rather than degrading to a porous denylist.
- The epistemic tier has two parts, named honestly: a hard tier that is a real
deterministic membrane (it contains/blocks), and a soft tier that is
not a membrane but an advisory flag (it qualifies/flags, never blocks).
The reproducible threat-model matrix
(
evidence/demos/run_threat_matrix_demo.py, rendered indocs/ARCHITECTURE.md) shows exactly what each layer catches — including where a schema-valid but fabricated statement passes the hard layers and is only flagged.
© Szőke László-Ferenc — MetaSpace.Bio Engine Project. Patent pending. Licensed under the Business Source License 1.1 — see LICENSE. Source-available: free to use, copy, modify and redistribute for any non-competing purpose (internal use, research, education, and products that merely depend on it); each version converts to Apache-2.0 four years after its release. The only reserved use is offering a competing commercial safety-membrane product/service. For commercial or competing-use licensing: admin@metaspace.bio.
Designed and authored by Szőke László-Ferenc, with AI pair-programming assistance (Claude).
Metadata
Release files for metaspace-membrane 0.3.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| metaspace_membrane-0.3.3.tar.gz | 158.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| metaspace_membrane-0.3.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 327.0 kB
Release files / metaspace_membrane-0.3.3.tar.gz
| Download URL | metaspace_membrane-0.3.3.tar.gz |
|---|---|
| Size | 158.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2bf44134ddbf0f7e000eeaf73e38b52d21f7683030366875d9988d5b48f6bbb7
|
|
BLAKE2b-256 checksum How to use checksums |
9794a36e0b8416f23f97977f43fc7b989b592a1515bdec9e152400e912517106
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.6
|
Release files / metaspace_membrane-0.3.3-py3-none-any.whl
| Download URL | metaspace_membrane-0.3.3-py3-none-any.whl |
|---|---|
| Size | 169.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e47a187715b731600188ba78b7f1699411fe3e5b8c1a84fe487d04bfbb8d7fa6
|
|
BLAKE2b-256 checksum How to use checksums |
15e587b0b6e6ed1f22883d1310997e4833063e95ac0d509296b82ea1ead844e9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.6
|