@tai42/api-client 13.3.0 → 15.0.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/src/schemas.ts CHANGED
@@ -12,6 +12,35 @@ export const jsonValue: z.ZodType = z.unknown();
12
12
  /** A JSON Schema object (Pydantic-emitted). Permissive; parsed by the auto-form. */
13
13
  export const jsonSchema = z.record(z.string(), z.unknown());
14
14
 
15
+ /**
16
+ * One authored-text value: either inline `content` (text written in place) or a
17
+ * stored template `id` (a template resource fetched and rendered), never both and
18
+ * never neither. `kwargs` are the render parameters and apply in BOTH cases — a
19
+ * prompt with placeholders needs its values whether it was typed inline or fetched.
20
+ * `.strict()` refuses any other key so a drifting field fails the parse loudly.
21
+ */
22
+ export const templatedText = z
23
+ .object({
24
+ content: z.string().optional(),
25
+ id: z.string().optional(),
26
+ kwargs: z.record(z.string(), z.unknown()).optional(),
27
+ })
28
+ .strict()
29
+ .refine((value) => (value.content === undefined) !== (value.id === undefined), {
30
+ message: 'A templated-text value sets exactly one of `content` or `id`.',
31
+ });
32
+ export type TemplatedText = z.infer<typeof templatedText>;
33
+
34
+ /**
35
+ * A templated-text value that must carry a source: inline `content` is non-empty, or
36
+ * a stored template `id` is chosen. Used where the platform contract requires a
37
+ * value (e.g. a state binding's subject, an update's adapter when present).
38
+ */
39
+ export const requiredTemplatedText = templatedText.refine(
40
+ (value) => (value.id !== undefined ? value.id.length > 0 : (value.content ?? '').length > 0),
41
+ { message: 'Provide inline text or choose a stored template.' },
42
+ );
43
+
15
44
  // -- tools -------------------------------------------------------------------
16
45
 
17
46
  export const toolNames = z.array(z.string());
@@ -115,8 +144,9 @@ export const presetExtensions = z.array(z.array(presetExtensionElement));
115
144
  * One preset as `GET /api/presets` returns it. Every preset is versioned, so
116
145
  * `active_version` is always an int; `conflicted` marks a QUARANTINED row (its
117
146
  * name collided with a foreign tool at boot — delete-only). `extensions` are the
118
- * ACTIVE version's extension combos and `output_schema` the optional author-set
119
- * output JSON Schema. Categorization tags live in the tool_meta overlay
147
+ * ACTIVE version's extension combos, `output_schema` the optional author-set
148
+ * output JSON Schema, and `input_schema` the optional author-set input JSON
149
+ * Schema. Categorization tags live in the tool_meta overlay
120
150
  * (`GET /api/tool-meta`), never on the record. A drift throws `ApiSchemaError`;
121
151
  * nothing is coerced.
122
152
  */
@@ -127,6 +157,7 @@ export const presetRecord = z.object({
127
157
  active_version: z.number(),
128
158
  extensions: presetExtensions,
129
159
  output_schema: z.record(z.string(), z.unknown()).nullable(),
160
+ input_schema: z.record(z.string(), z.unknown()).nullable(),
130
161
  conflicted: z.boolean(),
131
162
  // The human-readable cause a row is quarantined (its name collided with a
132
163
  // foreign tool at boot), or `null` when the row is not conflicted. Rendered
@@ -147,6 +178,79 @@ export const presetDetail = presetRecord.extend({
147
178
  });
148
179
  export type PresetDetail = z.infer<typeof presetDetail>;
149
180
 
181
+ /**
182
+ * One input injection of a state binding: BEFORE the run, a value is produced and
183
+ * placed into the run input under `into` (the run-input field name). A template
184
+ * `input` jq (`template_jq`, named `name` or attachment-qualified `template.name`) reads the
185
+ * record — its input is the record (`.`), with declared params bound as `$params`; a
186
+ * custom `jq` reads `{record, input}` → the value. Exactly one of `template_jq`/`jq`
187
+ * carries the program; the other is `null`.
188
+ */
189
+ export const stateInjection = z.object({
190
+ // `template_jq` names a program the attached state template ships; it is resolved
191
+ // through compiled programs, never rendered as text, so it stays a plain string.
192
+ template_jq: z.string().nullable().default(null),
193
+ jq: templatedText.nullable().default(null),
194
+ into: z.string(),
195
+ });
196
+ export type StateInjection = z.infer<typeof stateInjection>;
197
+
198
+ /**
199
+ * One update of a state binding: AFTER the run, a template-relative op batch is
200
+ * applied through the store. A NAMED update (`template_jq`) runs the template `update`
201
+ * jq over `{record, input}` where `input` is built by `adapter` — a jq over
202
+ * `{output, input}` that constructs the update jq's declared input object. A custom
203
+ * `jq` runs over `{record, output, input}` → `[{op, path, value}]` and carries no
204
+ * adapter. `op_id` is an optional idempotency-key expression. Exactly one of
205
+ * `template_jq`/`jq` carries the program.
206
+ */
207
+ export const stateUpdate = z.object({
208
+ // `template_jq` names a program the attached state template ships; resolved through
209
+ // compiled programs, never rendered as text, so it stays a plain string.
210
+ template_jq: z.string().nullable().default(null),
211
+ jq: templatedText.nullable().default(null),
212
+ // A named update's adapter is either an authored value or `null` (no adapter — the
213
+ // run input passes through). When present it must carry a source (the platform
214
+ // compile-checks a non-null adapter and refuses an empty one).
215
+ adapter: requiredTemplatedText.nullable().default(null),
216
+ op_id: templatedText.nullable().default(null),
217
+ });
218
+ export type StateUpdate = z.infer<typeof stateUpdate>;
219
+
220
+ /**
221
+ * One attached state of a binding: the `state`, one or more `templates`
222
+ * (attach-on-use — attached to the state on the binding's save), the `subject_expr`
223
+ * (a jq yielding the record KEY — a bare key string OR a full subject object — that
224
+ * this binding reads and updates), an optional `scope_expr` (a boolean jq predicate;
225
+ * when it is false this state is skipped for the run), and the ordered
226
+ * `input_injections` (before the run) and `updates` (after it).
227
+ */
228
+ export const stateAttach = z.object({
229
+ state: z.string(),
230
+ templates: z.array(z.string()).default([]),
231
+ // The platform contract enforces a subject that carries a source; an empty one is
232
+ // rejected here, never sent for the server to refuse.
233
+ subject_expr: requiredTemplatedText,
234
+ scope_expr: templatedText.nullable().default(null),
235
+ input_injections: z.array(stateInjection).default([]),
236
+ updates: z.array(stateUpdate).default([]),
237
+ });
238
+ export type StateAttach = z.infer<typeof stateAttach>;
239
+
240
+ /**
241
+ * The one generic binding shape carried, optionally, on every runnable definition
242
+ * (a preset, a channel route, a schedule, a hook) and repeated per node by the
243
+ * flow engine. It attaches one or more states, each with its templates, subject,
244
+ * injections and updates. `null` on a definition means no binding. Mirrors the
245
+ * platform `StateBinding` document.
246
+ */
247
+ export const stateBinding = z.object({
248
+ // At least one attached state: the platform contract refuses a zero-state binding, so
249
+ // "no binding" is spelled `null` on the definition, never `{ states: [] }`.
250
+ states: z.array(stateAttach).min(1),
251
+ });
252
+ export type StateBinding = z.infer<typeof stateBinding>;
253
+
150
254
  /** The full version body a preset stores under `kind="preset"`. */
151
255
  export const presetBody = z.object({
152
256
  base_tool: z.string(),
@@ -154,6 +258,10 @@ export const presetBody = z.object({
154
258
  fixed_kwargs: z.record(z.string(), z.unknown()),
155
259
  extensions: presetExtensions,
156
260
  output_schema: z.record(z.string(), z.unknown()).nullable(),
261
+ input_schema: z.record(z.string(), z.unknown()).nullable(),
262
+ // The optional door-layer state binding this preset applies around every run
263
+ // (`null` when the preset touches no state).
264
+ state_binding: stateBinding.nullable().default(null),
157
265
  });
158
266
  export type PresetBody = z.infer<typeof presetBody>;
159
267
 
@@ -1140,6 +1248,9 @@ export const conversationRoute = z.object({
1140
1248
  turns_per_hour_override: z.number().int().nullable().default(null),
1141
1249
  error_reply_text: z.string().nullable().default(null),
1142
1250
  execution_key_fingerprint: z.string(),
1251
+ // The door-layer state binding the backend stores on the route's target config and
1252
+ // returns on read (`null` when the route touches no state) — the edit form prefills it.
1253
+ state_binding: stateBinding.nullable().default(null),
1143
1254
  });
1144
1255
  export type ConversationRoute = z.infer<typeof conversationRoute>;
1145
1256
 
@@ -1176,6 +1287,9 @@ export const conversationRouteCreate = z.object({
1176
1287
  callback_url: z.string().nullable().default(null),
1177
1288
  turns_per_hour_override: z.number().int().positive().nullable().default(null),
1178
1289
  error_reply_text: z.string().min(1).max(2000).nullable().default(null),
1290
+ // The optional door-layer state binding this route applies around every turn's
1291
+ // tool run (`null` when the route touches no state).
1292
+ state_binding: stateBinding.nullable().default(null),
1179
1293
  });
1180
1294
  export type ConversationRouteCreate = z.infer<typeof conversationRouteCreate>;
1181
1295
 
@@ -1495,8 +1609,8 @@ export type Notifications = z.infer<typeof notifications>;
1495
1609
 
1496
1610
  // -- hooks -------------------------------------------------------------------
1497
1611
  // Shapes match tai42_contract.hooks.HookParams: a hook fires a `tool` on a `topic`,
1498
- // optionally gated by a `condition` and shaped by an `expr` (each either an inline
1499
- // spec or a registered id, with its own kwargs).
1612
+ // optionally gated by a `condition` and shaped by an `expr` (each an authored
1613
+ // templated-text value: inline content or a stored template id, with render kwargs).
1500
1614
 
1501
1615
  /** A fire door — who may trigger a path, not what the fire may do. A string enum. */
1502
1616
  export const triggerAuth = z.enum([
@@ -1532,14 +1646,11 @@ export const hookParams = z.object({
1532
1646
  // The optional state subject the fire targets; `null` leaves it with no ambient
1533
1647
  // state context (a state tool it calls must then carry an explicit subject).
1534
1648
  subject: hookSubject.nullable().default(null),
1535
- condition: z.string().nullable().default(null),
1536
- condition_id: z.string().nullable().default(null),
1537
- // The `*_kwargs` pair is non-optional in the contract (defaults to {}, never
1538
- // null) — unlike the sibling condition/expr string fields, which are nullable.
1539
- condition_kwargs: z.record(z.string(), z.unknown()).default({}),
1540
- expr: z.string().nullable().default(null),
1541
- expr_id: z.string().nullable().default(null),
1542
- expr_kwargs: z.record(z.string(), z.unknown()).default({}),
1649
+ condition: templatedText.nullable().default(null),
1650
+ expr: templatedText.nullable().default(null),
1651
+ // The optional door-layer state binding this hook applies around its fire's tool
1652
+ // run (`null` when the hook touches no state).
1653
+ state_binding: stateBinding.nullable().default(null),
1543
1654
  });
1544
1655
  export type HookParams = z.infer<typeof hookParams>;
1545
1656
 
@@ -1718,16 +1829,14 @@ export type RoleGrants = z.infer<typeof roleGrants>;
1718
1829
  * read-only base-tier ceiling — the seeded jq `condition` plus `base_tier`
1719
1830
  * (`editor`/`viewer`, or `null` for the reserved `allow_all` admin). Layer 2 is the
1720
1831
  * editable per-tag `grants` map. `allow_all` (admin) carries an empty `grants` map
1721
- * and reaches everything, un-lockable. `condition`/`condition_id`/`condition_kwargs`
1722
- * are the base-tier jq — READ-ONLY here (no raw-jq authoring surface).
1832
+ * and reaches everything, un-lockable. `condition` is the base-tier jq (an authored
1833
+ * templated-text value) — READ-ONLY here (no raw-jq authoring surface).
1723
1834
  */
1724
1835
  export const roleBody = z.object({
1725
1836
  name: z.string(),
1726
1837
  description: z.string(),
1727
1838
  scopes: z.array(z.string()),
1728
- condition: z.string().nullable(),
1729
- condition_id: z.string().nullable(),
1730
- condition_kwargs: jsonValue.nullable(),
1839
+ condition: templatedText.nullable(),
1731
1840
  base_tier: z.string().nullable(),
1732
1841
  allow_all: z.boolean(),
1733
1842
  grants: roleGrants,
@@ -1795,9 +1904,7 @@ export const tokensPayload = z.array(
1795
1904
  description: z.string(),
1796
1905
  scopes: z.array(z.string()),
1797
1906
  policy_data: jsonValue,
1798
- condition: z.string().nullable().optional(),
1799
- condition_id: z.string().nullable().optional(),
1800
- condition_kwargs: jsonValue.nullable().optional(),
1907
+ condition: templatedText.nullable().optional(),
1801
1908
  }),
1802
1909
  );
1803
1910
  export type TokensPayload = z.infer<typeof tokensPayload>;
@@ -1977,15 +2084,13 @@ export type ValidateConditionResult = z.infer<typeof validateConditionResult>;
1977
2084
  /**
1978
2085
  * The enforced policy shape a version body carries. SECRET-ADJACENT — `condition`
1979
2086
  * can reveal auth logic, so its fixtures are hand-authored, never captured.
1980
- * `condition`/`condition_id` are mutually exclusive at author time; both are
1981
- * nullable here because whichever mode is unused is stored as `null`.
2087
+ * `condition` is an authored templated-text value (inline content or a stored
2088
+ * template id); `null` when the policy carries no condition.
1982
2089
  */
1983
2090
  export const policyBody = z.object({
1984
2091
  scopes: z.array(z.string()),
1985
2092
  policy_data: jsonValue,
1986
- condition: z.string().nullable(),
1987
- condition_id: z.string().nullable(),
1988
- condition_kwargs: jsonValue.nullable(),
2093
+ condition: templatedText.nullable(),
1989
2094
  });
1990
2095
  export type PolicyBody = z.infer<typeof policyBody>;
1991
2096
 
@@ -2613,11 +2718,11 @@ export { toolRunSubmitResult, toolRunRecord, toolRunList } from './tool-runs';
2613
2718
 
2614
2719
  // -- states ------------------------------------------------------------------
2615
2720
  // Shapes mirror tai42_contract.states.models: a declared JSON document, one per
2616
- // subject. The base document, module fragments, write regimes and effective schema
2721
+ // subject. The base document, template fragments, write regimes and effective schema
2617
2722
  // are permissive JSON records — the auto-form and JsonTree interpret them at runtime;
2618
- // a drift throws ApiSchemaError. Fields that WP-3's router is finishing concurrently
2619
- // (`effective_schema`, `regimes`, list/stats derived columns) are modelled optional so
2620
- // a server that has not yet composed them still parses.
2723
+ // a drift throws ApiSchemaError. Server-composed fields (`effective_schema`, `regimes`,
2724
+ // list/stats derived columns) are modelled optional so a response that omits them still
2725
+ // parses.
2621
2726
 
2622
2727
  /** One addressed subject: the conversation-target scope plus the (kind, key) within it. */
2623
2728
  export const stateSubject = z.object({
@@ -2628,12 +2733,12 @@ export const stateSubject = z.object({
2628
2733
  });
2629
2734
  export type StateSubject = z.infer<typeof stateSubject>;
2630
2735
 
2631
- /** One absolute write-regime rule composed over the mounts: `{path, regime}`, permissive. */
2736
+ /** One absolute write-regime rule composed over the attachments: `{path, regime}`, permissive. */
2632
2737
  export const stateRegime = z.record(z.string(), z.unknown());
2633
2738
 
2634
2739
  /**
2635
2740
  * A declared state served on every read. `schema` is the base JSON Schema;
2636
- * `effective_schema` (the base composed with every mounted module's fragment) and
2741
+ * `effective_schema` (the base composed with every attached template's fragment) and
2637
2742
  * `regimes` (the absolute write-regime rules) are platform-COMPUTED and served on every
2638
2743
  * read — modelled optional so a write body that omits them, or a server yet to compose
2639
2744
  * them, still parses. A drift throws ApiSchemaError.
@@ -2662,19 +2767,19 @@ export const stateListItem = stateDeclaration.extend({
2662
2767
  export type StateListItem = z.infer<typeof stateListItem>;
2663
2768
  export const stateList = z.array(stateListItem);
2664
2769
 
2665
- /** One module mount on a state: where the fragment lands + its param/declaration values. */
2666
- export const stateMount = z.object({
2667
- module: z.string(),
2770
+ /** One template attachment on a state: where the fragment lands + its param/declaration values. */
2771
+ export const stateAttachment = z.object({
2772
+ template: z.string(),
2668
2773
  path: z.array(z.string()),
2669
2774
  parameters: z.record(z.string(), z.unknown()).default({}),
2670
2775
  declarations: z.record(z.string(), z.unknown()).default({}),
2671
2776
  });
2672
- export type StateMount = z.infer<typeof stateMount>;
2673
- export const stateMountList = z.array(stateMount);
2777
+ export type StateAttachment = z.infer<typeof stateAttachment>;
2778
+ export const stateAttachmentList = z.array(stateAttachment);
2674
2779
 
2675
- /** `GET /api/states/{name}` — the declaration (with effective schema + regimes) plus mounts. */
2780
+ /** `GET /api/states/{name}` — the declaration (with effective schema + regimes) plus attachments. */
2676
2781
  export const stateDetail = stateDeclaration.extend({
2677
- mounts: z.array(stateMount).default([]),
2782
+ attachments: z.array(stateAttachment).default([]),
2678
2783
  });
2679
2784
  export type StateDetail = z.infer<typeof stateDetail>;
2680
2785
 
@@ -2692,34 +2797,84 @@ export const stateStats = z.object({
2692
2797
  });
2693
2798
  export type StateStats = z.infer<typeof stateStats>;
2694
2799
 
2695
- /** The platform half of a state-module document (mirrors StateModuleDocument). */
2696
- export const stateModuleDocument = z.object({
2697
- kind: z.literal('state-module').default('state-module'),
2800
+ /**
2801
+ * One template jq: `jq` is a program over the subject's attached subtree, authored as a
2802
+ * templated text (inline `content` or a stored template `id`); its `purpose` is either
2803
+ * `input` (a read-only program feeding a tool argument) or `update` (a program returning
2804
+ * an op batch that mutates the record). `params` are its declared argument names;
2805
+ * `reads`/`writes` are the template-relative record paths an `update` declares, each a
2806
+ * list of key segments; `description` is the human label.
2807
+ */
2808
+ export const templateJq = z.object({
2809
+ description: z.string().default(''),
2810
+ purpose: z.enum(['input', 'update']),
2811
+ params: z.array(z.string()).default([]),
2812
+ reads: z.array(z.array(z.string())).default([]),
2813
+ writes: z.array(z.array(z.string())).default([]),
2814
+ jq: templatedText,
2815
+ });
2816
+ export type TemplateJq = z.infer<typeof templateJq>;
2817
+
2818
+ /**
2819
+ * How a declarations edit settles open records: `orphans` returns the items a record
2820
+ * orphans against the new declarations, `close` builds the op batch that closes one
2821
+ * orphan, `resolutions` names the resolutions a close may name — each a templated-text
2822
+ * jq program (inline `content` or a stored template `id`).
2823
+ */
2824
+ export const templateReconcile = z.object({
2825
+ orphans: templatedText,
2826
+ close: templatedText,
2827
+ resolutions: templatedText,
2828
+ });
2829
+ export type TemplateReconcile = z.infer<typeof templateReconcile>;
2830
+
2831
+ /**
2832
+ * A template's declarations section: `schema` is the JSON schema of the static values an
2833
+ * attachment stores, and `check` is an optional attach-time predicate authored as a
2834
+ * templated text (inline `content` or a stored template `id`), `null` when the template
2835
+ * declares none.
2836
+ */
2837
+ export const templateDeclarations = z.object({
2838
+ schema: jsonSchema,
2839
+ check: templatedText.nullable().default(null),
2840
+ });
2841
+ export type TemplateDeclarations = z.infer<typeof templateDeclarations>;
2842
+
2843
+ /**
2844
+ * The platform half of a state-template document (mirrors StateTemplateDocument).
2845
+ * `template_jq` maps a name to its definition (each carrying its `purpose`);
2846
+ * `reconcile` is the settle policy; `declarations` is the static-values section — all
2847
+ * optional (`null` when the template declares none).
2848
+ */
2849
+ export const stateTemplateDocument = z.object({
2850
+ kind: z.literal('state-template').default('state-template'),
2698
2851
  name: z.string(),
2699
2852
  description: z.string().default(''),
2700
2853
  parameters: z.record(z.string(), z.unknown()).default({}),
2701
2854
  schema: jsonSchema,
2702
2855
  regimes: z.array(stateRegime).default([]),
2703
- declarations: z.record(z.string(), z.unknown()).nullable().default(null),
2856
+ declarations: templateDeclarations.nullable().default(null),
2704
2857
  trace: z.record(z.string(), z.unknown()).default({}),
2858
+ template_jq: z.record(z.string(), templateJq).nullable().default(null),
2859
+ reconcile: templateReconcile.nullable().default(null),
2705
2860
  });
2706
- export type StateModuleDocument = z.infer<typeof stateModuleDocument>;
2861
+ export type StateTemplateDocument = z.infer<typeof stateTemplateDocument>;
2707
2862
 
2708
2863
  /**
2709
- * One row of `GET /api/state-modules`. The module document plus the two derived columns
2710
- * the Modules tab shows: `mounted_on` (how many states mount it — a delete is refused
2711
- * while > 0) and `shipped_default` (a platform-shipped module). ASSUMED derived fields
2712
- * (WP-3 owns the list router); the document fields are verbatim.
2864
+ * One row of `GET /api/state-templates`. The template document plus the two derived columns
2865
+ * the Templates tab shows: `attached_to` (how many states attach it — a delete is refused
2866
+ * while > 0) and `shipped_default` (a platform-shipped template). Both are server-derived
2867
+ * columns; the document fields are verbatim.
2713
2868
  */
2714
- export const stateModuleListItem = stateModuleDocument.extend({
2715
- mounted_on: z.number().default(0),
2869
+ export const stateTemplateListItem = stateTemplateDocument.extend({
2870
+ attached_to: z.number().default(0),
2716
2871
  shipped_default: z.boolean().default(false),
2717
2872
  });
2718
- export type StateModuleListItem = z.infer<typeof stateModuleListItem>;
2719
- export const stateModuleList = z.array(stateModuleListItem);
2873
+ export type StateTemplateListItem = z.infer<typeof stateTemplateListItem>;
2874
+ export const stateTemplateList = z.array(stateTemplateListItem);
2720
2875
 
2721
2876
  /** A read record: the state, its subject, the document + monotonic seq, and any fold. */
2722
- export const recordView = z.object({
2877
+ export const stateRecord = z.object({
2723
2878
  state: z.string(),
2724
2879
  subject: stateSubject,
2725
2880
  data: z.record(z.string(), z.unknown()).default({}),
@@ -2727,7 +2882,7 @@ export const recordView = z.object({
2727
2882
  canonical_subject: stateSubject,
2728
2883
  folded_from: z.array(stateSubject).default([]),
2729
2884
  });
2730
- export type RecordView = z.infer<typeof recordView>;
2885
+ export type StateRecord = z.infer<typeof stateRecord>;
2731
2886
 
2732
2887
  /** The outcome of an `apply` (a delta batch): whether it applied + the resulting doc. */
2733
2888
  export const applyResult = z.object({
@@ -2738,6 +2893,33 @@ export const applyResult = z.object({
2738
2893
  });
2739
2894
  export type ApplyResult = z.infer<typeof applyResult>;
2740
2895
 
2896
+ /**
2897
+ * `GET …/template-jq/{name}` — the evaluated template jq's `name`, its `purpose`, and
2898
+ * its `value` (the `input` jq's read). GET evaluates ONLY an `input`-purpose jq; a GET
2899
+ * on an `update`-purpose name is refused with 422, so the result's purpose is always
2900
+ * `input`.
2901
+ */
2902
+ export const templateJqResult = z.object({
2903
+ name: z.string(),
2904
+ purpose: z.literal('input'),
2905
+ value: z.unknown(),
2906
+ });
2907
+ export type TemplateJqResult = z.infer<typeof templateJqResult>;
2908
+
2909
+ /**
2910
+ * `POST …/template-jq/{name}` — the applied template jq's outcome. The jq lands an op
2911
+ * batch through the same `apply` chokepoint as a delta, so `applied`/`data`/`seq`/`skipped`
2912
+ * carry that outcome.
2913
+ */
2914
+ export const templateJqApplyResult = z.object({
2915
+ name: z.string(),
2916
+ applied: z.boolean(),
2917
+ data: z.record(z.string(), z.unknown()).nullable().default(null),
2918
+ seq: z.number().nullable().default(null),
2919
+ skipped: z.array(z.record(z.string(), z.unknown())).default([]),
2920
+ });
2921
+ export type TemplateJqApplyResult = z.infer<typeof templateJqApplyResult>;
2922
+
2741
2923
  /**
2742
2924
  * One paged subject row: the addressed `subject` plus its record's last-write
2743
2925
  * `updated_at` — epoch seconds (the store's `extract(epoch FROM updated_at)`), served
@@ -2831,29 +3013,29 @@ export type StateConsumers = z.infer<typeof stateConsumers>;
2831
3013
  /** `DELETE /api/states/{name}` — the removed state. */
2832
3014
  export const stateDeleted = z.object({ name: z.string(), deleted: z.literal(true) });
2833
3015
 
2834
- /** `PUT /api/states/{name}/mounts/{module}` — the module now mounted on the state. */
2835
- export const stateMounted = z.object({
2836
- mounted: z.literal(true),
3016
+ /** `PUT /api/states/{name}/attachments/{template}` — the template now attached to the state. */
3017
+ export const stateAttached = z.object({
3018
+ attached: z.literal(true),
2837
3019
  state: z.string(),
2838
- module: z.string(),
3020
+ template: z.string(),
2839
3021
  });
2840
- export type StateMounted = z.infer<typeof stateMounted>;
3022
+ export type StateAttached = z.infer<typeof stateAttached>;
2841
3023
 
2842
- /** `PATCH /api/states/{name}/mounts/{module}` — the mount whose declarations were rewritten. */
2843
- export const stateMountUpdated = z.object({
3024
+ /** `PATCH /api/states/{name}/attachments/{template}` — the attachment whose declarations were rewritten. */
3025
+ export const stateAttachmentUpdated = z.object({
2844
3026
  updated: z.literal(true),
2845
3027
  state: z.string(),
2846
- module: z.string(),
3028
+ template: z.string(),
2847
3029
  });
2848
- export type StateMountUpdated = z.infer<typeof stateMountUpdated>;
3030
+ export type StateAttachmentUpdated = z.infer<typeof stateAttachmentUpdated>;
2849
3031
 
2850
- /** `DELETE /api/states/{name}/mounts/{module}` — the module unmounted from the state. */
2851
- export const stateUnmounted = z.object({
2852
- unmounted: z.literal(true),
3032
+ /** `DELETE /api/states/{name}/attachments/{template}` — the template detached from the state. */
3033
+ export const stateDetached = z.object({
3034
+ detached: z.literal(true),
2853
3035
  state: z.string(),
2854
- module: z.string(),
3036
+ template: z.string(),
2855
3037
  });
2856
- export type StateUnmounted = z.infer<typeof stateUnmounted>;
3038
+ export type StateDetached = z.infer<typeof stateDetached>;
2857
3039
 
2858
3040
  /**
2859
3041
  * `POST /api/states/{name}/records/.../fold` — the fold report: the `mode`, the
@@ -2869,8 +3051,8 @@ export const stateFoldReport = z.object({
2869
3051
  });
2870
3052
  export type StateFoldReport = z.infer<typeof stateFoldReport>;
2871
3053
 
2872
- /** `DELETE /api/state-modules/{name}` — the removed module document. */
2873
- export const stateModuleDeleted = z.object({ name: z.string(), deleted: z.literal(true) });
3054
+ /** `DELETE /api/state-templates/{name}` — the removed template document. */
3055
+ export const stateTemplateDeleted = z.object({ name: z.string(), deleted: z.literal(true) });
2874
3056
 
2875
3057
  /** `DELETE /api/states/{name}/records/...` — the erased record marker. */
2876
3058
  export const recordErased = z.object({ erased: z.literal(true) });