@substrat-run/kernel 0.88.0 → 0.90.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/denial-query.d.ts +3 -1
- package/dist/denial-query.d.ts.map +1 -1
- package/dist/denial-query.js +2 -1
- package/dist/denial-query.js.map +1 -1
- package/dist/idempotency.d.ts +143 -0
- package/dist/idempotency.d.ts.map +1 -0
- package/dist/idempotency.js +197 -0
- package/dist/idempotency.js.map +1 -0
- package/dist/impersonation.d.ts +102 -0
- package/dist/impersonation.d.ts.map +1 -0
- package/dist/impersonation.js +202 -0
- package/dist/impersonation.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/platform-request-query.d.ts +1 -1
- package/dist/platform-request-query.d.ts.map +1 -1
- package/dist/platform-request-query.js +1 -1
- package/dist/platform-request-query.js.map +1 -1
- package/dist/scope-host.d.ts +104 -5
- package/dist/scope-host.d.ts.map +1 -1
- package/dist/scope-host.js +7 -0
- package/dist/scope-host.js.map +1 -1
- package/dist/timeline.d.ts +97 -0
- package/dist/timeline.d.ts.map +1 -0
- package/dist/timeline.js +112 -0
- package/dist/timeline.js.map +1 -0
- package/package.json +2 -2
package/dist/scope-host.js
CHANGED
|
@@ -50,6 +50,13 @@ export function attachmentBlobKey(scopeId, attachmentId) {
|
|
|
50
50
|
* `held` is every key projected for the tenant, expired ones included and marked: a lapsed
|
|
51
51
|
* grant denies exactly like an absent one, and "you have it, it ran out" is a different fix
|
|
52
52
|
* from "you never had it".
|
|
53
|
+
*
|
|
54
|
+
* **Its code is `not_found`** at all three throw sites (#113). Not an oversight and not
|
|
55
|
+
* `forbidden`: the taxonomy's `not_found` row already covers "exists, and must read as
|
|
56
|
+
* absent" for K-3's cross-tenant case, and every vertical had independently arrived at a
|
|
57
|
+
* 404 here for the same reason — *"a 403 would confirm the feature exists"*
|
|
58
|
+
* ([`todo/routes.ts`](../../../demos/todo/src/routes.ts)). Naming the code once is what
|
|
59
|
+
* retires those hand-written patterns.
|
|
53
60
|
*/
|
|
54
61
|
export function entitlementDenial(operation, requiredKey, held) {
|
|
55
62
|
const inventory = held.length === 0
|
package/dist/scope-host.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope-host.js","sourceRoot":"","sources":["../src/scope-host.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scope-host.js","sourceRoot":"","sources":["../src/scope-host.ts"],"names":[],"mappings":"AAu3BA;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAA2B;IAC5D,OAAO;QACL,WAAW,EAAE,KAAK,EAAE,WAAW,IAAI,CAAC;QACpC,WAAW,EAAE,KAAK,EAAE,WAAW,IAAI,KAAK;QACxC,UAAU,EAAE,KAAK,EAAE,UAAU,IAAI,OAAO;KACzC,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CACvB,QAAgB,EAChB,KAAoC,EACpC,IAAU;IAEV,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAChF,MAAM,QAAQ,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC;IACnE,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;AAC3D,CAAC;AAqJD,MAAM,UAAU,YAAY;IAC1B,OAAO,CAAoC,QAA+C,EAAK,EAAE,CAAC,QAAQ,CAAC;AAC7G,CAAC;AA+/CD;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,YAAoB;IACrE,OAAO,SAAS,OAAO,QAAQ,YAAY,EAAE,CAAC;AAChD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,iBAAiB,CAC/B,SAAiB,EACjB,WAAmB,EACnB,IAAkD;IAElD,MAAM,SAAS,GACb,IAAI,CAAC,MAAM,KAAK,CAAC;QACf,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7E,OAAO,2BAA2B,SAAS,4BAA4B,WAAW,aAAa,SAAS,EAAE,CAAC;AAC7G,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAA8B;IACnE,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxC,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAE,MAAsB,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,6EAA6E;QAC7E,kFAAkF;QAClF,0DAA0D;QAC1D,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAmFD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { type EntityRef, type HistoryEntry, type ListPage, type Page, type TimelineEntry } from '@substrat-run/contracts';
|
|
2
|
+
import type { ScopedSql } from './scope-host.js';
|
|
3
|
+
/**
|
|
4
|
+
* Reading an entity's history out of the spine (#800).
|
|
5
|
+
*
|
|
6
|
+
* `_substrat_outbox` is the kernel's table and a timeline read of it is a
|
|
7
|
+
* SANCTIONED projection — rule 3 bans writes to `_substrat_*`, not reads, because
|
|
8
|
+
* "show me the history of this thing" has no other honest source. What was
|
|
9
|
+
* missing is a supported SHAPE for it, and five demos wrote the query by hand in
|
|
10
|
+
* its absence. They did not agree, and the disagreements were not cosmetic:
|
|
11
|
+
*
|
|
12
|
+
* | Demo | Order | Cursor |
|
|
13
|
+
* |---|---|---|
|
|
14
|
+
* | callout, handlebar | `rowid` | `rowid` |
|
|
15
|
+
* | meridian, rally | `occurred_at, rowid` | `occurred_at` |
|
|
16
|
+
* | manyfold | `rowid` | *(unpaged)* |
|
|
17
|
+
*
|
|
18
|
+
* **Meridian's and rally's paging drops events.** The cursor is `occurred_at`
|
|
19
|
+
* and the walk is `occurred_at > ?`, so every row sharing the last row's
|
|
20
|
+
* timestamp is skipped — and sharing it is the NORM, not a rare tie: `ctx.now()`
|
|
21
|
+
* is stable for the whole invocation (#812), so every event one operation emits
|
|
22
|
+
* carries the identical instant. A page boundary landing inside an operation's
|
|
23
|
+
* events silently loses the rest of them, and no test would catch it.
|
|
24
|
+
*
|
|
25
|
+
* So the walk here is `ORDER BY id`, and the cursor is `id`:
|
|
26
|
+
*
|
|
27
|
+
* - **`id` IS the entity's version at that point** (#901). The same token
|
|
28
|
+
* `ctx.versionOf` returns and `If-Match` compares (#129/#906), so listing the
|
|
29
|
+
* history, naming a version, and refusing a stale write stop being three
|
|
30
|
+
* vocabularies.
|
|
31
|
+
* - **Creation order, exactly.** `ulid()` uses the spec's monotonic factory, so
|
|
32
|
+
* two ids minted in one millisecond still sort in the order they were made.
|
|
33
|
+
* That property is what `entityVersionQuery` already relies on; a timeline
|
|
34
|
+
* ordering by `rowid` was the odd one out.
|
|
35
|
+
* - **The index already exists.** `OUTBOX_ENTITY_INDEX` is
|
|
36
|
+
* `(entity_type, entity_id, id)`, built for `entityVersionQuery`, and it makes
|
|
37
|
+
* this a seek with no new DDL. A `rowid` cursor cannot use it.
|
|
38
|
+
* - **`rowid` does not survive a restore. `id` does.**
|
|
39
|
+
*
|
|
40
|
+
* ## These do NOT check a permission, deliberately
|
|
41
|
+
*
|
|
42
|
+
* Every caller does its own `assertAllowed(await ctx.check(read, entity))` first,
|
|
43
|
+
* and that stays the caller's job: a helper that gated itself would become a
|
|
44
|
+
* second, invisible policy surface, and one that gated itself on nothing would be
|
|
45
|
+
* an unchecked read path into every event in the scope. Neither is better than
|
|
46
|
+
* the one line at the call site.
|
|
47
|
+
*
|
|
48
|
+
* ```ts
|
|
49
|
+
* assertAllowed(await ctx.check(WO.read, entity));
|
|
50
|
+
* return readTimeline(ctx, entity, input);
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* ## Read-only by construction
|
|
54
|
+
*
|
|
55
|
+
* Both build a `SELECT` and nothing else. `boundary-lint`'s ban on writing
|
|
56
|
+
* `_substrat_*` is untouched and must stay that way — this is a way to read the
|
|
57
|
+
* spine, never a way to forge it.
|
|
58
|
+
*/
|
|
59
|
+
/** What the reads need from a context: the scope's SQL, and only its query half. */
|
|
60
|
+
export interface TimelineReader {
|
|
61
|
+
readonly sql: Pick<ScopedSql, 'query'>;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* An entity's timeline — WHAT happened to it, WHEN, and BY WHOM.
|
|
65
|
+
*
|
|
66
|
+
* The envelope only: no payload, so there is no disclosure decision to make and
|
|
67
|
+
* nothing an erasure can leave behind. `readHistory` is the same walk with what a
|
|
68
|
+
* history VIEW needs.
|
|
69
|
+
*
|
|
70
|
+
* Paged like an HTTP list read rather than like a kernel read — an unset `limit`
|
|
71
|
+
* is `LIST_PAGE_DEFAULT`, not unbounded — because the caller is an app walking a
|
|
72
|
+
* screen, and an entity that has been touched ten thousand times must not answer
|
|
73
|
+
* with ten thousand rows because nobody said a number.
|
|
74
|
+
*/
|
|
75
|
+
export declare function readTimeline(ctx: TimelineReader, entity: EntityRef, page?: ListPage): Page<TimelineEntry>;
|
|
76
|
+
/**
|
|
77
|
+
* An entity's history — the timeline, plus what was said and under what
|
|
78
|
+
* authority.
|
|
79
|
+
*
|
|
80
|
+
* Three fields beyond the envelope, each answering something a history strip
|
|
81
|
+
* needs and a timeline cannot:
|
|
82
|
+
*
|
|
83
|
+
* - **`payload`** — the fat event, i.e. the NEW values. Field-level "X → Y" is
|
|
84
|
+
* reconstructed by diffing consecutive payloads; nothing stores a before-state.
|
|
85
|
+
* **Null after a shred** — a supported result, not an error (see `historyEntry`).
|
|
86
|
+
* - **`authorization`** (K-34) — the checks the emitting operation passed, and
|
|
87
|
+
* which grant allowed each. Not just who changed it but under what authority,
|
|
88
|
+
* which most systems cannot answer at all and this one gets for free.
|
|
89
|
+
* - **`piiClass` / `subjectId`** — so the caller can decide what is safe to
|
|
90
|
+
* render before it renders it.
|
|
91
|
+
*
|
|
92
|
+
* Same permission posture as `readTimeline`: the caller checks, this does not.
|
|
93
|
+
* The payload makes that more load-bearing here, not less — this is the read that
|
|
94
|
+
* can disclose what an event said.
|
|
95
|
+
*/
|
|
96
|
+
export declare function readHistory(ctx: TimelineReader, entity: EntityRef, page?: ListPage): Page<HistoryEntry>;
|
|
97
|
+
//# sourceMappingURL=timeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeline.d.ts","sourceRoot":"","sources":["../src/timeline.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EAGd,KAAK,YAAY,EAGjB,KAAK,QAAQ,EACb,KAAK,IAAI,EAET,KAAK,aAAa,EACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AAEH,oFAAoF;AACpF,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;CACxC;AAiGD;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,SAAS,EACjB,IAAI,CAAC,EAAE,QAAQ,GACd,IAAI,CAAC,aAAa,CAAC,CAKrB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,SAAS,EACjB,IAAI,CAAC,EAAE,QAAQ,GACd,IAAI,CAAC,YAAY,CAAC,CAKpB"}
|
package/dist/timeline.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { listLimitOf, pageOf, } from '@substrat-run/contracts';
|
|
2
|
+
/** The envelope columns, in the order `mapTimelineRow` expects. */
|
|
3
|
+
const TIMELINE_COLUMNS = 'id, type, occurred_at, actor';
|
|
4
|
+
/** …plus what a history VIEW needs. See `historyEntry` for why two are nullable. */
|
|
5
|
+
const HISTORY_COLUMNS = `${TIMELINE_COLUMNS}, payload, authorization, impersonation, pii_class, subject_id`;
|
|
6
|
+
/**
|
|
7
|
+
* The one SELECT behind both reads, for the reason `entityVersionQuery` is one
|
|
8
|
+
* function: two surfaces answering the same question from one table must not
|
|
9
|
+
* drift on what the answer means.
|
|
10
|
+
*
|
|
11
|
+
* The cursor is EXCLUSIVE and compares against `id` — strictly after it walking
|
|
12
|
+
* `asc`, strictly before it walking `desc`. `desc` exists because a history strip
|
|
13
|
+
* is usually rendered newest-first; `asc` stays the default, which is the order
|
|
14
|
+
* all five demos already returned.
|
|
15
|
+
*/
|
|
16
|
+
function timelineQuery(columns, entity, page, limit) {
|
|
17
|
+
const desc = page?.order === 'desc';
|
|
18
|
+
const cursor = page?.cursor;
|
|
19
|
+
return {
|
|
20
|
+
sql: `SELECT ${columns} FROM _substrat_outbox WHERE entity_type = ? AND entity_id = ?` +
|
|
21
|
+
(cursor === undefined ? '' : desc ? ' AND id < ?' : ' AND id > ?') +
|
|
22
|
+
` ORDER BY id ${desc ? 'DESC' : 'ASC'} LIMIT ?`,
|
|
23
|
+
params: cursor === undefined
|
|
24
|
+
? [entity.entityType, entity.entityId, limit]
|
|
25
|
+
: [entity.entityType, entity.entityId, cursor, limit],
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Decode the stored actor.
|
|
30
|
+
*
|
|
31
|
+
* Both adapters write `JSON.stringify(actor)` over a union whose first member is
|
|
32
|
+
* a bare `PrincipalId` STRING, so a principal is stored as `"01J…"` — quotes
|
|
33
|
+
* included — while a system or connector actor is stored as an object. That is the trap this whole helper exists to close: the
|
|
34
|
+
* column reads as usable and is not, and a caller resolving a name against the
|
|
35
|
+
* raw text misses every time.
|
|
36
|
+
*
|
|
37
|
+
* Cast rather than re-parsed, the way `mapDenialRow` treats the same encoding:
|
|
38
|
+
* the kernel is the only writer of this column, so a Zod pass per row would buy
|
|
39
|
+
* nothing but cost the walk.
|
|
40
|
+
*/
|
|
41
|
+
function actorOf(stored) {
|
|
42
|
+
return JSON.parse(stored);
|
|
43
|
+
}
|
|
44
|
+
function mapTimelineRow(row) {
|
|
45
|
+
return {
|
|
46
|
+
id: row.id,
|
|
47
|
+
type: row.type,
|
|
48
|
+
occurredAt: row.occurred_at,
|
|
49
|
+
actor: actorOf(row.actor),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function mapHistoryRow(row) {
|
|
53
|
+
return {
|
|
54
|
+
...mapTimelineRow(row),
|
|
55
|
+
// Null is a FACT here, twice over, and the two are different facts: a null
|
|
56
|
+
// payload is an erasure (§5.3 kept the envelope and destroyed what was
|
|
57
|
+
// said), a null authorization is a row written before K-34 recorded it.
|
|
58
|
+
payload: row.payload === null ? null : JSON.parse(row.payload),
|
|
59
|
+
authorization: row.authorization === null ? null : JSON.parse(row.authorization),
|
|
60
|
+
// K-42, and its null is a THIRD kind of fact: nobody was impersonating. The
|
|
61
|
+
// ordinary case, not an absence of recording — the kernel stamps this on
|
|
62
|
+
// every event raised under a session and on no other.
|
|
63
|
+
impersonation: row.impersonation === null ? null : JSON.parse(row.impersonation),
|
|
64
|
+
piiClass: row.pii_class,
|
|
65
|
+
subjectId: row.subject_id,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* An entity's timeline — WHAT happened to it, WHEN, and BY WHOM.
|
|
70
|
+
*
|
|
71
|
+
* The envelope only: no payload, so there is no disclosure decision to make and
|
|
72
|
+
* nothing an erasure can leave behind. `readHistory` is the same walk with what a
|
|
73
|
+
* history VIEW needs.
|
|
74
|
+
*
|
|
75
|
+
* Paged like an HTTP list read rather than like a kernel read — an unset `limit`
|
|
76
|
+
* is `LIST_PAGE_DEFAULT`, not unbounded — because the caller is an app walking a
|
|
77
|
+
* screen, and an entity that has been touched ten thousand times must not answer
|
|
78
|
+
* with ten thousand rows because nobody said a number.
|
|
79
|
+
*/
|
|
80
|
+
export function readTimeline(ctx, entity, page) {
|
|
81
|
+
const limit = listLimitOf(page?.limit);
|
|
82
|
+
const { sql, params } = timelineQuery(TIMELINE_COLUMNS, entity, page, limit);
|
|
83
|
+
const rows = ctx.sql.query(sql, params);
|
|
84
|
+
return pageOf(rows.map(mapTimelineRow), limit, (entry) => entry.id);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* An entity's history — the timeline, plus what was said and under what
|
|
88
|
+
* authority.
|
|
89
|
+
*
|
|
90
|
+
* Three fields beyond the envelope, each answering something a history strip
|
|
91
|
+
* needs and a timeline cannot:
|
|
92
|
+
*
|
|
93
|
+
* - **`payload`** — the fat event, i.e. the NEW values. Field-level "X → Y" is
|
|
94
|
+
* reconstructed by diffing consecutive payloads; nothing stores a before-state.
|
|
95
|
+
* **Null after a shred** — a supported result, not an error (see `historyEntry`).
|
|
96
|
+
* - **`authorization`** (K-34) — the checks the emitting operation passed, and
|
|
97
|
+
* which grant allowed each. Not just who changed it but under what authority,
|
|
98
|
+
* which most systems cannot answer at all and this one gets for free.
|
|
99
|
+
* - **`piiClass` / `subjectId`** — so the caller can decide what is safe to
|
|
100
|
+
* render before it renders it.
|
|
101
|
+
*
|
|
102
|
+
* Same permission posture as `readTimeline`: the caller checks, this does not.
|
|
103
|
+
* The payload makes that more load-bearing here, not less — this is the read that
|
|
104
|
+
* can disclose what an event said.
|
|
105
|
+
*/
|
|
106
|
+
export function readHistory(ctx, entity, page) {
|
|
107
|
+
const limit = listLimitOf(page?.limit);
|
|
108
|
+
const { sql, params } = timelineQuery(HISTORY_COLUMNS, entity, page, limit);
|
|
109
|
+
const rows = ctx.sql.query(sql, params);
|
|
110
|
+
return pageOf(rows.map(mapHistoryRow), limit, (entry) => entry.id);
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=timeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeline.js","sourceRoot":"","sources":["../src/timeline.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@substrat-run/kernel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.90.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,7 +22,7 @@
|
|
|
22
22
|
"dist"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@substrat-run/contracts": "^0.
|
|
25
|
+
"@substrat-run/contracts": "^0.90.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^22.0.0",
|