@substrat-run/kernel 0.125.0 → 0.127.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/entity-edges.d.ts +35 -0
- package/dist/entity-edges.d.ts.map +1 -0
- package/dist/entity-edges.js +112 -0
- package/dist/entity-edges.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/invocation-log.d.ts +57 -5
- package/dist/invocation-log.d.ts.map +1 -1
- package/dist/invocation-log.js +156 -45
- package/dist/invocation-log.js.map +1 -1
- package/dist/permission-eval.d.ts +10 -1
- package/dist/permission-eval.d.ts.map +1 -1
- package/dist/permission-eval.js +13 -3
- package/dist/permission-eval.js.map +1 -1
- package/dist/routed-node.d.ts +12 -0
- package/dist/routed-node.d.ts.map +1 -1
- package/dist/routed-node.js +15 -6
- package/dist/routed-node.js.map +1 -1
- package/dist/scope-host.d.ts +38 -2
- package/dist/scope-host.d.ts.map +1 -1
- package/dist/scope-host.js.map +1 -1
- package/dist/scope-repoint.d.ts +51 -0
- package/dist/scope-repoint.d.ts.map +1 -0
- package/dist/scope-repoint.js +70 -0
- package/dist/scope-repoint.js.map +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { scopeId, substratError } from '@substrat-run/contracts';
|
|
2
|
+
/**
|
|
3
|
+
* Re-point a dump's scope-level grants at the scope it lands in, the step every restore, fork
|
|
4
|
+
* and preview carry ends with (#1869). One definition for both adapters' `importDump`, so the
|
|
5
|
+
* DO and the pure host cannot move different rows. It was a `LIKE 'scope:%'`, which ignores
|
|
6
|
+
* case and so also moved an entity grant typed `Scope` or `SCOPE`.
|
|
7
|
+
*
|
|
8
|
+
* Scope-level grants are stored as `object = 'scope:<scopeId>'`, naming the scope the dump
|
|
9
|
+
* was captured FROM, so a copy landing anywhere else has to move them. Entity-narrowed
|
|
10
|
+
* grants are stored as `<entityType>:<entityId>` and travel with the dump unchanged.
|
|
11
|
+
*
|
|
12
|
+
* - **Exact**, when the source is named and either the dump holds a `scope:<source>` row or
|
|
13
|
+
* the source is `exact` (platform-exported): `scope:<source>` and nothing else moves. An
|
|
14
|
+
* entity grant whose type is spelled `scope` in any case stays put (the write verbs refuse
|
|
15
|
+
* that type since #1856, but rows written before it are still stored). When the source IS
|
|
16
|
+
* the destination (a carry onto a new version) nothing moves at all.
|
|
17
|
+
* - **Fallback**, for a dump the caller supplied, when no source is named (a caller that
|
|
18
|
+
* predates the field) or the dump holds no `scope:<source>` row (its stated provenance does
|
|
19
|
+
* not describe its rows, as when `substrat scope restore` stamps a local world with the
|
|
20
|
+
* target's id): every object whose first six characters are exactly `scope:`. That is the
|
|
21
|
+
* rule before #1869 minus LIKE's case folding, so `Scope:<id>` and `SCOPE:<id>` still stay
|
|
22
|
+
* put. An entity typed exactly `scope` cannot be told apart from a node grant here, and moves.
|
|
23
|
+
*
|
|
24
|
+
* A caller-supplied dump that holds its source's grants AND grants on a THIRD scope, shaped
|
|
25
|
+
* like a scope node (`scope:<ULID>`) and neither the source nor the destination, is refused:
|
|
26
|
+
* its stated provenance describes only part of it, and moving the rest would guess. The
|
|
27
|
+
* refusal throws inside the load's transaction, so the target keeps what it held. A platform
|
|
28
|
+
* copy (`exact`) is not refused: there a `scope:<X>` row authorized nothing in the source it
|
|
29
|
+
* was exported from, so it is left untouched and authorizes nothing here either. A
|
|
30
|
+
* `scope:<id>` whose id is not a scope id's shape is an entity grant, and is left alone.
|
|
31
|
+
*
|
|
32
|
+
* The probe and the update are separate statements rather than one with an `EXISTS` in its
|
|
33
|
+
* `WHERE`: the update rewrites the very rows the probe looks for, and the answer must not
|
|
34
|
+
* change part-way through.
|
|
35
|
+
*
|
|
36
|
+
* `COLLATE BINARY` is written out because the tuples table's DDL comes from the dump, and a
|
|
37
|
+
* column declared `COLLATE NOCASE` there would make a bare `=` fold case again.
|
|
38
|
+
*/
|
|
39
|
+
export function repointScopeGrants(sql, destScopeId, source) {
|
|
40
|
+
// `exact` is a claim about a named source; with none named it would silently take the fallback.
|
|
41
|
+
if (source !== undefined && !source.scopeId) {
|
|
42
|
+
throw substratError('validation_failed', 'restore refused: `exact` needs the scope the dump came from');
|
|
43
|
+
}
|
|
44
|
+
const dest = `scope:${destScopeId}`;
|
|
45
|
+
const update = 'UPDATE OR REPLACE _substrat_tuples SET object = ? WHERE object <> ? COLLATE BINARY AND';
|
|
46
|
+
const from = source === undefined ? undefined : `scope:${source.scopeId}`;
|
|
47
|
+
if (from === undefined || (!source?.exact && sql.all(SOURCE_PROBE, from).length === 0)) {
|
|
48
|
+
sql.run(`${update} substr(object, 1, 6) = 'scope:' COLLATE BINARY`, dest, dest);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const strays = source.exact
|
|
52
|
+
? []
|
|
53
|
+
: sql
|
|
54
|
+
.all(STRAY_SCOPES, from, dest)
|
|
55
|
+
.map((r) => String(r.object))
|
|
56
|
+
.filter((o) => scopeId.safeParse(o.slice('scope:'.length)).success);
|
|
57
|
+
if (strays.length > 0) {
|
|
58
|
+
throw substratError('validation_failed', `restore refused: the dump holds grants on ${strays.length} scope(s) other than its source ` +
|
|
59
|
+
`(${source.scopeId}) and this scope (${destScopeId}), which a restore cannot re-point: ` +
|
|
60
|
+
`${strays.slice(0, 3).join(', ')}${strays.length > 3 ? ', …' : ''}`);
|
|
61
|
+
}
|
|
62
|
+
sql.run(`${update} object = ? COLLATE BINARY`, dest, dest, from);
|
|
63
|
+
}
|
|
64
|
+
const SOURCE_PROBE = 'SELECT 1 FROM _substrat_tuples WHERE object = ? COLLATE BINARY LIMIT 1';
|
|
65
|
+
// Live rows only: a revoked grant (K-21 tombstone) on a third scope authorizes nothing anywhere.
|
|
66
|
+
const STRAY_SCOPES = `SELECT DISTINCT object FROM _substrat_tuples
|
|
67
|
+
WHERE substr(object, 1, 6) = 'scope:' COLLATE BINARY AND object <> ? COLLATE BINARY AND object <> ? COLLATE BINARY
|
|
68
|
+
AND revoked_at IS NULL
|
|
69
|
+
ORDER BY object`;
|
|
70
|
+
//# sourceMappingURL=scope-repoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-repoint.js","sourceRoot":"","sources":["../src/scope-repoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAejE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAc,EAAE,WAAmB,EAAE,MAAsB;IAC5F,gGAAgG;IAChG,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAC5C,MAAM,aAAa,CAAC,mBAAmB,EAAE,6DAA6D,CAAC,CAAC;IAC1G,CAAC;IACD,MAAM,IAAI,GAAG,SAAS,WAAW,EAAE,CAAC;IACpC,MAAM,MAAM,GAAG,wFAAwF,CAAC;IACxG,MAAM,IAAI,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,OAAO,EAAE,CAAC;IAC1E,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,EAAE,KAAK,IAAI,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;QACvF,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,iDAAiD,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAChF,OAAO;IACT,CAAC;IACD,MAAM,MAAM,GAAG,MAAO,CAAC,KAAK;QAC1B,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,GAAG;aACA,GAAG,CAAC,YAAY,EAAE,IAAI,EAAE,IAAI,CAAC;aAC7B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;aAC5B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAC1E,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,aAAa,CACjB,mBAAmB,EACnB,6CAA6C,MAAM,CAAC,MAAM,kCAAkC;YAC1F,IAAI,MAAO,CAAC,OAAO,qBAAqB,WAAW,sCAAsC;YACzF,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CACtE,CAAC;IACJ,CAAC;IACD,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,4BAA4B,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,YAAY,GAAG,wEAAwE,CAAC;AAC9F,iGAAiG;AACjG,MAAM,YAAY,GAAG;;;kBAGH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@substrat-run/kernel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.127.0",
|
|
4
4
|
"description": "Substrat kernel contracts and services — pure TypeScript, no platform imports (D-14)",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"repository": {
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
"dist"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@substrat-run/contracts": "^0.
|
|
25
|
+
"@substrat-run/contracts": "^0.127.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@types/node": "^22.
|
|
29
|
-
"hono": "^4.
|
|
28
|
+
"@types/node": "^22.20.4",
|
|
29
|
+
"hono": "^4.13.9",
|
|
30
30
|
"typescript": "^7.0.0",
|
|
31
31
|
"vitest": "^3.2.7"
|
|
32
32
|
},
|