@yss123/cage-kernel 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +20 -2
  3. package/dist/brands.d.ts +32 -0
  4. package/dist/brands.js +35 -0
  5. package/dist/brands.js.map +1 -0
  6. package/dist/db/connect.d.ts +28 -0
  7. package/dist/db/connect.js +57 -0
  8. package/dist/db/connect.js.map +1 -0
  9. package/dist/db/ddl.d.ts +69 -0
  10. package/dist/db/ddl.js +522 -0
  11. package/dist/db/ddl.js.map +1 -0
  12. package/dist/db/index.d.ts +5 -0
  13. package/dist/db/index.js +7 -0
  14. package/dist/db/index.js.map +1 -0
  15. package/dist/db/migrate.d.ts +22 -0
  16. package/dist/db/migrate.js +87 -0
  17. package/dist/db/migrate.js.map +1 -0
  18. package/dist/db/rows.d.ts +10 -0
  19. package/dist/db/rows.js +59 -0
  20. package/dist/db/rows.js.map +1 -0
  21. package/dist/db/session.d.ts +4 -0
  22. package/dist/db/session.js +20 -0
  23. package/dist/db/session.js.map +1 -0
  24. package/dist/errors.d.ts +44 -0
  25. package/dist/errors.js +83 -0
  26. package/dist/errors.js.map +1 -0
  27. package/dist/index.d.ts +23 -0
  28. package/dist/index.js +25 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/kernel.d.ts +99 -0
  31. package/dist/kernel.js +456 -0
  32. package/dist/kernel.js.map +1 -0
  33. package/dist/mask.d.ts +13 -0
  34. package/dist/mask.js +67 -0
  35. package/dist/mask.js.map +1 -0
  36. package/dist/org.d.ts +46 -0
  37. package/dist/org.js +127 -0
  38. package/dist/org.js.map +1 -0
  39. package/dist/pipeline/idempotency.d.ts +10 -0
  40. package/dist/pipeline/idempotency.js +29 -0
  41. package/dist/pipeline/idempotency.js.map +1 -0
  42. package/dist/pipeline/load.d.ts +15 -0
  43. package/dist/pipeline/load.js +87 -0
  44. package/dist/pipeline/load.js.map +1 -0
  45. package/dist/primitives/aggregate.d.ts +75 -0
  46. package/dist/primitives/aggregate.js +69 -0
  47. package/dist/primitives/aggregate.js.map +1 -0
  48. package/dist/primitives/command.d.ts +101 -0
  49. package/dist/primitives/command.js +49 -0
  50. package/dist/primitives/command.js.map +1 -0
  51. package/dist/primitives/constraints.d.ts +36 -0
  52. package/dist/primitives/constraints.js +41 -0
  53. package/dist/primitives/constraints.js.map +1 -0
  54. package/dist/primitives/event.d.ts +31 -0
  55. package/dist/primitives/event.js +44 -0
  56. package/dist/primitives/event.js.map +1 -0
  57. package/dist/primitives/fields.d.ts +127 -0
  58. package/dist/primitives/fields.js +151 -0
  59. package/dist/primitives/fields.js.map +1 -0
  60. package/dist/primitives/flow.d.ts +126 -0
  61. package/dist/primitives/flow.js +90 -0
  62. package/dist/primitives/flow.js.map +1 -0
  63. package/dist/primitives/states.d.ts +19 -0
  64. package/dist/primitives/states.js +37 -0
  65. package/dist/primitives/states.js.map +1 -0
  66. package/dist/read.d.ts +53 -0
  67. package/dist/read.js +217 -0
  68. package/dist/read.js.map +1 -0
  69. package/dist/registry.d.ts +71 -0
  70. package/dist/registry.js +177 -0
  71. package/dist/registry.js.map +1 -0
  72. package/dist/relations.d.ts +14 -0
  73. package/dist/relations.js +58 -0
  74. package/dist/relations.js.map +1 -0
  75. package/dist/scope/index.d.ts +42 -0
  76. package/dist/scope/index.js +90 -0
  77. package/dist/scope/index.js.map +1 -0
  78. package/dist/telemetry.d.ts +11 -0
  79. package/dist/telemetry.js +35 -0
  80. package/dist/telemetry.js.map +1 -0
  81. package/dist/transfer/csv.d.ts +8 -0
  82. package/dist/transfer/csv.js +114 -0
  83. package/dist/transfer/csv.js.map +1 -0
  84. package/dist/transfer/index.d.ts +49 -0
  85. package/dist/transfer/index.js +245 -0
  86. package/dist/transfer/index.js.map +1 -0
  87. package/dist/transfer/schema.d.ts +4 -0
  88. package/dist/transfer/schema.js +31 -0
  89. package/dist/transfer/schema.js.map +1 -0
  90. package/dist/types.d.ts +52 -0
  91. package/dist/types.js +5 -0
  92. package/dist/types.js.map +1 -0
  93. package/dist/util/names.d.ts +9 -0
  94. package/dist/util/names.js +38 -0
  95. package/dist/util/names.js.map +1 -0
  96. package/dist/worker/consumers.d.ts +29 -0
  97. package/dist/worker/consumers.js +79 -0
  98. package/dist/worker/consumers.js.map +1 -0
  99. package/dist/worker/index.d.ts +36 -0
  100. package/dist/worker/index.js +122 -0
  101. package/dist/worker/index.js.map +1 -0
  102. package/dist/worker/outbox.d.ts +38 -0
  103. package/dist/worker/outbox.js +121 -0
  104. package/dist/worker/outbox.js.map +1 -0
  105. package/dist/worker/scheduler.d.ts +7 -0
  106. package/dist/worker/scheduler.js +77 -0
  107. package/dist/worker/scheduler.js.map +1 -0
  108. package/package.json +58 -3
package/dist/kernel.js ADDED
@@ -0,0 +1,456 @@
1
+ // 内核:唯一的写入入口 execute。HTTP、审批流程、定时任务、反应、批量导入都调用它,
2
+ // 所以检查只写一遍,顺序永远一样(设计文档第 5 节的 12 关)。
3
+ import { randomUUID } from 'node:crypto';
4
+ import { sql } from 'kysely';
5
+ import { connect } from './db/connect.js';
6
+ import { diffFields, fieldsToColumns } from './db/rows.js';
7
+ import { setSessionVars } from './db/session.js';
8
+ import { CageError, cageError, isDomainError, toCageError } from './errors.js';
9
+ import { auditDiff, maskValue, present } from './mask.js';
10
+ import { loadUserGrants, systemCtx, userCtx } from './org.js';
11
+ import { bindReads, loadScoped } from './pipeline/load.js';
12
+ import { idempotency } from './pipeline/idempotency.js';
13
+ import { defaultPayload } from './primitives/event.js';
14
+ import { ReadSide } from './read.js';
15
+ import { buildRegistry } from './registry.js';
16
+ import { consoleLogger, step, traceCarrier } from './telemetry.js';
17
+ import { DataTransfers } from './transfer/index.js';
18
+ import { writeRelations } from './relations.js';
19
+ function zodIssues(e) {
20
+ return e.issues.map((i) => ({ path: i.path.join('.'), message: i.message }));
21
+ }
22
+ export class Kernel {
23
+ registry;
24
+ app;
25
+ readDb;
26
+ read;
27
+ transfers;
28
+ log;
29
+ handles = [];
30
+ maxDepth;
31
+ constructor(opts) {
32
+ this.registry = buildRegistry(opts.domain, opts.registryOptions);
33
+ this.log = opts.logger ?? consoleLogger;
34
+ this.maxDepth = opts.maxReactionDepth ?? 5;
35
+ if (opts.db) {
36
+ this.app = opts.db.app;
37
+ this.readDb = opts.db.read;
38
+ }
39
+ else if (opts.urls) {
40
+ const a = connect(opts.urls.app, { max: opts.poolSize, applicationName: 'cage-kernel' });
41
+ const r = connect(opts.urls.read, { max: opts.poolSize, applicationName: 'cage-read' });
42
+ this.handles.push(a, r);
43
+ this.app = a.db;
44
+ this.readDb = r.db;
45
+ }
46
+ else {
47
+ throw new Error('[CAGE-ENV-001] createKernel 需要 urls 或 db');
48
+ }
49
+ this.read = new ReadSide(this);
50
+ this.transfers = new DataTransfers(this);
51
+ }
52
+ async close() {
53
+ for (const h of this.handles)
54
+ await h.close();
55
+ }
56
+ resolve(ref) {
57
+ const rc = this.registry.command(ref);
58
+ if (!rc) {
59
+ throw new Error(`[CAGE-REG-001] 找不到命令 ${typeof ref === 'string' ? ref : ref.agg.name + '.?'},它是否从 domain 导出了?`);
60
+ }
61
+ return rc;
62
+ }
63
+ // ---------------- 写入 ----------------
64
+ /** 执行一个命令(自己开事务)。返回按当前主体掩码后的新快照。 */
65
+ async execute(ref, raw, ctx) {
66
+ const rc = this.resolve(ref);
67
+ try {
68
+ return await step(`execute ${rc.capability}`, () => this.app.transaction().execute(async (tx) => {
69
+ const r = await this.run(tx, rc, raw, ctx, 0);
70
+ return r.replay !== undefined ? r.replay : r.presented;
71
+ }));
72
+ }
73
+ catch (e) {
74
+ const ce = toCageError(e);
75
+ if (ce.code === 'INTERNAL')
76
+ this.log.error({ err: e, capability: rc.capability, requestId: ctx.requestId }, '命令执行异常');
77
+ if (ce.code === 'FORBIDDEN' || ce.code === 'NOT_FOUND' || ce.code === 'CONSTRAINT_VIOLATED') {
78
+ void this.auditDenied(rc, raw, ctx, ce);
79
+ }
80
+ throw ce;
81
+ }
82
+ }
83
+ /** 在已有事务里执行(同事务反应、审批桥接、批量整批原子模式用)。返回未掩码的快照。 */
84
+ async executeIn(tx, ref, raw, ctx, depth = 1) {
85
+ const rc = this.resolve(ref);
86
+ const r = await this.run(tx, rc, raw, ctx, depth);
87
+ return (r.next ?? r.replay);
88
+ }
89
+ /** 批量写入:每一行都完整走 12 关;默认逐行独立提交,可选整批原子。批量没有快捷路径。 */
90
+ async executeBatch(ref, rows, ctx, opts = {}) {
91
+ const rc = this.resolve(ref);
92
+ const bctx = { ...ctx, source: ctx.source === 'api' ? 'import' : ctx.source, idempotencyKey: undefined };
93
+ if (!opts.atomic) {
94
+ const out = [];
95
+ for (let i = 0; i < rows.length; i++) {
96
+ try {
97
+ out.push({ index: i, ok: true, data: await this.execute(rc.cmd, rows[i], bctx) });
98
+ }
99
+ catch (e) {
100
+ out.push({ index: i, ok: false, error: toCageError(e).toJSON() });
101
+ }
102
+ }
103
+ return out;
104
+ }
105
+ let failedAt = -1;
106
+ let failure = null;
107
+ const results = [];
108
+ try {
109
+ await this.app.transaction().execute(async (tx) => {
110
+ for (let i = 0; i < rows.length; i++) {
111
+ try {
112
+ const r = await this.run(tx, rc, rows[i], bctx, 0);
113
+ results.push({ index: i, ok: true, data: r.presented });
114
+ }
115
+ catch (e) {
116
+ failedAt = i;
117
+ failure = toCageError(e);
118
+ throw e;
119
+ }
120
+ }
121
+ });
122
+ return results;
123
+ }
124
+ catch {
125
+ return rows.map((_, i) => ({
126
+ index: i,
127
+ ok: false,
128
+ error: i === failedAt && failure ? failure.toJSON() : { code: 'ABORTED', detail: '整批原子模式:其他行失败,本行已回滚' },
129
+ }));
130
+ }
131
+ }
132
+ async run(tx, rc, raw, ctx, depth) {
133
+ const { cmd, capability } = rc;
134
+ const agg = cmd.agg;
135
+ if (depth > this.maxDepth)
136
+ throw new Error(`[CAGE-REACT-002] 同事务反应嵌套超过 ${this.maxDepth} 层`);
137
+ // 第 1 关:认证
138
+ if (!ctx.actor || (ctx.actor.kind === 'anonymous' && !cmd.public))
139
+ throw cageError('UNAUTHENTICATED');
140
+ // 第 2 关:校验输入
141
+ const { expectedVersion, rest } = splitRaw(raw);
142
+ const parsed = cmd.input.safeParse(rest);
143
+ if (!parsed.success)
144
+ throw cageError('INVALID_INPUT', zodIssues(parsed.error));
145
+ const input = parsed.data;
146
+ const fields = agg.fields;
147
+ const inverseKeys = Object.keys(fields).filter((key) => fields[key].kind === 'hasMany');
148
+ // hasMany 的归属保存在子对象的 ref 上;拒绝写入,避免调用者误以为传入数组就会搬动子对象。
149
+ if (rest && typeof rest === 'object' && inverseKeys.some((key) => Object.hasOwn(rest, key)))
150
+ throw cageError('INVALID_INPUT', { message: 'hasMany 是只读反查,请通过子对象命令修改 mappedBy 指向的外键' });
151
+ // 第 3 关:调用方与能力
152
+ assertInvoker(cmd, ctx, capability);
153
+ if (!cmd.public && !ctx.capabilities.has(capability))
154
+ throw cageError('FORBIDDEN', { capability });
155
+ // 幂等:先抢占幂等键(键按主体和能力点隔离)
156
+ const idemKey = depth === 0 && ctx.idempotencyKey ? `${ctx.actor.id}:${capability}:${ctx.idempotencyKey}` : undefined;
157
+ const claim = await idempotency.claim(tx, idemKey);
158
+ if (!claim.fresh)
159
+ return { replay: claim.result };
160
+ await setSessionVars(tx, ctx);
161
+ const now = new Date();
162
+ const actorUserId = ctx.onBehalfOf ?? ctx.userId ?? null;
163
+ const isNew = cmd.from === 'new';
164
+ const fieldKeys = Object.keys(fields).filter((key) => fields[key].kind !== 'hasMany');
165
+ let cur;
166
+ if (isNew) {
167
+ // 新建:跳过第 4、5 关,由内核生成 id 和初始版本号;输入里的同名字段预填进草稿
168
+ // 输入里带了 id(确定性主键,例如库存锁用采购单 id)时使用它,重复时报 CONFLICT
169
+ const givenId = typeof input.id === 'string' ? input.id : undefined;
170
+ cur = { id: givenId ?? randomUUID(), status: cmd.to, version: 0, createdAt: now.toISOString(), updatedAt: now.toISOString() };
171
+ for (const k of fieldKeys)
172
+ cur[k] = k in input ? input[k] : fields[k].kind === 'manyToMany' ? [] : null;
173
+ if (agg.scope.deptField && agg.scope.deptField !== 'id' && cur[agg.scope.deptField] == null)
174
+ cur[agg.scope.deptField] = ctx.deptId;
175
+ }
176
+ else {
177
+ if (typeof input.id !== 'string')
178
+ throw cageError('INVALID_INPUT', [{ path: 'id', message: '缺少 id' }]);
179
+ // 第 4 关:按范围加载并加行锁;范围外和不存在一律 404
180
+ const loaded = await step('loadScoped', () => loadScoped(tx, agg, input.id, ctx, true));
181
+ if (!loaded)
182
+ throw cageError('NOT_FOUND');
183
+ cur = loaded;
184
+ // 第 5 关:状态守卫
185
+ if (!cmd.from.includes(cur.status)) {
186
+ throw cageError('INVALID_TRANSITION', { status: cur.status, allowed: cmd.from });
187
+ }
188
+ if (expectedVersion !== undefined && expectedVersion !== cur.version)
189
+ throw cageError('CONFLICT', { expected: expectedVersion, actual: cur.version });
190
+ }
191
+ // 第 6 关:硬约束
192
+ const meta = {
193
+ capability,
194
+ capabilitiesOf: (uid) => this.capabilitiesOf(uid, ctx.tenantId),
195
+ load: async (aggName, id) => {
196
+ const a = this.registry.aggregate(aggName);
197
+ return a && /^[0-9a-f-]{36}$/i.test(id) ? loadScoped(tx, a, id, ctx, false) : null;
198
+ },
199
+ catalog: () => this.catalogCaps(),
200
+ };
201
+ for (const c of cmd.constraints) {
202
+ const r = await c.check(cur, ctx, input, meta);
203
+ if (!r.ok)
204
+ throw new CageError('CONSTRAINT_VIOLATED', { constraint: c.name, message: r.message });
205
+ }
206
+ // 第 7 关:只注入 reads 里声明的只读仓储
207
+ const deps = bindReads(tx, cmd.reads, ctx);
208
+ // 第 8 关:调用 handler(AI 写的代码)
209
+ const draft = structuredClone(cur);
210
+ const result = await step('handler', async () => cmd.handler(draft, input, deps, Object.freeze({ now, actorUserId })));
211
+ if (isDomainError(result))
212
+ throw new CageError('DOMAIN_ERROR', result.detail, result.code);
213
+ const changes = { ...draft, ...(result && typeof result === 'object' ? result : {}) };
214
+ if (inverseKeys.some((key) => Object.hasOwn(changes, key)))
215
+ throw cageError('INVALID_INPUT', { message: 'handler 不能给 hasMany 赋值;请调用子对象命令' });
216
+ // 第 9 关:状态只由内核推进;创建人字段只由内核设置
217
+ const next = { ...cur };
218
+ for (const k of fieldKeys)
219
+ if (k in changes)
220
+ next[k] = changes[k] === undefined ? null : changes[k];
221
+ const owner = agg.scope.ownerField;
222
+ if (owner)
223
+ next[owner] = isNew ? actorUserId ?? changes[owner] ?? null : cur[owner];
224
+ // 保持状态的命令使用第 4 关加锁读出的状态,而不是 handler 返回值。
225
+ // 因此晚到的第三方回执可以更新字段,但不能把已取消的单据重新推进到已审批。
226
+ next.status = cmd.to ?? cur.status;
227
+ const record = Object.fromEntries(fieldKeys.map((k) => [k, next[k] ?? (agg.fields[k].isOptional ? null : undefined)]));
228
+ const valid = agg.schema.safeParse(record);
229
+ if (!valid.success)
230
+ throw cageError('INVALID_INPUT', zodIssues(valid.error));
231
+ // 关系是无序集合;统一 UUID 大小写、去重并排序,让审计及重试只记录真正的关联变化。
232
+ for (const k of fieldKeys)
233
+ if (fields[k].kind === 'manyToMany')
234
+ next[k] = [...new Set(next[k].map((id) => id.toLowerCase()))].sort();
235
+ // 第 10 关:不变量
236
+ for (const [name, fn] of Object.entries(agg.invariants)) {
237
+ let holds = false;
238
+ try {
239
+ holds = !!fn(next);
240
+ }
241
+ catch {
242
+ holds = false;
243
+ }
244
+ if (!holds)
245
+ throw cageError('INVARIANT_VIOLATED', { invariant: `${agg.name}.${name}` });
246
+ }
247
+ // 第 11 关:带版本号写入 + 审计 + outbox + 同事务反应,全部在一个事务里
248
+ const table = `${agg.table.schema}.${agg.table.name}`;
249
+ if (isNew) {
250
+ await tx
251
+ .insertInto(table)
252
+ .values({ id: next.id, tenant_id: ctx.tenantId, ...fieldsToColumns(agg, record), status: next.status, version: 1, created_at: now, updated_at: now })
253
+ .execute();
254
+ next.version = 1;
255
+ // 新建的数据也必须在自己的范围内(不能替别的部门建单)
256
+ const visible = await loadScoped(tx, agg, next.id, ctx, false);
257
+ if (!visible)
258
+ throw new CageError('CONSTRAINT_VIOLATED', { constraint: 'scope', message: '新建的数据不在你的数据范围内' });
259
+ }
260
+ else {
261
+ const changed = diffFields(agg, cur, next);
262
+ const res = await tx
263
+ .updateTable(table)
264
+ .set({ ...fieldsToColumns(agg, Object.fromEntries(changed.map((k) => [k, next[k]]))), status: next.status, version: cur.version + 1, updated_at: now })
265
+ .where('id', '=', cur.id)
266
+ .where('version', '=', cur.version)
267
+ .executeTakeFirst();
268
+ if (Number(res.numUpdatedRows) === 0)
269
+ throw cageError('CONFLICT');
270
+ next.version = cur.version + 1;
271
+ }
272
+ next.updatedAt = now.toISOString();
273
+ await writeRelations(tx, this.registry, agg, isNew ? {} : cur, next, ctx);
274
+ const changed = isNew ? fieldKeys.filter((k) => next[k] !== null) : diffFields(agg, cur, next);
275
+ await this.writeAudit(tx, {
276
+ tenantId: ctx.tenantId,
277
+ actor: ctx.actor.id,
278
+ actorKind: ctx.actor.kind,
279
+ onBehalfOf: ctx.onBehalfOf ?? null,
280
+ source: ctx.source,
281
+ kind: 'write',
282
+ capability,
283
+ command: capability,
284
+ aggregate: agg.name,
285
+ aggregateId: next.id,
286
+ result: 'ok',
287
+ diff: auditDiff(agg, isNew ? null : cur, next, changed),
288
+ requestId: ctx.requestId ?? null,
289
+ idempotencyKey: ctx.idempotencyKey ?? null,
290
+ client: ctx.client ?? null,
291
+ });
292
+ const events = await this.enqueueEvents(tx, cmd, next, input, ctx, isNew ? null : cur);
293
+ for (const ev of events) {
294
+ for (const { r, name } of this.registry.reactionsFor(ev.event)) {
295
+ if (r.tx !== 'same')
296
+ continue;
297
+ const rin = r.map(ev.payload);
298
+ if (rin === null || rin === undefined)
299
+ continue;
300
+ const rctx = systemCtx({
301
+ kind: 'reaction', name, tenantId: ctx.tenantId, capabilities: [this.registry.capabilityOf(r.command)],
302
+ onBehalfOf: actorUserId, requestId: ctx.requestId,
303
+ });
304
+ await this.run(tx, this.resolve(r.command), rin, rctx, depth + 1);
305
+ }
306
+ }
307
+ if (agg.options.grants) {
308
+ // 授权变化:事务提交后通知所有实例清掉上下文缓存(回滚就不会发)
309
+ const payload = agg.options.grants === 'self' ? String(next.id) : '*';
310
+ await sql `select pg_notify('cage_grants', ${payload})`.execute(tx);
311
+ }
312
+ const presented = present(agg, next, ctx);
313
+ await idempotency.complete(tx, idemKey, presented);
314
+ // 第 12 关:函数返回即提交事务;随后由 outbox 投递器异步分发事件
315
+ return { next, presented };
316
+ }
317
+ async enqueueEvents(tx, cmd, next, input, ctx, prev) {
318
+ const out = [];
319
+ if (cmd.emits.length === 0)
320
+ return out;
321
+ const carrier = traceCarrier();
322
+ for (const spec of cmd.emits) {
323
+ const ev = spec.event;
324
+ const rawPayload = spec.map ? spec.map(next, input, prev) : defaultPayload(ev, next, input);
325
+ const p = ev.schema.safeParse(rawPayload);
326
+ if (!p.success) {
327
+ throw new Error(`[CAGE-EVENT-001] 事件 ${ev.name} 的载荷不符合声明:${JSON.stringify(zodIssues(p.error))}`);
328
+ }
329
+ const payload = maskEventPayload(ev, p.data);
330
+ const row = await tx
331
+ .insertInto('sys.outbox')
332
+ .values({
333
+ tenant_id: ctx.tenantId,
334
+ event: ev.name,
335
+ aggregate: cmd.agg.name,
336
+ aggregate_id: next.id,
337
+ payload: JSON.stringify(payload),
338
+ actor: JSON.stringify({ kind: ctx.actor?.kind, id: ctx.actor?.id, userId: ctx.userId, onBehalfOf: ctx.onBehalfOf ?? null }),
339
+ trace: JSON.stringify(carrier),
340
+ request_id: ctx.requestId ?? null,
341
+ })
342
+ .returning('id')
343
+ .executeTakeFirstOrThrow();
344
+ out.push({ outboxId: Number(row.id), event: ev.name, payload });
345
+ }
346
+ await sql `select pg_notify('cage_outbox', '')`.execute(tx);
347
+ return out;
348
+ }
349
+ // ---------------- 审计 ----------------
350
+ async writeAudit(db, e) {
351
+ await db
352
+ .insertInto('sys.audit_log')
353
+ .values({
354
+ tenant_id: e.tenantId,
355
+ actor: e.actor,
356
+ actor_kind: e.actorKind,
357
+ on_behalf_of: e.onBehalfOf ?? null,
358
+ source: e.source,
359
+ kind: e.kind,
360
+ capability: e.capability ?? null,
361
+ command: e.command ?? null,
362
+ aggregate: e.aggregate ?? null,
363
+ aggregate_id: e.aggregateId ?? null,
364
+ result: e.result,
365
+ diff: e.diff === undefined || e.diff === null ? null : JSON.stringify(e.diff),
366
+ request_id: e.requestId ?? null,
367
+ idempotency_key: e.idempotencyKey ?? null,
368
+ client: e.client ? JSON.stringify(e.client) : null,
369
+ })
370
+ .execute();
371
+ }
372
+ /** 被拒绝的尝试异步记录,用于发现探测和配置问题;记录失败不影响请求 */
373
+ async auditDenied(rc, raw, ctx, err) {
374
+ try {
375
+ const id = raw?.id;
376
+ await this.writeAudit(this.app, {
377
+ tenantId: ctx.tenantId,
378
+ actor: ctx.actor?.id ?? 'anonymous',
379
+ actorKind: ctx.actor?.kind ?? 'anonymous',
380
+ onBehalfOf: ctx.onBehalfOf ?? null,
381
+ source: ctx.source,
382
+ kind: 'denied',
383
+ capability: rc.capability,
384
+ command: rc.capability,
385
+ aggregate: rc.cmd.agg.name,
386
+ aggregateId: typeof id === 'string' && /^[0-9a-f-]{36}$/i.test(id) ? id : null,
387
+ result: err.code,
388
+ diff: err.detail && typeof err.detail === 'object' ? { detail: err.detail } : null,
389
+ requestId: ctx.requestId ?? null,
390
+ client: ctx.client ?? null,
391
+ });
392
+ }
393
+ catch (e) {
394
+ this.log.warn({ err: String(e) }, '拒绝审计写入失败');
395
+ }
396
+ }
397
+ // ---------------- 上下文 ----------------
398
+ catalogCache;
399
+ catalogCaps() {
400
+ return (this.catalogCache ??= this.registry.capabilityCatalog().map((c) => c.capability));
401
+ }
402
+ async capabilitiesOf(userId, tenantId) {
403
+ const g = await loadUserGrants(this.app, userId, tenantId);
404
+ return g && g.active ? g.capabilities : new Map();
405
+ }
406
+ /** 把一个用户解析成上下文(HTTP 层会加缓存) */
407
+ async contextFor(userId, tenantId, extra = {}) {
408
+ const g = await loadUserGrants(this.app, userId, tenantId);
409
+ return g ? userCtx(g, extra) : null;
410
+ }
411
+ /** 审批流程身份:代表最后一位审批人调用结论命令 */
412
+ processCtx(opts) {
413
+ return systemCtx({ kind: 'process', name: opts.process, tenantId: opts.tenantId, capabilities: opts.capabilities, onBehalfOf: opts.onBehalfOf, requestId: opts.requestId });
414
+ }
415
+ }
416
+ export function createKernel(opts) {
417
+ return new Kernel(opts);
418
+ }
419
+ function splitRaw(raw) {
420
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw))
421
+ return { rest: raw ?? {} };
422
+ const { expectedVersion, ...rest } = raw;
423
+ if (expectedVersion === undefined || expectedVersion === null)
424
+ return { rest };
425
+ const v = Number(expectedVersion);
426
+ if (!Number.isInteger(v))
427
+ throw cageError('INVALID_INPUT', [{ path: 'expectedVersion', message: '版本号必须是整数' }]);
428
+ return { expectedVersion: v, rest };
429
+ }
430
+ /** 第 3 关之一:流程专用命令只接受流程身份;用户命令可以被声明过它的系统身份调用 */
431
+ function assertInvoker(cmd, ctx, capability) {
432
+ const kind = ctx.actor.kind;
433
+ if (kind === 'system')
434
+ return;
435
+ if (kind === 'user' || kind === 'anonymous') {
436
+ if (!cmd.invokedBy.includes('user')) {
437
+ throw cageError('FORBIDDEN', { capability, message: `该命令只接受 ${cmd.invokedBy.join('/')} 调用` });
438
+ }
439
+ return;
440
+ }
441
+ const as = kind === 'reaction' ? 'process' : kind;
442
+ if (!cmd.invokedBy.includes('user') && !cmd.invokedBy.includes(as)) {
443
+ throw cageError('FORBIDDEN', { capability, message: `${kind} 身份不能调用该命令` });
444
+ }
445
+ }
446
+ function maskEventPayload(ev, payload) {
447
+ const out = { ...payload };
448
+ for (const [k, f] of Object.entries(ev.fields)) {
449
+ if (f.sensitiveKind && k in out)
450
+ out[k] = maskValue(f.sensitiveKind, out[k]);
451
+ if (f.isHidden)
452
+ delete out[k];
453
+ }
454
+ return out;
455
+ }
456
+ //# sourceMappingURL=kernel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kernel.js","sourceRoot":"","sources":["../src/kernel.ts"],"names":[],"mappings":"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"}
package/dist/mask.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import { type AnyAggregate } from './primitives/aggregate.js';
2
+ import { type SensitiveKind } from './primitives/fields.js';
3
+ import type { Ctx } from './types.js';
4
+ export declare function maskValue(kind: SensitiveKind | string, val: unknown): unknown;
5
+ /** 能不能看某聚合某种类的明文 */
6
+ export declare function canUnmask(ctx: Ctx | null, aggName: string, kind: string): boolean;
7
+ /** 对外呈现快照:去掉隐藏字段;敏感字段按当前主体掩码(ctx 为 null 时一律掩码) */
8
+ export declare function present(agg: AnyAggregate, snap: Record<string, any>, ctx: Ctx | null): Record<string, any>;
9
+ /** 审计 diff:敏感字段掩码,隐藏字段只记录「已修改」 */
10
+ export declare function auditDiff(agg: AnyAggregate, cur: Record<string, any> | null, next: Record<string, any>, changed: string[]): Record<string, {
11
+ from: unknown;
12
+ to: unknown;
13
+ }>;
package/dist/mask.js ADDED
@@ -0,0 +1,67 @@
1
+ // 内存掩码:与数据库里的 sys.mask 语义一致,用于命令响应、审计 diff、事件载荷和日志。
2
+ import { hiddenFields, sensitiveFields } from './primitives/aggregate.js';
3
+ import { isRelation } from './primitives/fields.js';
4
+ export function maskValue(kind, val) {
5
+ if (val === null || val === undefined)
6
+ return val;
7
+ const s = String(val);
8
+ switch (kind) {
9
+ case 'phone':
10
+ return s.length >= 7 ? `${s.slice(0, 3)}****${s.slice(-4)}` : '****';
11
+ case 'idCard':
12
+ return s.length >= 8 ? `${s.slice(0, 4)}**********${s.slice(-4)}` : '****';
13
+ case 'bankCard':
14
+ return `**** **** **** ${s.slice(-4)}`;
15
+ case 'email': {
16
+ const at = s.indexOf('@');
17
+ return at > 0 ? `${s.slice(0, 1)}***${s.slice(at)}` : '******';
18
+ }
19
+ case 'name':
20
+ return `${s.slice(0, 1)}**`;
21
+ case 'address':
22
+ return `${s.slice(0, 6)}******`;
23
+ default:
24
+ return '******';
25
+ }
26
+ }
27
+ /** 能不能看某聚合某种类的明文 */
28
+ export function canUnmask(ctx, aggName, kind) {
29
+ return !!ctx && (ctx.unmask.includes(`${aggName}.${kind}`) || ctx.unmask.includes(`*.${kind}`));
30
+ }
31
+ /** 对外呈现快照:去掉隐藏字段;敏感字段按当前主体掩码(ctx 为 null 时一律掩码) */
32
+ export function present(agg, snap, ctx) {
33
+ const out = { ...snap };
34
+ // 关联集合按需分页读取。命令响应不暴露内部完整 ID 集合,也不隐式读取目标内容。
35
+ for (const [key, field] of Object.entries(agg.fields))
36
+ if (isRelation(field))
37
+ delete out[key];
38
+ for (const k of hiddenFields(agg))
39
+ delete out[k];
40
+ for (const [k, kind] of Object.entries(sensitiveFields(agg))) {
41
+ if (k in out && !canUnmask(ctx, agg.name, kind))
42
+ out[k] = maskValue(kind, out[k]);
43
+ }
44
+ delete out.tenantId;
45
+ return out;
46
+ }
47
+ /** 审计 diff:敏感字段掩码,隐藏字段只记录「已修改」 */
48
+ export function auditDiff(agg, cur, next, changed) {
49
+ const sens = sensitiveFields(agg);
50
+ const hidden = new Set(hiddenFields(agg));
51
+ const diff = {};
52
+ for (const k of changed) {
53
+ if (hidden.has(k)) {
54
+ diff[k] = { from: '[hidden]', to: '[hidden]' };
55
+ continue;
56
+ }
57
+ const kind = sens[k];
58
+ diff[k] = {
59
+ from: kind ? maskValue(kind, cur?.[k]) : cur?.[k] ?? null,
60
+ to: kind ? maskValue(kind, next[k]) : next[k] ?? null,
61
+ };
62
+ }
63
+ if (!cur || cur.status !== next.status)
64
+ diff.status = { from: cur?.status ?? null, to: next.status };
65
+ return diff;
66
+ }
67
+ //# sourceMappingURL=mask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mask.js","sourceRoot":"","sources":["../src/mask.ts"],"names":[],"mappings":"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"}
package/dist/org.d.ts ADDED
@@ -0,0 +1,46 @@
1
+ import type { Kysely } from 'kysely';
2
+ import type { CapabilityParams, Combinator, Ctx, ScopeGrant } from './types.js';
3
+ export interface RoleGrantRow {
4
+ capabilities: {
5
+ capability: string;
6
+ params?: CapabilityParams;
7
+ }[];
8
+ scopes: {
9
+ aggregate: string;
10
+ combinator: Combinator;
11
+ deptIds?: string[];
12
+ }[];
13
+ }
14
+ /** 多角色能力取并集,数值参数(额度)取最大值 */
15
+ export declare function mergeCaps(roles: RoleGrantRow[]): Map<string, CapabilityParams>;
16
+ /** 多角色范围取并集:同一聚合的多个组合子用 OR 连接;deptSet 的部门合并 */
17
+ export declare function mergeScopes(roles: RoleGrantRow[]): Record<string, ScopeGrant[]>;
18
+ /** 能力点 X.unmask.kind → 明文权限 X.kind */
19
+ export declare function unmaskFrom(caps: Map<string, CapabilityParams>): string[];
20
+ export interface UserGrants {
21
+ userId: string;
22
+ tenantId: string;
23
+ deptId: string | null;
24
+ deptPath: string | null;
25
+ capabilities: Map<string, CapabilityParams>;
26
+ scopes: Record<string, ScopeGrant[]>;
27
+ unmask: string[];
28
+ active: boolean;
29
+ }
30
+ /** 从系统表读取一个用户的授权(内核账号) */
31
+ export declare function loadUserGrants(db: Kysely<any>, userId: string, tenantId: string): Promise<UserGrants | null>;
32
+ /** 用户上下文:禁用的用户没有任何能力 */
33
+ export declare function userCtx(g: UserGrants, extra?: Partial<Ctx>): Ctx;
34
+ export declare function anonymousCtx(tenantId: string, extra?: Partial<Ctx>): Ctx;
35
+ /**
36
+ * 系统身份上下文:能力只包含它声明过的命令;范围为全部(仍受租户约束)。
37
+ * 审批流程、定时任务、入站回调、反应各自用它。
38
+ */
39
+ export declare function systemCtx(opts: {
40
+ kind: 'process' | 'job' | 'external' | 'reaction' | 'system';
41
+ name: string;
42
+ tenantId: string;
43
+ capabilities: string[];
44
+ onBehalfOf?: string | null;
45
+ requestId?: string;
46
+ }): Ctx;