@substrat-run/contracts 0.67.0 → 0.69.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.
package/dist/index.d.ts CHANGED
@@ -35,4 +35,5 @@ export * from './ci.js';
35
35
  export * from './money.js';
36
36
  export * from './attachments.js';
37
37
  export * from './model.js';
38
+ export * from './operations.js';
38
39
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -35,4 +35,5 @@ export * from './ci.js';
35
35
  export * from './money.js';
36
36
  export * from './attachments.js';
37
37
  export * from './model.js';
38
+ export * from './operations.js';
38
39
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC"}
package/dist/model.d.ts CHANGED
@@ -32,11 +32,18 @@ export interface EntityDef<Names extends string = string> {
32
32
  /** The row shape. Field names are what `key`, `searchables` and events check against. */
33
33
  readonly fields: z.ZodObject<z.ZodRawShape>;
34
34
  /**
35
- * The parent entity permission flows along (design doc §4.2 rule 3).
36
- * Checked against the declared entities — a typo is a compile error, where
37
- * today it is a silently dead edge.
35
+ * The parent entity types permission may flow along (design doc §4.2 rule 3).
36
+ * Checked against the declared entities — a typo is a compile error, where it
37
+ * used to be a silently dead edge.
38
+ *
39
+ * **Plural, and an array even for one.** `entityRelations` is an ALLOWLIST,
40
+ * not an assertion: the kernel accumulates permitted parents into a *set* per
41
+ * entity type and `ctx.link` checks membership. `reservation` already hangs
42
+ * off both `resource` and `member`; `protocol` off both `workorder` and
43
+ * `employee`. Singular `parent` said "the parent", which is not what the
44
+ * kernel means and cannot express the real cases.
38
45
  */
39
- readonly parent?: Names;
46
+ readonly parents?: readonly Names[];
40
47
  /** Natural key, if any. Must name fields that exist. */
41
48
  readonly key?: readonly string[];
42
49
  /** Fields an erasure must be able to reach (§12). Must name fields that exist. */
@@ -79,7 +86,8 @@ export type EntityName<T> = keyof T & string;
79
86
  export interface EmittedEntity {
80
87
  readonly table: string;
81
88
  readonly fields: Record<string, unknown>;
82
- readonly parent?: string;
89
+ /** The permitted parent types, sorted. One shape, always. */
90
+ readonly parents?: readonly string[];
83
91
  readonly key?: readonly string[];
84
92
  readonly erasable?: readonly string[];
85
93
  }
@@ -140,50 +148,37 @@ type EntityRefs<T extends Record<string, EntityDef>, M> = {
140
148
  readonly view: string;
141
149
  }[];
142
150
  /**
143
- * Parent edges whose CHILD this module does not own.
151
+ * The engine registries this module composes, so relation edges naming their
152
+ * entities can be checked.
153
+ */
154
+ readonly engines?: readonly Record<string, EntityDef>[];
155
+ /**
156
+ * Parent edges involving an entity this module does not own.
144
157
  *
145
158
  * A vertical legitimately declares these: an engine is entity-agnostic, so
146
159
  * only the vertical knows that a work order hangs off a bike, or a protocol
147
- * off a work order. The child name belongs to an engine and cannot be checked
148
- * here but the PARENT often can be, and throwing that away would be giving
149
- * up a check we hold.
160
+ * off a work order. **Both sides are checked** against the local entities plus
161
+ * every entity of every registry in `engines`.
150
162
  *
151
- * So the parent is checked whenever it is one of this module's own entities:
163
+ * Local-to-local edges do not belong here they are DERIVED from the
164
+ * entities' own `parents`, and declaring one twice is how two descriptions of
165
+ * a fact come to disagree.
152
166
  *
153
- * ```ts
154
- * foreignChildren: [
155
- * { entityType: 'workorder', parentType: 'bike' }, // parent CHECKED
156
- * { entityType: 'protocol', parentType: 'workorder' }, // parent foreign too
157
- * ]
158
- * ```
159
- *
160
- * `parentType` accepts a declared entity name or an arbitrary string, and a
161
- * typo that happens to look like neither is still accepted — TypeScript cannot
162
- * express "one of these, or any other string, but tell me which". What it does
163
- * buy is autocomplete on the local names and a compile error on the mixed edge
164
- * once `foreignParents` (below) is used instead.
165
- *
166
- * Both become fully checkable when engines export their entity-type constants
167
- * (#696 item 3), at which point these two fields collapse back into `parent`.
167
+ * This replaces the `foreignChildOf` / `foreignChildren` pair, which existed
168
+ * only because foreign names were uncheckable. They are now, so the split has
169
+ * nothing left to say.
168
170
  */
169
- readonly foreignChildren?: readonly {
170
- readonly entityType: string;
171
- readonly parentType: (keyof T & string) | (string & {});
172
- }[];
173
- /**
174
- * The mixed edge, stated so the checkable half IS checked: a child this module
175
- * does not own, hanging off a parent it does. `parentType` here is strictly a
176
- * declared entity — a typo is a compile error.
177
- *
178
- * `bike_shop`'s `workorder → bike` is the case: `workorder` is the engine's,
179
- * `bike` is the vertical's, and the vertical is the only place that knows the
180
- * edge exists.
181
- */
182
- readonly foreignChildOf?: readonly {
183
- readonly entityType: string;
184
- readonly parentType: keyof T & string;
171
+ readonly relations?: readonly {
172
+ readonly entityType: (keyof T & string) | (M extends {
173
+ engines: readonly (infer R)[];
174
+ } ? NamesOf<R> : never);
175
+ readonly parentType: (keyof T & string) | (M extends {
176
+ engines: readonly (infer R)[];
177
+ } ? NamesOf<R> : never);
185
178
  }[];
186
179
  };
180
+ /** Every entity name in one registry. */
181
+ type NamesOf<R> = R extends Record<string, EntityDef> ? keyof R & string : never;
187
182
  /**
188
183
  * Compose the entity-referencing manifest fragments against the registry.
189
184
  *
@@ -217,5 +212,38 @@ export declare function manifestEntities<const T extends Record<string, EntityDe
217
212
  entityViews: M['entityViews'];
218
213
  };
219
214
  };
215
+ /**
216
+ * The row type of a declared entity — what `ctx.sql.query` returns for it.
217
+ *
218
+ * `ctx.sql.query` leaves `T` to the vertical, so every handler writes its own
219
+ * row interface and the schema ends up described three times: the DDL, the
220
+ * registry, and a hand-written `interface CustomerRow`. This collapses the
221
+ * third into the second.
222
+ *
223
+ * ```ts
224
+ * export type CustomerRow = EntityRow<typeof calloutEntities, 'customer'>;
225
+ * ```
226
+ */
227
+ export type EntityRow<T extends Record<string, EntityDef>, K extends keyof T> = T[K] extends {
228
+ fields: infer F;
229
+ } ? F extends z.ZodObject<z.ZodRawShape> ? z.infer<F> : never : never;
230
+ /**
231
+ * Column names per table, read out of a migration journal's SQL.
232
+ *
233
+ * **Test tooling**, exported because three engines had hand-rolled a copy and
234
+ * the copies had already drifted — none followed `RENAME TO`, so a journal that
235
+ * rebuilds a table under a temporary name would report the pre-rebuild columns
236
+ * forever.
237
+ *
238
+ * It exists because a registry and a journal are two descriptions of one schema
239
+ * until migrations are derived from the registry. Holding them to each other is
240
+ * what keeps that duplication safe in the meantime.
241
+ *
242
+ * Handles what real journals do: multi-line `CHECK (...)` constraints (tracked
243
+ * by paren depth, so a continuation line is not read as a column), `ADD COLUMN`,
244
+ * `DROP TABLE`, and `RENAME TO` — append-only journals rebuild a table by
245
+ * creating a `_new`, copying, dropping the original and renaming onto its name.
246
+ */
247
+ export declare function journalColumns(sql: string): Map<string, Set<string>>;
220
248
  export {};
221
249
  //# sourceMappingURL=model.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
package/dist/model.js CHANGED
@@ -50,7 +50,7 @@ export function emitModel(entities) {
50
50
  out[name] = {
51
51
  table: e.table,
52
52
  fields,
53
- ...(e.parent ? { parent: e.parent } : {}),
53
+ ...(e.parents?.length ? { parents: [...e.parents].sort() } : {}),
54
54
  ...(e.key ? { key: [...e.key].sort() } : {}),
55
55
  ...(e.erasable ? { erasable: [...e.erasable].sort() } : {}),
56
56
  };
@@ -69,8 +69,10 @@ export function entityRelationsOf(entities) {
69
69
  return Object.keys(entities)
70
70
  .sort()
71
71
  .flatMap((name) => {
72
- const parent = entities[name]?.parent;
73
- return parent ? [{ entityType: name, parentType: parent }] : [];
72
+ const parents = entities[name]?.parents;
73
+ if (!parents?.length)
74
+ return [];
75
+ return [...parents].sort().map((parentType) => ({ entityType: name, parentType }));
74
76
  });
75
77
  }
76
78
  /**
@@ -100,14 +102,66 @@ export function manifestEntities(entities, refs) {
100
102
  attachmentTargets: (refs.attachmentTargets ?? []),
101
103
  searchables: refs.searchables,
102
104
  // Derived edges first, then the ones this module cannot check.
103
- entityRelations: [
104
- ...entityRelationsOf(entities),
105
- // Checked parent, foreign child — the mixed edge.
106
- ...(refs.foreignChildOf ?? []),
107
- // Neither side checkable here.
108
- ...(refs.foreignChildren ?? []),
109
- ],
105
+ // Local edges are derived from the entities' own `parents`; edges involving
106
+ // a composed engine's entity are declared, and both sides are checked.
107
+ entityRelations: [...entityRelationsOf(entities), ...(refs.relations ?? [])],
110
108
  ui: { entityViews: refs.entityViews },
111
109
  };
112
110
  }
111
+ /**
112
+ * Column names per table, read out of a migration journal's SQL.
113
+ *
114
+ * **Test tooling**, exported because three engines had hand-rolled a copy and
115
+ * the copies had already drifted — none followed `RENAME TO`, so a journal that
116
+ * rebuilds a table under a temporary name would report the pre-rebuild columns
117
+ * forever.
118
+ *
119
+ * It exists because a registry and a journal are two descriptions of one schema
120
+ * until migrations are derived from the registry. Holding them to each other is
121
+ * what keeps that duplication safe in the meantime.
122
+ *
123
+ * Handles what real journals do: multi-line `CHECK (...)` constraints (tracked
124
+ * by paren depth, so a continuation line is not read as a column), `ADD COLUMN`,
125
+ * `DROP TABLE`, and `RENAME TO` — append-only journals rebuild a table by
126
+ * creating a `_new`, copying, dropping the original and renaming onto its name.
127
+ */
128
+ export function journalColumns(sql) {
129
+ const tables = new Map();
130
+ for (const [, table, body] of sql.matchAll(/CREATE TABLE (?:IF NOT EXISTS )?([a-z_][a-z0-9_]*)\s*\(([\s\S]*?)\n\s*\);/gi)) {
131
+ if (!table || !body)
132
+ continue;
133
+ const cols = new Set();
134
+ let depth = 0;
135
+ for (const raw of body.split('\n')) {
136
+ const line = raw.trim();
137
+ const atTop = depth === 0;
138
+ depth += (line.match(/\(/g) ?? []).length - (line.match(/\)/g) ?? []).length;
139
+ if (!atTop)
140
+ continue;
141
+ if (!line || line.startsWith('--') || /^(PRIMARY|FOREIGN|UNIQUE|CHECK|CONSTRAINT)\b/i.test(line))
142
+ continue;
143
+ const name = /^([a-z_][a-z0-9_]*)\b/i.exec(line)?.[1];
144
+ if (name)
145
+ cols.add(name);
146
+ }
147
+ tables.set(table, cols);
148
+ }
149
+ // Replayed in statement order: a journal may add a column and later rename the
150
+ // table, or rename onto a name it has just dropped.
151
+ for (const m of sql.matchAll(/(?:ALTER TABLE ([a-z_][a-z0-9_]*)\s+ADD COLUMN\s+([a-z_][a-z0-9_]*))|(?:ALTER TABLE ([a-z_][a-z0-9_]*)\s+RENAME TO\s+([a-z_][a-z0-9_]*))|(?:DROP TABLE (?:IF EXISTS )?([a-z_][a-z0-9_]*))/gi)) {
152
+ const [, addTable, addCol, fromTable, toTable, dropped] = m;
153
+ if (addTable && addCol)
154
+ tables.get(addTable)?.add(addCol);
155
+ else if (dropped)
156
+ tables.delete(dropped);
157
+ else if (fromTable && toTable) {
158
+ const cols = tables.get(fromTable);
159
+ if (cols) {
160
+ tables.delete(fromTable);
161
+ tables.set(toTable, cols);
162
+ }
163
+ }
164
+ }
165
+ return tables;
166
+ }
113
167
  //# sourceMappingURL=model.js.map
package/dist/model.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA8BxB;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAO5B,QAAW;IACX,OAAO,QAAQ,CAAC;AAClB,CAAC;AA6BD;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAsC,QAAW;IACxE,MAAM,GAAG,GAAkC,EAAE,CAAC;IAC9C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAChD,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,CAGvG,CAAC;QACF,GAAG,CAAC,IAAI,CAAC,GAAG;YACV,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,MAAM;YACN,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5C,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5D,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;AAC3B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAW;IAEX,OAAO,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;SACzB,IAAI,EAAE;SACN,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAChB,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QACtC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAClE,CAAC,CAAC,CAAC;AACP,CAAC;AAsFD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,gBAAgB,CAI9B,QAAW,EACX,IAAO;IAOP,OAAO;QACL,iBAAiB,EAAE,CAAC,IAAI,CAAC,iBAAiB,IAAI,EAAE,CAA6C;QAC7F,WAAW,EAAE,IAAI,CAAC,WAA+B;QACjD,+DAA+D;QAC/D,eAAe,EAAE;YACf,GAAG,iBAAiB,CAAC,QAAQ,CAAC;YAC9B,kDAAkD;YAClD,GAAG,CAAC,IAAI,CAAC,cAAc,IAAI,EAAE,CAAC;YAC9B,+BAA+B;YAC/B,GAAG,CAAC,IAAI,CAAC,eAAe,IAAI,EAAE,CAAC;SAChC;QACD,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,WAA+B,EAAE;KAC1D,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,223 @@
1
+ /**
2
+ * The operation surface of the model (#707).
3
+ *
4
+ * #697 declared the entities. This declares what can be *done* to them, and
5
+ * checks the joins that today are unchecked strings: which permission an
6
+ * operation requires, which output field an event takes its subject from,
7
+ * whether a payload carries something an erasure must be able to reach.
8
+ *
9
+ * ## A composer, not a second `defineModel`
10
+ *
11
+ * `defineOperations` sits beside `defineEntities` rather than swallowing it.
12
+ * Each half stays independently adoptable — which is what let the entity half
13
+ * ship and be taken up by two verticals before this existed. A vertical adopts
14
+ * operations when it is ready, not as the price of adopting entities.
15
+ *
16
+ * ## `input`, and the transcription that is not here
17
+ *
18
+ * `input` is the Zod object the handler already parses — the same object, not a
19
+ * description of it. That is the whole reason the model is TypeScript (#680): a
20
+ * schema language would need the shape written twice, and transcription is what
21
+ * produced 40 wrong argument names in the one app where this was measured.
22
+ */
23
+ import { z } from 'zod';
24
+ import type { EntityDef } from './model.js';
25
+ /** `{var}` names in a literal path. */
26
+ type PathParams<S extends string> = S extends `${string}{${infer P}}${infer Rest}` ? P | PathParams<Rest> : never;
27
+ type InputKeys<O> = O extends {
28
+ input: infer I;
29
+ } ? (I extends z.ZodType ? keyof z.infer<I> & string : never) : never;
30
+ type OutputKeys<O> = O extends {
31
+ output: infer R;
32
+ } ? (R extends z.ZodType ? keyof z.infer<R> & string : never) : never;
33
+ /** Every `{var}` must name an input field, or the path type collapses. */
34
+ type CheckedPath<O> = O extends {
35
+ http: {
36
+ path: infer P;
37
+ };
38
+ } ? P extends string ? [PathParams<P>] extends [InputKeys<O>] ? P : never : never : string;
39
+ /**
40
+ * The erasable fields OF THE ENTITY THIS EVENT IS ABOUT.
41
+ *
42
+ * Resolving through `emits.entity` rather than matching field names across all
43
+ * entities is what makes the §12 check exact. A `contactPerson.email` marked
44
+ * erasable must not stop an event about an `office` carrying its own `email` —
45
+ * a rule that refuses correct code trains people to route around it, which is
46
+ * how a PII rule stops being obeyed.
47
+ */
48
+ type ErasableOf<Entities, O> = O extends {
49
+ emits: {
50
+ entity: infer N;
51
+ };
52
+ } ? N extends keyof Entities ? Entities[N] extends {
53
+ erasable: readonly (infer F)[];
54
+ } ? F & string : never : never : never;
55
+ /**
56
+ * The platform's own event invariant, moved from runtime to compile time.
57
+ * `contracts/events.ts` enforces it with a `superRefine`: *"subjectId is
58
+ * required when piiClass is 'direct' — crypto-shredding must be able to key the
59
+ * erasure"*. Classification is mandatory here for the same reason it is there:
60
+ * an unclassified event type cannot be declared.
61
+ */
62
+ type PiiShape<O, OutKeys extends string> = O extends {
63
+ emits: {
64
+ piiClass: 'none';
65
+ };
66
+ } ? {
67
+ readonly piiClass: 'none';
68
+ readonly subjectId?: never;
69
+ } : {
70
+ readonly piiClass: 'pseudonymous' | 'direct';
71
+ readonly subjectId: OutKeys;
72
+ };
73
+ /**
74
+ * An operation carries a leading `permission` OR `narrows` with a reason, never
75
+ * both and never neither (rule 5 / CRM-EFF's check 14). `narrows` is the
76
+ * per-row proof walk: a salesperson listing their own customers must get their
77
+ * list, not a denial.
78
+ */
79
+ type OpAuthority<O, PermKey extends string> = O extends {
80
+ narrows: unknown;
81
+ } ? {
82
+ readonly narrows: {
83
+ readonly reason: string;
84
+ };
85
+ readonly permission?: never;
86
+ } : {
87
+ readonly permission: PermKey;
88
+ readonly narrows?: never;
89
+ };
90
+ /**
91
+ * The per-operation constraint, self-referential in `O`.
92
+ *
93
+ * Each operation is checked against ITS OWN declared input and output rather
94
+ * than an erased supertype. Written the obvious way every check below compiles
95
+ * clean and enforces nothing — see `test/operations.test.ts`, which exists to
96
+ * prove they still bite.
97
+ */
98
+ type OperationShape<O, Entities, PermKey extends string> = {
99
+ /** One line, imperative — what invoking this does. Feeds the API document. */
100
+ readonly summary: string;
101
+ /**
102
+ * The request body — the SAME Zod object the handler parses.
103
+ *
104
+ * **Omitted means no body at all**, and the handler then takes `undefined`.
105
+ * Found by the first adopter: three of Callout's six operations take no input,
106
+ * and a required `z.object({})` cannot say so — a handler accepting only
107
+ * `undefined` is not assignable to one accepting `{}`.
108
+ *
109
+ * This mirrors `ApiOperationDoc.input` ("Omit = no body") rather than
110
+ * inventing a second vocabulary for the same fact.
111
+ */
112
+ readonly input?: z.ZodObject<z.ZodRawShape>;
113
+ /** True when the handler accepts a body but also accepts none (filter-style reads). */
114
+ readonly inputOptional?: boolean;
115
+ /**
116
+ * Declared, not inferred (#695 Ask 2). Inference documents accidents: one
117
+ * inferred return carried `contacts?: undefined`, an artefact of an early
118
+ * return, which generation would have cemented into the published API.
119
+ *
120
+ * Declare a return where a caller branches on it — a UI lane is a caller that
121
+ * branches, which is why #682/#683 depend on this.
122
+ */
123
+ readonly output: z.ZodType;
124
+ readonly http?: {
125
+ readonly method: 'GET' | 'POST' | 'PATCH' | 'DELETE';
126
+ readonly path: CheckedPath<O>;
127
+ };
128
+ readonly emits?: {
129
+ /** The entity the event is about — a declared entity. */
130
+ readonly entity: keyof Entities & string;
131
+ /**
132
+ * Which OUTPUT field carries that entity's id.
133
+ *
134
+ * The #695 defect: 18 operations emitted `entityId: String(result.id)` on
135
+ * objects that answer with `contractId` / `runId` / `instanceId`. For a
136
+ * mutation writing a child the event is about the PARENT, so the two differ
137
+ * and nothing downstream would ever have flagged it.
138
+ */
139
+ readonly entityIdFrom: OutputKeys<O>;
140
+ readonly type: string;
141
+ readonly schemaVersion: number;
142
+ /**
143
+ * Fat payload, drawn from the output — minus anything the entity marks
144
+ * `erasable`. Immutable events are the one place in a scope an erasure
145
+ * cannot reach.
146
+ */
147
+ readonly payload?: readonly Exclude<OutputKeys<O>, ErasableOf<Entities, O>>[];
148
+ } & PiiShape<O, OutputKeys<O>>;
149
+ /**
150
+ * Per-field permission on the projection: omission, not denial. The caller
151
+ * still gets the row, without the fields they may not see.
152
+ */
153
+ readonly gates?: {
154
+ readonly [F in OutputKeys<O>]?: PermKey;
155
+ };
156
+ } & OpAuthority<O, PermKey>;
157
+ /**
158
+ * Declare a module's operations against its entities and permission keys.
159
+ *
160
+ * Curried so the entities and permissions are given explicitly while each
161
+ * operation still infers its own input and output — a callback parameter cannot
162
+ * be contextually typed by a generic being inferred from the object containing
163
+ * it.
164
+ *
165
+ * ```ts
166
+ * export const ops = defineOperations(calloutEntities, PERMISSIONS)({
167
+ * 'customer/create': {
168
+ * summary: 'Register a customer',
169
+ * permission: 'customer:manage',
170
+ * input: z.object({ name: z.string() }),
171
+ * output: z.object({ id: z.string(), number: z.string() }),
172
+ * http: { method: 'POST', path: '/customers' },
173
+ * emits: {
174
+ * entity: 'customer', entityIdFrom: 'id',
175
+ * type: 'callout.customer-created', schemaVersion: 1, piiClass: 'none',
176
+ * },
177
+ * },
178
+ * });
179
+ * ```
180
+ */
181
+ export declare function defineOperations<const Entities extends Record<string, EntityDef>, const Perms extends readonly string[]>(_entities: Entities, _permissions: Perms): <const Ops extends { readonly [K in keyof Ops]: OperationShape<Ops[K], Entities, Perms[number]>; }>(operations: Ops) => Ops;
182
+ /**
183
+ * The permission keys an operation set actually requires, for the manifest.
184
+ *
185
+ * Read structurally rather than through a `{ permission?: string }` parameter:
186
+ * a `narrows` operation has neither `permission` nor `emits`, and TypeScript's
187
+ * weak-type rule rejects an object sharing no properties with the parameter.
188
+ */
189
+ export declare function permissionsUsedBy(operations: Readonly<Record<string, object>>): string[];
190
+ /** The event types an operation set emits, for `manifest.events.emits`. */
191
+ export declare function eventsEmittedBy(operations: Readonly<Record<string, object>>): {
192
+ type: string;
193
+ schemaVersion: number;
194
+ }[];
195
+ /**
196
+ * The handler map a declared operation set requires — CRM-EFF's `satisfies Impl`
197
+ * seam, which is what makes the declaration BINDING rather than decorative.
198
+ *
199
+ * ```ts
200
+ * export const operations = { … } satisfies OperationImpl<typeof calloutOps, OperationContext>;
201
+ * ```
202
+ *
203
+ * Four things become compile errors at the exact method: a handler whose input
204
+ * disagrees with the declared `input`, one whose return disagrees with the
205
+ * declared `output`, an operation declared and not implemented, and one
206
+ * implemented and not declared.
207
+ *
208
+ * `Ctx` is a parameter rather than `OperationContext` because contracts is below
209
+ * the kernel and must not import it. The vertical supplies it.
210
+ */
211
+ export type OperationImpl<Ops, Ctx> = {
212
+ [K in keyof Ops]: Ops[K] extends {
213
+ output: infer O;
214
+ } ? O extends z.ZodType ? (ctx: Ctx, input: ImplInput<Ops[K]>) => z.infer<O> | Promise<z.infer<O>> : never : never;
215
+ };
216
+ /** No declared `input` means the handler takes `undefined`. */
217
+ type ImplInput<O> = O extends {
218
+ input: infer I;
219
+ } ? I extends z.ZodType ? O extends {
220
+ inputOptional: true;
221
+ } ? z.infer<I> | undefined : z.infer<I> : undefined : undefined;
222
+ export {};
223
+ //# sourceMappingURL=operations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../src/operations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * The operation surface of the model (#707).
3
+ *
4
+ * #697 declared the entities. This declares what can be *done* to them, and
5
+ * checks the joins that today are unchecked strings: which permission an
6
+ * operation requires, which output field an event takes its subject from,
7
+ * whether a payload carries something an erasure must be able to reach.
8
+ *
9
+ * ## A composer, not a second `defineModel`
10
+ *
11
+ * `defineOperations` sits beside `defineEntities` rather than swallowing it.
12
+ * Each half stays independently adoptable — which is what let the entity half
13
+ * ship and be taken up by two verticals before this existed. A vertical adopts
14
+ * operations when it is ready, not as the price of adopting entities.
15
+ *
16
+ * ## `input`, and the transcription that is not here
17
+ *
18
+ * `input` is the Zod object the handler already parses — the same object, not a
19
+ * description of it. That is the whole reason the model is TypeScript (#680): a
20
+ * schema language would need the shape written twice, and transcription is what
21
+ * produced 40 wrong argument names in the one app where this was measured.
22
+ */
23
+ import { z } from 'zod';
24
+ // ---------------------------------------------------------------------------
25
+ // The composer.
26
+ // ---------------------------------------------------------------------------
27
+ /**
28
+ * Declare a module's operations against its entities and permission keys.
29
+ *
30
+ * Curried so the entities and permissions are given explicitly while each
31
+ * operation still infers its own input and output — a callback parameter cannot
32
+ * be contextually typed by a generic being inferred from the object containing
33
+ * it.
34
+ *
35
+ * ```ts
36
+ * export const ops = defineOperations(calloutEntities, PERMISSIONS)({
37
+ * 'customer/create': {
38
+ * summary: 'Register a customer',
39
+ * permission: 'customer:manage',
40
+ * input: z.object({ name: z.string() }),
41
+ * output: z.object({ id: z.string(), number: z.string() }),
42
+ * http: { method: 'POST', path: '/customers' },
43
+ * emits: {
44
+ * entity: 'customer', entityIdFrom: 'id',
45
+ * type: 'callout.customer-created', schemaVersion: 1, piiClass: 'none',
46
+ * },
47
+ * },
48
+ * });
49
+ * ```
50
+ */
51
+ export function defineOperations(_entities, _permissions) {
52
+ return (operations) => operations;
53
+ }
54
+ /**
55
+ * The permission keys an operation set actually requires, for the manifest.
56
+ *
57
+ * Read structurally rather than through a `{ permission?: string }` parameter:
58
+ * a `narrows` operation has neither `permission` nor `emits`, and TypeScript's
59
+ * weak-type rule rejects an object sharing no properties with the parameter.
60
+ */
61
+ export function permissionsUsedBy(operations) {
62
+ const keys = Object.values(operations).flatMap((op) => {
63
+ const permission = op.permission;
64
+ return typeof permission === 'string' ? [permission] : [];
65
+ });
66
+ return [...new Set(keys)].sort();
67
+ }
68
+ /** The event types an operation set emits, for `manifest.events.emits`. */
69
+ export function eventsEmittedBy(operations) {
70
+ const seen = new Map();
71
+ for (const op of Object.values(operations)) {
72
+ const emits = op.emits;
73
+ if (typeof emits?.type === 'string' && typeof emits.schemaVersion === 'number') {
74
+ seen.set(emits.type, emits.schemaVersion);
75
+ }
76
+ }
77
+ return [...seen.entries()]
78
+ .sort(([a], [b]) => a.localeCompare(b))
79
+ .map(([type, schemaVersion]) => ({ type, schemaVersion }));
80
+ }
81
+ //# sourceMappingURL=operations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.js","sourceRoot":"","sources":["../src/operations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAiIxB,8EAA8E;AAC9E,gBAAgB;AAChB,8EAA8E;AAE9E;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,gBAAgB,CAG9B,SAAmB,EAAE,YAAmB;IACxC,OAAO,CAKL,UAAe,EACV,EAAE,CAAC,UAAU,CAAC;AACvB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAA4C;IAC5E,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE;QACpD,MAAM,UAAU,GAAI,EAA+B,CAAC,UAAU,CAAC;QAC/D,OAAO,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AACnC,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,eAAe,CAC7B,UAA4C;IAE5C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IACvC,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAI,EAA8D,CAAC,KAAK,CAAC;QACpF,IAAI,OAAO,KAAK,EAAE,IAAI,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,aAAa,KAAK,QAAQ,EAAE,CAAC;YAC/E,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;SACvB,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;SACtC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,aAAa,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;AAC/D,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@substrat-run/contracts",
3
- "version": "0.67.0",
3
+ "version": "0.69.0",
4
4
  "description": "Substrat kernel contract schemas — Zod is the source of truth (master plan D-22); OAS/JSON Schema are emitted artifacts",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {