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