@substrat-run/vertical-host 0.74.0 → 0.75.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.
@@ -13,6 +13,13 @@
13
13
  * **Scope.** It mounts the operations THIS module declares. A composed engine's
14
14
  * operations carry no `http` — the engine is entity-agnostic and does not own a
15
15
  * URL shape, so the vertical decides theirs and mounts them itself.
16
+ *
17
+ * Two things a hand-written table did for free, and this derivation therefore
18
+ * has to do deliberately: a query string carries no types (§ `queryCoercers`),
19
+ * and registration ORDER decides which of two overlapping paths wins
20
+ * (§ `comparePaths`). Both were found by a production vertical with 195
21
+ * declared routes that could not switch to this mount without the first — 29 of
22
+ * its 81 reads carried a `limit` the model declares as a number (#785).
16
23
  */
17
24
  import type { Context, Hono } from 'hono';
18
25
  import type { ScopeStub } from '@substrat-run/kernel';
@@ -35,6 +42,9 @@ export interface MountOperationsOptions {
35
42
  * Mount one route per declared operation. Returns what it mounted — a caller
36
43
  * can assert on it, and a test that expects N routes fails loudly at zero
37
44
  * rather than passing over an empty table.
45
+ *
46
+ * The returned table is in registration order, which is the order that decides
47
+ * dispatch: read it to see which of two overlapping paths wins.
38
48
  */
39
49
  export declare function mountOperations(app: Hono<any, any, any>, operations: Readonly<Record<string, object>>, resolveStub: ResolveStub, options?: MountOperationsOptions): {
40
50
  operation: string;
@@ -1 +1 @@
1
- {"version":3,"file":"operations-routes.d.ts","sourceRoot":"","sources":["../src/operations-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;AAgD7D,MAAM,WAAW,sBAAsB;IACrC,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;;;OAQG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC7C;AAYD;;;;GAIG;AACH,wBAAgB,eAAe,CAE7B,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EACxB,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAC5C,WAAW,EAAE,WAAW,EACxB,OAAO,GAAE,sBAA2B,GACnC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAuDvD"}
1
+ {"version":3,"file":"operations-routes.d.ts","sourceRoot":"","sources":["../src/operations-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;AAmI7D,MAAM,WAAW,sBAAsB;IACrC,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;;;OAQG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC7C;AAuFD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAE7B,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EACxB,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAC5C,WAAW,EAAE,WAAW,EACxB,OAAO,GAAE,sBAA2B,GACnC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAgFvD"}
@@ -1,3 +1,12 @@
1
+ /**
2
+ * Read a schema's definition without `instanceof`, which fails across duplicate
3
+ * copies of the library — the same reason the rest of this file reads Zod
4
+ * structurally.
5
+ */
6
+ function defOf(schema) {
7
+ return (schema?._zod?.def ??
8
+ schema?._def);
9
+ }
1
10
  /**
2
11
  * Input fields the model pins to a single value — supplied by the route rather
3
12
  * than by the caller.
@@ -9,9 +18,6 @@
9
18
  * it here removes a whole category of "route that cannot be derived" without
10
19
  * adding any vocabulary, which is the better kind of fix: the model was not
11
20
  * missing information, the emitter was not listening.
12
- *
13
- * Read structurally across Zod's internal layouts rather than with `instanceof`,
14
- * which fails across duplicate copies of the library.
15
21
  */
16
22
  function pinnedFields(input) {
17
23
  const shape = input?.shape;
@@ -19,8 +25,7 @@ function pinnedFields(input) {
19
25
  return {};
20
26
  const out = {};
21
27
  for (const [field, schema] of Object.entries(shape)) {
22
- const def = (schema._zod?.def ??
23
- schema._def);
28
+ const def = defOf(schema);
24
29
  if (def?.type !== 'literal')
25
30
  continue;
26
31
  // Zod 4 carries `values` (a literal may name several); older layouts carry
@@ -31,6 +36,78 @@ function pinnedFields(input) {
31
36
  }
32
37
  return out;
33
38
  }
39
+ /**
40
+ * A URL carries no types: `?limit=100` arrives as the string `'100'`, and an
41
+ * operation declaring `limit: z.number().int().optional()` rejects it with
42
+ * "expected number, received string". Every read with a non-string field is
43
+ * affected — in a production vertical that was most paged reads, plus every
44
+ * year/month filter (#785).
45
+ *
46
+ * The fix reads the declared shape and coerces only the fields whose declared
47
+ * type cannot be a string: number, boolean, bigint. That is deliberately
48
+ * narrower than coercing by JSON grammar, which would have to guess — `?q=123`
49
+ * is a number to the grammar and a search term to the caller — and narrower
50
+ * than telling verticals to declare `z.coerce.number()`, which pushes an HTTP
51
+ * transport detail into a model that has to stay transport-agnostic (the same
52
+ * schema the handler parses).
53
+ *
54
+ * A value the declared type cannot accept is passed through UNCHANGED, so the
55
+ * error the caller reads still names what they actually sent.
56
+ *
57
+ * Unions are skipped: `z.union([z.number(), z.string()])` has no single answer,
58
+ * and guessing is what this function exists to avoid.
59
+ */
60
+ function queryCoercers(input) {
61
+ const shape = input?.shape;
62
+ if (!shape)
63
+ return {};
64
+ const out = {};
65
+ for (const [field, schema] of Object.entries(shape)) {
66
+ const coerce = coercerFor(schema);
67
+ if (coerce)
68
+ out[field] = coerce;
69
+ }
70
+ return out;
71
+ }
72
+ /**
73
+ * The coercion a declared field wants, looking through the wrappers that do not
74
+ * change its type — `optional`, `nullable`, `default`, `catch`, `readonly`, and
75
+ * a pipe's input side (`z.coerce.number()` is one, and coercing ahead of it is
76
+ * idempotent rather than wrong).
77
+ */
78
+ function coercerFor(schema, depth = 0) {
79
+ if (depth > 8)
80
+ return undefined; // a cycle cannot happen in a Zod schema, but a bound is cheap
81
+ const def = defOf(schema);
82
+ switch (def?.type) {
83
+ case 'number':
84
+ return (raw) => {
85
+ if (raw.trim() === '')
86
+ return raw;
87
+ const n = Number(raw);
88
+ return Number.isFinite(n) ? n : raw;
89
+ };
90
+ case 'bigint':
91
+ return (raw) => (/^[+-]?\d+$/.test(raw.trim()) ? BigInt(raw.trim()) : raw);
92
+ case 'boolean':
93
+ // Only the two spellings a URL can mean unambiguously. `?flag` with no
94
+ // value arrives as '' and stays '' — "present" is not "true" here.
95
+ return (raw) => (raw === 'true' ? true : raw === 'false' ? false : raw);
96
+ case 'optional':
97
+ case 'nullable':
98
+ case 'nullish':
99
+ case 'default':
100
+ case 'prefault':
101
+ case 'catch':
102
+ case 'readonly':
103
+ case 'nonoptional':
104
+ return coercerFor(def.innerType, depth + 1);
105
+ case 'pipe':
106
+ return coercerFor(def.in, depth + 1);
107
+ default:
108
+ return undefined;
109
+ }
110
+ }
34
111
  /** `{listId}` in the model is `:listId` to Hono. */
35
112
  function toHonoPath(path) {
36
113
  return path.replace(/\{(\w+)\}/g, ':$1');
@@ -39,10 +116,85 @@ function toHonoPath(path) {
39
116
  function pathParams(path) {
40
117
  return [...path.matchAll(/\{(\w+)\}/g)].map((m) => m[1]);
41
118
  }
119
+ /**
120
+ * Order two declared paths so the more specific one is registered first.
121
+ *
122
+ * Hono dispatches in REGISTRATION order, so `/users/{id}` registered before
123
+ * `/users/invites` answers `/users/invites` with `id: 'invites'` and the static
124
+ * route is unreachable — no error, no warning, just an endpoint that silently
125
+ * belongs to its neighbour. Registering in alphabetical OPERATION order (what
126
+ * this did until #785) decides that by a name that has nothing to do with
127
+ * routing: `support/get` sorts before `support/list-mine`, and a live
128
+ * `GET /support/issues/mine` disappeared behind `GET /support/issues/{id}`.
129
+ *
130
+ * So compare the paths instead, segment by segment, static before parameter —
131
+ * a lexicographic order over the key `[isParam, text]` per segment, which makes
132
+ * it a real total order (transitive, and the same table every time) rather than
133
+ * a pile of pairwise special cases. Paths that cannot overlap are unaffected;
134
+ * paths that can, resolve the way a reader of the URLs expects.
135
+ *
136
+ * **Why order rather than refuse.** #785 argued for detecting the collision and
137
+ * refusing to mount, on the grounds that the silence is the real defect and the
138
+ * vertical should decide. The silence is the defect — but a reserved word in an
139
+ * id slot has one correct reading, not an ambiguous one, and it is the reading
140
+ * every path-template spec already writes down: OpenAPI resolves a concrete
141
+ * path ahead of a templated one for exactly this case. Refusing would make a
142
+ * soluble collision a boot failure and force live URLs to be renamed to satisfy
143
+ * a router that had the whole table in front of it. What ordering CANNOT
144
+ * resolve still throws (`assertNoUnreachable`), so nothing stays silent.
145
+ */
146
+ function comparePaths(a, b) {
147
+ const as = a.split('/');
148
+ const bs = b.split('/');
149
+ for (let i = 0; i < Math.min(as.length, bs.length); i++) {
150
+ const x = as[i];
151
+ const y = bs[i];
152
+ if (x === y)
153
+ continue;
154
+ const xParam = x.startsWith('{');
155
+ const yParam = y.startsWith('{');
156
+ if (xParam !== yParam)
157
+ return xParam ? 1 : -1;
158
+ return x < y ? -1 : 1;
159
+ }
160
+ return as.length - bs.length;
161
+ }
162
+ /**
163
+ * The shape a path DISPATCHES as: parameter names are internal to the handler,
164
+ * so `/users/{id}` and `/users/{slug}` are one route to any router.
165
+ */
166
+ function dispatchShape(path) {
167
+ return path.replace(/\{\w+\}/g, '{}');
168
+ }
169
+ /**
170
+ * Refuse a table where one operation can never be reached.
171
+ *
172
+ * Ordering resolves a static path against its parameter sibling (§
173
+ * `comparePaths`). What it cannot resolve is two declarations that dispatch
174
+ * IDENTICALLY — same method, same shape, different parameter names — because
175
+ * there is no reading under which both are live. That is the case #785 is
176
+ * really about: an endpoint that quietly stops existing. Here it fails at
177
+ * mount, naming both operations, rather than at the first request nobody makes.
178
+ */
179
+ function assertNoUnreachable(declared) {
180
+ const claimed = new Map();
181
+ for (const [name, op] of declared) {
182
+ const key = `${op.http.method} ${dispatchShape(op.http.path)}`;
183
+ const first = claimed.get(key);
184
+ if (first !== undefined) {
185
+ throw new Error(`mountOperations: '${first}' and '${name}' both declare ${key} — they dispatch ` +
186
+ 'identically, so one of them can never be reached; give one a distinct path');
187
+ }
188
+ claimed.set(key, name);
189
+ }
190
+ }
42
191
  /**
43
192
  * Mount one route per declared operation. Returns what it mounted — a caller
44
193
  * can assert on it, and a test that expects N routes fails loudly at zero
45
194
  * rather than passing over an empty table.
195
+ *
196
+ * The returned table is in registration order, which is the order that decides
197
+ * dispatch: read it to see which of two overlapping paths wins.
46
198
  */
47
199
  export function mountOperations(
48
200
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -50,10 +202,16 @@ app, operations, resolveStub, options = {}) {
50
202
  const base = options.basePath ?? '/api';
51
203
  const known = options.knownOperations ? new Set(options.knownOperations) : undefined;
52
204
  const mounted = [];
53
- for (const name of Object.keys(operations).sort()) {
54
- const op = operations[name];
55
- if (!op?.http)
56
- continue;
205
+ const declared = Object.keys(operations)
206
+ .map((name) => [name, operations[name]])
207
+ .filter((entry) => Boolean(entry[1]?.http))
208
+ // Path specificity decides dispatch; method and name only keep the table
209
+ // deterministic for two operations that share a path (`GET`/`POST /lists`).
210
+ .sort(([aName, a], [bName, b]) => comparePaths(a.http.path, b.http.path) ||
211
+ (a.http.method < b.http.method ? -1 : a.http.method > b.http.method ? 1 : 0) ||
212
+ (aName < bName ? -1 : aName > bName ? 1 : 0));
213
+ assertNoUnreachable(declared);
214
+ for (const [name, op] of declared) {
57
215
  if (known && !known.has(name)) {
58
216
  throw new Error(`mountOperations: '${name}' is bound to ${op.http.method} ${op.http.path} but no ` +
59
217
  'registered module provides it — check the name against the engine that owns it');
@@ -63,6 +221,16 @@ app, operations, resolveStub, options = {}) {
63
221
  const full = `${base}${toHonoPath(path)}`;
64
222
  const takesBody = method === 'POST' || method === 'PUT' || method === 'PATCH';
65
223
  const pinned = pinnedFields(op.input);
224
+ const coercers = queryCoercers(op.input);
225
+ /** Types the values a URL hands over as strings, per the declared shape. */
226
+ const typed = (values) => {
227
+ const out = {};
228
+ for (const [field, raw] of Object.entries(values)) {
229
+ const coerce = coercers[field];
230
+ out[field] = coerce && raw !== undefined ? coerce(raw) : raw;
231
+ }
232
+ return out;
233
+ };
66
234
  const handler = async (c) => {
67
235
  const stub = await resolveStub(c);
68
236
  const fromPath = {};
@@ -78,11 +246,11 @@ app, operations, resolveStub, options = {}) {
78
246
  if (takesBody) {
79
247
  const raw = await c.req.text();
80
248
  const body = raw ? JSON.parse(raw) : {};
81
- payload = { ...body, ...pinned, ...fromPath };
249
+ // A body is JSON and already typed; only the URL's own values need it.
250
+ payload = { ...body, ...pinned, ...typed(fromPath) };
82
251
  }
83
252
  else {
84
- const query = c.req.query();
85
- payload = { ...query, ...pinned, ...fromPath };
253
+ payload = { ...typed(c.req.query()), ...pinned, ...typed(fromPath) };
86
254
  }
87
255
  if (!op.input && params.length === 0)
88
256
  payload = undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"operations-routes.js","sourceRoot":"","sources":["../src/operations-routes.ts"],"names":[],"mappings":"AAkCA;;;;;;;;;;;;;;GAcG;AACH,SAAS,YAAY,CAAC,KAAwB;IAC5C,MAAM,KAAK,GAAG,KAAK,EAAE,KAAK,CAAC;IAC3B,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,CAAE,MAAuC,CAAC,IAAI,EAAE,GAAG;YAC5D,MAA6B,CAAC,IAAI,CAExB,CAAC;QACd,IAAI,GAAG,EAAE,IAAI,KAAK,SAAS;YAAE,SAAS;QACtC,2EAA2E;QAC3E,0EAA0E;QAC1E,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;QACjF,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,GAAG,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAiBD,oDAAoD;AACpD,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;AAC3C,CAAC;AAED,8DAA8D;AAC9D,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAW,CAAC,CAAC;AACrE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe;AAC7B,8DAA8D;AAC9D,GAAwB,EACxB,UAA4C,EAC5C,WAAwB,EACxB,OAAO,GAA2B,EAAE;IAEpC,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,IAAI,MAAM,CAAC;IACxC,MAAM,KAAK,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACrF,MAAM,OAAO,GAA0D,EAAE,CAAC;IAE1E,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAClD,MAAM,EAAE,GAAG,UAAU,CAAC,IAAI,CAAyB,CAAC;QACpD,IAAI,CAAC,EAAE,EAAE,IAAI;YAAE,SAAS;QACxB,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CACb,qBAAqB,IAAI,iBAAiB,EAAE,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,UAAU;gBAChF,gFAAgF,CACnF,CAAC;QACJ,CAAC;QACD,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC;QACjC,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,IAAI,GAAG,GAAG,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1C,MAAM,SAAS,GAAG,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,OAAO,CAAC;QAC9E,MAAM,MAAM,GAAG,YAAY,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;QAEtC,MAAM,OAAO,GAAG,KAAK,EAAE,CAAU,EAAE,EAAE;YACnC,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,CAAC,CAAC,CAAC;YAClC,MAAM,QAAQ,GAA4B,EAAE,CAAC;YAC7C,KAAK,MAAM,CAAC,IAAI,MAAM;gBAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAErD,sEAAsE;YACtE,sEAAsE;YACtE,yEAAyE;YACzE,wDAAwD;YACxD,IAAI,OAA4C,CAAC;YACjD,2EAA2E;YAC3E,kEAAkE;YAClE,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;gBAC/B,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAA6B,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrE,OAAO,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;YAChD,CAAC;iBAAM,CAAC;gBACN,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;gBAC5B,OAAO,GAAG,EAAE,GAAG,KAAK,EAAE,GAAG,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;YACjD,CAAC;YACD,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,GAAG,SAAS,CAAC;YAE1D,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QAClD,CAAC,CAAC;QAEF,IAAI,MAAM,KAAK,KAAK;YAAE,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;aACxC,IAAI,MAAM,KAAK,MAAM;YAAE,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;aAC/C,IAAI,MAAM,KAAK,KAAK;YAAE,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;aAC7C,IAAI,MAAM,KAAK,OAAO;YAAE,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;;YACjD,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAE/B,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"operations-routes.js","sourceRoot":"","sources":["../src/operations-routes.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@substrat-run/vertical-host",
3
- "version": "0.74.0",
3
+ "version": "0.75.0",
4
4
  "description": "The platform's /internal/* surface + error envelope, authored once — mount it in a vertical worker instead of re-copying the control-plane contract",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {
@@ -23,8 +23,8 @@
23
23
  ],
24
24
  "dependencies": {
25
25
  "hono": "^4.6.0",
26
- "@substrat-run/contracts": "^0.74.0",
27
- "@substrat-run/kernel": "^0.74.0"
26
+ "@substrat-run/contracts": "^0.75.0",
27
+ "@substrat-run/kernel": "^0.75.0"
28
28
  },
29
29
  "devDependencies": {
30
30
  "typescript": "^7.0.0",