@krizaka/audit

中文文档
0.1.6发布于 2026/11/01Apache-2.0TypeScriptES Module构建来源已验证

Who did what, for every Krizaka product: an append-only audit trail in its own schema, written inside the caller's transaction or quietly beside it, filtered for the admin, exported and redacted for Loi 25, purged after a retention set by the admin. No da

原始使用文档

@krizaka/audit

Who did what, for every Krizaka product. The trail is append-only and lives in the product's database, in the Postgres schema audit.

  • Two ways to write: inside the caller's transaction (it commits or rolls back with the work), or quietly beside it (a failure is logged, never thrown).
  • For the admin: filtered and paginated.
  • For Loi 25: exported and redacted.
  • Retention: purged after a retention the admin sets.

There is no database client and no wall clock: you pass a Query and a Clock.

pnpm add @krizaka/audit @krizaka/db

Add its schema to your migrations

The schema is embedded through @krizaka/db, in your own sequence:

import { emitMigration } from "@krizaka/db";
import { auditSchema } from "@krizaka/audit";

// commit the output as one of your migrations (drizzle-kit `generate --custom`, or your list)
emitMigration(auditSchema, 1, { tables: { owner: "accounts" } });

The table is audit.entry. It holds the time, the actor (references your accounts, ON DELETE SET NULL), a readable label, the dotted action (billing.checkout_started), an optional target, the detail (jsonb) and the IP.

Use

import { createAudit } from "@krizaka/audit";
import { transaction } from "@krizaka/db";

const audit = createAudit({ clock: { now: () => new Date() }, onError: (e) => logger.warn(e) });

// Inside a unit of work: the entry exists only if the work commits.
await transaction(connect, async (tx) => {
  await suspendUser(tx, userId);
  await audit.record(tx, { actorId: admin.id, actorLabel: admin.name, action: "admin.user_suspended", target: { type: "account", id: userId } });
});

// Beside it: never fails the request.
await audit.recordQuietly(query, { actorId: null, actorLabel: "stripe webhook", action: "billing.event_ignored", detail: { type } });

// The admin's view: newest first, filtered, paged by cursor.
const page = await audit.list(query, { actionPrefix: "admin.", limit: 50 });
const next = await audit.list(query, { actionPrefix: "admin.", limit: 50, before: page.at(-1)?.id });
  • Loi 25:

    • exportFor(query, accountId) gives the person's entries;
    • redactActor(tx, accountId) keeps the facts and removes the person: the id and IP become null, and the label becomes « erased ».

    Put as little personal data in detail as the action needs.

  • Retention: register auditSettings in your @krizaka/settings registry (audit.retentionDays: default 1095, 30–3650 days). Your job then calls audit.purge(tx, { retentionDays }).

  • Input from a request is checked the same way for every store: a page size must be a positive integer (capped at 200), a cursor must be an entry id, an IP must be an address, and a retention must be within the setting's bounds (30–3650 days), so a bad value never purges the whole trail. Each refusal is an AuditError with a stable code (AUDIT_BAD_FILTER, AUDIT_BAD_IP, AUDIT_BAD_RETENTION…).

  • A fixed list of actions: createAudit({ allowedActions: [...] }) refuses anything else (AUDIT_UNKNOWN_ACTION).

  • Another store runs the contract kit: auditStoreContract from @krizaka/audit/testkit. memoryAuditStore() is the reference.

版本与发布记录

@krizaka/audit 共发布 8 个版本,首次发布于 2026/10/24;过去 12 个月发布了 8 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.1.6latest2026/11/011 天前
0.1.52026/10/295 天前
0.1.42026/10/277 天前
0.1.32026/10/277 天前
0.1.22026/10/268 天前
0.1.12026/10/268 天前

关于 @krizaka/audit 的常见问题

@krizaka/audit 是什么?

对于每个Krizaka产品,谁做了什么:在自己的模式中只添加审计跟踪,写在调用者的事务中或悄悄地在它旁边,为管理员过滤,为Loi 25导出和编辑,在管理员设置保留后清除。没有达

如何安装 @krizaka/audit?

在项目目录运行 npm install @krizaka/audit,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:zod(>=3.23)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@krizaka/audit 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@krizaka/audit 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@krizaka/audit 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@krizaka/audit 可以商用吗?

@krizaka/audit 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@krizaka/audit 还在维护吗?

最新版本 0.1.6 发布于 2026/11/01(1 天前);至今共发布 8 个版本,其中过去 12 个月发布了 8 个;首次发布于 2026/10/24。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。