@krizaka/privacy

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

每件Krizaka产品的隐私(Loi 25):一次性书面同意,并显示通知版本,从保存个人数据的每个模块中组装导出,在一次交易中运行的擦除操作并留下没有个人数据的记录

中文使用文档

@krizaka /隐私

每款Krizaka产品的隐私(Loi 25): 目的同意,此人的数据 出口 从每个承载它的模块, 抹去 从一个事务中的每个模块中获取,并且 保留 根据管理员设置的目的。6个产品有部分拷贝(由弥久坂同意,出口并删除;秋田aza同意) recordConsent 和 eraseClient;异步导出和管理员导出所携带的产品;同意列)。这是一个版本。

import { transaction } from "@krizaka/db";
import { auditContributor, createPrivacy, privacySchema } from "@krizaka/privacy";
import { privacySettings, retentionFromSettings } from "@krizaka/privacy/settings";

emitMigration(privacySchema, 1, { tables: {} }); // commit the SQL once, in your migrations: privacy.consent and privacy.request

const privacy = createPrivacy({
  clock: { now: () => new Date() },
  purposes: ["marketing", "screening"],                 // the purposes the product declares
  contributors: [auditContributor(audit), ordersContributor, filesContributor], // every module that holds personal data
  transaction: (work) => transaction(connect, work),
  retentionDays: retentionFromSettings((key) => settings.get(key)), // privacy.retention.<purpose>Days
  audit, outbox,                                         // optional: the erasure is recorded; a large export goes through the outbox
});

const eric = { kind: "account", id: account.id };         // a subject is a kind and an id: an account, a client file, an application
await privacy.recordConsent(query, { subject: eric, purpose: "marketing", version: "2026-10-01", granted: true, means: "checkbox" });
await privacy.hasConsent(query, eric, "marketing");       // the consent with the last word; never having said anything is a no
const document = await privacy.exportSubject(query, eric); // { format: 1, subject, generatedAt, modules: { audit, orders, files } }
await privacy.eraseSubject(eric);                         // every contributor, one transaction, consents withdrawn, a record without personal data
await privacy.purge(query);                               // from the product's job: what is past each purpose's retention
  • 主体是一种,也是一种本我,不一定是一个帐户:Akinaza的数据主体是一个客户文件,Yomizaka是一个应用程序的租户。
  • privacy.consent 写一次:触发器拒绝每次更新;退场是新的一排;最后一排 seq 赢了。每个同意持有 所示通知的版本手段和瞬间:证明人们同意了什么。
  • PrivacyContributor 是每个模块实现的端口: exportFor(query, subject), eraseFor(tx, subject) (通过交易将其删除或匿名化:一个将发票保存6年的模块将名称清空并保留行),以及可选的 purgeExpired(tx, { purpose, before }). 产品为自己的表注册一个。 auditContributor(audit) 是为 @krizaka/audit (导出列出演员的条目;擦除将它们分离并保留事实)。数据库外部的副作用(存储中的文件)没有被执行 eraseFor:在同一事务中将其附加到发件箱中。
  • 出口 为每个贡献者组装一个JSON文档;失败的贡献者使导出失败,并将其命名(无声的遗漏将是谎言)。 大量出口 是在呼叫方的事务中询问的 requestExport(tx, subject) (附加 evt.privacy.export_requested.v1 发送到发件箱,仅保存请求id)和一个工作调用 fulfilExport(query, requestId, deliver):异步模式。
  • 擦除 运行每个贡献者的 eraseFor 在一个事务中,撤回实时同意(每个新行,版本) erasure (或您通过的那个),记录请求和审计条目 privacy.erasure_completed 它命名了请求和模块 没有人. 如果贡献者失败,则不会删除任何内容,请求将被记录为 failed 使用代码,并抛出错误(如果记录失败也失败) AggregateError 以原文为先)。
  • 保留: privacySettings({ screening: { retentionDays: 365 } }) (@krizaka/privacy/settings,需要 @krizaka/settings 和 zod)声明 privacy.retention.screeningDays (payment-history → paymentHistoryDays)。 purge 打电话给每个投稿人 purgeExpired 对于每一个目的,都有保留。
  • 请求表包含主题的id,而不包含其他个人数据,因此它可以在它所证明的擦除之后继续存在。 privacyStoreContract (从 @krizaka/privacy/testkit)是每家商店都遵守的合同。

保密事件登记册

有关保护私营部门个人资料的法案(CQLR c. p . 39.1(第3.5至3.8条)要求每个企业保留,其内容和保留由 有关保密事故的规例. 简而言之,正如我们所读到的(不是法律建议):有理由相信事件发生,降低风险并防止新的事件发生;根据信息的敏感性、预期的后果和滥用的可能性,评估造成严重伤害的风险;风险严重的,及时通知欧盟会计信息委员会和有关人员; 并将每一事件,无论严重与否,在获悉后至少五年内保存一份登记册,并应委员会要求提交。

import { createIncidentRegister, registerToCsv, suggestSeriousInjury } from "@krizaka/privacy";

emitMigration(privacySchema, 2, { tables: {} });            // privacy.incident (after version 1)
const incidents = createIncidentRegister({ clock: { now: () => new Date() }, audit });
const admin = { id: account.id, label: account.name };

const { id } = await incidents.open(query, { scope: tenantId, kind: "access", description: "…", information: ["lease"], personsConcerned: 3 }, admin);
await incidents.recordMeasure(query, tenantId, id, "Session revoked", admin);
await incidents.assess(query, tenantId, id, { sensitivity: "high", consequences: "high", likelihood: "medium", seriousInjury: suggestSeriousInjury(factors), rationale: "…" }, admin);
await incidents.recordNotice(query, tenantId, id, "cai", { channel: "form" }, admin);     // and "persons"
await incidents.close(query, tenantId, id, admin);       // a serious injury closes once both notices are recorded
registerToCsv((await incidents.exportRegister(query, tenantId)).entries);
  • 每个电话都是由 scope (租户):另一个范围的条目永远不会被发现、编辑或导出。商店是 IncidentStore 端口(memoryIncidentStore, dbIncidentStore; incidentStoreContract 从 @krizaka/privacy/testkit);时钟被注入。
  • 该登记册不载有有关人士的个人资料信息有多少,信息的种类,而不是信息的种类。
  • 保存了五年: retainUntil 五年之后 awareAt;数据库拒绝删除之前的条目,并拒绝编辑已关闭的条目。钻头被标记为(drill),并留在登记册内。
  • suggestSeriousInjury 是负责人的向导;决定(seriousInjury)是他们的,并记录了其基本原理。未造成严重伤害的事故无需通知(recordNotice 拒绝)。
  • 与 audit,每一步跟踪为 privacy.incident_* 没有描述,也没有任何人。

版本与发布记录

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

版本发布日期距今
0.2.3latest2026/11/011 天前
0.2.22026/10/304 天前
0.2.12026/10/295 天前
0.2.02026/10/286 天前
0.1.12026/10/277 天前
0.1.02026/10/277 天前

关于 @krizaka/privacy 的常见问题

@krizaka/privacy 是什么?

每件Krizaka产品的隐私(Loi 25):一次性书面同意,并显示通知版本,从保存个人数据的每个模块中组装导出,在一次交易中运行的擦除操作并留下没有个人数据的记录

如何安装 @krizaka/privacy?

在项目目录运行 npm install @krizaka/privacy,或使用 pnpm add / yarn add / bun add。

@krizaka/privacy 支持 TypeScript 吗?

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

@krizaka/privacy 支持 ESM 还是 CommonJS?

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

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

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

@krizaka/privacy 可以商用吗?

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

@krizaka/privacy 还在维护吗?

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