Repository navigation
Releases: Insomniac-VibeLabs/two-key
Release list
release-v0.7.3
Two-Key 0.7.3
Beta (pre-1.0). The first release of new code since 0.7.0: PyPI's 0.7.1 and 0.7.2 were the 0.7.0 code, repackaged.
Install
pip install "two-key[yaml]==0.7.3"
pip install "two-key[mcp]==0.7.3" # for the MCP proxy
What's new
- two-key setup writes a whole deployment (principal key, constitution, judges, proxy.yaml, ledger) from answers or a file, checks it before it is in place, and records it.
- two-key config set and undo change one setting at a time. The whole set must still pass config check, a weaker change needs a typed yes, a signed setting needs the principal key, and every change is a config_changed ledger entry with no values. config get, show and check read a config without starting anything. See docs/SETUP.md.
- The principal key can be encrypted with a passphrase; the proxy reads it from an owner-only keys.passphrase_file.
- A signed serial in the constitution. Once a ledger has run one, it refuses an older constitution, a reused serial, or none, so nobody can quietly go back to older rules. Two proxies started at once on one ledger cannot both run one serial.
- The start-up checks now cover the upstream server's own files behind a launcher such as sudo, plus upstream.check_paths for the rest (#13).
- Shared ledgers are sturdier: each write and the checkpoint that signs it happen in one hold of the lock, and the SIEM copy of an entry another proxy wrote is marked replay.
- Only the tool's id is required in a tool spec: irreversible and data_class_floor default to true and classified, the strict side. Existing constitutions sign to the same bytes.
- docs/SETTINGS.md lists every setting, generated from the code. CI covers Python 3.10 to 3.14 on Linux, macOS and Windows, with hash-pinned installs.
- Live-tested by GrokBot across runs 9 to 9t (175 cases). Every Two-Key finding is fixed; the last three regression rounds found none.
Upgrading from 0.7.0, 0.7.1 or 0.7.2
- Everything loads unchanged and nothing needs re-signing.
- Read the proxy's start-up output: it may now name the upstream server's files, or warn upstream_paths_unchecked when a launcher such as sudo or npx hides them (under high_assurance it refuses). Give the program as an absolute path or list its folder in upstream.check_paths.
- To turn on rollback protection, add "serial: 1" to your rules file and sign it again; count up by one for each new constitution.
- config check now fails if the monitored agent's credential variable is unset.
- With two proxies on one ledger, dedupe SIEM events on entry_hash.
- A tool spec may now leave out irreversible and data_class_floor; left out, they are true and classified, so a reversible or lower-class tool should still say so.
Full details: CHANGES.md, "Release v0.7.3" and "Upgrading from 0.7.0".
release-v0.7.0
Two-Key v0.7.0
SIEM Export, Security Boundary Hardening, and Operational Visibility
Two-Key v0.7.0 adds optional SIEM integration and strengthens the security boundary around monitored agents. This release makes the authorization ledger easier to integrate with an organization's existing security monitoring while preserving the principle that the ledger remains the authoritative record.
Highlights
SIEM Export
Two-Key can now send a live, controlled copy of ledger events to an external SIEM or security collector as decisions are recorded.
Supported destinations include:
- Syslog
- TLS (RFC 5425), the default
- TCP (RFC 6587)
- UDP (RFC 5426)
- HTTPS webhooks
Events can be emitted using:
- Two-Key's native SIEM schema
- Elastic Common Schema (ECS)
- Open Cybersecurity Schema Framework (OCSF)
Supported formats are JSON and CEF.
The exported event contains security-relevant metadata such as:
- decision and reason codes
- ledger sequence numbers and entry hashes
- Path A results
- Path B vote counts
- tool identifiers
- data classifications
- policy and identity digests
- token identifiers and hashes
- content-scanning results
- witness fingerprints
- agent and integration metadata
- sizes and cryptographic digests of selected inputs
Sensitive call content is not exported. Argument values, proposal text, derived amounts, counterparties, custom field values, judge rationales, credentials, token text, scanner threat names, and file contents remain outside the SIEM event.
The exported data is controlled by an explicit per-event allowlist. A newly introduced ledger field is not automatically exposed.
SIEM Export and Verification
For environments that do not use a live collector, Two-Key now provides:
two-key siem-exportto create an export from the verified ledger.
Exports can subsequently be checked with:
two-key siem-verifyVerification checks the event sequence, entry hashes, ledger membership, exported fields, gaps, duplicates, and unexpected events. A complete verification can therefore distinguish a missing SIEM event from an event that was never present in the ledger.
Both operations work from the verified ledger; an invalid ledger is not silently exported.
SIEM Delivery Does Not Gate Authorization
SIEM delivery is deliberately asynchronous.
Once a ledger entry has been written and synchronized to disk, the event is placed on a bounded queue and handled by a separate sender thread. A slow, unavailable, or disconnected collector therefore does not block authorization.
Per-sink cursors allow delivery to resume after an outage. Events delivered later are marked as replayed so that their delivery time is not confused with the authorization itself.
With no SIEM configuration, Two-Key's existing authorization behavior is unchanged.
Refused-Token Visibility
Previously, a forged, expired, or malformed capability token was rejected before it could create a ledger entry, leaving no ledger event.
v0.7.0 adds operational visibility without changing that security property.
Gateway token refusals are counted in memory by category:
bad_signatureexpiredmalformedother
Counts are reported periodically rather than creating a ledger entry for every rejected token. When SIEM export is enabled, these appear as gateway_token_refused events.
Importantly, refused-token events are not ledger entries and do not retain token text, token digests, or unverified JTIs.
Monitored-Agent Account Check
The MCP proxy now checks the actual account under which its parent process is running before opening the ledger.
The proxy refuses to start when the monitored agent:
- runs as the same account used by Two-Key;
- runs as root;
- has an account that cannot be determined;
- can modify a path that Two-Key itself executes or reads.
The account information comes from the operating system rather than an environment variable, preventing the check from being satisfied merely by changing caller-supplied environment data.
The default behavior is on_agent_access: refuse, with a warning mode available where appropriate.
Shared-Ledger Handling
The ledger now handles entries appended by another Two-Key process more safely.
When a shared ledger has grown, a process detects and verifies the new entries under the cross-process lock before exposing them to observers. A shortened ledger or partial appended line remains an error rather than being treated as a normal update.
Testing and Validation
v0.7.0 includes additional validation around the new functionality, including:
- SIEM field-by-field allowlist testing
- protection against accidental export of sensitive canary values
- live syslog and HTTPS webhook delivery
- replay and cursor behavior
- SIEM export and verification
- refused-token reporting
- monitored-agent account checks
- shared-ledger behavior
- Elasticsearch/Kibana integration testing
- multi-platform CI improvements
The release PR reports 1,018 tests across Linux, macOS, and Windows, Python 3.10–3.12, with and without the MCP extra. Bandit, Semgrep, CodeQL, and the SonarCloud gate are reported as passing. Live runs covering four monitored-agent personas were also performed, with findings fixed and recorded in CHANGES.md.
The repository also adds a non-required Elasticsearch/Kibana integration workflow that exercises both SIEM sinks, verifies that expected event types arrive, checks that sensitive test values do not leave the system, and imports the example Kibana dashboard.
Documentation
v0.7.0 adds dedicated SIEM documentation covering configuration, supported sinks, schemas, formats, export/verification, refused-token reporting, and an Elasticsearch/Kibana example.
Documentation and package metadata are updated for version 0.7.0, including the v0.7.0 Git installation reference.
Known Limitations
Two limitations remain intentionally documented rather than being represented as solved by this release:
- A monitored agent connecting from another machine has not yet received its own live end-to-end run; the remote-agent/SSH behavior remains documented as a limitation.
- Windows cannot yet determine the monitored process's parent account in the same way as Linux/macOS. Windows therefore requires the appropriate warning behavior until that support is ported.
These limitations are documented in the project roadmap and connection documentation rather than being hidden by the release.
Upgrade from 0.6.0
v0.7.0 is designed as an additive release.
SIEM integration is opt-in. If no siem configuration is supplied, no SIEM traffic is generated and the existing authorization, judge, token, and ledger behavior remains unchanged.
The package version is 0.7.0; the release tag is v0.7.0. The package is not currently published to PyPI.
What v0.7.0 Does Not Do
Two-Key does not become a SIEM or log-storage system itself.
The SIEM functionality exports a controlled copy of the authorization record to infrastructure operated by the user. The authoritative security record remains the Two-Key ledger.
Likewise, this release does not add an antivirus engine, SIEM storage, PKI, FIPS mode, or the post-1.0 GUI. Those remain separate roadmap items.
release-v0.7.0
Two-Key v0.7.0
SIEM Export, Security Boundary Hardening, and Operational Visibility
Two-Key v0.7.0 adds optional SIEM integration and strengthens the security boundary around monitored agents. This release makes the authorization ledger easier to integrate with an organization's existing security monitoring while preserving the principle that the ledger remains the authoritative record.
Highlights
SIEM Export
Two-Key can now send a live, controlled copy of ledger events to an external SIEM or security collector as decisions are recorded.
Supported destinations include:
- Syslog
- TLS (RFC 5425), the default
- TCP (RFC 6587)
- UDP (RFC 5426)
- HTTPS webhooks
Events can be emitted using:
- Two-Key's native SIEM schema
- Elastic Common Schema (ECS)
- Open Cybersecurity Schema Framework (OCSF)
Supported formats are JSON and CEF.
The exported event contains security-relevant metadata such as:
- decision and reason codes
- ledger sequence numbers and entry hashes
- Path A results
- Path B vote counts
- tool identifiers
- data classifications
- policy and identity digests
- token identifiers and hashes
- content-scanning results
- witness fingerprints
- agent and integration metadata
- sizes and cryptographic digests of selected inputs
Sensitive call content is not exported. Argument values, proposal text, derived amounts, counterparties, custom field values, judge rationales, credentials, token text, scanner threat names, and file contents remain outside the SIEM event.
The exported data is controlled by an explicit per-event allowlist. A newly introduced ledger field is not automatically exposed.
SIEM Export and Verification
For environments that do not use a live collector, Two-Key now provides:
two-key siem-exportto create an export from the verified ledger.
Exports can subsequently be checked with:
two-key siem-verifyVerification checks the event sequence, entry hashes, ledger membership, exported fields, gaps, duplicates, and unexpected events. A complete verification can therefore distinguish a missing SIEM event from an event that was never present in the ledger.
Both operations work from the verified ledger; an invalid ledger is not silently exported.
SIEM Delivery Does Not Gate Authorization
SIEM delivery is deliberately asynchronous.
Once a ledger entry has been written and synchronized to disk, the event is placed on a bounded queue and handled by a separate sender thread. A slow, unavailable, or disconnected collector therefore does not block authorization.
Per-sink cursors allow delivery to resume after an outage. Events delivered later are marked as replayed so that their delivery time is not confused with the authorization itself.
With no SIEM configuration, Two-Key's existing authorization behavior is unchanged.
Refused-Token Visibility
Previously, a forged, expired, or malformed capability token was rejected before it could create a ledger entry, leaving no ledger event.
v0.7.0 adds operational visibility without changing that security property.
Gateway token refusals are counted in memory by category:
bad_signatureexpiredmalformedother
Counts are reported periodically rather than creating a ledger entry for every rejected token. When SIEM export is enabled, these appear as gateway_token_refused events.
Importantly, refused-token events are not ledger entries and do not retain token text, token digests, or unverified JTIs.
Monitored-Agent Account Check
The MCP proxy now checks the actual account under which its parent process is running before opening the ledger.
The proxy refuses to start when the monitored agent:
- runs as the same account used by Two-Key;
- runs as root;
- has an account that cannot be determined;
- can modify a path that Two-Key itself executes or reads.
The account information comes from the operating system rather than an environment variable, preventing the check from being satisfied merely by changing caller-supplied environment data.
The default behavior is on_agent_access: refuse, with a warning mode available where appropriate.
Shared-Ledger Handling
The ledger now handles entries appended by another Two-Key process more safely.
When a shared ledger has grown, a process detects and verifies the new entries under the cross-process lock before exposing them to observers. A shortened ledger or partial appended line remains an error rather than being treated as a normal update.
Testing and Validation
v0.7.0 includes additional validation around the new functionality, including:
- SIEM field-by-field allowlist testing
- protection against accidental export of sensitive canary values
- live syslog and HTTPS webhook delivery
- replay and cursor behavior
- SIEM export and verification
- refused-token reporting
- monitored-agent account checks
- shared-ledger behavior
- Elasticsearch/Kibana integration testing
- multi-platform CI improvements
The release PR reports 1,018 tests across Linux, macOS, and Windows, Python 3.10–3.12, with and without the MCP extra. Bandit, Semgrep, CodeQL, and the SonarCloud gate are reported as passing. Live runs covering four monitored-agent personas were also performed, with findings fixed and recorded in CHANGES.md.
The repository also adds a non-required Elasticsearch/Kibana integration workflow that exercises both SIEM sinks, verifies that expected event types arrive, checks that sensitive test values do not leave the system, and imports the example Kibana dashboard.
Documentation
v0.7.0 adds dedicated SIEM documentation covering configuration, supported sinks, schemas, formats, export/verification, refused-token reporting, and an Elasticsearch/Kibana example.
Documentation and package metadata are updated for version 0.7.0, including the v0.7.0 Git installation reference.
Known Limitations
Two limitations remain intentionally documented rather than being represented as solved by this release:
- A monitored agent connecting from another machine has not yet received its own live end-to-end run; the remote-agent/SSH behavior remains documented as a limitation.
- Windows cannot yet determine the monitored process's parent account in the same way as Linux/macOS. Windows therefore requires the appropriate warning behavior until that support is ported.
These limitations are documented in the project roadmap and connection documentation rather than being hidden by the release.
Upgrade from 0.6.0
v0.7.0 is designed as an additive release.
SIEM integration is opt-in. If no siem configuration is supplied, no SIEM traffic is generated and the existing authorization, judge, token, and ledger behavior remains unchanged.
The package version is 0.7.0; the release tag is v0.7.0. The package is not currently published to PyPI.
What v0.7.0 Does Not Do
Two-Key does not become a SIEM or log-storage system itself.
The SIEM functionality exports a controlled copy of the authorization record to infrastructure operated by the user. The authoritative security record remains the Two-Key ledger.
Likewise, this release does not add an antivirus engine, SIEM storage, PKI, FIPS mode, or the post-1.0 GUI. Those remain separate roadmap items.
v0.6.0: Merge pull request #12 from Insomniac-VibeLabs/working
Two-Key 0.6.0: Windows, content scanning, writable-path check
Two-Key now runs on Windows. It can also ask your own antivirus or DLP product to check each tool call before both keys decide, and at start it warns about any file or folder it runs or reads that another account could change. Beta, maintainer-reviewed, not independently audited. Apache-2.0.
pip install "two-key[yaml] @ git+https://github.com/Insomniac-VibeLabs/two-key.git@v0.6.0"
pip install "two-key[mcp] @ git+https://github.com/Insomniac-VibeLabs/two-key.git@v0.6.0" # with the MCP proxyWhat's new
- Windows support. Keys get an access list for the current user only. A key that anyone but the user, SYSTEM, Administrators, or OWNER RIGHTS can open is refused, and so is a reparse point. The ledger lock is
LockFileEx. Linux and macOS behave as before. - Content scanning (optional). Two-Key calls your antivirus or DLP product for every call to a tool your signed constitution marks, files included. Two-Key alone starts the scan; the agent cannot ask for one, skip one, or answer one. The verdict (clean, flagged, or unavailable) is a fact your signed rule decides on, in default, strict, or monitor stance. The judges are told the verdict, and the ledger records it without the content. A timeout or error is never treated as clean. A file Two-Key cannot read, or one over its limit, is denied before both keys. Adapters: ClamAV
clamd, ICAP products (icaps://needs TLS 1.2 or later), a command, or your own Python. Two-Key adds no scanning engine of its own. See docs/SCANNERS.md. - Start-up check for writable paths. Two-Key names each file or folder it runs or reads that another account could change. It warns by default;
on_writable_paths: refusemakes it refuse to start, andhigh_assurancealways refuses. docs/CONNECTING.md shows how to connect the agent so it cannot go around Two-Key, and how to run Two-Key as its own service account. - Judge connection reuse (#6). Judge connections are pooled per origin across quorum rounds.
- Clearer key errors. A public key given to
--keynow says so (key_file_public), and CLI key errors are one line.
Upgrading from 0.5.0
- Constitutions, ledgers, keys, backups,
judges.yaml, andproxy.yamlfrom 0.5.0 load unchanged. Nothing needs re-signing. - Check the start-up output first. Look for
two-key: WARNING: writable_path:lines. Underhigh_assurance(and thesection4profile), Two-Key refuses to start until there are none. Fix the owner or permissions, or run Two-Key as a service account. - Scanning is off until you configure a scanner. Without one, the judge prompts, tokens, and ledger are the same as in 0.5.0.
- A constitution that signs
encrypted: passneeds 0.6.0; 0.5.0 refuses it.
Testing
- CI runs on Linux, macOS, and Windows: 866 tests on Python 3.10 to 3.12, the demo, the build, bandit, and CodeQL. Semgrep and coverage run on Linux. Semgrep reports 0 findings, and the SonarCloud and DeepSource gates pass.
- Live run 7 (content scanning, 49 cases) and run 7x (a new organization, 52 cases, 33 of them attacks designed by a security practitioner) passed every case, with no referee incident.
- After those live runs, fourteen functions were split up to meet SonarCloud's complexity limit, with no change in behavior, and
sign-constitution --outnow writes a new file and renames it into place. The tests and CI cover these changes; a live run will cover them in 0.7.0.
Next
0.7.0: a ledger export for a SIEM, a rate-limited count (kept outside the ledger) of tokens the gateway refuses without a ledger entry, and a live run that covers the 0.6.0 refactoring.
Full details: CHANGES.md, "Release v0.6.0".
release-v0.5.0
Two-Key 0.5.0: MCP proxy and caller-supplied facts
Two-Key can now sit in front of an MCP server. The agent sees only the tools you signed, and every tool call must
pass both keys (the Path A rules and the judge quorum) before it reaches the server.
New
- MCP proxy (
two-key mcp-proxy). A stdio proxy between an MCP client and one upstream MCP server. It shows
only the signed tools and pins their schemas. Everytools/callgoes through both keys and runs through the
in-process gateway with a single-use token. It starts only if it can tell which service runs each judge and the
agent, unless you allow otherwise. Install it with themcpextra. - Spec drafter (
two-key mcp-draft-specs). Draftstool_specsand the schema digest from the upstream
server, for you to review and sign. It never signs. It warns about every input Path A reads that the server
leaves undescribed, whatever the field. - Caller-supplied facts. A field declared
source: caller(for example, "this invoice matches its purchase
order") takes its value from your integration, never from the agent. It is looked up again just before the tool
runs (fact_mismatch). - Guard core (
two_key.guard.Guard). Runs one call through both keys, with the fact lookups, for any agent
loop. The proxy is built on it.
From live testing (run 6)
- Every tool must map, or mark
not_applicable, each field adeny_if_fieldsrule reads. A forgotten decision is
refused at signing and on load, and the message names every missing field and every rule that reads it. case: exactstring fields, for case-sensitive ids.@domainallow entries: any plain address at exactly one domain, with no subdomains and no wildcards. Signing
warns when the tool also carries free text.- A call that cannot be read under its spec is denied without asking the judges (
skipped:derive_failed). - A start-up warning when one judge can approve a call alone.
sign-constitutionprints a clear refusal instead of a traceback.
Upgrading from 0.4.0
- Check your constitution first. A tool that neither maps nor marks a field a rule reads no longer loads.
Add the marks, or map the fields, and re-sign; the result is constitution v3. - An
allowentry that starts with@now means a whole domain. - A v3 constitution needs 0.5.0 or later. A constitution without the new features signs exactly as before.
- Code that reads
tool_specs.<tool>.fieldsdirectly: an entry may now be the stringnot_applicable.
Install
pip install "two-key[yaml] @ git+https://github.com/Insomniac-VibeLabs/two-key.git@v0.5.0"
pip install "two-key[mcp] @ git+https://github.com/Insomniac-VibeLabs/two-key.git@v0.5.0" # MCP proxy
Testing
- 722 unit tests, with and without the
mcpextra, on Python 3.10 to 3.12. Bandit, CodeQL, Semgrep and
SonarCloud pass. - Live runs 6 and 6z with LLM agents and judges: 36 cases, 34 passed, 2 inconclusive (case design, since fixed),
0 failed.
Known limits
- Beta (pre-1.0), maintainer-reviewed, not independently audited. Not on PyPI.
- The proxy speaks stdio to one upstream server. An agent that can reach that server directly bypasses it.
- Two-Key checks where a fact came from, not whether the hook that supplies it is right.
- Give each judge a fresh context for every ballot. A judge that remembers earlier calls can carry the agent's
text from one call into another.
Details: CHANGES.md, "Release v0.5.0".