@substrat-run/kernel 0.138.0 → 0.140.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/admin-log-ddl.d.ts +21 -0
- package/dist/admin-log-ddl.d.ts.map +1 -0
- package/dist/admin-log-ddl.js +32 -0
- package/dist/admin-log-ddl.js.map +1 -0
- package/dist/attachment-extractor.d.ts +21 -2
- package/dist/attachment-extractor.d.ts.map +1 -1
- package/dist/attachment-extractor.js +31 -6
- package/dist/attachment-extractor.js.map +1 -1
- package/dist/attachment-text.d.ts +64 -0
- package/dist/attachment-text.d.ts.map +1 -1
- package/dist/attachment-text.js +87 -16
- package/dist/attachment-text.js.map +1 -1
- package/dist/attribution.d.ts +36 -3
- package/dist/attribution.d.ts.map +1 -1
- package/dist/attribution.js +21 -8
- package/dist/attribution.js.map +1 -1
- package/dist/audit-outcome.d.ts +149 -0
- package/dist/audit-outcome.d.ts.map +1 -0
- package/dist/audit-outcome.js +233 -0
- package/dist/audit-outcome.js.map +1 -0
- package/dist/connect-links.d.ts +91 -0
- package/dist/connect-links.d.ts.map +1 -0
- package/dist/connect-links.js +189 -0
- package/dist/connect-links.js.map +1 -0
- package/dist/connect-state.d.ts +12 -3
- package/dist/connect-state.d.ts.map +1 -1
- package/dist/connect-state.js +8 -3
- package/dist/connect-state.js.map +1 -1
- package/dist/derived-object.d.ts +14 -0
- package/dist/derived-object.d.ts.map +1 -0
- package/dist/derived-object.js +2 -0
- package/dist/derived-object.js.map +1 -0
- package/dist/derived-objects.d.ts +108 -0
- package/dist/derived-objects.d.ts.map +1 -0
- package/dist/derived-objects.js +199 -0
- package/dist/derived-objects.js.map +1 -0
- package/dist/email-intent.d.ts +56 -0
- package/dist/email-intent.d.ts.map +1 -0
- package/dist/email-intent.js +71 -0
- package/dist/email-intent.js.map +1 -0
- package/dist/entity-edges.d.ts +6 -1
- package/dist/entity-edges.d.ts.map +1 -1
- package/dist/entity-edges.js +13 -0
- package/dist/entity-edges.js.map +1 -1
- package/dist/entity-grant-shape.d.ts +94 -0
- package/dist/entity-grant-shape.d.ts.map +1 -0
- package/dist/entity-grant-shape.js +329 -0
- package/dist/entity-grant-shape.js.map +1 -0
- package/dist/entity-grant.d.ts +45 -0
- package/dist/entity-grant.d.ts.map +1 -0
- package/dist/entity-grant.js +71 -0
- package/dist/entity-grant.js.map +1 -0
- package/dist/entity-state-reads.d.ts +40 -0
- package/dist/entity-state-reads.d.ts.map +1 -0
- package/dist/entity-state-reads.js +91 -0
- package/dist/entity-state-reads.js.map +1 -0
- package/dist/entity-state.d.ts +204 -0
- package/dist/entity-state.d.ts.map +1 -0
- package/dist/entity-state.js +356 -0
- package/dist/entity-state.js.map +1 -0
- package/dist/entity-trash.d.ts +245 -0
- package/dist/entity-trash.d.ts.map +1 -0
- package/dist/entity-trash.js +380 -0
- package/dist/entity-trash.js.map +1 -0
- package/dist/findings.d.ts +143 -0
- package/dist/findings.d.ts.map +1 -0
- package/dist/findings.js +463 -0
- package/dist/findings.js.map +1 -0
- package/dist/grant-scoped-read.d.ts +41 -0
- package/dist/grant-scoped-read.d.ts.map +1 -0
- package/dist/grant-scoped-read.js +100 -0
- package/dist/grant-scoped-read.js.map +1 -0
- package/dist/index.d.ts +40 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -6
- package/dist/index.js.map +1 -1
- package/dist/kernel-outbox.d.ts +14 -0
- package/dist/kernel-outbox.d.ts.map +1 -0
- package/dist/kernel-outbox.js +37 -0
- package/dist/kernel-outbox.js.map +1 -0
- package/dist/list-index.d.ts +34 -3
- package/dist/list-index.d.ts.map +1 -1
- package/dist/list-index.js +83 -31
- package/dist/list-index.js.map +1 -1
- package/dist/mail-sender.d.ts +78 -0
- package/dist/mail-sender.d.ts.map +1 -0
- package/dist/mail-sender.js +2 -0
- package/dist/mail-sender.js.map +1 -0
- package/dist/membership-executor.d.ts +7 -47
- package/dist/membership-executor.d.ts.map +1 -1
- package/dist/membership-executor.js +28 -53
- package/dist/membership-executor.js.map +1 -1
- package/dist/migration-digest.d.ts +161 -0
- package/dist/migration-digest.d.ts.map +1 -0
- package/dist/migration-digest.js +237 -0
- package/dist/migration-digest.js.map +1 -0
- package/dist/module-erasure.d.ts +156 -0
- package/dist/module-erasure.d.ts.map +1 -0
- package/dist/module-erasure.js +440 -0
- package/dist/module-erasure.js.map +1 -0
- package/dist/module-migrations.d.ts +6 -3
- package/dist/module-migrations.d.ts.map +1 -1
- package/dist/module-migrations.js +12 -5
- package/dist/module-migrations.js.map +1 -1
- package/dist/peer.d.ts +9 -1
- package/dist/peer.d.ts.map +1 -1
- package/dist/peer.js +29 -0
- package/dist/peer.js.map +1 -1
- package/dist/permission-checker.d.ts +6 -0
- package/dist/permission-checker.d.ts.map +1 -1
- package/dist/permission-checker.js.map +1 -1
- package/dist/permission-eval.d.ts +51 -1
- package/dist/permission-eval.d.ts.map +1 -1
- package/dist/permission-eval.js +104 -2
- package/dist/permission-eval.js.map +1 -1
- package/dist/platform-sweep.d.ts +8 -2
- package/dist/platform-sweep.d.ts.map +1 -1
- package/dist/platform-sweep.js +17 -0
- package/dist/platform-sweep.js.map +1 -1
- package/dist/scope-host.d.ts +479 -24
- package/dist/scope-host.d.ts.map +1 -1
- package/dist/scope-host.js +82 -7
- package/dist/scope-host.js.map +1 -1
- package/dist/scope-role-admin.d.ts +68 -0
- package/dist/scope-role-admin.d.ts.map +1 -0
- package/dist/scope-role-admin.js +80 -0
- package/dist/scope-role-admin.js.map +1 -0
- package/dist/search-index.d.ts +21 -1
- package/dist/search-index.d.ts.map +1 -1
- package/dist/search-index.js +60 -37
- package/dist/search-index.js.map +1 -1
- package/dist/spine-guard.d.ts +71 -2
- package/dist/spine-guard.d.ts.map +1 -1
- package/dist/spine-guard.js +393 -10
- package/dist/spine-guard.js.map +1 -1
- package/dist/spine-restore.d.ts.map +1 -1
- package/dist/spine-restore.js +5 -0
- package/dist/spine-restore.js.map +1 -1
- package/dist/sql-identifier.d.ts +12 -0
- package/dist/sql-identifier.d.ts.map +1 -0
- package/dist/sql-identifier.js +17 -0
- package/dist/sql-identifier.js.map +1 -0
- package/dist/sql-statements.d.ts +71 -0
- package/dist/sql-statements.d.ts.map +1 -0
- package/dist/sql-statements.js +191 -0
- package/dist/sql-statements.js.map +1 -0
- package/dist/subject-redaction.d.ts +9 -1
- package/dist/subject-redaction.d.ts.map +1 -1
- package/dist/subject-redaction.js.map +1 -1
- package/dist/system-switch-record.d.ts +3 -0
- package/dist/system-switch-record.d.ts.map +1 -1
- package/dist/system-switch-record.js +2 -0
- package/dist/system-switch-record.js.map +1 -1
- package/dist/table-ownership.d.ts +103 -0
- package/dist/table-ownership.d.ts.map +1 -0
- package/dist/table-ownership.js +285 -0
- package/dist/table-ownership.js.map +1 -0
- package/dist/timeline.d.ts +4 -4
- package/dist/timeline.js +4 -4
- package/dist/visible-continuation.d.ts +38 -0
- package/dist/visible-continuation.d.ts.map +1 -0
- package/dist/visible-continuation.js +162 -0
- package/dist/visible-continuation.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derived-objects.js","sourceRoot":"","sources":["../src/derived-objects.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type PlatformOutcomeEvent, type PlatformRequestFailure, type PlatformRequestId, type PlatformRequestStatus, type ScopeId, type SendEmailRequest, type TenantId } from '@substrat-run/contracts';
|
|
2
|
+
import type { OperationContext } from './scope-host.js';
|
|
3
|
+
import type { SwitchSql } from './system-switch.js';
|
|
4
|
+
/**
|
|
5
|
+
* Ask the platform to send one email, inside the operation (#2102).
|
|
6
|
+
*
|
|
7
|
+
* The send is a platform intent: a row written in this operation's transaction, so an
|
|
8
|
+
* operation that throws afterwards sends nothing, and one that commits is delivered by the
|
|
9
|
+
* platform's drain — retried while the provider defers it, and reported back as an
|
|
10
|
+
* `email.sent`, `email.refused` or `email.dead-lettered` event on `mail.about` (or on the
|
|
11
|
+
* intent, when the mail names no entity). The returned id is the `request` those events carry.
|
|
12
|
+
*
|
|
13
|
+
* Name the recipient's `subjectId` when they are a person in your data: the row holds their
|
|
14
|
+
* address and the message, and that id is how a subject erasure finds and cancels it.
|
|
15
|
+
*
|
|
16
|
+
* Parsed here rather than at drain time, so a malformed address fails the operation that wrote
|
|
17
|
+
* it, in front of the person who typed it, instead of a refusal event minutes later. Needs the
|
|
18
|
+
* vertical's `emailSender` grant, as the relay always has; without it the send is refused.
|
|
19
|
+
*/
|
|
20
|
+
export declare function requestEmail(ctx: Pick<OperationContext, 'requestPlatform'>, mail: Omit<SendEmailRequest, 'piiClass'>): PlatformRequestId;
|
|
21
|
+
/** What the scope stamps on an outcome event it writes: the drain names the rest. */
|
|
22
|
+
export interface OutcomeEventStamp {
|
|
23
|
+
tenantId: TenantId;
|
|
24
|
+
scopeId: ScopeId;
|
|
25
|
+
/** ISO 8601 — the settle's instant. */
|
|
26
|
+
now: string;
|
|
27
|
+
mintEventId(ms: number): string;
|
|
28
|
+
/** The deploy writing it, for the outbox's `version` column. */
|
|
29
|
+
version: string | null;
|
|
30
|
+
}
|
|
31
|
+
export interface PlatformRequestSettle {
|
|
32
|
+
status: PlatformRequestStatus;
|
|
33
|
+
result?: unknown;
|
|
34
|
+
lastError?: string | null;
|
|
35
|
+
failure?: PlatformRequestFailure | null;
|
|
36
|
+
/** #2102: the event this settle writes into the scope, when it moves the row out of `pending`. */
|
|
37
|
+
event?: PlatformOutcomeEvent | null;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Journal a platform-request outcome, and write its outcome event (#2102) — one step, so both
|
|
41
|
+
* adapters say the same thing and the event commits with the settle or not at all. Run it in a
|
|
42
|
+
* transaction.
|
|
43
|
+
*
|
|
44
|
+
* **Compare-and-set on `pending` (#1600 review).** The drain reads pending rows, runs a handler,
|
|
45
|
+
* then settles — and between the read and the settle a subject erasure can redact the row.
|
|
46
|
+
* Settling by `id` alone let that stale pass overwrite the redaction and write a provider's
|
|
47
|
+
* reply, which can quote the person, back into `last_error`. A settle that finds the row
|
|
48
|
+
* already terminal does nothing, deliberately silently — throwing would make the drain's
|
|
49
|
+
* blanket catch retry a row that is correctly over. The event follows the same rule: written
|
|
50
|
+
* only by the settle that actually moved the row, so a repeated settle never writes it twice.
|
|
51
|
+
*
|
|
52
|
+
* The event is refused (before anything is written) on a `pending` settle — an outcome event
|
|
53
|
+
* says the request is over — and when its `request` is not the row being settled.
|
|
54
|
+
*/
|
|
55
|
+
export declare function settlePlatformRequestIn(db: SwitchSql, id: PlatformRequestId, outcome: PlatformRequestSettle, stamp: OutcomeEventStamp): void;
|
|
56
|
+
//# sourceMappingURL=email-intent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-intent.d.ts","sourceRoot":"","sources":["../src/email-intent.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,OAAO,EACZ,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EACd,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,IAAI,CAAC,gBAAgB,EAAE,iBAAiB,CAAC,EAC9C,IAAI,EAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,GACvC,iBAAiB,CAKnB;AAED,qFAAqF;AACrF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,uCAAuC;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,gEAAgE;IAChE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,qBAAqB,CAAC;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;IACxC,kGAAkG;IAClG,KAAK,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;CACrC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,uBAAuB,CACrC,EAAE,EAAE,SAAS,EACb,EAAE,EAAE,iBAAiB,EACrB,OAAO,EAAE,qBAAqB,EAC9B,KAAK,EAAE,iBAAiB,GACvB,IAAI,CAsCN"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { SEND_EMAIL_KIND, domainEvent, eventId, platformOutcomeEvent, sendEmailRequest, } from '@substrat-run/contracts';
|
|
2
|
+
import { KERNEL_ACTOR, kernelOutboxInsertSql } from './kernel-outbox.js';
|
|
3
|
+
/**
|
|
4
|
+
* Ask the platform to send one email, inside the operation (#2102).
|
|
5
|
+
*
|
|
6
|
+
* The send is a platform intent: a row written in this operation's transaction, so an
|
|
7
|
+
* operation that throws afterwards sends nothing, and one that commits is delivered by the
|
|
8
|
+
* platform's drain — retried while the provider defers it, and reported back as an
|
|
9
|
+
* `email.sent`, `email.refused` or `email.dead-lettered` event on `mail.about` (or on the
|
|
10
|
+
* intent, when the mail names no entity). The returned id is the `request` those events carry.
|
|
11
|
+
*
|
|
12
|
+
* Name the recipient's `subjectId` when they are a person in your data: the row holds their
|
|
13
|
+
* address and the message, and that id is how a subject erasure finds and cancels it.
|
|
14
|
+
*
|
|
15
|
+
* Parsed here rather than at drain time, so a malformed address fails the operation that wrote
|
|
16
|
+
* it, in front of the person who typed it, instead of a refusal event minutes later. Needs the
|
|
17
|
+
* vertical's `emailSender` grant, as the relay always has; without it the send is refused.
|
|
18
|
+
*/
|
|
19
|
+
export function requestEmail(ctx, mail) {
|
|
20
|
+
const parsed = sendEmailRequest.parse(mail);
|
|
21
|
+
// Classified like an event naming the same person, so a subject erasure reaches the row.
|
|
22
|
+
const payload = parsed.subjectId ? { ...parsed, piiClass: 'direct' } : parsed;
|
|
23
|
+
return ctx.requestPlatform({ kind: SEND_EMAIL_KIND, payload });
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Journal a platform-request outcome, and write its outcome event (#2102) — one step, so both
|
|
27
|
+
* adapters say the same thing and the event commits with the settle or not at all. Run it in a
|
|
28
|
+
* transaction.
|
|
29
|
+
*
|
|
30
|
+
* **Compare-and-set on `pending` (#1600 review).** The drain reads pending rows, runs a handler,
|
|
31
|
+
* then settles — and between the read and the settle a subject erasure can redact the row.
|
|
32
|
+
* Settling by `id` alone let that stale pass overwrite the redaction and write a provider's
|
|
33
|
+
* reply, which can quote the person, back into `last_error`. A settle that finds the row
|
|
34
|
+
* already terminal does nothing, deliberately silently — throwing would make the drain's
|
|
35
|
+
* blanket catch retry a row that is correctly over. The event follows the same rule: written
|
|
36
|
+
* only by the settle that actually moved the row, so a repeated settle never writes it twice.
|
|
37
|
+
*
|
|
38
|
+
* The event is refused (before anything is written) on a `pending` settle — an outcome event
|
|
39
|
+
* says the request is over — and when its `request` is not the row being settled.
|
|
40
|
+
*/
|
|
41
|
+
export function settlePlatformRequestIn(db, id, outcome, stamp) {
|
|
42
|
+
const event = outcome.event == null ? null : platformOutcomeEvent.parse(outcome.event);
|
|
43
|
+
if (event && outcome.status === 'pending') {
|
|
44
|
+
throw new Error(`settle of platform request ${id}: an outcome event needs a terminal status, not 'pending'`);
|
|
45
|
+
}
|
|
46
|
+
if (event && event.payload.request !== id) {
|
|
47
|
+
throw new Error(`settle of platform request ${id}: the outcome event names request ${event.payload.request}`);
|
|
48
|
+
}
|
|
49
|
+
const was = db.all('SELECT status FROM _substrat_platform_requests WHERE id = ?', id)[0]?.status;
|
|
50
|
+
db.run(`UPDATE _substrat_platform_requests
|
|
51
|
+
SET status = ?, result = COALESCE(?, result), last_error = ?, last_failure = ?,
|
|
52
|
+
attempts = attempts + 1, settled_at = ?
|
|
53
|
+
WHERE id = ? AND status = 'pending'`, outcome.status, outcome.result === undefined ? null : JSON.stringify(outcome.result), outcome.lastError ?? null, outcome.failure == null ? null : JSON.stringify(outcome.failure), outcome.status === 'pending' ? null : stamp.now, id);
|
|
54
|
+
if (!event || was !== 'pending')
|
|
55
|
+
return;
|
|
56
|
+
const full = domainEvent.parse({
|
|
57
|
+
id: eventId.parse(stamp.mintEventId(Date.parse(stamp.now))),
|
|
58
|
+
type: event.type,
|
|
59
|
+
schemaVersion: 1,
|
|
60
|
+
occurredAt: stamp.now,
|
|
61
|
+
tenantId: stamp.tenantId,
|
|
62
|
+
scopeId: stamp.scopeId,
|
|
63
|
+
actor: KERNEL_ACTOR,
|
|
64
|
+
entity: event.entity,
|
|
65
|
+
piiClass: 'none',
|
|
66
|
+
payload: event.payload,
|
|
67
|
+
});
|
|
68
|
+
const st = kernelOutboxInsertSql(full, stamp.version);
|
|
69
|
+
db.run(st.sql, ...st.params);
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=email-intent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-intent.js","sourceRoot":"","sources":["../src/email-intent.ts"],"names":[],"mappings":"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"}
|
package/dist/entity-edges.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type DomainEventInput, type Instant } from '@substrat-run/contracts';
|
|
1
|
+
import { type DomainEventInput, type EntityRef, type Instant } from '@substrat-run/contracts';
|
|
2
2
|
import type { OperationContext, ScopedSql } from './scope-host.js';
|
|
3
3
|
/**
|
|
4
4
|
* `ctx.link` and `ctx.relink` (K-16, #1864), written once — both adapters hand the same
|
|
@@ -29,6 +29,11 @@ export interface EntityEdgeDeps {
|
|
|
29
29
|
emit: (event: DomainEventInput) => void;
|
|
30
30
|
/** K-42's read-only refusal, for the effecting verbs. */
|
|
31
31
|
assertWrites: (verb: string) => void;
|
|
32
|
+
/**
|
|
33
|
+
* Is this entity out of reach as a parent (#119) — its type declares trash, and it is binned or
|
|
34
|
+
* missing (`isUnreachableParent`)? Refused by `link` and as `relink`'s `to`, one answer for both.
|
|
35
|
+
*/
|
|
36
|
+
isUnreachableParent: (entity: EntityRef) => boolean;
|
|
32
37
|
}
|
|
33
38
|
export type EntityEdgeVerbs = Pick<OperationContext, 'link' | 'relink'>;
|
|
34
39
|
export declare function createEntityEdgeVerbs(deps: EntityEdgeDeps): EntityEdgeVerbs;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity-edges.d.ts","sourceRoot":"","sources":["../src/entity-edges.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,gBAAgB,
|
|
1
|
+
{"version":3,"file":"entity-edges.d.ts","sourceRoot":"","sources":["../src/entity-edges.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,OAAO,EACb,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEnE;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,cAAc;IAC7B,2FAA2F;IAC3F,GAAG,EAAE,SAAS,CAAC;IACf,mFAAmF;IACnF,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IACpD,kEAAkE;IAClE,GAAG,EAAE,OAAO,CAAC;IACb,2EAA2E;IAC3E,IAAI,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACxC,yDAAyD;IACzD,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC;;;OAGG;IACH,mBAAmB,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC;CACrD;AAED,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC;AAExE,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,cAAc,GAAG,eAAe,CA4J3E"}
|
package/dist/entity-edges.js
CHANGED
|
@@ -7,6 +7,17 @@ export function createEntityEdgeVerbs(deps) {
|
|
|
7
7
|
`(declare it in a module manifest's entityRelations)`);
|
|
8
8
|
}
|
|
9
9
|
};
|
|
10
|
+
/**
|
|
11
|
+
* A binned entity is gone from everyone's view until it is restored (#119), so nothing new
|
|
12
|
+
* hangs off it. The refusal is the one a MISSING parent of the same type gets, word for word:
|
|
13
|
+
* `link` checks no permission, so a refusal that named the trash would tell a caller who may not
|
|
14
|
+
* see the parent that it exists. An ARCHIVED parent passes: archived is filed away and readable.
|
|
15
|
+
*/
|
|
16
|
+
const assertParentReachable = (verb, parent) => {
|
|
17
|
+
if (deps.isUnreachableParent(parent)) {
|
|
18
|
+
throw substratError('not_found', `${verb}: ${parent.entityType}:${parent.entityId} not found`);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
10
21
|
/**
|
|
11
22
|
* Refuse when `ancestorCandidate` is `child` itself, or already lies beneath `child` in the
|
|
12
23
|
* live parent graph — shared by `link` (candidate = the new `parent`) and `relink` (candidate
|
|
@@ -54,6 +65,7 @@ export function createEntityEdgeVerbs(deps) {
|
|
|
54
65
|
const c = entityObjectRef(child, 'ctx.link'); // #1856: an edge the walk can read back
|
|
55
66
|
const p = entityObjectRef(parent, 'ctx.link');
|
|
56
67
|
assertDeclared('ctx.link', child, parent);
|
|
68
|
+
assertParentReachable('ctx.link', parent);
|
|
57
69
|
// Refuse a parent that is the child itself or already beneath it (#1875) — same question
|
|
58
70
|
// `relink` asks of `to`, same walk.
|
|
59
71
|
assertNoCycle('ctx.link', 'link', c, p);
|
|
@@ -80,6 +92,7 @@ export function createEntityEdgeVerbs(deps) {
|
|
|
80
92
|
// whether or not its relation is still declared, so an edge that grants must stay
|
|
81
93
|
// movable. What `from` must be is an edge that exists.
|
|
82
94
|
assertDeclared('ctx.relink', child, to);
|
|
95
|
+
assertParentReachable('ctx.relink', to);
|
|
83
96
|
// The walk's own `live` predicate, so "is a parent" means what a check means by it.
|
|
84
97
|
const live = deps.sql.query(`SELECT 1 AS live FROM _substrat_tuples
|
|
85
98
|
WHERE subject = ? AND relation = 'parent' AND object = ? AND ${liveTupleSql()}`, [c, f, deps.now]);
|
package/dist/entity-edges.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity-edges.js","sourceRoot":"","sources":["../src/entity-edges.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,qBAAqB,EACrB,aAAa,GAId,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"entity-edges.js","sourceRoot":"","sources":["../src/entity-edges.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { type EntityGrantShape, type EntityRef, type PrincipalId } from '@substrat-run/contracts';
|
|
2
|
+
import type { SwitchSql } from './system-switch.js';
|
|
3
|
+
/**
|
|
4
|
+
* A declared entity-grant SHAPE, reconciled (#2071).
|
|
5
|
+
*
|
|
6
|
+
* A vertical declares the keys a person is given on their own record (`ENTITY_GRANTS`:
|
|
7
|
+
* meridian's `EMPLOYEE_SELF` on `employee`, todo's owner grant on `owner`). They used to be
|
|
8
|
+
* minted key by key, once, when the person arrived, so a key added to the shape by a later
|
|
9
|
+
* release reached only the people who arrived after it, while `PERMISSIONS.md` said everyone
|
|
10
|
+
* held it.
|
|
11
|
+
*
|
|
12
|
+
* Three pieces, each one statement shared by both adapters:
|
|
13
|
+
*
|
|
14
|
+
* - {@link grantEntityShapeIn}: the grant. The shape's keys plus a MARKER tuple
|
|
15
|
+
* (`ENTITY_SHAPE_MARKER_RELATION`) on the same entity. The marker is what makes a person a
|
|
16
|
+
* holder of the shape, which no set of keys can: someone `ctx.grant`ed one of those keys
|
|
17
|
+
* holds part of the shape and must never be topped up to all of it.
|
|
18
|
+
* - {@link topUpEntityGrantShapes}: one bounded pass of the reconcile, writing each top-up's
|
|
19
|
+
* `entity.grants-topped-up` event beside it. Each live marker whose
|
|
20
|
+
* entity lacks a key of the CURRENT shape gets that key. A key with any row at all is
|
|
21
|
+
* skipped, and that includes a tombstone (K-21): a key someone took back from that person
|
|
22
|
+
* stays taken back. A key merely dropped from the shape is left where it is, because silently
|
|
23
|
+
* revoking authority on a deploy is the riskier mistake.
|
|
24
|
+
* - The retirement (#2082), in the same pass and budget, between the backfill and the top-up: a
|
|
25
|
+
* key the shape declares `retired` is tombstoned for every live marker that still holds it
|
|
26
|
+
* live, with one `entity.grants-retired` event per (person, entity). The tombstones are the
|
|
27
|
+
* progress; a record tuple (`shape:<type>`, `shape-retired:<key>`, `scope:<id>`) ends it once
|
|
28
|
+
* a batch comes back short, so a key granted to a holder again afterwards is left alone. A key
|
|
29
|
+
* back in the shape's `permissions` tombstones that record, so a later release may retire it
|
|
30
|
+
* again. One tuple is one authority: a direct grant of the key on the same entity to the same
|
|
31
|
+
* person is that row, and goes with it.
|
|
32
|
+
* - The backfill, inside the same budget, until it is done once per (scope, entity type): how
|
|
33
|
+
* people granted before markers existed become holders. For own-record holders it reads
|
|
34
|
+
* provenance, never key sets alone.
|
|
35
|
+
* The shape's declared `holder` says whose record each entity is (`'self'`: the entity id is
|
|
36
|
+
* the principal; a table column naming the principal), and a person is marked only on their
|
|
37
|
+
* own record, and only when they hold a row there (live or tombstoned) for some key of the
|
|
38
|
+
* shape — evidence they were given it. Someone `ctx.grant`ed even the whole shape on another
|
|
39
|
+
* person's record is never marked. A shape with no `holder` gets no backfill. Each batch marks
|
|
40
|
+
* at most what the pass's budget allows; the markers are the progress, since a marked pair is
|
|
41
|
+
* no longer a candidate, and a record tuple (`shape:<type>`, `shape-backfilled`, `scope:<id>`)
|
|
42
|
+
* ends it once a batch comes back short.
|
|
43
|
+
* - `holder: 'grantee'` (#2083), for a record that names no principal (a portal customer, a
|
|
44
|
+
* contact): whoever holds a live current or retired key of the shape on such an entity was given it.
|
|
45
|
+
* Each pass records current and retired keys (`shape-grantee-key`), and the explicit tuple
|
|
46
|
+
* writer makes non-shape grants refuse them on that entity type. A tuple from before the
|
|
47
|
+
* first such pass cannot be told apart. A marker already written by a shape grant persists
|
|
48
|
+
* through retirement, so its holder receives the new keys even if their old key was K alone.
|
|
49
|
+
*
|
|
50
|
+
* Only a shape declared `bootstrap: true` is reconciled: one a person is GIVEN on their own
|
|
51
|
+
* record. A sharing shape, which people reach through `ctx.grant` (todo's `list`), is skipped
|
|
52
|
+
* whole, backfill included, so a sharee is never marked a holder.
|
|
53
|
+
*/
|
|
54
|
+
/** Holders topped up per pass — one transaction each, so a large scope never holds one long. */
|
|
55
|
+
export declare const SHAPE_TOP_UP_BATCH = 500;
|
|
56
|
+
/** The largest batch a caller may ask for: past this a pass is the long transaction it exists to avoid. */
|
|
57
|
+
export declare const SHAPE_TOP_UP_BATCH_MAX = 5000;
|
|
58
|
+
/** `batch`, or `validation_failed`: a pass size is a positive integer no larger than the max. */
|
|
59
|
+
export declare function shapeTopUpBatch(batch?: number): number;
|
|
60
|
+
/**
|
|
61
|
+
* The shape's grant to one person on one entity: the marker and every key, each an explicit
|
|
62
|
+
* write, so a re-grant brings back what a revoke tombstoned — as `ctx.grant` does.
|
|
63
|
+
* `entityObjectRef` refuses a ref the walk could not read back (#1856). Run it in ONE
|
|
64
|
+
* transaction, so the marker and its keys land together or not at all.
|
|
65
|
+
*/
|
|
66
|
+
export declare function grantEntityShapeIn(db: SwitchSql, principal: PrincipalId, entity: EntityRef, permissions: readonly string[]): void;
|
|
67
|
+
/** Where a pass runs and how its events are stamped — the facts only the adapter holds. */
|
|
68
|
+
export interface ShapePass {
|
|
69
|
+
tenantId: string;
|
|
70
|
+
scopeId: string;
|
|
71
|
+
shapes: readonly EntityGrantShape[];
|
|
72
|
+
/** The pass's one instant: marker liveness and every event's `occurredAt`. */
|
|
73
|
+
now: string;
|
|
74
|
+
/** Rows of work at most: a backfill mark or a holder topped up each count one. */
|
|
75
|
+
limit: number;
|
|
76
|
+
/** The adapter's monotonic event-id mint, given the instant in ms. */
|
|
77
|
+
mintEventId: (ms: number) => string;
|
|
78
|
+
/** The deploy writing the events, for the outbox `version` column. */
|
|
79
|
+
version: string | null;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* One pass of the reconcile over one scope, at most `limit` rows of work: backfill marks for any
|
|
83
|
+
* shape whose backfill is not done here, then holders whose retired keys are taken back, each
|
|
84
|
+
* with its `entity.grants-retired` event, then holders topped up, each with its
|
|
85
|
+
* `entity.grants-topped-up` event. `done` is false when the budget ran out, and the caller runs
|
|
86
|
+
* another pass. Run it inside ONE transaction, so the keys and their events commit together.
|
|
87
|
+
* Re-running a finished scope writes nothing.
|
|
88
|
+
*/
|
|
89
|
+
export declare function topUpEntityGrantShapes(db: SwitchSql, pass: ShapePass): {
|
|
90
|
+
toppedUp: number;
|
|
91
|
+
retired: number;
|
|
92
|
+
done: boolean;
|
|
93
|
+
};
|
|
94
|
+
//# sourceMappingURL=entity-grant-shape.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-grant-shape.d.ts","sourceRoot":"","sources":["../src/entity-grant-shape.ts"],"names":[],"mappings":"AAAA,OAAO,EAUL,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,WAAW,EACjB,MAAM,yBAAyB,CAAC;AAMjC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAEH,gGAAgG;AAChG,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,2GAA2G;AAC3G,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAE3C,iGAAiG;AACjG,wBAAgB,eAAe,CAAC,KAAK,GAAE,MAA2B,GAAG,MAAM,CAS1E;AAiBD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CASjI;AAED,2FAA2F;AAC3F,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACpC,8EAA8E;IAC9E,GAAG,EAAE,MAAM,CAAC;IACZ,kFAAkF;IAClF,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,sEAAsE;IACtE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,SAAS,EACb,IAAI,EAAE,SAAS,GACd;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CA+EtD"}
|