@open-matrix/system-audit (1.1.32)
Installation
@open-matrix:registry=npm install @open-matrix/system-audit@1.1.32"@open-matrix/system-audit": "1.1.32"About this package
system.audit
PostgreSQL append-only event ledger with source idempotency and a hash chain per home.
The existing audit.append stores who (actorPrincipalId), what (eventType), target
(subjectRef/objectRef), when (occurredAt) and producer-owned result data (eventJson).
Configure the shared system-postgres pool before starting storage operations.
audit.query requires a home busToken. A platform operator may set allHomes: true
with that same authenticated browser token; system.audit verifies it through
system-auth before widening the query. Direct service callers may instead supply a
platform operator sessionToken.
Auth resolves a bus caller's home; an optional authorityRoot must belong to that caller
(including authorized membership). Caller-supplied principal IDs cannot select identity.
A session token must pass auth.platform.operator.check; operators query all homes by
omitting authorityRoot, or select one home explicitly. A hosted caller passes
allHomes: true with its verified operator session to query all homes despite
the facade's stamped home. Bus-only callers are refused this option.
Filters: actor (actorPrincipalId alias), kind (eventType alias), outcome
(eventJson.result, normally success or refused), sourceAuthority,
subjectRef, objectRef, correlationId, and ISO from (inclusive) / to (exclusive)
occurrence timestamps. Results are newest sequence first, with limit default 50 and
maximum 100. Response: {ok,events,count,cursor}. Pass the returned cursor with the same
home and filters; page size may change. beforeSeq remains supported, but cannot be
combined with a cursor. Authentication is checked again on every page.
audit.renderer.decision.append is the single hosted write operation. It requires the caller's
verified bus token from the same home, accepts only the bounded renderer-policy
schema, and derives actor and home from immutable operation context. Duplicate idempotency keys
return the existing event, so one decision occupies one hash-chain row. Generic audit.append
remains internal and is not exposed through a home facade.
audit.list uses the same authenticated query path. audit.get {eventId} applies the
same home/operator admission, returning the same not-found error for missing and foreign
records. audit.append, audit.verify and audit.status retain their existing internal
service behavior. Home facades expose query/get/list and the narrow renderer decision append.
Run pnpm test for SQL-backed actor-dispatch query isolation, filters, cursor paging,
legacy read-path protection, hash-chain preservation and existing hash tests. Run
pnpm build for the package runtime and declarations.
Owner packages may use ManagementAuditOutbox inside their existing PostgreSQL
transaction. The auth and capabilities owners enqueue successful management
outcomes, then replay to this ledger using stable event UUIDs. Acknowledged rows
are deleted; pending rows never expire. Each owner holds at most 10,000 pending
rows and refuses its mutation at capacity. A replay batch handles at most 100;
startup and the 60-second maintenance cadence recover from lost replies or owner
restarts. Account deletion preserves audit intents. Capability grant/revoke replay
receipts enqueue no duplicate intent. Replay releases the owner database connection
before sending; concurrent workers may resend one immutable intent, and ledger
idempotency makes their acknowledgements safe. Intents support a principal actor or
an explicit system actor with no principal. System events identify the source owner
as their subject; malformed or ambiguous actor shapes are rejected before commit.
The immutable write boundary applies core's shared CredentialShapes rule to free-form
references and event data. Credential-shaped spans are replaced in place, so the audit
record remains useful without persisting a replayable secret.
Active records are retained for 365 days, then moved transactionally to
system_audit.archive_events; authenticated reads and audit.verify span both tiers.
Archived records expire after seven years. Expiry is explicit: the record is permanently
removed and its final per-home sequence and hash remain in retention_anchors, so later
records continue the same verifiable chain. Retention runs at service startup and before
the first append in each 24-hour window, in bounded batches of 1,000 rows; repeated
sweeps drain larger backlogs without an unbounded transaction.
Runtime mutations still require their separately owned producer integration.
Dependencies
Dependencies
| ID | Version |
|---|---|
| @open-matrix/core | 1.1.32 |
| @open-matrix/system-postgres | 1.1.32 |
Development Dependencies
| ID | Version |
|---|---|
| @matrix/test-utils | 1.1.32 |
| @types/node | ^20.0.0 |
| esbuild | ^0.25.0 |
| tsx | ^4.0.0 |
| typescript | ^5.3.0 |