Skip to main content

Tamper-evident append-only audit ledger with SHA-256 hash chain, optional Ed25519 signing, and optional Bitcoin anchoring via OpenTimestamps

Project description

Nexuscone

Tamper-evident append-only audit ledger with a SHA-256 hash chain and optional Ed25519 signing, designed for AI systems, agent platforms, and regulated software where every action needs to be provably unmodified after the fact.

PyPI Python Downloads CI License Typed

What this is

Nexuscone is a small, dependency-light Python library that writes every audit event to a SQLite database in an append-only, hash-chained, optionally Ed25519-signed format, so any later edit to a stored row, including via raw SQL, breaks verification. The chain anchors at a genesis row whose previous_hash is sixty-four zeros, every subsequent row's previous_hash equals the prior row's entry_hash, and entry_hash is the SHA-256 of the canonical JSON of the row's identifying fields. Walking the chain end-to-end recomputes every hash from scratch, so tamper detection is mechanical rather than trust-based.

From v0.2.0, the chain head can be anchored periodically to Bitcoin's blockchain through OpenTimestamps, and in parallel to a regulator-friendly RFC 3161 Time-Stamp Authority, so the integrity proof no longer rests on trusting Aperintel or any single party but on Bitcoin's proof-of-work and a signed TSA token. A small set of optional witnesses can also sign the chain head between Bitcoin confirmations to close the confirmation gap.

This is the package extracted from the audit ledger that ships inside Metacarpal (a personal autonomous-agent operating system with twenty-one specialist agents and 150 passing tests) and the Aperintel AI Gateway (a multi-model AI router with a cryptographic audit chain on every request). It is the same chain logic, generalised into a standalone library so anyone building governance-first AI infrastructure can drop it into their stack without rebuilding the cryptographic primitives.

Install

pip install nexuscone

For the optional Ed25519 signing layer:

pip install "nexuscone[signing]"

Quick start

import asyncio
from nexuscone import Ledger


async def main() -> None:
    async with Ledger("data/audit.db") as ledger:
        await ledger.log(
            actor="user_service",
            action="user_login",
            payload={"user_id": "u-001", "ip": "203.0.113.7"},
        )
        await ledger.log(
            actor="payment_service",
            action="charge",
            payload={"user_id": "u-001", "amount_pence": 1299},
        )
        count = await ledger.verify_chain()
        print(f"chain valid, {count} entries")


asyncio.run(main())

With Ed25519 signing

import asyncio
import secrets

from nexuscone import Ledger
from nexuscone.signing import Ed25519Signer, Ed25519Verifier


async def main() -> None:
    signer = Ed25519Signer.from_seed("aks_2026q2_main", secrets.token_hex(32))
    verifier = Ed25519Verifier({signer.key_id: signer.public_key_hex})

    async with Ledger("data/audit.db") as ledger:
        await ledger.log(
            actor="judge",
            action="approve",
            payload={"request_id": "r-123", "verdict": "allow"},
            signer=signer,
        )
        count = await ledger.verify_chain(verifier=verifier)
        print(f"chain valid with signatures, {count} entries")


asyncio.run(main())

With Bitcoin-anchored timestamps

import asyncio

from nexuscone import Ledger
from nexuscone.anchor_schedule import AnchorSchedule


async def main() -> None:
    schedule = AnchorSchedule(
        every_n_entries=1000,
        every_m_minutes=60,
        enabled=True,
    )

    async with Ledger("data/audit.db", anchor_schedule=schedule) as ledger:
        await ledger.log(actor="api", action="request", payload={"id": "r-001"})
        await ledger.log(actor="api", action="request", payload={"id": "r-002"})

        anchor = await ledger.anchor()
        if anchor is not None:
            print(f"anchored {anchor.chain_head_hash[:16]} at {anchor.submitted_at}")


asyncio.run(main())

Anchoring runs two proof tracks in parallel for every submission. OpenTimestamps submits the chain head to free public calendar servers which roll it into the next Bitcoin block, giving a trust-minimised proof that confirms in roughly an hour. An RFC 3161 Time-Stamp Authority signs the same head immediately, giving a regulator-friendly token that is verifiable the moment it arrives. Either track can fail without blocking the other.

Once Bitcoin mines the relevant block, a background task asks each calendar to upgrade the OpenTimestamps proof in place and writes the upgraded blob plus the confirmed block height back to the anchor row:

from nexuscone.poller import upgrade_pending_anchors

counters = await upgrade_pending_anchors(ledger)
print(f"{counters['upgraded']} of {counters['attempted']} anchors confirmed")

Standalone verification

The package ships a CLI verifier you can run against any Nexuscone database file:

nexuscone-verify data/audit.db

This walks the chain end-to-end, recomputes every hash, and exits 0 on a clean chain or 1 with the failing row on tamper. Equivalent to python -m nexuscone.verifier data/audit.db.

From v0.2.0 the same CLI exposes the anchor and TimeStampToken verification surfaces:

nexuscone-verify data/audit.db --check-anchors      # verify OpenTimestamps proofs against the stored heights
nexuscone-verify data/audit.db --check-tst          # verify RFC 3161 tokens against their chain heads
nexuscone-verify data/audit.db --upgrade-pending    # ask calendars to upgrade incomplete proofs
nexuscone-verify data/audit.db --print-anchor 1     # pretty-print one anchor row

Trust model

Nexuscone gives you three levels of integrity guarantee that stack on top of each other.

The first is chain integrity. Walking the chain recomputes every hash, so any post-write edit to any field on any row produces a hash mismatch on the next verification pass. This level requires only the SQLite database and is always on.

The second is Ed25519 signatures. Every signed row carries a signature that proves the row could not have been produced by anyone without the matching private signing key. This level requires the database and the public key, and is opt-in by passing a signer to log().

The third is anchored timestamps, available from v0.2.0. Every anchor row binds a specific chain head either to a Bitcoin block through OpenTimestamps (around an hour to confirm, no wallet or node required), or to a regulator-friendly RFC 3161 token signed immediately by a Time-Stamp Authority, or to both in parallel. This level requires the database, the stored proof blobs, and access to either Bitcoin block headers or the TSA's certificate depending on which proof is being verified. It is opt-in by passing an enabled AnchorSchedule to the Ledger.

Choose the level that matches your regulatory or operational setting. The lower levels are always available; the higher levels add stronger guarantees at the cost of a few more dependencies on external infrastructure.

Design

The chain is anchored at a genesis row whose previous_hash is sixty-four zero characters. Each subsequent row's previous_hash equals the previous row's entry_hash. Each row's entry_hash is the SHA-256 hex digest of the canonical JSON serialisation of the row's identifying fields. From v0.2.0 the hash inputs are entry_id, timestamp, actor, action, event_type, payload, and previous_hash, while v0.1.0 chains continue to verify under their original six-field formula because the verifier dispatches by format_version. Any post-write edit to any of those fields produces a hash mismatch on the next verification pass.

Writes are serialised under an asyncio lock so the tip of the chain (the max entry_id and its entry_hash) is always observed consistently by the next writer, which is the property that makes concurrent writes safe under contention.

When a signer is provided to log, the entry_hash is also signed with Ed25519 and the signature plus signing_key_id are stored on the row. Verification with a matching Verifier checks every signed row's signature against the recorded key id, and rows without signatures are skipped on the signature path while still being hash-verified.

The package is intentionally small, with no orchestration, no agent system, no AI specifics, no opinions about what fields go in payload, and no opinions about deployment. It is a primitive you compose into a larger governance stack.

When to use this

This library fits applications where you need to prove after the fact that a stored event has not been modified since it was written. Concrete cases are AI agent action logs (so an evaluator can verify the agent did exactly what the chain records), regulated software audit trails (so a compliance team can verify the audit file is the same one written at the time of the action), and append-only operational ledgers (so an oncall engineer can verify the log has not been retroactively edited during an incident).

If you do not need tamper-evidence and a regular log file is fine for your case, you do not need this. If you need a full enterprise governance platform with dashboards, alerting, regional hosting, and customer onboarding, Nexuscone is the primitive you build that platform on top of rather than the platform itself.

Production usage

Nexuscone is the extracted core of the audit chain that runs inside Metacarpal (the personal autonomous-agent operating system this library was extracted from) and the Aperintel AI Gateway (the Aperintel multi-model router). The Aperintel governance product Nexus, which is being built on top of the same primitive, treats Nexuscone as its open-core dependency and adds the dashboards, the BYOK onboarding, the per-customer regional hosting, the FCA and HIPAA evidence packs, and the commercial subscription on top.

Local development

git clone https://github.com/nexuscone/nexuscone.git
cd nexuscone
pip install -e ".[dev]"
pytest tests/ -v

Lint and type checks:

ruff check src tests
mypy src

CI runs pytest on Python 3.10, 3.11, 3.12, and 3.13 against every push to main and every pull request.

License

Apache 2.0. See LICENSE.

About

Built by Julius (Osi) Abu, founder of Aperintel, as the open-core audit primitive underneath the Aperintel governance product family. Aperintel is a self-employed AI studio building governance-first AI infrastructure. Portfolio at osiabu.vercel.app, LinkedIn at linkedin.com/in/osiabu.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nexuscone-0.2.0.tar.gz (54.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nexuscone-0.2.0-py3-none-any.whl (38.5 kB view details)

Uploaded Python 3

File details

Details for the file nexuscone-0.2.0.tar.gz.

File metadata

  • Download URL: nexuscone-0.2.0.tar.gz
  • Upload date:
  • Size: 54.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for nexuscone-0.2.0.tar.gz
Algorithm Hash digest
SHA256 e036f7ffa8d5cb62819041fe726c8f25329a3bf7b8dfba6648440b71589ca8f7
MD5 68b6374d94c007c3d3928ab1bff6da0e
BLAKE2b-256 9e64b7eb6ca00ec00e598d986cac84667f813a7e251ac54625fc3007a2987d8d

See more details on using hashes here.

File details

Details for the file nexuscone-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: nexuscone-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 38.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for nexuscone-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 da2e4006880c9f3300950e1d0abbb22ed57186d30821c5b692536596f0863932
MD5 109e426808eaad12074f146f8493c773
BLAKE2b-256 d9687d53ac4d1e71a56fffe68837203eda825cca2597c4a041444f4da40cdeb7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page