@substrat-run/kernel 0.136.0 → 0.138.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 +2 -0
- package/dist/capability.d.ts.map +1 -1
- package/dist/capability.js +2 -0
- package/dist/capability.js.map +1 -1
- package/dist/delivery-refusal.d.ts +21 -0
- package/dist/delivery-refusal.d.ts.map +1 -0
- package/dist/delivery-refusal.js +21 -0
- package/dist/delivery-refusal.js.map +1 -0
- package/dist/index.d.ts +23 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -12
- package/dist/index.js.map +1 -1
- package/dist/invocation-log.d.ts +25 -1
- package/dist/invocation-log.d.ts.map +1 -1
- package/dist/invocation-log.js +45 -6
- package/dist/invocation-log.js.map +1 -1
- package/dist/job-run.d.ts +370 -47
- package/dist/job-run.d.ts.map +1 -1
- package/dist/job-run.js +472 -81
- package/dist/job-run.js.map +1 -1
- package/dist/lifecycle-flow.d.ts.map +1 -1
- package/dist/lifecycle-flow.js +2 -1
- package/dist/lifecycle-flow.js.map +1 -1
- package/dist/membership-executor.d.ts +97 -0
- package/dist/membership-executor.d.ts.map +1 -0
- package/dist/membership-executor.js +246 -0
- package/dist/membership-executor.js.map +1 -0
- package/dist/membership-fence.d.ts +57 -0
- package/dist/membership-fence.d.ts.map +1 -0
- package/dist/membership-fence.js +90 -0
- package/dist/membership-fence.js.map +1 -0
- package/dist/operation-series.d.ts +58 -0
- package/dist/operation-series.d.ts.map +1 -0
- package/dist/operation-series.js +63 -0
- package/dist/operation-series.js.map +1 -0
- package/dist/peer.d.ts +13 -8
- package/dist/peer.d.ts.map +1 -1
- package/dist/peer.js +13 -14
- package/dist/peer.js.map +1 -1
- package/dist/permission-eval.d.ts +48 -1
- package/dist/permission-eval.d.ts.map +1 -1
- package/dist/permission-eval.js +137 -18
- package/dist/permission-eval.js.map +1 -1
- package/dist/read-only-sql.d.ts +2 -26
- package/dist/read-only-sql.d.ts.map +1 -1
- package/dist/read-only-sql.js +13 -9
- package/dist/read-only-sql.js.map +1 -1
- package/dist/refusal-query.d.ts +4 -1
- package/dist/refusal-query.d.ts.map +1 -1
- package/dist/refusal-query.js +6 -4
- package/dist/refusal-query.js.map +1 -1
- package/dist/refusals.d.ts +80 -8
- package/dist/refusals.d.ts.map +1 -1
- package/dist/refusals.js +141 -22
- package/dist/refusals.js.map +1 -1
- package/dist/scope-copy.d.ts +18 -0
- package/dist/scope-copy.d.ts.map +1 -1
- package/dist/scope-copy.js +18 -0
- package/dist/scope-copy.js.map +1 -1
- package/dist/scope-host.d.ts +266 -15
- package/dist/scope-host.d.ts.map +1 -1
- package/dist/scope-host.js +41 -0
- package/dist/scope-host.js.map +1 -1
- package/dist/spine-restore.d.ts +7 -2
- package/dist/spine-restore.d.ts.map +1 -1
- package/dist/spine-restore.js +13 -5
- package/dist/spine-restore.js.map +1 -1
- package/dist/system-switch-record.d.ts +290 -74
- package/dist/system-switch-record.d.ts.map +1 -1
- package/dist/system-switch-record.js +353 -101
- package/dist/system-switch-record.js.map +1 -1
- package/dist/system-switch.d.ts +146 -20
- package/dist/system-switch.d.ts.map +1 -1
- package/dist/system-switch.js +135 -27
- package/dist/system-switch.js.map +1 -1
- package/dist/timeline.d.ts +23 -0
- package/dist/timeline.d.ts.map +1 -1
- package/dist/timeline.js +30 -0
- package/dist/timeline.js.map +1 -1
- package/dist/ulid.d.ts +5 -0
- package/dist/ulid.d.ts.map +1 -1
- package/dist/ulid.js +9 -0
- package/dist/ulid.js.map +1 -1
- package/dist/vertical-events.d.ts +7 -1
- package/dist/vertical-events.d.ts.map +1 -1
- package/dist/vertical-events.js +14 -0
- package/dist/vertical-events.js.map +1 -1
- package/package.json +4 -4
package/dist/refusals.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Refused transitions, recorded (#1745).
|
|
2
|
+
* Refused transitions and refusing guards, recorded (#1745).
|
|
3
3
|
*
|
|
4
4
|
* An illegal move is refused inside the operation by `assertTransition`, which throws a
|
|
5
|
-
* `conflict
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* `conflict`; a manifest-declared guard (K-38) refuses the operation it stands before the
|
|
6
|
+
* same way, before the handler runs. The operation's transaction rolls back with either, so
|
|
7
|
+
* nothing about the attempt survives — the denial log holds permission refusals only, and
|
|
8
|
+
* the outbox only what committed. That made "someone tried to reopen a closed conversation
|
|
9
|
+
* twelve times" a fact nobody could see: not on the process map, not in a finding.
|
|
9
10
|
*
|
|
10
11
|
* Recorded the way a denial is (K-35): on the failure path, AFTER the rollback, as a write
|
|
11
12
|
* of its own, so the attempt survives the transaction that refused it. Kernel-owned and
|
|
@@ -14,53 +15,171 @@
|
|
|
14
15
|
*
|
|
15
16
|
* Only a refusal that FAILED the operation is recorded. One a vertical caught inside
|
|
16
17
|
* `ctx.atomic` and recovered from is the vertical's business — its operation committed.
|
|
18
|
+
*
|
|
19
|
+
* **What a row holds, and what it never does.** Keys and vocabulary only: the record's type
|
|
20
|
+
* (held to the entity-type grammar, `refusalEntityType`) and id, state names, operation and
|
|
21
|
+
* predicate names, the problem code (held to the `problemReason` grammar), the actor's id
|
|
22
|
+
* and the call's. Never the error's message, the operation's input, or a guard's config —
|
|
23
|
+
* any of those can quote what a person typed. So a row has nothing for a subject erasure to rewrite
|
|
24
|
+
* (master-plan §5.3: pseudonymous keys and transaction facts remain), which is the denial
|
|
25
|
+
* log's position too, and it is kept the way the denial log is: `drained_at` marks a shipped
|
|
26
|
+
* row, and rows drain rather than expire.
|
|
17
27
|
*/
|
|
18
|
-
import { refusedTransitionOf } from '@substrat-run/contracts';
|
|
28
|
+
import { errorCodeOf, INVALID_TRANSITION, problemReason, UNRECOGNIZED_REFUSAL_REASON, refusalEntityType, refusedRecordOf, refusedTransitionOf, } from '@substrat-run/contracts';
|
|
19
29
|
import { ulid } from './ulid.js';
|
|
20
|
-
|
|
30
|
+
/** The table alone — what `REFUSALS_REBUILD` creates under its scratch name. */
|
|
31
|
+
export const REFUSALS_TABLE_DDL = `
|
|
21
32
|
CREATE TABLE IF NOT EXISTS _substrat_refusals (
|
|
22
33
|
id TEXT PRIMARY KEY,
|
|
23
|
-
-- 'transition'
|
|
34
|
+
-- 'transition' (assertTransition) or 'guard' (a manifest-declared guard, K-38).
|
|
24
35
|
kind TEXT NOT NULL,
|
|
25
36
|
tenant_id TEXT NOT NULL,
|
|
26
37
|
scope_id TEXT,
|
|
27
|
-
-- The record the
|
|
28
|
-
--
|
|
38
|
+
-- The record the refusal was about. NULL when the refusing code did not name it: the
|
|
39
|
+
-- attempt is still recorded, and cannot be counted against an entity.
|
|
29
40
|
entity_type TEXT,
|
|
30
41
|
entity_id TEXT,
|
|
31
|
-
|
|
42
|
+
-- The state the record was in. NULL on a guard row: a guard stands before an operation,
|
|
43
|
+
-- and the kernel that ran it cannot know the state of the record behind it.
|
|
44
|
+
from_state TEXT,
|
|
32
45
|
-- Where the operation leads where it IS legal; NULL when that is not one state.
|
|
33
46
|
attempted_state TEXT,
|
|
34
|
-
-- The lifecycle's operation (what the edge is keyed by)
|
|
35
|
-
--
|
|
47
|
+
-- The lifecycle's operation (what the edge is keyed by), or the one a guard stands
|
|
48
|
+
-- before, and the invoke() string the call ran as.
|
|
36
49
|
operation TEXT NOT NULL,
|
|
37
50
|
invoked_operation TEXT,
|
|
51
|
+
-- The guard's named predicate; NULL on a transition row.
|
|
52
|
+
guard TEXT,
|
|
53
|
+
-- The problem code the operation failed with (the 409's reason). NULL on a row written
|
|
54
|
+
-- before the column, where the kind implies it.
|
|
55
|
+
reason TEXT,
|
|
38
56
|
actor TEXT NOT NULL,
|
|
39
57
|
impersonation TEXT,
|
|
40
58
|
invocation_id TEXT,
|
|
41
59
|
at TEXT NOT NULL,
|
|
42
60
|
drained_at TEXT
|
|
43
61
|
);
|
|
44
|
-
|
|
62
|
+
`;
|
|
63
|
+
/** The process map's read: one entity type's refusals in a window. */
|
|
64
|
+
export const REFUSALS_INDEX = `
|
|
45
65
|
CREATE INDEX IF NOT EXISTS _substrat_refusals_entity_at ON _substrat_refusals (entity_type, at);
|
|
46
66
|
`;
|
|
67
|
+
/**
|
|
68
|
+
* The table and its index. The adapters interpolate the two literals above instead, which
|
|
69
|
+
* is what `lint:spine-ddl` can resolve; this is for a caller that wants the whole thing.
|
|
70
|
+
*/
|
|
71
|
+
export const REFUSALS_DDL = REFUSALS_TABLE_DDL + REFUSALS_INDEX;
|
|
72
|
+
/**
|
|
73
|
+
* `_substrat_refusals` rebuilt to the shape above on a store created before guard refusals:
|
|
74
|
+
* `from_state` loses its NOT NULL and `guard` / `reason` join. Create-copy-drop-rename,
|
|
75
|
+
* because SQLite cannot relax a constraint in place — `SCHEDULE_STATE_REBUILD`'s shape and
|
|
76
|
+
* reasons (#1288), detected the same way (`refusalsAdmitGuards`, off `sqlite_master.sql`,
|
|
77
|
+
* which DO SQLite serves and `PRAGMA` does not).
|
|
78
|
+
*
|
|
79
|
+
* The new table is `REFUSALS_TABLE_DDL` under a temporary name, so the rebuilt shape cannot drift
|
|
80
|
+
* from the created one, and every row is copied verbatim: the two new columns are NULL on a
|
|
81
|
+
* transition row written before them, which the reader takes as "implied by the kind". The
|
|
82
|
+
* index is dropped with the old table and created again on the renamed one.
|
|
83
|
+
*
|
|
84
|
+
* **Run inside the adapter's transaction API**, as both callers do: un-wrapped, a stop
|
|
85
|
+
* between the DROP and the RENAME leaves the next wake's `CREATE TABLE IF NOT EXISTS` an
|
|
86
|
+
* empty table of the new shape, detection reads it as migrated, and the copied rows are
|
|
87
|
+
* orphaned in the scratch table. The leading `DROP TABLE IF EXISTS` makes a re-run start
|
|
88
|
+
* clean. A restore never reaches this: it builds the table from the current DDL and loads a
|
|
89
|
+
* legacy dump's rows by column name.
|
|
90
|
+
*/
|
|
91
|
+
export const REFUSALS_REBUILD = `
|
|
92
|
+
DROP TABLE IF EXISTS _substrat_refusals_new;
|
|
93
|
+
${REFUSALS_TABLE_DDL.replace('CREATE TABLE IF NOT EXISTS _substrat_refusals (', 'CREATE TABLE _substrat_refusals_new (')}
|
|
94
|
+
INSERT INTO _substrat_refusals_new
|
|
95
|
+
(id, kind, tenant_id, scope_id, entity_type, entity_id, from_state, attempted_state,
|
|
96
|
+
operation, invoked_operation, actor, impersonation, invocation_id, at, drained_at)
|
|
97
|
+
SELECT id, kind, tenant_id, scope_id, entity_type, entity_id, from_state, attempted_state,
|
|
98
|
+
operation, invoked_operation, actor, impersonation, invocation_id, at, drained_at
|
|
99
|
+
FROM _substrat_refusals;
|
|
100
|
+
DROP TABLE _substrat_refusals;
|
|
101
|
+
ALTER TABLE _substrat_refusals_new RENAME TO _substrat_refusals;
|
|
102
|
+
${REFUSALS_INDEX}
|
|
103
|
+
`;
|
|
104
|
+
/**
|
|
105
|
+
* Whether a store's `_substrat_refusals` already admits a guard row, read off the `sql`
|
|
106
|
+
* column of `sqlite_master`. `false` means `REFUSALS_REBUILD` is due.
|
|
107
|
+
*/
|
|
108
|
+
export function refusalsAdmitGuards(tableSql) {
|
|
109
|
+
// Line-anchored: the stored DDL keeps its comments, and a comment may say "guard".
|
|
110
|
+
return /^\s*guard TEXT,?\s*$/m.test(tableSql);
|
|
111
|
+
}
|
|
112
|
+
const REFUSED_GUARD = Symbol.for('substrat.refused-guard');
|
|
113
|
+
/**
|
|
114
|
+
* Mark a guard predicate's throw as a refusal, when it is one — called by both adapters'
|
|
115
|
+
* `runGuards` around each predicate, so the two cannot disagree about what counts.
|
|
116
|
+
*
|
|
117
|
+
* A refusal is a `conflict`: what a predicate throws to say "not yet" (`protocol_required`).
|
|
118
|
+
* Anything else — a validation failure, a bug, a denied check (which the denial log has) —
|
|
119
|
+
* is not a guard refusing, and is left unmarked. So is a throw that already carries a
|
|
120
|
+
* refused transition: it is recorded once, as the transition it is.
|
|
121
|
+
*/
|
|
122
|
+
export function markGuardRefusal(err, predicate, operation) {
|
|
123
|
+
if (err === null || typeof err !== 'object' || refusedTransitionOf(err))
|
|
124
|
+
return;
|
|
125
|
+
if (errorCodeOf(err) !== 'conflict')
|
|
126
|
+
return;
|
|
127
|
+
const record = refusedRecordOf(err);
|
|
128
|
+
err[REFUSED_GUARD] = {
|
|
129
|
+
kind: 'guard',
|
|
130
|
+
predicate,
|
|
131
|
+
operation,
|
|
132
|
+
reason: keptReason(err.extensions?.reason),
|
|
133
|
+
entityType: record?.entityType ?? null,
|
|
134
|
+
entityId: record?.entityId ?? null,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* The reason a row keeps: the problem's code when it is one (`problemReason`), the fixed
|
|
139
|
+
* `UNRECOGNIZED_REFUSAL_REASON` when it is anything else, null when there was none. The
|
|
140
|
+
* wire accepts any non-empty string here, so a predicate could put request text in it.
|
|
141
|
+
*/
|
|
142
|
+
function keptReason(reason) {
|
|
143
|
+
if (reason === undefined || reason === null)
|
|
144
|
+
return null;
|
|
145
|
+
return problemReason.safeParse(reason).success ? reason : UNRECOGNIZED_REFUSAL_REASON;
|
|
146
|
+
}
|
|
147
|
+
/** The refusal an operation failed with — a transition, a guard, or null for anything else. */
|
|
148
|
+
export function refusalOf(err) {
|
|
149
|
+
const transition = refusedTransitionOf(err);
|
|
150
|
+
if (transition)
|
|
151
|
+
return transition;
|
|
152
|
+
if (err === null || typeof err !== 'object')
|
|
153
|
+
return null;
|
|
154
|
+
const g = err[REFUSED_GUARD];
|
|
155
|
+
return g !== null && typeof g === 'object' ? g : null;
|
|
156
|
+
}
|
|
47
157
|
/** The one INSERT both adapters run, so the rows they write cannot differ. */
|
|
48
158
|
export function refusalInsert(row) {
|
|
159
|
+
const r = row.refused;
|
|
160
|
+
const guard = 'kind' in r && r.kind === 'guard' ? r : null;
|
|
161
|
+
const transition = guard ? null : r;
|
|
49
162
|
return {
|
|
50
163
|
sql: `INSERT INTO _substrat_refusals
|
|
51
164
|
(id, kind, tenant_id, scope_id, entity_type, entity_id, from_state, attempted_state,
|
|
52
|
-
operation, invoked_operation, actor, impersonation, invocation_id, at)
|
|
53
|
-
VALUES (?,
|
|
165
|
+
operation, invoked_operation, guard, reason, actor, impersonation, invocation_id, at)
|
|
166
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
54
167
|
params: [
|
|
55
168
|
ulid(),
|
|
169
|
+
guard ? 'guard' : 'transition',
|
|
56
170
|
row.tenantId,
|
|
57
171
|
row.scopeId,
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
172
|
+
// The type reaches here from code that may be handed request data; kept only when it
|
|
173
|
+
// is spelled as one. The id stays: it is the record's key, the join every log shares.
|
|
174
|
+
refusalEntityType(r.entityType),
|
|
175
|
+
r.entityId,
|
|
176
|
+
transition?.from ?? null,
|
|
177
|
+
transition?.attempted ?? null,
|
|
178
|
+
r.operation,
|
|
63
179
|
row.invokedOperation,
|
|
180
|
+
guard?.predicate ?? null,
|
|
181
|
+
// Bounded here too, the one INSERT, so no caller of this function can keep raw text.
|
|
182
|
+
guard ? keptReason(guard.reason) : INVALID_TRANSITION,
|
|
64
183
|
row.actor,
|
|
65
184
|
row.impersonation,
|
|
66
185
|
row.invocationId,
|
|
@@ -68,6 +187,6 @@ export function refusalInsert(row) {
|
|
|
68
187
|
],
|
|
69
188
|
};
|
|
70
189
|
}
|
|
71
|
-
/** The refused transition an operation failed with, or null
|
|
190
|
+
/** The refused transition an operation failed with, or null. */
|
|
72
191
|
export { refusedTransitionOf };
|
|
73
192
|
//# sourceMappingURL=refusals.js.map
|
package/dist/refusals.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refusals.js","sourceRoot":"","sources":["../src/refusals.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"refusals.js","sourceRoot":"","sources":["../src/refusals.ts"],"names":[],"mappings":"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"}
|
package/dist/scope-copy.d.ts
CHANGED
|
@@ -13,6 +13,24 @@ import type { SwitchSql } from './system-switch.js';
|
|
|
13
13
|
* An unknown source (`sourceScopeId` or `destScopeId` absent) counts as a copy: a load that cannot
|
|
14
14
|
* say where the dump came from cannot show it is a return. Only a control plane that predates the
|
|
15
15
|
* field sends a restore with no source.
|
|
16
|
+
*
|
|
17
|
+
* Two kinds of state are decided here without a rule in the load, because the load never sees
|
|
18
|
+
* the part that holds the power (#2004):
|
|
19
|
+
*
|
|
20
|
+
* - **Staff impersonation sessions (K-42).** `_substrat_impersonations` is a DIRECTORY table on
|
|
21
|
+
* both adapters, never a scope table, so no dump carries a session and a copy holds none. The
|
|
22
|
+
* session's power is checked at the door, against the (tenant, scope) the session names
|
|
23
|
+
* (`assertSessionUsable`), so a live session opened on the source is refused at every copy of
|
|
24
|
+
* it and still honoured at the source after a return. What a copy does carry is the history:
|
|
25
|
+
* the impersonation stamps on the rows the session wrote, as the source recorded them.
|
|
26
|
+
* - **Cross-vertical import cursors (#1705).** `_substrat_import_cursors` and `_substrat_imports`
|
|
27
|
+
* are carried as they are, on a copy and on a return. A cursor is written in the same
|
|
28
|
+
* transaction as the import handlers' writes, so it describes the data it sits beside, and the
|
|
29
|
+
* journal is what dedupes a re-delivery. Reset either and the data would be handed events whose
|
|
30
|
+
* effects it already holds. The power to consume lives in the delivery, not the cursor: the
|
|
31
|
+
* sweep visits primary scopes only (`isPrimaryScope`), and `deliverToPeer` into a copy answers
|
|
32
|
+
* `paused` with nothing run and the watermark unmoved. The producer keeps no record of a
|
|
33
|
+
* consumer's position, so a copy's cursor acknowledges nothing at the source either.
|
|
16
34
|
*/
|
|
17
35
|
export declare const isCopyLoad: (destScopeId: string | undefined, sourceScopeId: string | undefined) => boolean;
|
|
18
36
|
/**
|
package/dist/scope-copy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope-copy.d.ts","sourceRoot":"","sources":["../src/scope-copy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD
|
|
1
|
+
{"version":3,"file":"scope-copy.d.ts","sourceRoot":"","sources":["../src/scope-copy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,UAAU,gBAAiB,MAAM,GAAG,SAAS,iBAAiB,MAAM,GAAG,SAAS,KAAG,OACpC,CAAC;AAK7D;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,SAAS,OAAO,EAAE,CAAA;CAAE,EACtF,MAAM,EAAE,CAAC,EAAE,EACX,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,aAAa,EAAE,MAAM,GAAG,SAAS,GAChC,CAAC,EAAE,CAGL;AAcD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,eAAe,8cAW3B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,WAAW,sBAAiB,MACqD,CAAC;AAE/F;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,GAAG,EAAE,MAAM,GACV,IAAI,CAiDN;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAInE;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,QAEa,CAAC;AAE/C;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAIpE;AAED;;;;;GAKG;AACH,eAAO,MAAM,WAAW,0FAA0F,CAAC"}
|
package/dist/scope-copy.js
CHANGED
|
@@ -13,6 +13,24 @@ import { CAPABILITY_TABLE_NAMES } from './capability.js';
|
|
|
13
13
|
* An unknown source (`sourceScopeId` or `destScopeId` absent) counts as a copy: a load that cannot
|
|
14
14
|
* say where the dump came from cannot show it is a return. Only a control plane that predates the
|
|
15
15
|
* field sends a restore with no source.
|
|
16
|
+
*
|
|
17
|
+
* Two kinds of state are decided here without a rule in the load, because the load never sees
|
|
18
|
+
* the part that holds the power (#2004):
|
|
19
|
+
*
|
|
20
|
+
* - **Staff impersonation sessions (K-42).** `_substrat_impersonations` is a DIRECTORY table on
|
|
21
|
+
* both adapters, never a scope table, so no dump carries a session and a copy holds none. The
|
|
22
|
+
* session's power is checked at the door, against the (tenant, scope) the session names
|
|
23
|
+
* (`assertSessionUsable`), so a live session opened on the source is refused at every copy of
|
|
24
|
+
* it and still honoured at the source after a return. What a copy does carry is the history:
|
|
25
|
+
* the impersonation stamps on the rows the session wrote, as the source recorded them.
|
|
26
|
+
* - **Cross-vertical import cursors (#1705).** `_substrat_import_cursors` and `_substrat_imports`
|
|
27
|
+
* are carried as they are, on a copy and on a return. A cursor is written in the same
|
|
28
|
+
* transaction as the import handlers' writes, so it describes the data it sits beside, and the
|
|
29
|
+
* journal is what dedupes a re-delivery. Reset either and the data would be handed events whose
|
|
30
|
+
* effects it already holds. The power to consume lives in the delivery, not the cursor: the
|
|
31
|
+
* sweep visits primary scopes only (`isPrimaryScope`), and `deliverToPeer` into a copy answers
|
|
32
|
+
* `paused` with nothing run and the watermark unmoved. The producer keeps no record of a
|
|
33
|
+
* consumer's position, so a copy's cursor acknowledges nothing at the source either.
|
|
16
34
|
*/
|
|
17
35
|
export const isCopyLoad = (destScopeId, sourceScopeId) => destScopeId === undefined || sourceScopeId !== destScopeId;
|
|
18
36
|
/** The capability tables, as `capabilitiesForLoad` matches a dump's (lowercased) names. */
|
package/dist/scope-copy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope-copy.js","sourceRoot":"","sources":["../src/scope-copy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAGzD
|
|
1
|
+
{"version":3,"file":"scope-copy.js","sourceRoot":"","sources":["../src/scope-copy.ts"],"names":[],"mappings":"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"}
|