@substrat-run/kernel 0.114.0 → 0.117.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/capability.d.ts +220 -0
- package/dist/capability.d.ts.map +1 -0
- package/dist/capability.js +537 -0
- package/dist/capability.js.map +1 -0
- package/dist/check-key.d.ts +30 -0
- package/dist/check-key.d.ts.map +1 -0
- package/dist/check-key.js +37 -0
- package/dist/check-key.js.map +1 -0
- package/dist/denial-query.d.ts +35 -2
- package/dist/denial-query.d.ts.map +1 -1
- package/dist/denial-query.js +70 -28
- package/dist/denial-query.js.map +1 -1
- package/dist/index.d.ts +23 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -4
- package/dist/index.js.map +1 -1
- package/dist/job-run.d.ts +493 -0
- package/dist/job-run.d.ts.map +1 -0
- package/dist/job-run.js +655 -0
- package/dist/job-run.js.map +1 -0
- package/dist/outbox-event.d.ts +131 -0
- package/dist/outbox-event.d.ts.map +1 -0
- package/dist/outbox-event.js +185 -0
- package/dist/outbox-event.js.map +1 -0
- package/dist/permission-checker.d.ts +8 -1
- package/dist/permission-checker.d.ts.map +1 -1
- package/dist/permission-checker.js +18 -0
- package/dist/permission-checker.js.map +1 -1
- package/dist/permission-eval.d.ts +8 -0
- package/dist/permission-eval.d.ts.map +1 -1
- package/dist/permission-eval.js +164 -91
- package/dist/permission-eval.js.map +1 -1
- package/dist/platform-request-query.d.ts +58 -1
- package/dist/platform-request-query.d.ts.map +1 -1
- package/dist/platform-request-query.js +61 -1
- package/dist/platform-request-query.js.map +1 -1
- package/dist/platform-sweep.d.ts +180 -8
- package/dist/platform-sweep.d.ts.map +1 -1
- package/dist/platform-sweep.js +243 -34
- package/dist/platform-sweep.js.map +1 -1
- package/dist/row-decode.d.ts +107 -0
- package/dist/row-decode.d.ts.map +1 -0
- package/dist/row-decode.js +93 -0
- package/dist/row-decode.js.map +1 -0
- package/dist/scope-host.d.ts +444 -9
- package/dist/scope-host.d.ts.map +1 -1
- package/dist/scope-host.js +33 -0
- package/dist/scope-host.js.map +1 -1
- package/dist/scope-tuple-seat.d.ts +72 -0
- package/dist/scope-tuple-seat.d.ts.map +1 -0
- package/dist/scope-tuple-seat.js +93 -0
- package/dist/scope-tuple-seat.js.map +1 -0
- package/dist/subject-redaction.d.ts +160 -0
- package/dist/subject-redaction.d.ts.map +1 -0
- package/dist/subject-redaction.js +210 -0
- package/dist/subject-redaction.js.map +1 -0
- package/dist/system-switch.d.ts +108 -0
- package/dist/system-switch.d.ts.map +1 -0
- package/dist/system-switch.js +145 -0
- package/dist/system-switch.js.map +1 -0
- package/dist/timeline.d.ts.map +1 -1
- package/dist/timeline.js +115 -52
- package/dist/timeline.js.map +1 -1
- package/package.json +2 -2
package/dist/permission-eval.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { objectRef, subjectRef, } from '@substrat-run/contracts';
|
|
2
|
+
import { capabilityGrantOf, capabilityLive } from './capability.js';
|
|
2
3
|
/**
|
|
3
4
|
* The built-in constrained relationship-tuple evaluator (design doc §4.2, plan D-23),
|
|
4
5
|
* as ONE implementation both adapters call.
|
|
@@ -40,6 +41,45 @@ const nodeObjectsOf = (node) => node.scopeId
|
|
|
40
41
|
{ obj: `tenant:${node.tenantId}`, scoped: false },
|
|
41
42
|
]
|
|
42
43
|
: [{ obj: `tenant:${node.tenantId}`, scoped: false }];
|
|
44
|
+
/**
|
|
45
|
+
* Rule 3's walk, as ONE function: from `start`, look for a hit at each frontier object, then
|
|
46
|
+
* expand one level of declared `parent` edges, to `ENTITY_WALK_DEPTH`. `probe` decides what a
|
|
47
|
+
* hit is — a live entity-narrowed grant for a principal, the capability's own root for a
|
|
48
|
+
* capability subject — so both subjects travel exactly the same edges, to exactly the same
|
|
49
|
+
* depth, skipping exactly the same revoked edges. A capability that reached further than an
|
|
50
|
+
* entity grant (or less far) would be a second algebra.
|
|
51
|
+
*/
|
|
52
|
+
async function walkParents(scope, start, now, probe) {
|
|
53
|
+
let frontier = [{ ref: start, chain: [] }];
|
|
54
|
+
for (let depth = 0; depth <= ENTITY_WALK_DEPTH && frontier.length > 0; depth++) {
|
|
55
|
+
for (const candidate of frontier) {
|
|
56
|
+
const hit = await probe(candidate.ref, candidate.chain);
|
|
57
|
+
if (hit !== undefined)
|
|
58
|
+
return hit;
|
|
59
|
+
}
|
|
60
|
+
// Nothing consults the frontier past the last depth, so expanding it there is a
|
|
61
|
+
// read per candidate for an answer no one asks for.
|
|
62
|
+
if (depth === ENTITY_WALK_DEPTH)
|
|
63
|
+
break;
|
|
64
|
+
const next = [];
|
|
65
|
+
for (const candidate of frontier) {
|
|
66
|
+
for (const p of await scope.parents(candidate.ref)) {
|
|
67
|
+
// A revoked parent edge stops expanding. Without this the tombstone would work
|
|
68
|
+
// for grants and membership but silently NOT for entity edges — which is the
|
|
69
|
+
// case open question 15 is actually about (a facility moving management
|
|
70
|
+
// company must stop being reachable).
|
|
71
|
+
if (!live(p, now))
|
|
72
|
+
continue;
|
|
73
|
+
next.push({
|
|
74
|
+
ref: p.object,
|
|
75
|
+
chain: [...candidate.chain, t(p.subject, 'parent', p.object)],
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
frontier = next;
|
|
80
|
+
}
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
43
83
|
/**
|
|
44
84
|
* Build the evaluator over one adapter's reader. Stateless per call: everything it knows it
|
|
45
85
|
* reads at check time, which is what makes check-after-write consistent (the "no zookies"
|
|
@@ -85,6 +125,124 @@ export function createTupleEvaluator(reader) {
|
|
|
85
125
|
}
|
|
86
126
|
return out;
|
|
87
127
|
};
|
|
128
|
+
/**
|
|
129
|
+
* A CAPABILITY subject (#1672). Resolved against the capability's own directory row —
|
|
130
|
+
* never against tuples, so no `capability:` tuple anywhere could widen it — in four steps,
|
|
131
|
+
* each of which denies on its own:
|
|
132
|
+
*
|
|
133
|
+
* 1. **Usable.** The row exists, can act (`mode: 'act'`), and is neither revoked nor
|
|
134
|
+
* expired — `capabilityLive`, the predicate the session door and the exchange share.
|
|
135
|
+
* 2. **The key.** `permission` is one the capability carries.
|
|
136
|
+
* 3. **The subtree.** An entity is named, and it is the capability's root or lies beneath
|
|
137
|
+
* it along declared parent edges — `walkParents`, the walk entity grants take. A
|
|
138
|
+
* capability holds NO node-level authority: a check without an entity denies.
|
|
139
|
+
* 4. **The minter, now.** The principal who minted it must hold `permission` on this
|
|
140
|
+
* entity at this moment, by the ordinary check. This is what makes "a capability never
|
|
141
|
+
* grants more than its minter holds" true on every use rather than only at mint time:
|
|
142
|
+
* revoke the minter's access and their links stop granting it.
|
|
143
|
+
*
|
|
144
|
+
* The proof is the minter's own chain, a `minted-by` link, the parent chain, and last the
|
|
145
|
+
* capability's grant on its root — last so K-34's `grantRefFromProof` names the root.
|
|
146
|
+
*/
|
|
147
|
+
async function checkCapability(id, permission, node, entity) {
|
|
148
|
+
const deny = { allowed: false, checked: permission, node };
|
|
149
|
+
if (!entity || !node.scopeId)
|
|
150
|
+
return deny;
|
|
151
|
+
const scope = reader.scopeFor(node);
|
|
152
|
+
if (!scope?.capability)
|
|
153
|
+
return deny;
|
|
154
|
+
const now = reader.now();
|
|
155
|
+
const row = await scope.capability(id);
|
|
156
|
+
if (!row || !capabilityLive(row, now))
|
|
157
|
+
return deny;
|
|
158
|
+
const grant = capabilityGrantOf(row);
|
|
159
|
+
if (!grant || !grant.mintedBy || !grant.permissions.includes(permission))
|
|
160
|
+
return deny;
|
|
161
|
+
const root = `${grant.entity.entityType}:${grant.entity.entityId}`;
|
|
162
|
+
const self = `capability:${id}`;
|
|
163
|
+
const chain = await walkParents(scope, `${entity.entityType}:${entity.entityId}`, now, async (ref, walked) => ref === root ? [...walked, t(self, `granted:${permission}`, root)] : undefined);
|
|
164
|
+
if (!chain)
|
|
165
|
+
return deny;
|
|
166
|
+
const minter = await check({ kind: 'principal', id: grant.mintedBy }, permission, node, entity);
|
|
167
|
+
if (!minter.allowed)
|
|
168
|
+
return deny;
|
|
169
|
+
return {
|
|
170
|
+
allowed: true,
|
|
171
|
+
proof: [...minter.proof, t(self, 'minted-by', `principal:${grant.mintedBy}`), ...chain],
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
async function check(subject, permission, node, entity) {
|
|
175
|
+
if (subject.kind === 'capability') {
|
|
176
|
+
return checkCapability(subject.id, permission, node, entity);
|
|
177
|
+
}
|
|
178
|
+
const now = reader.now();
|
|
179
|
+
const deny = { allowed: false, checked: permission, node };
|
|
180
|
+
const scope = reader.scopeFor(node);
|
|
181
|
+
const getRole = roleReaderFor(node.tenantId);
|
|
182
|
+
// Rule 4 — membership: the subject set is the caller plus its orgs. Shared with
|
|
183
|
+
// `covers` (§ `subjectsOf`).
|
|
184
|
+
const subjects = await subjectsOf(subject, node, now);
|
|
185
|
+
const tuplesFor = async (subjectRefValue, prefix, scoped) => scoped
|
|
186
|
+
? scope
|
|
187
|
+
? scope.tuples(subjectRefValue, prefix)
|
|
188
|
+
: []
|
|
189
|
+
: reader.tenantTuples(node.tenantId, subjectRefValue, prefix);
|
|
190
|
+
for (const nodeObj of nodeObjectsOf(node)) {
|
|
191
|
+
for (const s of subjects) {
|
|
192
|
+
// Rule 1 — role expansion.
|
|
193
|
+
for (const row of await tuplesFor(s.ref, 'role:', nodeObj.scoped)) {
|
|
194
|
+
if (row.object !== nodeObj.obj || !live(row, now))
|
|
195
|
+
continue;
|
|
196
|
+
const roleKey = row.relation.slice('role:'.length);
|
|
197
|
+
const role = await getRole(roleKey);
|
|
198
|
+
if (role?.permissions.includes(permission)) {
|
|
199
|
+
return {
|
|
200
|
+
allowed: true,
|
|
201
|
+
proof: [
|
|
202
|
+
...(s.via ? [s.via] : []),
|
|
203
|
+
t(row.subject, row.relation, row.object),
|
|
204
|
+
t(`role:${roleKey}`, `granted:${permission}`, nodeObj.obj),
|
|
205
|
+
],
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// Direct grants at the node.
|
|
210
|
+
for (const row of await tuplesFor(s.ref, `granted:${permission}`, nodeObj.scoped)) {
|
|
211
|
+
if (row.object === nodeObj.obj &&
|
|
212
|
+
row.relation === `granted:${permission}` &&
|
|
213
|
+
live(row, now)) {
|
|
214
|
+
return {
|
|
215
|
+
allowed: true,
|
|
216
|
+
proof: [...(s.via ? [s.via] : []), t(row.subject, row.relation, row.object)],
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// Rule 3 — entity walk along declared parent edges (entity grants are scope-local by
|
|
223
|
+
// construction, so no scope store means no walk).
|
|
224
|
+
if (entity && scope) {
|
|
225
|
+
const found = await walkParents(scope, `${entity.entityType}:${entity.entityId}`, now, async (ref, chain) => {
|
|
226
|
+
for (const s of subjects) {
|
|
227
|
+
const grant = await scope.grant(s.ref, `granted:${permission}`, ref);
|
|
228
|
+
if (grant && live(grant, now)) {
|
|
229
|
+
return {
|
|
230
|
+
allowed: true,
|
|
231
|
+
proof: [
|
|
232
|
+
...(s.via ? [s.via] : []),
|
|
233
|
+
...chain,
|
|
234
|
+
t(grant.subject, grant.relation, grant.object),
|
|
235
|
+
],
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return undefined;
|
|
240
|
+
});
|
|
241
|
+
if (found)
|
|
242
|
+
return found;
|
|
243
|
+
}
|
|
244
|
+
return deny;
|
|
245
|
+
}
|
|
88
246
|
return {
|
|
89
247
|
/**
|
|
90
248
|
* The subject's effective permission set at the node, compared against `required`
|
|
@@ -103,6 +261,11 @@ export function createTupleEvaluator(reader) {
|
|
|
103
261
|
// prove the empty set is a subset of anything.
|
|
104
262
|
if (required.length === 0)
|
|
105
263
|
return { covered: true, missing: [] };
|
|
264
|
+
// A capability holds no node-level authority by construction (#1672) — everything it
|
|
265
|
+
// carries is narrowed onto one entity — so it covers nothing and can confer nothing.
|
|
266
|
+
if (subject.kind === 'capability') {
|
|
267
|
+
return { covered: false, missing: [...new Set(required)] };
|
|
268
|
+
}
|
|
106
269
|
const now = reader.now();
|
|
107
270
|
const scope = reader.scopeFor(node);
|
|
108
271
|
const subjects = await subjectsOf(subject, node, now);
|
|
@@ -138,97 +301,7 @@ export function createTupleEvaluator(reader) {
|
|
|
138
301
|
}
|
|
139
302
|
return missing.length === 0 ? { covered: true, missing: [] } : { covered: false, missing };
|
|
140
303
|
},
|
|
141
|
-
|
|
142
|
-
const now = reader.now();
|
|
143
|
-
const deny = { allowed: false, checked: permission, node };
|
|
144
|
-
const scope = reader.scopeFor(node);
|
|
145
|
-
const getRole = roleReaderFor(node.tenantId);
|
|
146
|
-
// Rule 4 — membership: the subject set is the caller plus its orgs. Shared with
|
|
147
|
-
// `covers` (§ `subjectsOf`).
|
|
148
|
-
const subjects = await subjectsOf(subject, node, now);
|
|
149
|
-
const tuplesFor = async (subjectRefValue, prefix, scoped) => scoped
|
|
150
|
-
? scope
|
|
151
|
-
? scope.tuples(subjectRefValue, prefix)
|
|
152
|
-
: []
|
|
153
|
-
: reader.tenantTuples(node.tenantId, subjectRefValue, prefix);
|
|
154
|
-
for (const nodeObj of nodeObjectsOf(node)) {
|
|
155
|
-
for (const s of subjects) {
|
|
156
|
-
// Rule 1 — role expansion.
|
|
157
|
-
for (const row of await tuplesFor(s.ref, 'role:', nodeObj.scoped)) {
|
|
158
|
-
if (row.object !== nodeObj.obj || !live(row, now))
|
|
159
|
-
continue;
|
|
160
|
-
const roleKey = row.relation.slice('role:'.length);
|
|
161
|
-
const role = await getRole(roleKey);
|
|
162
|
-
if (role?.permissions.includes(permission)) {
|
|
163
|
-
return {
|
|
164
|
-
allowed: true,
|
|
165
|
-
proof: [
|
|
166
|
-
...(s.via ? [s.via] : []),
|
|
167
|
-
t(row.subject, row.relation, row.object),
|
|
168
|
-
t(`role:${roleKey}`, `granted:${permission}`, nodeObj.obj),
|
|
169
|
-
],
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
// Direct grants at the node.
|
|
174
|
-
for (const row of await tuplesFor(s.ref, `granted:${permission}`, nodeObj.scoped)) {
|
|
175
|
-
if (row.object === nodeObj.obj &&
|
|
176
|
-
row.relation === `granted:${permission}` &&
|
|
177
|
-
live(row, now)) {
|
|
178
|
-
return {
|
|
179
|
-
allowed: true,
|
|
180
|
-
proof: [...(s.via ? [s.via] : []), t(row.subject, row.relation, row.object)],
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
// Rule 3 — entity walk along declared parent edges (entity grants are scope-local by
|
|
187
|
-
// construction, so no scope store means no walk).
|
|
188
|
-
if (entity && scope) {
|
|
189
|
-
let frontier = [{ ref: `${entity.entityType}:${entity.entityId}`, chain: [] }];
|
|
190
|
-
for (let depth = 0; depth <= ENTITY_WALK_DEPTH && frontier.length > 0; depth++) {
|
|
191
|
-
// grant lookup at current frontier objects
|
|
192
|
-
for (const candidate of frontier) {
|
|
193
|
-
for (const s of subjects) {
|
|
194
|
-
const grant = await scope.grant(s.ref, `granted:${permission}`, candidate.ref);
|
|
195
|
-
if (grant && live(grant, now)) {
|
|
196
|
-
return {
|
|
197
|
-
allowed: true,
|
|
198
|
-
proof: [
|
|
199
|
-
...(s.via ? [s.via] : []),
|
|
200
|
-
...candidate.chain,
|
|
201
|
-
t(grant.subject, grant.relation, grant.object),
|
|
202
|
-
],
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
// Nothing consults the frontier past the last depth, so expanding it there is a
|
|
208
|
-
// read per candidate for an answer no one asks for.
|
|
209
|
-
if (depth === ENTITY_WALK_DEPTH)
|
|
210
|
-
break;
|
|
211
|
-
// expand one level of parents
|
|
212
|
-
const next = [];
|
|
213
|
-
for (const candidate of frontier) {
|
|
214
|
-
for (const p of await scope.parents(candidate.ref)) {
|
|
215
|
-
// A revoked parent edge stops expanding. Without this the tombstone would work
|
|
216
|
-
// for grants and membership but silently NOT for entity edges — which is the
|
|
217
|
-
// case open question 15 is actually about (a facility moving management
|
|
218
|
-
// company must stop being reachable).
|
|
219
|
-
if (!live(p, now))
|
|
220
|
-
continue;
|
|
221
|
-
next.push({
|
|
222
|
-
ref: p.object,
|
|
223
|
-
chain: [...candidate.chain, t(p.subject, 'parent', p.object)],
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
frontier = next;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
return deny;
|
|
231
|
-
},
|
|
304
|
+
check,
|
|
232
305
|
};
|
|
233
306
|
}
|
|
234
307
|
//# sourceMappingURL=permission-eval.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permission-eval.js","sourceRoot":"","sources":["../src/permission-eval.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,UAAU,GASX,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"permission-eval.js","sourceRoot":"","sources":["../src/permission-eval.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type PlatformRequestFilter } from '@substrat-run/contracts';
|
|
1
|
+
import { type Actor, type PlatformRequest, type PlatformRequestFilter } from '@substrat-run/contracts';
|
|
2
2
|
/**
|
|
3
3
|
* The one SELECT behind every read of a scope's intent journal (#618).
|
|
4
4
|
*
|
|
@@ -16,4 +16,61 @@ export declare function platformRequestHistoryQuery(filter?: PlatformRequestFilt
|
|
|
16
16
|
sql: string;
|
|
17
17
|
params: (string | number)[];
|
|
18
18
|
};
|
|
19
|
+
/** A stored `_substrat_platform_requests` row — snake_case, the JSON columns still text. */
|
|
20
|
+
export interface PlatformRequestRawRow {
|
|
21
|
+
id: string;
|
|
22
|
+
kind: string;
|
|
23
|
+
payload: string;
|
|
24
|
+
requested_by: string;
|
|
25
|
+
impersonation: string | null;
|
|
26
|
+
status: string;
|
|
27
|
+
attempts: number;
|
|
28
|
+
last_error: string | null;
|
|
29
|
+
last_failure: string | null;
|
|
30
|
+
result: string | null;
|
|
31
|
+
requested_at: string;
|
|
32
|
+
settled_at: string | null;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* What `requestedBy` reads as when the stored actor did not decode. The field is required and
|
|
36
|
+
* an actor has no empty value, so this is a marker that names itself rather than a plausible
|
|
37
|
+
* requester: a guessed principal would be the one thing worse than admitting nobody can tell.
|
|
38
|
+
* The same marker every tolerant spine read uses (#1636), so it is one value, not four.
|
|
39
|
+
*/
|
|
40
|
+
export declare const UNDECODED_REQUESTER: Actor;
|
|
41
|
+
/**
|
|
42
|
+
* A stored row → the `PlatformRequest` contract shape — TOLERANTLY, and saying so (#1588).
|
|
43
|
+
*
|
|
44
|
+
* Every read of the journal returns a LIST, and this decode used to be strict: one row whose
|
|
45
|
+
* JSON would not parse threw out of the map and took every other intent on the scope with it.
|
|
46
|
+
* That disabled the drain's own queue, and `listPlatformRequestHistory` too — the read that
|
|
47
|
+
* exists so a settled intent's failure is legible afterwards (#618), switched off by the row
|
|
48
|
+
* that failed. Each field is now decoded against its own contract field, and whatever did not
|
|
49
|
+
* decode is named, by column, in `decodeError`, with the field EMPTY in its place:
|
|
50
|
+
*
|
|
51
|
+
* - a JSON column comes back `null`, or {@link UNDECODED_REQUESTER} for the one that cannot be
|
|
52
|
+
* null. Never the raw text: a raw `payload` would read as a string payload that was never
|
|
53
|
+
* sent, which is a guess dressed as a fact.
|
|
54
|
+
* - a nullable scalar (`last_error`, `settled_at`) comes back `null`.
|
|
55
|
+
*
|
|
56
|
+
* **Every value this returns satisfies the contract.** A field is only ever replaced by a value
|
|
57
|
+
* its own schema accepts, so the type is not asserting something the published schema would
|
|
58
|
+
* refuse — a consumer switching on `status` or passing `id` on as a branded id can trust both.
|
|
59
|
+
* The price is the REQUIRED scalars (`id`, `kind`, `status`, `attempts`, `requested_at`): they
|
|
60
|
+
* have no empty value, so a row that breaks one of them cannot be a `PlatformRequest` without
|
|
61
|
+
* lying, and it throws, naming every column it broke — the strict decode this replaced, kept
|
|
62
|
+
* for exactly the part it cannot honestly be relaxed for. JSON is what a foreign dump actually
|
|
63
|
+
* gets wrong; representing a row whose identity itself is corrupt needs a variant beside
|
|
64
|
+
* `PlatformRequest` on every read, which is a contract change of its own.
|
|
65
|
+
*
|
|
66
|
+
* A row the kernel wrote decodes whole and carries no `decodeError` at all, so a healthy list
|
|
67
|
+
* is exactly what it was. This is the READ's half of #1587's rule — strict where work happens,
|
|
68
|
+
* tolerant where evidence is read; the work half is the drain, which refuses any row carrying
|
|
69
|
+
* `decodeError` rather than run a handler on it.
|
|
70
|
+
*
|
|
71
|
+
* Reachable without a forge: `importDump` replays a dump's rows verbatim, so a dump from
|
|
72
|
+
* another world, or one edited by hand, is enough. The field-by-field mechanics are
|
|
73
|
+
* `rowDecoder`'s, shared with the history and denial reads (#1636).
|
|
74
|
+
*/
|
|
75
|
+
export declare function platformRequestOf(row: PlatformRequestRawRow): PlatformRequest;
|
|
19
76
|
//# sourceMappingURL=platform-request-query.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-request-query.d.ts","sourceRoot":"","sources":["../src/platform-request-query.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"platform-request-query.d.ts","sourceRoot":"","sources":["../src/platform-request-query.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,KAAK,EACV,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC3B,MAAM,yBAAyB,CAAC;AAGjC;;;;;;;;;;GAUG;AAEH,0FAA0F;AAC1F,eAAO,MAAM,wBAAwB,iIAC2F,CAAC;AAEjI,wBAAgB,2BAA2B,CAAC,MAAM,CAAC,EAAE,qBAAqB,GAAG;IAC3E,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;CAC7B,CAoBA;AAED,4FAA4F;AAC5F,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAAuB,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,qBAAqB,GAAG,eAAe,CAiB7E"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { DEFAULT_PLATFORM_REQUEST_HISTORY_LIMIT, platformRequestFilter, } from '@substrat-run/contracts';
|
|
1
|
+
import { DEFAULT_PLATFORM_REQUEST_HISTORY_LIMIT, platformRequest, platformRequestFilter, } from '@substrat-run/contracts';
|
|
2
|
+
import { rowDecoder, UNDECODED_ACTOR } from './row-decode.js';
|
|
2
3
|
/**
|
|
3
4
|
* The one SELECT behind every read of a scope's intent journal (#618).
|
|
4
5
|
*
|
|
@@ -32,4 +33,63 @@ export function platformRequestHistoryQuery(filter) {
|
|
|
32
33
|
params,
|
|
33
34
|
};
|
|
34
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* What `requestedBy` reads as when the stored actor did not decode. The field is required and
|
|
38
|
+
* an actor has no empty value, so this is a marker that names itself rather than a plausible
|
|
39
|
+
* requester: a guessed principal would be the one thing worse than admitting nobody can tell.
|
|
40
|
+
* The same marker every tolerant spine read uses (#1636), so it is one value, not four.
|
|
41
|
+
*/
|
|
42
|
+
export const UNDECODED_REQUESTER = UNDECODED_ACTOR;
|
|
43
|
+
/**
|
|
44
|
+
* A stored row → the `PlatformRequest` contract shape — TOLERANTLY, and saying so (#1588).
|
|
45
|
+
*
|
|
46
|
+
* Every read of the journal returns a LIST, and this decode used to be strict: one row whose
|
|
47
|
+
* JSON would not parse threw out of the map and took every other intent on the scope with it.
|
|
48
|
+
* That disabled the drain's own queue, and `listPlatformRequestHistory` too — the read that
|
|
49
|
+
* exists so a settled intent's failure is legible afterwards (#618), switched off by the row
|
|
50
|
+
* that failed. Each field is now decoded against its own contract field, and whatever did not
|
|
51
|
+
* decode is named, by column, in `decodeError`, with the field EMPTY in its place:
|
|
52
|
+
*
|
|
53
|
+
* - a JSON column comes back `null`, or {@link UNDECODED_REQUESTER} for the one that cannot be
|
|
54
|
+
* null. Never the raw text: a raw `payload` would read as a string payload that was never
|
|
55
|
+
* sent, which is a guess dressed as a fact.
|
|
56
|
+
* - a nullable scalar (`last_error`, `settled_at`) comes back `null`.
|
|
57
|
+
*
|
|
58
|
+
* **Every value this returns satisfies the contract.** A field is only ever replaced by a value
|
|
59
|
+
* its own schema accepts, so the type is not asserting something the published schema would
|
|
60
|
+
* refuse — a consumer switching on `status` or passing `id` on as a branded id can trust both.
|
|
61
|
+
* The price is the REQUIRED scalars (`id`, `kind`, `status`, `attempts`, `requested_at`): they
|
|
62
|
+
* have no empty value, so a row that breaks one of them cannot be a `PlatformRequest` without
|
|
63
|
+
* lying, and it throws, naming every column it broke — the strict decode this replaced, kept
|
|
64
|
+
* for exactly the part it cannot honestly be relaxed for. JSON is what a foreign dump actually
|
|
65
|
+
* gets wrong; representing a row whose identity itself is corrupt needs a variant beside
|
|
66
|
+
* `PlatformRequest` on every read, which is a contract change of its own.
|
|
67
|
+
*
|
|
68
|
+
* A row the kernel wrote decodes whole and carries no `decodeError` at all, so a healthy list
|
|
69
|
+
* is exactly what it was. This is the READ's half of #1587's rule — strict where work happens,
|
|
70
|
+
* tolerant where evidence is read; the work half is the drain, which refuses any row carrying
|
|
71
|
+
* `decodeError` rather than run a handler on it.
|
|
72
|
+
*
|
|
73
|
+
* Reachable without a forge: `importDump` replays a dump's rows verbatim, so a dump from
|
|
74
|
+
* another world, or one edited by hand, is enough. The field-by-field mechanics are
|
|
75
|
+
* `rowDecoder`'s, shared with the history and denial reads (#1636).
|
|
76
|
+
*/
|
|
77
|
+
export function platformRequestOf(row) {
|
|
78
|
+
const shape = platformRequest.shape;
|
|
79
|
+
const d = rowDecoder(`platform request row ${JSON.stringify(row.id)}`, 'PlatformRequest');
|
|
80
|
+
return d.finish({
|
|
81
|
+
id: d.required('id', shape.id, row.id),
|
|
82
|
+
kind: d.required('kind', shape.kind, row.kind),
|
|
83
|
+
payload: d.json('payload', shape.payload, row.payload, null),
|
|
84
|
+
requestedBy: d.json('requested_by', shape.requestedBy, row.requested_by, UNDECODED_REQUESTER),
|
|
85
|
+
impersonation: d.json('impersonation', shape.impersonation, row.impersonation, null),
|
|
86
|
+
status: d.required('status', shape.status, row.status),
|
|
87
|
+
attempts: d.required('attempts', shape.attempts, row.attempts),
|
|
88
|
+
lastError: d.nullable('last_error', shape.lastError, row.last_error),
|
|
89
|
+
failure: d.json('last_failure', shape.failure, row.last_failure, null),
|
|
90
|
+
result: d.json('result', shape.result, row.result, null),
|
|
91
|
+
requestedAt: d.required('requested_at', shape.requestedAt, row.requested_at),
|
|
92
|
+
settledAt: d.nullable('settled_at', shape.settledAt, row.settled_at),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
35
95
|
//# sourceMappingURL=platform-request-query.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-request-query.js","sourceRoot":"","sources":["../src/platform-request-query.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sCAAsC,EACtC,qBAAqB,
|
|
1
|
+
{"version":3,"file":"platform-request-query.js","sourceRoot":"","sources":["../src/platform-request-query.ts"],"names":[],"mappings":"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"}
|