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:
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 "git+https://github.com/LemonScripter/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.
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 — 22/22 on Linux (including the kernel-enforced Landlock
sandbox) and 21 pass + 1 skip on Windows (the Landlock proof 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.
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 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.1
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.1.tar.gz | 127.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| metaspace_membrane-0.3.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 262.8 kB
Release files / metaspace_membrane-0.3.1.tar.gz
| Download URL | metaspace_membrane-0.3.1.tar.gz |
|---|---|
| Size | 127.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
751c1bc0ad8cec08bb921cec37bdb04be7970c484fa965e424bd78174ce31d55
|
|
BLAKE2b-256 checksum How to use checksums |
07bd90e9d561031a97975a3da19d5c394bd80931e41f7fff07d99bd9e51835aa
|
| 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.1-py3-none-any.whl
| Download URL | metaspace_membrane-0.3.1-py3-none-any.whl |
|---|---|
| Size | 134.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
81882b89ebc79b556bc5ecd69ecada568ec4804a237c6ed4640e7de877e21c9f
|
|
BLAKE2b-256 checksum How to use checksums |
9b8e7d5894f24112b7e18ff927443f764340f9b4ed7b59d9590f30152f04f36d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.6
|