Security Architecture

AGLedger produces one object: a signed record spanning the full lifecycle of a piece of automated work - the intent and authority at the start, the delegation in the middle, the result at the end, and the verdict when the work is gated. This whitepaper is written for security teams, compliance officers, and procurement reviewers: how the record is signed, what the signature covers, where the trust boundaries fall, how the software itself is built and signed, and how a third party confirms a chain offline. Every claim below is checkable offline against the exported bytes and a pin of the vault key taken from the operator, with no AGLedger account.

One signing key per Server instance. A single instance vault key (VAULT_SIGNING_KEY, Ed25519 by default) signs every entry in that Server’s chain; during a key change the outgoing and incoming keys overlap until the old one is retired (§6). There is no per-principal and no per-agent key. The signature is the notary’s.

Attribution lives inside the signature. The accountable principal (principal_agent_id) and the acting credential are named inside the signed payload, so the signature covers the attribution. This is notary-attested, tamper-evident attribution - not principal-held non-repudiation: the principal does not sign, and we do not represent that it did.

Self-hosted by design. AGLedger runs in your infrastructure and sends nothing to AGLedger LLC. Data leaves it only where you point it: webhooks to your endpoints, federation to peers you name, optional external anchoring, and on AWS Marketplace deployments the entitlement check with AWS License Manager. Federation carries only signed bytes.

Zero content inspection. AGLedger records accountability metadata - who notarized what, who delivered, who accepted. It never inspects, stores, or processes your business data, prompts, or model outputs.

Standards-based. COSE_Sign1 (RFC 9052, tag 18) over an in-toto v1 Statement payload, deterministic CBOR (RFC 8949 §4.2.1), Ed25519 + SHA-256, CWT Claims (RFC 8392 / RFC 9597), HMAC-SHA256, RFC 9421 HTTP Message Signatures, RFC 8785 JSON canonicalization, RFC 9457 problem details. No bespoke primitives.

1. The signed record - what the signature covers

The agent reports with its key; the notary signs what it reported. The agent (or any caller) makes the API call that records a stage of the work. The Server - not the caller - assembles the entry, encodes it, and signs it with the instance vault key. The authority being recorded is the principal’s; the signature is the notary’s.

Because the attribution rides inside the signed payload, an entry cannot be re-pointed at a different principal without invalidating the signature. The protected header carries the actor identity as a CWT private claim ({ key_id, role, owner_id }); any delegation context rides in the in-toto Statement predicate as on_behalf_of. Both are covered by the Ed25519 signature. To the auditor, the claim is exact: the chain proves what was reported, signed, and recorded, and that the attribution has not been altered since.

Agents are not required to hold signing keys. The default path needs no client-side cryptography from the agent: it authenticates and reports, and the notary signs. An optional per-request attestation path (X-Agent-Signature / X-Agent-Signature-Content-Hash), a no-op by default, lets a cert-bound caller co-sign its own request; the co-signature is carried into the envelope as predicate.on_behalf_of.agent_signature and honored only when the caller authenticated with an ephemeral cert (§7).

2. Deployment model and trust boundaries

AGLedger is software you deploy, not a service you send data to. One role: Server. Every install is the same binary. A Server is a sovereign domain: its own database, auth, agents, contracts, signing key, and chain. Federation participation is a per-record / per-contract / global flag, not a deployment mode.

┌─────────────────────────────────────────────────┐ │ YOUR INFRASTRUCTURE │ │ │ │ ┌───────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Your Apps │───▶│ AGLedger │───▶│ Postgres │ │ │ │ & Agents │ │ Server │ │ DB │ │ │ └───────────┘ └────┬─────┘ └──────────┘ │ │ │ │ │ Webhooks to │ │ your systems │ │ │ └─────────────────────────────────────────────────┘ │ (only if a record's share flag is on) ▼ ┌──────────────┐ │ Counterparty│ Federation: signed bytes │ AGLedger │ cross this boundary, nothing │ Server │ else. └──────────────┘

AGLedger records accountability metadata in your infrastructure. Your data stays where it is, your traffic goes where it went, and a record reaches another organization only when its share flag is set. Topology, sizing, and the air-gapped install are on the install page.

3. Data classification and lifecycle

CategoryStorageSensitivity
Accountability metadataPostgreSQL (your DB)Business-sensitive
Audit vaultPostgreSQL (your DB)Integrity-critical
API credentialsPostgreSQL (your DB)Secret
Webhook secretsPostgreSQL (your DB)Secret

Not stored, not inspected

Model prompts, completions, or training data

Business document content - AGLedger validates structure, never value

PII beyond what customers include in record metadata (customer-controlled)

Payment card data or banking credentials

All data resides in the PostgreSQL instance you provision. No external data stores, no phone-home: AGLedger does not collect product usage information.

Retention and deletion. The customer controls retention as the database operator. The audit vault is append-only by design, which is in deliberate tension with deletion regulations (GDPR Article 17, CCPA): Signed Statements hold accountability metadata, while record criteria and completion evidence live in separate tables that can be archived or purged. In encrypted mode (§4) the server stores only the encrypted evidence envelope and an evidence hash, so destroying the encryption key renders the content irrecoverable while chain integrity is preserved - cryptographic erasure.

4. Cryptographic architecture

LayerStandardPurpose
Credential storageHMAC-SHA256API keys stored as hashes, never plaintext
Webhook signingHMAC-SHA256 · Ed25519 (RFC 9421)Delivery integrity by default; RFC 9421 signatures for non-repudiable Settlement Signal payloads, verifiable against the published Server keys
Federation transportEd25519 per-request signing; RFC 8785 (JCS)Peer authentication with per-instance keys over a domain-separated sign input addressed to the receiving Server; canonical JSON for body hashes and schema digests
Audit envelopeCOSE_Sign1 (RFC 9052, tag 18) + Ed25519Signed Statement envelope; the COSE_Sign1 bytes feed the SHA-256 hash chain
Payload formatin-toto v1 Statement, CBOR per RFC 8949 §4.2.1Deterministic encoding of the audit payload
Identity in headerCWT Claims, RFC 8392 (label 15) / RFC 9597Issuer, subject, and actor named in the signed protected header
Data at restSHA-256 hash chain / AES-256-GCMVault tamper evidence; secret storage
Client-side encryptionAES-256-GCM / AES-256-GCM-SIVServer-blind completion evidence: the server stores the encrypted envelope and an evidence hash; criteria stays server-readable

Independent keys. The vault signing key and the federation signing key are separate per-instance keys, generated independently and never derived from each other.

Algorithm identifiers everywhere. Every artifact carries its alg, so verification dispatches on the recorded algorithm instead of assuming one (§15).

Domain-separated derivation. Where keys are derived, HKDF-SHA256 with purpose-specific labels keeps them cryptographically independent.

Federation payloads are signed, not encrypted. Every federation message carries an Ed25519 signature from the sending Server; there is no application-layer encryption and no key exchange for one, so transport privacy is TLS. What crosses the boundary is limited by schema (§8).

5. Audit vault integrity and offline verification

The audit vault is the core primitive: an append-only ledger of every accountability event. Each entry surfaces to customers as a Signed Statement:

Entry N (Signed Statement): chain_position: N event_type: RECORD_STATE_CHANGE envelope: 18([ // COSE_Sign1, RFC 9052 tag 18 <<{ 1: -8, 4: <kid>, // protected: alg=EdDSA, kid, 15: { iss, sub, iat, // CWT_Claims (RFC 8392/9597), -65539: { // actor identity (signed): 1: key_id, // key id 2: role, // role 3: owner_id } } }>>,// owner / principal { ... }, // unprotected headers <<in-toto-v1-Statement>>, // payload, CBOR per RFC 8949 §4.2.1 // subject, predicateType, // predicate (incl. on_behalf_of) <Ed25519 signature> // over Sig_structure (RFC 9052 §4.4) ]) hash: SHA-256(COSE_Sign1 bytes) previous_hash: Entry[N-1].hash (genesis: null) signing_key_id: <vault key fingerprint>
TamperingMechanismDetection
InsertionHash chain breaks previous_hash linkCHAIN_LINK_BROKEN
DeletionSequential chain_position gapCHAIN_POSITION_GAP
ModificationRecomputed hash mismatchCHAIN_HASH_MISMATCH
Payload editVisible payload jsonb diverges from signed bytesCHAIN_PAYLOAD_BINDING_MISMATCH
ForgerySignature fails against the key the entry namesCHAIN_SIGNATURE_INVALID
Re-attributionRow actor fields diverge from the signed actor claimCHAIN_ACTOR_ATTRIBUTION_MISMATCH
Key substitutionEntry signed by a key no signed key statement links to the auditor’s pinCHAIN_SIGNING_KEY_UNANCHORED

Enforcement layers

Database: UPDATE and DELETE are revoked on the vault tables; partition-level TRUNCATE is blocked by trigger. A DDL event trigger (agledger_block_audit_drop) refuses an in-band DROP of the audit vault, its partitions, the admin-read tables, and the signing-key registry; creating it is the one privileged step in an install, because CREATE EVENT TRIGGER is superuser-only and the migration role needs a one-time superuser-equivalent grant (rds_superuser on Aurora). Startup and post-restore checks confirm the runtime role privileges and the trigger before the server accepts traffic. A privileged operator who edits the human-readable payload jsonb is caught at verification: the audit export reports chainIntegrityReason: 'payload_drift' and the offline verifier reports the same finding as CHAIN_PAYLOAD_BINDING_MISMATCH. The signed envelope, not the visible copy, is the source of truth.

Application: vault writes occur inside the same transaction as the state change - the entry exists if and only if the state change committed.

Cryptographic: the hash chain and signatures provide tamper evidence independent of database access controls.

Operational: signed checkpoints on a configurable cadence (6 hours by default). Optional external anchoring to S3-compatible storage with COMPLIANCE-mode object lock.

Offline verification

Verification means one thing in this document: checking the cryptography. Three properties are independently checkable: the signatures are genuine under keys that signed key statements link to a key you pinned, the hash chain recomputes end to end (a break is located at the exact position it occurs), and the visible payload has not drifted from the signed bytes. A pass does not prove the claim inside a record was true or the work behind it good - the principal renders that verdict at the Gate, and verification confirms the verdict is authentic and untampered like every other entry.

GET /v1/records/{id}/audit-export exports a record’s chain as a self-contained signed bundle for verification on a machine that never talks to AGLedger. The export carries the signing keys and the signed key statements that admit them: a genesis for the install’s first key, a succession signed by the old and new key at each rotation, a closure at each retirement. The one external input is a pin, the SHA-256 of a vault key’s SPKI (sha256:<hex>), which the installer prints and the operator hands the auditor out of band. The same keys are served unauthenticated at GET /v1/verification-keys and GET /.well-known/agledger-vault-keys.json: anchored keys only, retired ones included with their signed windows, each with its statements, plus anchoredFrom, the serving process’s own pin, to compare against yours. A key document is only as trustworthy as whatever served it, which is why the pin and not the document decides trust. The standalone verifier, the CLI, the SDKs, and the MCP server all check the same exported bytes; step-by-step commands are in the offline verification guide.

The verifier is deliberately small, so that trusting it is not the same as trusting the Server: @agledger/verify-core has a single runtime dependency, a CBOR codec. A pin goes in as --trust-anchor sha256:<hex>, and the verifier walks the key statements from it, so a chain re-signed wholesale under a key written into the database, or shipped inside the export, fails with CHAIN_SIGNING_KEY_UNANCHORED. Each run reports a verdict: trusted (clean, every signing key anchored to the pin), unanchored (clean, no pin given), or failed. A run without a pin passes flagged as not anchored and never as trusted. Where a key came from is not whether it is trusted: --keys supplies keys from elsewhere and --require-supplied-keys refuses the export’s own, but keys fetched from the Server come from the same database an attacker would write to, and only the pin anchors them. Exit codes separate verified (0, with the verdict saying whether it was anchored), verification failed (1), and could-not-verify (2, malformed or missing input including a mistyped pin), so an inconclusive run never reads as a pass.

No AGLedger code is required on the verification path. Every entry is a standard COSE_Sign1 envelope, so a stock COSE library can confirm a chain on its own; our verifier is a convenience, not a dependency. The chain also exports as DSSE envelopes wrapped in Sigstore Bundle format (v0.3, BYO-key), verifiable with cosign in private-infrastructure mode. Where the Transparency Service is enabled, an export can include SCITT Receipts - RFC 9162 Merkle inclusion proofs in COSE, opt-in via ?receipts=true - proving an entry was admitted to the transparency log at a known position, independent of the chain itself.

Because verification needs nothing but the bytes and the published keys, an auditor, a counterparty, a regulator, or a court can confirm a chain years later - with the Server shut down, the license lapsed, or the vendor gone. The proof outlives the vendor.

6. Key management and rotation

The vault signing key is held outside the database, and the chain’s trust starts there. It is supplied as VAULT_SIGNING_KEY - required in production and customer-held: AGLedger LLC never possesses it. The customer protects the private key with their own secrets manager (§13). The install script generates the keypair locally, on your machine, and prints its pin. At boot the key is read from an environment variable or a file, or fetched from AWS SSM Parameter Store (SecureString) or HashiCorp Vault KV v2; it can instead stay in AWS KMS (VAULT_SIGNING_KEY_KMS_ARN), where the private half never leaves KMS.

The key registry holds public keys only, and is append-only in the same way the chain is. DELETE and TRUNCATE are refused by trigger, and the single UPDATE the trigger permits is the active-to-retired transition: key material, algorithm, and activation instant are immutable once written. A registry row alone is trusted for nothing. A key counts only when a signed key statement (genesis, succession, or closure, kept in an append-only table of its own) links it to a key a process holds outside the database, so a key row written with database access alone is absent from the published keys and every entry it signs breaks as unanchored. Retired keys stay published with the activation and retirement instants their statements sign, and the offline verifier checks each entry’s write time against the validity window of the key that signed it.

Zero-downtime rotation

Rotation needs no downtime and no re-signing, and it is two separate steps. Staging is a restart: a process started on the new VAULT_SIGNING_KEY with VAULT_SIGNING_KEY_PREVIOUS set to the key in use registers the new key and writes a succession statement signed by both keys, which is what carries an auditor’s pin forward. A process on a new key that nothing links to the registry’s history registers nothing and signs nothing. Staging retires nothing, so both keys are active while processes roll, and each keeps signing inside its own published window.

Retirement is an explicit call, POST /v1/admin/vault/signing-keys/{keyId}/retire, sent to a process holding a different anchored key. It writes a closure statement over the retirement instant; after it, an entry under the retired key is a chain break, and entries written before it stay valid. POST /v1/admin/vault/signing-keys/rotate performs the staging on demand and answers already_active once the restart has done it.

The procedure is in the day-2 operations runbook, and the compromise order in the signing-key compromise runbook.

Key loss does not invalidate history. Verification uses the public keys and the key statements that sign them, not the private key in the environment. Losing the private key stops new signing; it does not retroactively break the existing chain. A replacement that nothing links to that history registers only when the operator pins the history it vouches for in VAULT_TRUST_ANCHORS; it starts under a fresh genesis, and auditors take its pin. The registry supports unlimited rotations and records an algorithm per key, so a chain spanning two algorithms verifies entry by entry against the key that signed it (§15).

7. Authentication and access control

Two authentication paths, same protocol on the wire. Enterprise installs lead with OIDC-bound ephemeral signing certificates: agents exchange a JWT from the customer’s own identity provider (Auth0, Okta, Azure AD, Keycloak, GCP WIF, K8s service-account tokens) for a short-lived AGLedger cert via POST /v1/auth/oidc/cert - 10 minutes by default, configurable per issuer up to one hour - and present it as the Bearer credential. No agent holds a long-lived key; blast radius on credential compromise is minutes.

Long-lived API keys remain fully supported for development, the quickstart, and single-operator installs. Keys are never stored in plaintext - the server computes HMAC-SHA256 and looks up the hash. Both credential types produce the same chain envelope, and the actor identity each carries is named inside the signed payload (§1). Only asymmetric algorithms are accepted: HS* and none are excluded, with per-issuer overrides available on the trusted issuer. The HMAC secret behind key storage rotates without downtime through a previous-secret window. The provenance of an OIDC validation (the key thumbprint and the instant it was validated) is recorded into the signed chain alongside the record it authorized. Trust anchors are configured per-org via POST /v1/admin/trusted-issuers - one row per IdP per purpose with an applies_to discriminator (agent / principal / admin / any); JWKS endpoints are auto-discovered via OIDC well-known. See the Authentication guide.

RoleCapabilitiesTypical user
PlatformSystem administration, enterprise provisioning, vault management (cross-org by design)AGLedger operator
AdminConfiguration, oversight, compliance exports, key managementOrg administrator
AgentRecord lifecycle operations scoped to authorized actionsAI agent, RPA bot, service

Each API key carries a scope list, and anti-escalation prevents creating keys with broader scopes than the creating key. Roles are enforced by middleware with scope checks layered on top, so a scope cannot stand in for a role. Agent and admin access is org-scoped - the platform role is the one deliberate cross-org identity, held by the operator. Additional controls: per-key IP allowlisting, key expiration, and the optional per-request agent signature (§1).

Admin actions are themselves evidence. Privileged operations - key creation and revocation, configuration changes, queue interventions - are written to the chain as signed entries, so the audit trail covers its own administration.

8. Federation and privacy boundary

Across organizations, federation is peer-to-peer signed-message transport over TLS. Each Server signs every request with its own per-instance Ed25519 key over a domain-separated sign input addressed to the receiving Server (its instance id, then method, path, RFC 8785-canonical body hash, timestamp, nonce), so a message signed for one peer does not verify at another; there is no shared key and no central coordinator.

Crosses the boundary

Server identity + public keys

Agent IDs

Record ID, contract type

State transitions (state, timestamp, signature)

Gate verdict (accept/reject)

Settlement Signal payload (SETTLE/HOLD/RELEASE)

Never crosses

Record criteria (actual acceptance terms)

Completion evidence (work product)

Audit vault entries

Prompts, context, or business logic

API keys or auth credentials

Webhook URLs or delivery payloads

Each Server remains sovereign: it records the signed bytes a peer sent, verifies them against the peer’s published key, and never holds the peer’s underlying business data. Transport mechanics live on the Federation page.

9. Application security

Schema-first validation. Every endpoint declares request and response JSON Schemas enforced by the framework. Unknown fields rejected, no implicit type coercion. 1 MiB global request limit, 65 KiB record limit, 20-level JSON depth cap.

SQL injection prevention. All queries use parameterized SQL. Sort and filter columns are validated against explicit whitelists.

Webhook SSRF protection. Layered validation: private IP ranges, loopback, cloud metadata endpoints, alternative IP encodings, DNS re-resolution at connect time (TOCTOU), internal hostname suffixes, embedded credentials, HTTPS-only.

Customer-supplied patterns are budgeted. Gate-rule regexes and JSON Schema patterns run under a hard 250 ms wall-clock budget in an isolated node:vm context. Pattern and subject are passed as context values and never interpolated into source, and a budget overrun is its own outcome, never folded into a non-match.

Encrypted evidence binds to its record. The server validates envelope shape and never decrypts. Envelopes bind to their record id, so replaying a valid envelope against a different record is rejected.

Expression engine sandboxing. jsep AST parser (not eval). 50 AST nodes, depth 10, 1,000 operations max. No access to global scope, prototype chain, or Node.js APIs.

Rate limiting. Every authenticated key shares one per-key budget of 1,000 requests/min by default; platform keys, as root credentials, are effectively exempt (a 100,000/min ceiling applies). Unauthenticated traffic is IP-keyed with its own budget, and hot write routes carry tighter caps beneath the per-key budget (POST /v1/records is 200/min). State is in-memory per instance by default, with a PostgreSQL store option for multi-replica consistency. Errors return as RFC 9457 problem details.

10. Infrastructure hardening

Container

Red Hat UBI 10 minimal base (RPM-managed Node and OpenSSL, updated every build)

Node permission model grants filesystem read and nothing else (§11)

Non-root user (UID 65532)

Read-only filesystem + tmpfs for /tmp

512 MiB memory, 1.0 CPU limits

Liveness + readiness health probes

File-based secrets injection

Database

Separated identities: a least-privilege runtime role, a read-only monitor role, and a distinct owner connection used only for migrations

TLS required in production (sslmode=verify-full recommended)

Advisory-locked, checksummed migrations

Zero PostgreSQL extensions required, so managed Postgres needs no extension-allowlist negotiation (validated on Aurora and stock PostgreSQL)

Direct connections: transaction-mode poolers (PgBouncer, RDS Proxy) are incompatible, because the job queue uses LISTEN/NOTIFY

AWS RDS CA bundle shipped in the image

Node.js 24 LTS, pinned dependencies

11. Supply chain and release integrity

Every release is built and signed in CI; nothing is published by hand. Each artifact traces back to the commit and the workflow that produced it, checkable with stock tooling and no AGLedger account.

ArtifactWhat ships with it
Container imageSLSA Build Level 3 provenance, keyless cosign signature, CycloneDX SBOM, OpenVEX, and a ClamAV malware-scan attestation with a staleness positive-control
Helm chartKeyless cosign signature
npm packagesPublish provenance via Trusted Publishing, stated as L2-equivalent: OIDC-bound and non-forgeable, without the isolated-builder guarantee that earns L3. SDK, CLI, MCP server, and the verifiers
Python SDKPyPI Trusted Publishing with PEP 740 signed attestations
GitHub releaseSBOM, VEX, and the signed conformance corpus

Signing is keyless. GitHub OIDC to Fulcio to the public Rekor transparency log, so the signing identity is the workflow that built the artifact rather than a key a person holds. Image provenance is generated by the isolated slsa-github-generator reusable workflow, which signs in a build the release job itself cannot reach.

Publication is gated. VEX-aware Trivy scanning at CRITICAL and HIGH on both architectures, boot gates on both architectures, and a FIPS-mode boot gate all pass before an image publishes.

CI actions are SHA-pinned, with one deliberate exception: the SLSA builder workflow is tag-pinned, because its verifier resolves the trusted builder by tag.

Verification is yours to run. The deployment repository’s SECURITY.md carries the exact commands per artifact: cosign for image and chart signatures, the attestation checks worth asserting, and slsa-verifier for provenance. The installers verify signatures when cosign is present; set AGLEDGER_REQUIRE_VERIFY=true and a run that cannot verify refuses to install. Marketplace and ECR mirrors are checked by digest equality against the authoritative image.

Runtime image. Red Hat UBI 10 minimal with Node 24, built from a digest-pinned build stage and running as a non-root user. Node’s permission model grants the application filesystem read and nothing else: writes, child processes, native addons, the inspector, WASI, and worker threads are all denied. Dependency updates run continuously (Dependabot) and Semgrep SAST runs before each release.

12. Threat model

ThreatControls
Audit trail tamperingHash chain + signatures + DB enforcement (UPDATE/DELETE revoked, TRUNCATE blocked) + external checkpoints; payload edits surface as payload_drift
Attribution forgeryPrincipal and acting credential are inside the signed payload; re-pointing an entry invalidates the signature
Cross-tenant accessOrg-scoped agent and admin access; scoped API keys; principal enforcement
API key compromiseHMAC-hashed storage; IP allowlisting; expiration; scopes limit blast radius; ephemeral certs cap exposure at minutes
Webhook SSRFLayered validation including DNS re-resolution; HTTPS-only
Federation MITMTLS + per-request Ed25519 signing with per-instance keys
Signing key compromiseForced retirement stops chain appends under the key the instant it commits and revokes the certificates it minted; VAULT_DISTRUSTED_KEYS makes what it signs from the leak count for nothing; external anchors bound what it signed before
Rogue signing key (database write access)A key is trusted only through signed key statements linking it to a key held outside the database; an auditor’s pin decides trust offline
Denial of serviceTiered rate limiting; size caps; depth limits; handler timeouts

Explicitly out of scope

Compromised principals. If the entity creating records is malicious, AGLedger faithfully records what they reported. We attest accountability, not truthfulness - the chain proves what was said and signed, not that it was correct.

Content-level threats. AGLedger validates structure, not business content; zero content inspection is the boundary the product is designed around.

Infrastructure compromise. OS, network, and physical security are the customer’s responsibility.

13. Privacy, data protection, and shared responsibility

AGLedger is self-hosted software: in the typical deployment, AGLedger LLC is neither a data processor nor a data controller. Residency follows the customer’s database placement, license validation is an offline Ed25519 check, and no AGLedger LLC system sits in the data path. Zero sub-processors for Customer Personal Data in the standard deployment; no international transfers when sharing is off; encrypted mode enables cryptographic erasure (§3).

AGLedger provides

Application security (validation, SSRF, SQLi prevention)

Cryptographic integrity (hash chain, signatures, agility)

Access control (RBAC, scoping, rate limiting)

Secret handling (HMAC, AES-256-GCM, log redaction)

Container hardening (non-root, read-only filesystem)

Database role separation

Customer provides

Infrastructure security (network, OS, physical)

Database encryption at rest

TLS certificate management

Vault signing key protection (secrets manager)

Backup and disaster recovery

Monitoring, alerting, and SIEM integration

14. Compliance mapping

AGLedger captures signed records, delegation chains, and cross-org evidence transport regardless of regulation; downstream, these map to the obligations below. Detailed crosswalks live on the dedicated pages.

EU AI Act: Article 12 - automatic event logging. Article 14 is a boundary, not a mapping: AGLedger records that a halt was requested, and the interrupt itself lives in the systems that run the agent.

NIST AI RMF: GOVERN, MAP, MEASURE, MANAGE

ISO 42001: Capability crosswalk

ISO 27001:2022: Annex A theme A.5 organizational (supplier and ICT supply-chain controls, evidence collection, protection of records) and theme A.8 technological (access control, cryptography, logging, secure development). Themes A.6 people and A.7 physical sit with whoever operates the deployment.

NIST 800-53: AC, AU, IA, SC, SI families

Cyber Resilience Act: Readiness assessment, maintained alongside the coordinated vulnerability disclosure policy (§17)

The EU AI Act mapping reaches into the engine: it ships the Act’s risk-tier taxonomy (Article 5, Annex III, Article 50) as first-class record vocabulary, so the tier a system claims is recorded inside the signed payload rather than tracked beside it.

SOC 2: not a certification - AGLedger is self-hosted software, not a service organization, so your deployment runs under your existing certifications.

15. Algorithm agility and post-quantum readiness

All algorithms are current NIST-approved. NIST finalized post-quantum standards in August 2024 (ML-KEM / FIPS 203, ML-DSA / FIPS 204, SLH-DSA / FIPS 205).

Per-key algorithm registry. The signing-key registry derives the algorithm from the key material at registration, and verification dispatches on it rather than assuming one. Ed25519 is the default; ECDSA P-256 (ES256) is the second shipped algorithm, enabled by explicit opt-in for hosts whose crypto provider excludes EdDSA (see FIPS 140 hosts). Adding a third is a registry entry and a verifier release, not a format change.

No re-signing required. New entries use the new algorithm; old entries remain valid against the retired key that signed them. A chain spanning two algorithms is continuous.

Hybrid (classical + PQC) signatures are expected industry-wide in 2027–2028; the registry design means adopting them requires no customer action today.

16. Continuity and releases

As self-hosted software, RPO and RTO depend on the customer’s infrastructure and backup strategy. AGLedger provides the tooling: backup.sh, restore.sh, support-bundle.sh, and health probes for orchestrator-level recovery. The chain is self-verifying: after restoring from any backup, run the vault integrity check to confirm continuity.

Failover behavior. On a PostgreSQL failover the queue listeners reconnect with backoff and export a failure counter as a metric; while disconnected, caches degrade to TTL expiry rather than going stale silently. In-flight queue work is recovered by per-queue active-job timeouts, after which the job is re-fired, and the migration runner retries the error classes a failover produces.

Platform. PostgreSQL 17 or later, with 18 recommended and validated including Aurora 18. The bundled postgres:18-alpine container is production-capable: running production on it is licensed under Developer Edition and supported by the software, with every feature available. Connecting to an external or managed database instead, such as Aurora, RDS, or Cloud SQL, is what triggers an Enterprise license.

Upgrades. Releases use semantic versioning and ship at most one migration each. Shipped migrations are immutable and checksum-verified, and the runner refuses to start if one has been altered. The upgrade script takes a backup first and writes a rollback marker; rollback is a documented restore. Within a major version the schema is safe in both directions across the upgrade window. A new major is not: 2.0 does not upgrade a 1.x database. The migration and the upgrade script refuse one before changing anything, as does a 2.0 Helm chart over a release a 1.x chart installed on the bundled PostgreSQL, so 2.0 installs against a new, empty database and the 1.x database stays with the 1.x install that wrote it. Release signing and provenance are covered in §11.

Security fixes ship as new versions with CVE-referenced advisories.

17. Incident response and coordinated vulnerability disclosure

Detected tampering

If vault integrity verification detects tampering, the failure is logged with full context (chain position, expected vs. actual hash, signing key ID). Failed entries are flagged but never modified - the evidence of tampering is itself part of the audit record.

AGLedger Coordinated Vulnerability Disclosure Policy

Version: 1.6 Effective Date: June 4, 2026 Last Updated: September 15, 2026 Contact: security@agledger.ai

This is the canonical coordinated vulnerability disclosure ("CVD") policy for the AGLedger software product (the self-hosted Licensed Software, SDKs, CLI, MCP server, container images, Helm charts, and release artifacts). It is the policy referenced by the SECURITY.md and security.txt files distributed with the software and published at agledger.ai/security, and by Software License Agreement § 6.6.

AGLedger's public online resources (the website, the documentation, and the registries from which the software is distributed) are governed by the Acceptable Use Policy, which sets out in § 6 how to report a vulnerability in those resources and provides that good-faith research conducted in compliance with that section does not breach the AUP. The safe harbor, good-faith conditions, disclosure timeline, and recognition terms in this policy apply to research on the software product.

1. Scope

In scope:

Out of scope:

2. How to report

Email security@agledger.ai, or report privately through GitHub private vulnerability reporting on any public agledger-ai repository. If your report contains sensitive detail, say so in your first email without including the detail, and we will agree an encrypted channel with you before you send it. We do not currently publish a PGP key.

Please include:

  1. The affected component and version (and image digest, if applicable).
  2. A description of the vulnerability and its impact.
  3. Reproduction steps or proof-of-concept (minimal; see §3).
  4. Any suggested remediation.
  5. Whether you intend to disclose publicly, and on what timeline.

We aim to acknowledge receipt promptly and to provide an initial assessment as soon as practicable.

3. Safe harbor for good-faith research

If you make a good-faith effort to comply with this policy during your research, AGLedger will:

Good-faith research means you:

(a) report promptly and do not exploit the vulnerability beyond the minimum proof-of-concept necessary to demonstrate it; (b) do not access, modify, exfiltrate, or destroy data that is not your own, beyond minimal proof-of-concept evidence; (c) do not degrade, disrupt, or impair the availability of any system or any other party's deployment; (d) test only against your own deployment or systems you are authorized to test, and never against another customer's deployment; (e) give us a reasonable opportunity to remediate before any public disclosure (see §5); and (f) comply with all applicable law.

This safe harbor is a statement of how AGLedger will treat good-faith research; it does not authorize action against third parties and does not waive any third party's rights.

4. Our handling process

  1. Triage: confirm, reproduce, and assign a severity (CVSS-aligned).
  2. Remediate: develop and test a Security Fix. Remediation targets for licensed customers are in the Support Terms; they are targets, not guarantees, and are made to customers, not to reporters.
  3. Distribute: release the fix as signed artifacts through the public distribution channels, without authentication or entitlement checks. The contractual commitment to provide Security Fixes is made to Enterprise Edition Licensees under License Agreement §§ 6.2 and 6.4.
  4. Notify: inform affected customers and, where the law requires (including the EU Cyber Resilience Act reporting cadence for actively exploited vulnerabilities and severe incidents), notify the competent authorities (the CSIRT-coordinator and ENISA) within the required 24-hour / 72-hour / 14-day windows.
  5. Disclose: publish a security advisory and credit the reporter (with permission).

5. Coordinated disclosure timeline

We follow a 90-day coordinated disclosure window by default: we aim to release a fix and advisory within 90 days of a validated report, and we ask that you not disclose publicly before the earlier of (a) a fix being available or (b) 90 days, whichever comes first. For vulnerabilities under active exploitation, we will move faster and coordinate an accelerated timeline with you. We are happy to coordinate CVE assignment and joint disclosure.

6. Recognition

With your permission, we will acknowledge your contribution in the security advisory. AGLedger does not currently operate a paid bug-bounty program; this is a coordinated-disclosure (not a bounty) policy.

7. Changes

We may update this policy by posting a revised version with an updated effective date at agledger.ai/security. Material changes will be noted in the change log below.

DateVersionChange
2026-06-041.0Initial coordinated vulnerability disclosure policy for the software product. Supports EU Cyber Resilience Act Annex I Part II (CVD) and Article 14 reporting; referenced by License Agreement § 6.6.
2026-06-091.1Softened the §2 fixed "2 business days / 5 business days" researcher response clocks → "promptly / as soon as practicable" (fixed response times to anonymous external researchers are not guaranteed; a missed clock would be a published broken promise). Safe harbor, scope, and the legally-required CRA Art. 14 authority-reporting windows (24h/72h/14d) unchanged.
2026-09-101.2Removed the pointer to a PGP key at agledger.ai/security: no key is published anywhere, and security.txt carries no Encryption: field (agledger-legal#25). Reporters now flag sensitive detail in their first email and an encrypted channel is agreed before it is sent, matching SECURITY.md in the code repository. Added the @agledger/verify and @agledger/verify-core packages to §1 scope.
2026-09-151.6Facts whose home is elsewhere removed: the package list (the packages are named where they are published), the remediation numbers and the N and N-1 window (Support Terms), a threat-model explanation with an internal field name, a GitHub button label, and a restatement of License Agreement §§ 6.2 and 6.4 beside their citation.
2026-09-151.5Section 6 no longer promises a security acknowledgments page; none exists, and credit is given in the advisory.
2026-09-151.4Section 4 step 3 no longer states that a fix is available to every user at no charge. Nothing requires that statement to be published, and in a public policy it reads as a representation to everyone, including users outside the EU and outside any support period, where the underlying duty binds only as a manufacturer obligation. The operational fact remains: releases are public, unauthenticated and not entitlement-gated.
2026-09-151.3§4 step 3 corrected: Security Fixes are released publicly as signed artifacts at no charge to anyone, and the contractual commitment is to Enterprise Edition Licensees under License Agreement § 6.2 (the step previously said all perpetual licensees, which § 6.2 does not say). The introductory note no longer says the AUP covers public APIs or that the two documents share safe-harbor terms: the AUP governs the online resources and this policy's safe harbor applies to the software product. §2 adds GitHub private vulnerability reporting on the public repositories as a reporting channel. §4 step 2 calls the Support Terms remediation times targets. Em dashes rewritten.

Related

AGLedger is a product of AGLedger LLC. This document describes the security architecture of AGLedger software. It is not a guarantee of security and should be evaluated alongside your organization’s specific risk assessment. Contact: security@agledger.ai