@substrat-run/contracts 0.83.0 → 0.84.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 +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lifecycle.d.ts +235 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +245 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/manifest.d.ts +7 -0
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +18 -0
- package/dist/manifest.js.map +1 -1
- package/dist/model.d.ts +10 -1
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +14 -2
- package/dist/model.js.map +1 -1
- package/dist/openapi.d.ts +12 -1
- package/dist/openapi.d.ts.map +1 -1
- package/dist/openapi.js +49 -2
- package/dist/openapi.js.map +1 -1
- package/dist/operations.d.ts +189 -20
- package/dist/operations.d.ts.map +1 -1
- package/dist/operations.js +108 -1
- package/dist/operations.js.map +1 -1
- package/dist/pagination.d.ts +95 -0
- package/dist/pagination.d.ts.map +1 -1
- package/dist/pagination.js +85 -0
- package/dist/pagination.js.map +1 -1
- package/dist/platform-request.d.ts +78 -0
- package/dist/platform-request.d.ts.map +1 -1
- package/dist/platform-request.js +42 -0
- package/dist/platform-request.js.map +1 -1
- package/package.json +1 -1
package/dist/operations.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { primaryKeyOf } from './model.js';
|
|
2
3
|
// ---------------------------------------------------------------------------
|
|
3
4
|
// The composer.
|
|
4
5
|
// ---------------------------------------------------------------------------
|
|
@@ -27,7 +28,54 @@ import { z } from 'zod';
|
|
|
27
28
|
* ```
|
|
28
29
|
*/
|
|
29
30
|
export function defineOperations(_entities, _permissions, _engines) {
|
|
30
|
-
return (operations) =>
|
|
31
|
+
return (operations) => {
|
|
32
|
+
assertListsArePaged(operations);
|
|
33
|
+
return operations;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A read that answers with a whole table must say it is a page (#811).
|
|
38
|
+
*
|
|
39
|
+
* An unbounded list endpoint is a bug with a delay on it: it passes review, it
|
|
40
|
+
* passes tests, and then one tenant's table gets large. So a bare `z.array(...)`
|
|
41
|
+
* output with no `paged` beside it is refused — the operation either pages, or it
|
|
42
|
+
* is not a list.
|
|
43
|
+
*
|
|
44
|
+
* ## Why at module load rather than in a lint tool
|
|
45
|
+
*
|
|
46
|
+
* #811 asked for this as a `lint:model --check` gate. A tool has to FIND the
|
|
47
|
+
* declarations, and the ones it would have missed are exactly the ones that
|
|
48
|
+
* matter: `model-diff` reads entities, not operations, and `api-diff` only sees
|
|
49
|
+
* verticals that opted into `src/api.ts` — which is none of the four engines whose
|
|
50
|
+
* list reads this issue was filed about. Checking here reaches every module that
|
|
51
|
+
* declares operations at all, engine or vertical, with nothing to discover and
|
|
52
|
+
* nothing to opt into.
|
|
53
|
+
*
|
|
54
|
+
* Same reasoning that moved #844's "a state the field cannot hold" check to load
|
|
55
|
+
* time: it runs where it can actually bite. It fires in every build, every test
|
|
56
|
+
* and every dev server, so it cannot be true only of the modules a tool knew about.
|
|
57
|
+
*
|
|
58
|
+
* **A nested array is untouched.** `output: z.object({ ids: z.array(…) })` is an
|
|
59
|
+
* object with a list inside it — a shape whose size the operation controls — not a
|
|
60
|
+
* table read. Only a TOP-LEVEL array output is a list by this rule.
|
|
61
|
+
*/
|
|
62
|
+
function assertListsArePaged(operations) {
|
|
63
|
+
for (const [name, op] of Object.entries(operations)) {
|
|
64
|
+
const decl = op;
|
|
65
|
+
if (decl.paged !== undefined)
|
|
66
|
+
continue;
|
|
67
|
+
if (!(decl.output instanceof z.ZodArray))
|
|
68
|
+
continue;
|
|
69
|
+
throw new Error(`model: '${name}' returns a bare array and does not declare \`paged\` — a list read ` +
|
|
70
|
+
'that answers with the whole table is unbounded by construction.\n' +
|
|
71
|
+
' Remedy: declare the ENTRY as `output` and add `paged`. Either the kernel ' +
|
|
72
|
+
'composes the walk —\n' +
|
|
73
|
+
" paged: { over: { entity: 'thing', sortable: ['created_at'], filterable: ['status'] } }\n" +
|
|
74
|
+
' — or, where it cannot (a kernel table, a correlated subquery, a per-row ' +
|
|
75
|
+
'permission walk),\n' +
|
|
76
|
+
' the handler composes its own and names the entry field the cursor walks:\n' +
|
|
77
|
+
" paged: { sortKey: 'article' }");
|
|
78
|
+
}
|
|
31
79
|
}
|
|
32
80
|
/**
|
|
33
81
|
* The permission keys an operation set actually requires, for the manifest.
|
|
@@ -68,6 +116,65 @@ export function eventsEmittedBy(operations) {
|
|
|
68
116
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
69
117
|
.map(([type, schemaVersion]) => ({ type, schemaVersion }));
|
|
70
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* The paged lists an operation set declares, for the manifest (#811).
|
|
121
|
+
*
|
|
122
|
+
* Read off every `paged.over` the way `eventsEmittedBy` reads every `emits`, and
|
|
123
|
+
* for the identical reason: the index the kernel provisions and the columns the
|
|
124
|
+
* operation offers are ONE fact, and a manifest restating it by hand is how two
|
|
125
|
+
* descriptions come to disagree. `table` and `idColumn` are resolved here from
|
|
126
|
+
* the same registry the columns are compile-checked against, so nothing states
|
|
127
|
+
* twice where a work order lives.
|
|
128
|
+
*
|
|
129
|
+
* **Two operations may page the same entity** — `workorder/list` and a vertical's
|
|
130
|
+
* portal read over the same table — so their vocabularies are UNIONED rather than
|
|
131
|
+
* refused. The index has to cover both walks either way, and one of them being
|
|
132
|
+
* narrower is not a conflict. (Two *modules* claiming one entity type IS refused;
|
|
133
|
+
* that check belongs to the kernel, which is the only thing that sees them all.)
|
|
134
|
+
*/
|
|
135
|
+
export function listsDeclaredBy(operations, entities, engines = []) {
|
|
136
|
+
const byEntity = new Map();
|
|
137
|
+
for (const [name, op] of Object.entries(operations)) {
|
|
138
|
+
const over = op.paged?.over;
|
|
139
|
+
if (!over || typeof over.entity !== 'string')
|
|
140
|
+
continue;
|
|
141
|
+
const acc = byEntity.get(over.entity) ?? { sortable: [], filterable: [] };
|
|
142
|
+
for (const c of (over.sortable ?? [])) {
|
|
143
|
+
if (typeof c === 'string' && !acc.sortable.includes(c))
|
|
144
|
+
acc.sortable.push(c);
|
|
145
|
+
}
|
|
146
|
+
for (const c of (over.filterable ?? [])) {
|
|
147
|
+
if (typeof c === 'string' && !acc.filterable.includes(c))
|
|
148
|
+
acc.filterable.push(c);
|
|
149
|
+
}
|
|
150
|
+
if (!acc.sortable.length) {
|
|
151
|
+
throw new Error(`model: '${name}' declares \`paged.over\` with no sortable column`);
|
|
152
|
+
}
|
|
153
|
+
byEntity.set(over.entity, acc);
|
|
154
|
+
}
|
|
155
|
+
return [...byEntity.entries()]
|
|
156
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
157
|
+
.map(([entityType, acc]) => {
|
|
158
|
+
const entity = entities[entityType] ?? engines.map((r) => r[entityType]).find(Boolean);
|
|
159
|
+
if (!entity) {
|
|
160
|
+
throw new Error(`model: a paged list is declared over '${entityType}', which is not a declared entity`);
|
|
161
|
+
}
|
|
162
|
+
const key = primaryKeyOf(entityType, entity);
|
|
163
|
+
if (key.length !== 1) {
|
|
164
|
+
throw new Error(`model: '${entityType}' is keyed by (${key.join(', ')}) and cannot be paged — ` +
|
|
165
|
+
'a keyset walk needs one column to break ties on, and a composite key has none');
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
entityType,
|
|
169
|
+
// NOT sorted: the first sortable column is the DEFAULT sort, so the order
|
|
170
|
+
// of this array is part of the fact.
|
|
171
|
+
sortable: acc.sortable,
|
|
172
|
+
...(acc.filterable.length ? { filterable: [...acc.filterable].sort() } : {}),
|
|
173
|
+
table: entity.table,
|
|
174
|
+
idColumn: key[0],
|
|
175
|
+
};
|
|
176
|
+
});
|
|
177
|
+
}
|
|
71
178
|
/**
|
|
72
179
|
* The operation half of a module's manifest — derived, not written twice.
|
|
73
180
|
*
|
package/dist/operations.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../src/operations.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../src/operations.ts"],"names":[],"mappings":"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"}
|
package/dist/pagination.d.ts
CHANGED
|
@@ -18,6 +18,17 @@ import { z } from 'zod';
|
|
|
18
18
|
* needs no encoding and survives in a query string. A composite sort key joins
|
|
19
19
|
* its parts with `|` (first part always `|`-free: a ULID or enum).
|
|
20
20
|
*/
|
|
21
|
+
/**
|
|
22
|
+
* Resolve a requested page size against the platform's default and ceiling.
|
|
23
|
+
*
|
|
24
|
+
* One definition, because there are now three callers that must agree: the HTTP
|
|
25
|
+
* layer (`listPageQuery`), `ctx.page`, and every handler-composed read that
|
|
26
|
+
* builds its own `LIMIT`. An in-process caller — a test, a seed, another
|
|
27
|
+
* operation — legitimately passes nothing, and the answer it gets has to be the
|
|
28
|
+
* same page an HTTP caller would get, or a scenario proves something the wire
|
|
29
|
+
* does not do.
|
|
30
|
+
*/
|
|
31
|
+
export declare function listLimitOf(limit?: number): number;
|
|
21
32
|
/** Default page size on every HTTP list read. */
|
|
22
33
|
export declare const LIST_PAGE_DEFAULT = 20;
|
|
23
34
|
/** Hard ceiling on a requested page — same order as a table page (§ introspection). */
|
|
@@ -150,4 +161,88 @@ export declare function pageSchema<T extends z.ZodType>(entry: T, withTotal?: bo
|
|
|
150
161
|
entries: z.ZodArray<T>;
|
|
151
162
|
nextCursor: z.ZodNullable<z.ZodString>;
|
|
152
163
|
}, z.core.$strip>;
|
|
164
|
+
/**
|
|
165
|
+
* Re-shape a page's entries without touching its walk (#811).
|
|
166
|
+
*
|
|
167
|
+
* The kernel-composed half of a paged read (`paged.over`) returns a page of
|
|
168
|
+
* ROWS, because the kernel knows the table and nothing else: `toWorkOrder`,
|
|
169
|
+
* `facilities: […]`, a per-row aggregate are all the handler's business. So the
|
|
170
|
+
* handler maps, and the cursor and total have to survive that untouched.
|
|
171
|
+
*
|
|
172
|
+
* Written as a helper rather than left to a spread because the spread is wrong
|
|
173
|
+
* in a way that type-checks: `{ ...page, entries: page.entries.map(f) }` keeps
|
|
174
|
+
* `total` only when the source had one, which is exactly right — and
|
|
175
|
+
* `{ entries: …, nextCursor: page.nextCursor }` silently drops it, which is the
|
|
176
|
+
* mistake somebody makes once per adopter.
|
|
177
|
+
*/
|
|
178
|
+
/**
|
|
179
|
+
* Overloaded rather than conditional on a `P extends Page<A>` parameter: that
|
|
180
|
+
* form cannot infer `A` from the argument, so every call site had to name its
|
|
181
|
+
* entry type or fall back to `unknown`. The counted overload comes first so a
|
|
182
|
+
* `CountedPage` keeps its total in the RESULT type, not merely at runtime.
|
|
183
|
+
*/
|
|
184
|
+
export declare function mapPage<A, B>(page: CountedPage<A>, fn: (entry: A, index: number) => B): CountedPage<B>;
|
|
185
|
+
export declare function mapPage<A, B>(page: Page<A>, fn: (entry: A, index: number) => B): Page<B>;
|
|
186
|
+
/**
|
|
187
|
+
* The query parameter naming which declared sort a caller wants (#811).
|
|
188
|
+
*
|
|
189
|
+
* `sort` rather than `order_by`/`sortBy`: it is one word, it is what Stripe and
|
|
190
|
+
* GitHub both spell, and `order` — already taken, already shipped — is the
|
|
191
|
+
* DIRECTION. Two adjacent parameters whose names could be confused for each
|
|
192
|
+
* other is worth avoiding at the point where they are named, not documented
|
|
193
|
+
* around afterwards.
|
|
194
|
+
*/
|
|
195
|
+
export declare const LIST_SORT_PARAM = "sort";
|
|
196
|
+
/**
|
|
197
|
+
* A cursor is only valid for the sort that ISSUED it.
|
|
198
|
+
*
|
|
199
|
+
* Keyset paging compares against the sort column, so a cursor taken from a walk
|
|
200
|
+
* ordered by `number` and replayed against one ordered by `created_at` compares
|
|
201
|
+
* a number to a timestamp: the page is not wrong-looking, it is silently
|
|
202
|
+
* arbitrary. Nothing in the cursor says which sort produced it — `pagination.ts`
|
|
203
|
+
* pins it as "the last entry's sort key verbatim … it needs no encoding", and
|
|
204
|
+
* that stays true.
|
|
205
|
+
*
|
|
206
|
+
* **Following the `Link` header is always safe**, which is the whole reason the
|
|
207
|
+
* walk is handed over as a URL rather than a bare cursor: `nextPageLink` rebuilds
|
|
208
|
+
* it from the request, so `sort` and every filter ride along unchanged and a
|
|
209
|
+
* client that follows links cannot construct this mistake.
|
|
210
|
+
*
|
|
211
|
+
* A client that hand-assembles `?cursor=…&sort=other` can, and this is the
|
|
212
|
+
* documented reason not to. Encoding the sort into the cursor would let the
|
|
213
|
+
* server refuse it outright; that was weighed and declined here, because it
|
|
214
|
+
* breaks the "no encoding, survives in a query string" property that makes a
|
|
215
|
+
* cursor debuggable by eye — see K-041.
|
|
216
|
+
*/
|
|
217
|
+
export declare const CURSOR_BELONGS_TO_ITS_SORT = "a cursor is only valid for the sort it was issued under \u2014 follow the Link header";
|
|
218
|
+
/**
|
|
219
|
+
* A page of the entries a caller may actually SEE (#811).
|
|
220
|
+
*
|
|
221
|
+
* The shape a portal read needs, and the one a naive page gets wrong. Callout and
|
|
222
|
+
* Handlebar both list work orders and then check `read` per row, because the
|
|
223
|
+
* proof walk (workorder → facility → customer) is what decides visibility. Twenty
|
|
224
|
+
* rows fetched can leave three after that walk, so the fetch size and the page
|
|
225
|
+
* size are not the same number and cannot be made the same number.
|
|
226
|
+
*
|
|
227
|
+
* **This page may come back short, and a short page does NOT end the walk.** That
|
|
228
|
+
* is a deliberate divergence from `pageOf`, whose whole cursor rule is "full page
|
|
229
|
+
* ⇒ there may be more, short page ⇒ done". Under a per-row filter that rule is
|
|
230
|
+
* unavailable: the only honest signal left is the underlying cursor, so the walk
|
|
231
|
+
* ends where `nextCursor` is null and nowhere else. A client following the `Link`
|
|
232
|
+
* header does the right thing without knowing any of this; one that stops at the
|
|
233
|
+
* first short page will truncate its own results, which is why it is stated here
|
|
234
|
+
* rather than left to be discovered.
|
|
235
|
+
*
|
|
236
|
+
* The cursor returned is the underlying walk's — the last row EXAMINED, not the
|
|
237
|
+
* last row returned. Advancing by the last row returned would re-examine every
|
|
238
|
+
* row the filter rejected on the next request, and a page whose rows are all
|
|
239
|
+
* rejected would never advance at all.
|
|
240
|
+
*/
|
|
241
|
+
export declare function pageVisible<T>(fetch: (params: {
|
|
242
|
+
limit: number;
|
|
243
|
+
cursor?: string;
|
|
244
|
+
}) => Page<T>, params: {
|
|
245
|
+
limit?: number;
|
|
246
|
+
cursor?: string;
|
|
247
|
+
} | undefined, allow: (entry: T) => Promise<boolean> | boolean): Promise<Page<T>>;
|
|
153
248
|
//# sourceMappingURL=pagination.d.ts.map
|
package/dist/pagination.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../src/pagination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;;;;GAkBG;AAEH,iDAAiD;AACjD,eAAO,MAAM,iBAAiB,KAAK,CAAC;AACpC,uFAAuF;AACvF,eAAO,MAAM,aAAa,MAAM,CAAC;AAEjC;;;;GAIG;AACH,eAAO,MAAM,aAAa;;;;;;;iBAIxB,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CACxB;AAED,uDAAuD;AACvD,MAAM,WAAW,IAAI,CAAC,CAAC;IACrB,OAAO,EAAE,CAAC,EAAE,CAAC;IACb,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC,CAAE,SAAQ,IAAI,CAAC,CAAC,CAAC;IAC7C,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAGzF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAC7B,OAAO,EAAE,CAAC,EAAE,EACZ,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,EACzB,KAAK,EAAE,MAAM,GACZ,WAAW,CAAC,CAAC,CAAC,CAEhB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,gBAAgB,SAAS,CAAC;AAEvC,oEAAoE;AACpE,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAEjD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,oCAAiD,CAAC;AAEnF;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAKzF;AAED;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,CAO7D;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,UAAQ;;;kBAY1E"}
|
|
1
|
+
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../src/pagination.ts"],"names":[],"mappings":"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"}
|
package/dist/pagination.js
CHANGED
|
@@ -18,6 +18,21 @@ import { z } from 'zod';
|
|
|
18
18
|
* needs no encoding and survives in a query string. A composite sort key joins
|
|
19
19
|
* its parts with `|` (first part always `|`-free: a ULID or enum).
|
|
20
20
|
*/
|
|
21
|
+
/**
|
|
22
|
+
* Resolve a requested page size against the platform's default and ceiling.
|
|
23
|
+
*
|
|
24
|
+
* One definition, because there are now three callers that must agree: the HTTP
|
|
25
|
+
* layer (`listPageQuery`), `ctx.page`, and every handler-composed read that
|
|
26
|
+
* builds its own `LIMIT`. An in-process caller — a test, a seed, another
|
|
27
|
+
* operation — legitimately passes nothing, and the answer it gets has to be the
|
|
28
|
+
* same page an HTTP caller would get, or a scenario proves something the wire
|
|
29
|
+
* does not do.
|
|
30
|
+
*/
|
|
31
|
+
export function listLimitOf(limit) {
|
|
32
|
+
if (limit === undefined || !Number.isFinite(limit) || limit < 1)
|
|
33
|
+
return LIST_PAGE_DEFAULT;
|
|
34
|
+
return Math.min(Math.floor(limit), LIST_PAGE_MAX);
|
|
35
|
+
}
|
|
21
36
|
/** Default page size on every HTTP list read. */
|
|
22
37
|
export const LIST_PAGE_DEFAULT = 20;
|
|
23
38
|
/** Hard ceiling on a requested page — same order as a table page (§ introspection). */
|
|
@@ -135,4 +150,74 @@ export function pageSchema(entry, withTotal = false) {
|
|
|
135
150
|
})
|
|
136
151
|
: base;
|
|
137
152
|
}
|
|
153
|
+
export function mapPage(page, fn) {
|
|
154
|
+
return { ...page, entries: page.entries.map(fn) };
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* The query parameter naming which declared sort a caller wants (#811).
|
|
158
|
+
*
|
|
159
|
+
* `sort` rather than `order_by`/`sortBy`: it is one word, it is what Stripe and
|
|
160
|
+
* GitHub both spell, and `order` — already taken, already shipped — is the
|
|
161
|
+
* DIRECTION. Two adjacent parameters whose names could be confused for each
|
|
162
|
+
* other is worth avoiding at the point where they are named, not documented
|
|
163
|
+
* around afterwards.
|
|
164
|
+
*/
|
|
165
|
+
export const LIST_SORT_PARAM = 'sort';
|
|
166
|
+
/**
|
|
167
|
+
* A cursor is only valid for the sort that ISSUED it.
|
|
168
|
+
*
|
|
169
|
+
* Keyset paging compares against the sort column, so a cursor taken from a walk
|
|
170
|
+
* ordered by `number` and replayed against one ordered by `created_at` compares
|
|
171
|
+
* a number to a timestamp: the page is not wrong-looking, it is silently
|
|
172
|
+
* arbitrary. Nothing in the cursor says which sort produced it — `pagination.ts`
|
|
173
|
+
* pins it as "the last entry's sort key verbatim … it needs no encoding", and
|
|
174
|
+
* that stays true.
|
|
175
|
+
*
|
|
176
|
+
* **Following the `Link` header is always safe**, which is the whole reason the
|
|
177
|
+
* walk is handed over as a URL rather than a bare cursor: `nextPageLink` rebuilds
|
|
178
|
+
* it from the request, so `sort` and every filter ride along unchanged and a
|
|
179
|
+
* client that follows links cannot construct this mistake.
|
|
180
|
+
*
|
|
181
|
+
* A client that hand-assembles `?cursor=…&sort=other` can, and this is the
|
|
182
|
+
* documented reason not to. Encoding the sort into the cursor would let the
|
|
183
|
+
* server refuse it outright; that was weighed and declined here, because it
|
|
184
|
+
* breaks the "no encoding, survives in a query string" property that makes a
|
|
185
|
+
* cursor debuggable by eye — see K-041.
|
|
186
|
+
*/
|
|
187
|
+
export const CURSOR_BELONGS_TO_ITS_SORT = 'a cursor is only valid for the sort it was issued under — follow the Link header';
|
|
188
|
+
/**
|
|
189
|
+
* A page of the entries a caller may actually SEE (#811).
|
|
190
|
+
*
|
|
191
|
+
* The shape a portal read needs, and the one a naive page gets wrong. Callout and
|
|
192
|
+
* Handlebar both list work orders and then check `read` per row, because the
|
|
193
|
+
* proof walk (workorder → facility → customer) is what decides visibility. Twenty
|
|
194
|
+
* rows fetched can leave three after that walk, so the fetch size and the page
|
|
195
|
+
* size are not the same number and cannot be made the same number.
|
|
196
|
+
*
|
|
197
|
+
* **This page may come back short, and a short page does NOT end the walk.** That
|
|
198
|
+
* is a deliberate divergence from `pageOf`, whose whole cursor rule is "full page
|
|
199
|
+
* ⇒ there may be more, short page ⇒ done". Under a per-row filter that rule is
|
|
200
|
+
* unavailable: the only honest signal left is the underlying cursor, so the walk
|
|
201
|
+
* ends where `nextCursor` is null and nowhere else. A client following the `Link`
|
|
202
|
+
* header does the right thing without knowing any of this; one that stops at the
|
|
203
|
+
* first short page will truncate its own results, which is why it is stated here
|
|
204
|
+
* rather than left to be discovered.
|
|
205
|
+
*
|
|
206
|
+
* The cursor returned is the underlying walk's — the last row EXAMINED, not the
|
|
207
|
+
* last row returned. Advancing by the last row returned would re-examine every
|
|
208
|
+
* row the filter rejected on the next request, and a page whose rows are all
|
|
209
|
+
* rejected would never advance at all.
|
|
210
|
+
*/
|
|
211
|
+
export async function pageVisible(fetch, params, allow) {
|
|
212
|
+
// `params` may be absent entirely: an operation with no declared input, invoked
|
|
213
|
+
// in process by a test or a seed, is handed `undefined` rather than an empty
|
|
214
|
+
// object. `listLimitOf` then supplies the same page an HTTP caller would get.
|
|
215
|
+
const batch = fetch({ limit: listLimitOf(params?.limit), cursor: params?.cursor });
|
|
216
|
+
const entries = [];
|
|
217
|
+
for (const entry of batch.entries) {
|
|
218
|
+
if (await allow(entry))
|
|
219
|
+
entries.push(entry);
|
|
220
|
+
}
|
|
221
|
+
return { entries, nextCursor: batch.nextCursor };
|
|
222
|
+
}
|
|
138
223
|
//# sourceMappingURL=pagination.js.map
|
package/dist/pagination.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.js","sourceRoot":"","sources":["../src/pagination.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pagination.js","sourceRoot":"","sources":["../src/pagination.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,6 +23,64 @@ export declare const platformRequestInput: z.ZodObject<{
|
|
|
23
23
|
payload: z.ZodUnknown;
|
|
24
24
|
}, z.core.$strip>;
|
|
25
25
|
export type PlatformRequestInput = z.infer<typeof platformRequestInput>;
|
|
26
|
+
/**
|
|
27
|
+
* WHO refused a settled intent — the fact the drawer's caption was guessing at (#841).
|
|
28
|
+
*
|
|
29
|
+
* A `connector:<provider>` delivery passes through two authorities before it is over: our
|
|
30
|
+
* own permission check on the way to the bytes, and the provider's answer once they are
|
|
31
|
+
* sent. Both surfaced as a `lastError` string and nothing distinguished them, so the
|
|
32
|
+
* dashboard captioned every failure as the provider's — and a `permission denied:
|
|
33
|
+
* protocol:read` raised on OUR side of egress was rendered as *"what Scrive said, in
|
|
34
|
+
* full"*. An operator reading that goes to look at their Scrive account, presses **Test
|
|
35
|
+
* connection** (which passes, because the credential is fine), and concludes the platform
|
|
36
|
+
* is broken. That is the failure this record exists to end.
|
|
37
|
+
*
|
|
38
|
+
* - `platform` — one of ours, raised before anything reached the provider. The refusal
|
|
39
|
+
* carries a taxonomy `code`, so it can be said precisely rather than quoted.
|
|
40
|
+
* - `provider` — the provider ANSWERED and refused. Only this one may be captioned as
|
|
41
|
+
* their words.
|
|
42
|
+
* - `unknown` — classified and could not be told apart: a bug, a socket that never
|
|
43
|
+
* opened, a give-up at the attempt ceiling. Distinct from a NULL `failure`, which means
|
|
44
|
+
* nobody classified at all (a row settled before this field existed, or one that never
|
|
45
|
+
* failed) — honestly unrecorded rather than honestly unknown.
|
|
46
|
+
*/
|
|
47
|
+
export declare const platformRequestFailureOrigin: z.ZodEnum<{
|
|
48
|
+
platform: "platform";
|
|
49
|
+
provider: "provider";
|
|
50
|
+
unknown: "unknown";
|
|
51
|
+
}>;
|
|
52
|
+
export type PlatformRequestFailureOrigin = z.infer<typeof platformRequestFailureOrigin>;
|
|
53
|
+
/**
|
|
54
|
+
* How a settled intent's last failure was attributed. Written by the drain from the throw
|
|
55
|
+
* itself, never re-derived downstream from the message — a reader that has to regex prose
|
|
56
|
+
* to know who refused is the bug, not the fix.
|
|
57
|
+
*
|
|
58
|
+
* `permission` is the one extension lifted out of the error and given a column of its own,
|
|
59
|
+
* because it is what makes the join mechanical: a refused key that is absent from the
|
|
60
|
+
* connection's grants is the whole diagnosis, and both halves are already rendered inches
|
|
61
|
+
* apart in the integration drawer. Every other extension stays in the message.
|
|
62
|
+
*/
|
|
63
|
+
export declare const platformRequestFailure: z.ZodObject<{
|
|
64
|
+
origin: z.ZodEnum<{
|
|
65
|
+
platform: "platform";
|
|
66
|
+
provider: "provider";
|
|
67
|
+
unknown: "unknown";
|
|
68
|
+
}>;
|
|
69
|
+
code: z.ZodNullable<z.ZodEnum<{
|
|
70
|
+
conflict: "conflict";
|
|
71
|
+
forbidden: "forbidden";
|
|
72
|
+
internal: "internal";
|
|
73
|
+
not_found: "not_found";
|
|
74
|
+
permission_denied: "permission_denied";
|
|
75
|
+
precondition_failed: "precondition_failed";
|
|
76
|
+
rate_limited: "rate_limited";
|
|
77
|
+
unauthenticated: "unauthenticated";
|
|
78
|
+
unavailable: "unavailable";
|
|
79
|
+
validation_failed: "validation_failed";
|
|
80
|
+
}>>;
|
|
81
|
+
permission: z.ZodNullable<z.ZodString>;
|
|
82
|
+
}, z.core.$strip>;
|
|
83
|
+
export type PlatformRequestFailure = z.infer<typeof platformRequestFailure>;
|
|
26
84
|
/** The full kernel-stamped intent record as it lives in the spine and is read by the drain. */
|
|
27
85
|
export declare const platformRequest: z.ZodObject<{
|
|
28
86
|
id: z.core.$ZodBranded<z.ZodString, "PlatformRequestId", "out">;
|
|
@@ -40,6 +98,26 @@ export declare const platformRequest: z.ZodObject<{
|
|
|
40
98
|
}>;
|
|
41
99
|
attempts: z.ZodNumber;
|
|
42
100
|
lastError: z.ZodNullable<z.ZodString>;
|
|
101
|
+
failure: z.ZodNullable<z.ZodObject<{
|
|
102
|
+
origin: z.ZodEnum<{
|
|
103
|
+
platform: "platform";
|
|
104
|
+
provider: "provider";
|
|
105
|
+
unknown: "unknown";
|
|
106
|
+
}>;
|
|
107
|
+
code: z.ZodNullable<z.ZodEnum<{
|
|
108
|
+
conflict: "conflict";
|
|
109
|
+
forbidden: "forbidden";
|
|
110
|
+
internal: "internal";
|
|
111
|
+
not_found: "not_found";
|
|
112
|
+
permission_denied: "permission_denied";
|
|
113
|
+
precondition_failed: "precondition_failed";
|
|
114
|
+
rate_limited: "rate_limited";
|
|
115
|
+
unauthenticated: "unauthenticated";
|
|
116
|
+
unavailable: "unavailable";
|
|
117
|
+
validation_failed: "validation_failed";
|
|
118
|
+
}>>;
|
|
119
|
+
permission: z.ZodNullable<z.ZodString>;
|
|
120
|
+
}, z.core.$strip>>;
|
|
43
121
|
result: z.ZodNullable<z.ZodUnknown>;
|
|
44
122
|
requestedAt: z.core.$ZodBranded<z.ZodString, "Instant", "out">;
|
|
45
123
|
settledAt: z.ZodNullable<z.core.$ZodBranded<z.ZodString, "Instant", "out">>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-request.d.ts","sourceRoot":"","sources":["../src/platform-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"platform-request.d.ts","sourceRoot":"","sources":["../src/platform-request.ts"],"names":[],"mappings":"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"}
|
package/dist/platform-request.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { instant, platformRequestId, scopeId } from './ids.js';
|
|
3
3
|
import { actor, domainEvent } from './events.js';
|
|
4
|
+
import { errorCode } from './errors.js';
|
|
4
5
|
/**
|
|
5
6
|
* Platform intents (docs/architecture/platform-intents.md) — how a sandbox-clean vertical asks the
|
|
6
7
|
* platform to perform a privileged action (provision a sibling scope, request quota, …) without
|
|
@@ -19,6 +20,45 @@ export const platformRequestInput = z.object({
|
|
|
19
20
|
kind: z.string().min(1),
|
|
20
21
|
payload: z.unknown(),
|
|
21
22
|
});
|
|
23
|
+
/**
|
|
24
|
+
* WHO refused a settled intent — the fact the drawer's caption was guessing at (#841).
|
|
25
|
+
*
|
|
26
|
+
* A `connector:<provider>` delivery passes through two authorities before it is over: our
|
|
27
|
+
* own permission check on the way to the bytes, and the provider's answer once they are
|
|
28
|
+
* sent. Both surfaced as a `lastError` string and nothing distinguished them, so the
|
|
29
|
+
* dashboard captioned every failure as the provider's — and a `permission denied:
|
|
30
|
+
* protocol:read` raised on OUR side of egress was rendered as *"what Scrive said, in
|
|
31
|
+
* full"*. An operator reading that goes to look at their Scrive account, presses **Test
|
|
32
|
+
* connection** (which passes, because the credential is fine), and concludes the platform
|
|
33
|
+
* is broken. That is the failure this record exists to end.
|
|
34
|
+
*
|
|
35
|
+
* - `platform` — one of ours, raised before anything reached the provider. The refusal
|
|
36
|
+
* carries a taxonomy `code`, so it can be said precisely rather than quoted.
|
|
37
|
+
* - `provider` — the provider ANSWERED and refused. Only this one may be captioned as
|
|
38
|
+
* their words.
|
|
39
|
+
* - `unknown` — classified and could not be told apart: a bug, a socket that never
|
|
40
|
+
* opened, a give-up at the attempt ceiling. Distinct from a NULL `failure`, which means
|
|
41
|
+
* nobody classified at all (a row settled before this field existed, or one that never
|
|
42
|
+
* failed) — honestly unrecorded rather than honestly unknown.
|
|
43
|
+
*/
|
|
44
|
+
export const platformRequestFailureOrigin = z.enum(['platform', 'provider', 'unknown']);
|
|
45
|
+
/**
|
|
46
|
+
* How a settled intent's last failure was attributed. Written by the drain from the throw
|
|
47
|
+
* itself, never re-derived downstream from the message — a reader that has to regex prose
|
|
48
|
+
* to know who refused is the bug, not the fix.
|
|
49
|
+
*
|
|
50
|
+
* `permission` is the one extension lifted out of the error and given a column of its own,
|
|
51
|
+
* because it is what makes the join mechanical: a refused key that is absent from the
|
|
52
|
+
* connection's grants is the whole diagnosis, and both halves are already rendered inches
|
|
53
|
+
* apart in the integration drawer. Every other extension stays in the message.
|
|
54
|
+
*/
|
|
55
|
+
export const platformRequestFailure = z.object({
|
|
56
|
+
origin: platformRequestFailureOrigin,
|
|
57
|
+
/** The taxonomy code, when the refusal was one of ours. `null` for a provider's answer. */
|
|
58
|
+
code: errorCode.nullable(),
|
|
59
|
+
/** The permission key a `permission_denied` names, when it named one. */
|
|
60
|
+
permission: z.string().min(1).nullable(),
|
|
61
|
+
});
|
|
22
62
|
/** The full kernel-stamped intent record as it lives in the spine and is read by the drain. */
|
|
23
63
|
export const platformRequest = z.object({
|
|
24
64
|
id: platformRequestId,
|
|
@@ -28,6 +68,8 @@ export const platformRequest = z.object({
|
|
|
28
68
|
status: platformRequestStatus,
|
|
29
69
|
attempts: z.number().int().nonnegative(),
|
|
30
70
|
lastError: z.string().nullable(),
|
|
71
|
+
/** How `lastError` was attributed (#841). `null` = unrecorded, never "nobody's fault". */
|
|
72
|
+
failure: platformRequestFailure.nullable(),
|
|
31
73
|
result: z.unknown().nullable(),
|
|
32
74
|
requestedAt: instant, // stamped kernel-side
|
|
33
75
|
settledAt: instant.nullable(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-request.js","sourceRoot":"","sources":["../src/platform-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAC/D,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"platform-request.js","sourceRoot":"","sources":["../src/platform-request.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@substrat-run/contracts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.84.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": {
|