@substrat-run/kernel 0.9.0 → 0.11.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/index.d.ts CHANGED
@@ -1,10 +1,16 @@
1
- export type { AccessLogFilter, AuditLogFilter, ConsumerHandler, ExecutorHandler, GuardPredicate, HostAdmin, ModuleRegistration, OperationContext, OperationHandler, ProvisionScopeInput, RoleFilter, ScopedSql, ScopeFilter, ScopeHost, ScopeStub, SqlMigration, SqlValue, } from './scope-host.js';
1
+ export type { AccessLogFilter, AuditLogFilter, ConsumerHandler, ExecutorDeadLetter, ExecutorDrainReport, ExecutorHandler, ExecutorRetryPolicy, ConnectorConnection, ConnectorContext, ConnectorHandler, ConnectorOptions, ConnectorRequestInit, ConnectorResponse, FetchLike, GuardPredicate, HostAdmin, ModuleRegistration, OperationContext, OperationHandler, ProvisionScopeInput, RoleFilter, ScopedSql, ScopeFilter, ScopeHost, ScopeStub, SqlMigration, SqlValue, } from './scope-host.js';
2
+ export { backoffAt, resolveRetryPolicy } from './scope-host.js';
3
+ export { unconfiguredSecretBox, webCryptoSecretBox } from './secret-box.js';
4
+ export type { SealedSecret, SecretBox } from './secret-box.js';
2
5
  export { resolveScopeRecord } from './scope-record.js';
3
6
  export type { ResolvedScopeRecord } from './scope-record.js';
4
7
  export { assertAllowed, denyAllChecker, PermissionDenied, UNSAFE_allowAllChecker, } from './permission-checker.js';
8
+ export { asPrincipal } from './permission-checker.js';
5
9
  export type { PermissionChecker } from './permission-checker.js';
6
10
  export { ulid } from './ulid.js';
7
11
  export { readRoutedNode, RouterAssertionError } from './routed-node.js';
8
12
  export type { RoutedNode, HeaderReader } from './routed-node.js';
9
13
  export { assertPlatformCall, PlatformCallError, PLATFORM_SECRET_HEADER, } from './platform-call.js';
14
+ export { runPlatformSweep, startPlatformSweeper } from './platform-sweep.js';
15
+ export type { ConnectorSweeper, PlatformSweepOptions, PlatformSweepReport, PlatformSweeperHandle, StartPlatformSweeperOptions, } from './platform-sweep.js';
10
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,eAAe,EACf,cAAc,EACd,eAAe,EACf,eAAe,EACf,cAAc,EACd,SAAS,EACT,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,UAAU,EACV,SAAS,EACT,WAAW,EACX,SAAS,EACT,SAAS,EACT,YAAY,EACZ,QAAQ,GACT,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EACL,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,eAAe,EACf,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,SAAS,EACT,cAAc,EACd,SAAS,EACT,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,UAAU,EACV,SAAS,EACT,WAAW,EACX,SAAS,EACT,SAAS,EACT,YAAY,EACZ,QAAQ,GACT,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC5E,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EACL,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,YAAY,EACV,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,2BAA2B,GAC5B,MAAM,qBAAqB,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,10 @@
1
+ export { backoffAt, resolveRetryPolicy } from './scope-host.js';
2
+ export { unconfiguredSecretBox, webCryptoSecretBox } from './secret-box.js';
1
3
  export { resolveScopeRecord } from './scope-record.js';
2
4
  export { assertAllowed, denyAllChecker, PermissionDenied, UNSAFE_allowAllChecker, } from './permission-checker.js';
5
+ export { asPrincipal } from './permission-checker.js';
3
6
  export { ulid } from './ulid.js';
4
7
  export { readRoutedNode, RouterAssertionError } from './routed-node.js';
5
8
  export { assertPlatformCall, PlatformCallError, PLATFORM_SECRET_HEADER, } from './platform-call.js';
9
+ export { runPlatformSweep, startPlatformSweeper } from './platform-sweep.js';
6
10
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EACL,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExE,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA6BA,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EACL,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExE,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -1,4 +1,4 @@
1
- import { type Decision, type EntityRef, type Node, type PermissionKey, type PrincipalId } from '@substrat-run/contracts';
1
+ import { type Decision, type EntityRef, type Node, type PermissionKey, type CheckSubject, type PrincipalId } from '@substrat-run/contracts';
2
2
  /**
3
3
  * The evaluation seam (D-16): the MODEL is kernel-owned, the evaluation engine
4
4
  * is an adapter — the built-in default is a constrained relationship-tuple
@@ -10,8 +10,15 @@ import { type Decision, type EntityRef, type Node, type PermissionKey, type Prin
10
10
  * against entity-narrowed grants (§4.2 rule 3).
11
11
  */
12
12
  export interface PermissionChecker {
13
- check(principal: PrincipalId, permission: PermissionKey, node: Node, entity?: EntityRef): Promise<Decision>;
13
+ /**
14
+ * `subject` rather than `principal` since #97: a connection can hold a grant,
15
+ * and must not be laundered through a principal to do it. Every existing
16
+ * caller passes `{ kind: 'principal', id }` and behaves exactly as before.
17
+ */
18
+ check(subject: CheckSubject, permission: PermissionKey, node: Node, entity?: EntityRef): Promise<Decision>;
14
19
  }
20
+ /** Convenience for the overwhelmingly common case. */
21
+ export declare const asPrincipal: (id: PrincipalId) => CheckSubject;
15
22
  export declare class PermissionDenied extends Error {
16
23
  constructor(message: string);
17
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"permission-checker.d.ts","sourceRoot":"","sources":["../src/permission-checker.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,IAAI,EACT,KAAK,aAAa,EAClB,KAAK,WAAW,EACjB,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,CACH,SAAS,EAAE,WAAW,EACtB,UAAU,EAAE,aAAa,EACzB,IAAI,EAAE,IAAI,EACV,MAAM,CAAC,EAAE,SAAS,GACjB,OAAO,CAAC,QAAQ,CAAC,CAAC;CACtB;AAED,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAED,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAC5E,QAAQ,EACR;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,CAClB,CAIA;AAED,4FAA4F;AAC5F,eAAO,MAAM,cAAc,EAAE,iBAM5B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,iBAapC,CAAC"}
1
+ {"version":3,"file":"permission-checker.d.ts","sourceRoot":"","sources":["../src/permission-checker.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,IAAI,EACT,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,WAAW,EACjB,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,KAAK,CACH,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,aAAa,EACzB,IAAI,EAAE,IAAI,EACV,MAAM,CAAC,EAAE,SAAS,GACjB,OAAO,CAAC,QAAQ,CAAC,CAAC;CACtB;AAED,sDAAsD;AACtD,eAAO,MAAM,WAAW,GAAI,IAAI,WAAW,KAAG,YAA2C,CAAC;AAE1F,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAED,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAC5E,QAAQ,EACR;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,CAClB,CAIA;AAED,4FAA4F;AAC5F,eAAO,MAAM,cAAc,EAAE,iBAM5B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,iBAapC,CAAC"}
@@ -1,4 +1,6 @@
1
1
  import { objectRef, } from '@substrat-run/contracts';
2
+ /** Convenience for the overwhelmingly common case. */
3
+ export const asPrincipal = (id) => ({ kind: 'principal', id });
2
4
  export class PermissionDenied extends Error {
3
5
  constructor(message) {
4
6
  super(message);
@@ -1 +1 @@
1
- {"version":3,"file":"permission-checker.js","sourceRoot":"","sources":["../src/permission-checker.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,GAMV,MAAM,yBAAyB,CAAC;AAqBjC,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAED,sFAAsF;AACtF,MAAM,UAAU,aAAa,CAAC,QAAkB;IAI9C,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACtB,MAAM,IAAI,gBAAgB,CAAC,sBAAsB,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACvE,CAAC;AACH,CAAC;AAED,4FAA4F;AAC5F,MAAM,CAAC,MAAM,cAAc,GAAsB;IAC/C,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;QAC9C,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,UAAU;QACnB,IAAI;KACL,CAAC;CACH,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAsB;IACvD,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;QAC7C,OAAO,EAAE,IAAI;QACb,KAAK,EAAE;YACL;gBACE,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,aAAa,SAAS,EAAE,CAAC;gBAClD,QAAQ,EAAE,WAAW,UAAU,EAAE;gBACjC,MAAM,EAAE,SAAS,CAAC,KAAK,CACrB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,QAAQ,EAAE,CACnE;aACF;SACF;KACF,CAAC;CACH,CAAC"}
1
+ {"version":3,"file":"permission-checker.js","sourceRoot":"","sources":["../src/permission-checker.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,GAOV,MAAM,yBAAyB,CAAC;AA0BjC,sDAAsD;AACtD,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,EAAe,EAAgB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;AAE1F,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAED,sFAAsF;AACtF,MAAM,UAAU,aAAa,CAAC,QAAkB;IAI9C,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACtB,MAAM,IAAI,gBAAgB,CAAC,sBAAsB,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACvE,CAAC;AACH,CAAC;AAED,4FAA4F;AAC5F,MAAM,CAAC,MAAM,cAAc,GAAsB;IAC/C,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;QAC9C,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,UAAU;QACnB,IAAI;KACL,CAAC;CACH,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAsB;IACvD,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;QAC7C,OAAO,EAAE,IAAI;QACb,KAAK,EAAE;YACL;gBACE,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,aAAa,SAAS,EAAE,CAAC;gBAClD,QAAQ,EAAE,WAAW,UAAU,EAAE;gBACjC,MAAM,EAAE,SAAS,CAAC,KAAK,CACrB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,QAAQ,EAAE,CACnE;aACF;SACF;KACF,CAAC;CACH,CAAC"}
@@ -0,0 +1,96 @@
1
+ import type { ConnectionId, PlatformActorId } from '@substrat-run/contracts';
2
+ import type { ExecutorDrainReport, FetchLike, ScopeHost } from './scope-host.js';
3
+ /**
4
+ * A connector's reconcile sweep — the unit `runPlatformSweep` calls per live
5
+ * connection of a given provider (`sweepScriveReconciliations` is one).
6
+ *
7
+ * INJECTED, never imported: the driver — and the deployment that runs it —
8
+ * depends on no specific connector. A connector contributes `{ [provider]: its
9
+ * sweeper }` to the registry, and a provider with no entry is simply skipped.
10
+ */
11
+ export interface ConnectorSweeper {
12
+ (host: ScopeHost, connectionId: ConnectionId, opts: {
13
+ fetch: FetchLike;
14
+ }): Promise<unknown>;
15
+ }
16
+ export interface PlatformSweepOptions {
17
+ /** The platform actor the enumeration reads run as (`listScopes`/`listConnections`). */
18
+ actor: PlatformActorId;
19
+ /** Sanctioned egress handed to each connector sweeper. */
20
+ fetch: FetchLike;
21
+ /** provider slug → its reconcile sweeper. A connection whose provider is absent is skipped. */
22
+ sweepers: Record<string, ConnectorSweeper>;
23
+ /** Max scope drains / connection sweeps in flight at once. Default 8. */
24
+ concurrency?: number;
25
+ /**
26
+ * Also drain each active scope's due executor deliveries — the retry driver
27
+ * (connections.md §2.1), which has been landed and equally lacks a caller.
28
+ * Default `true`; set `false` to sweep only connectors.
29
+ */
30
+ drainRetries?: boolean;
31
+ }
32
+ export interface PlatformSweepReport {
33
+ /** Active scopes `drainDue` ran on. */
34
+ scopesDrained: number;
35
+ /** Drain outcomes summed across scopes. */
36
+ drainTotals: ExecutorDrainReport;
37
+ /** Connections a sweeper ran for. */
38
+ connectionsSwept: number;
39
+ /** Connections skipped — revoked, or their provider has no registered sweeper. */
40
+ connectionsSkipped: number;
41
+ /** Per-unit failures; the pass records and steps over each rather than aborting. */
42
+ errors: {
43
+ kind: 'drain' | 'sweep';
44
+ id: string;
45
+ error: string;
46
+ }[];
47
+ }
48
+ /**
49
+ * One pass of the platform's scheduled work: drain every active scope's due
50
+ * executor deliveries, then reconcile every live connection against its provider.
51
+ *
52
+ * This is the SCHEDULER'S UNIT OF WORK — a Cloudflare cron, a Durable Object
53
+ * alarm, or a node timer calls it; it holds no timer itself (see
54
+ * `startPlatformSweeper`, and docs/design/scheduler.md). Both halves are code
55
+ * that landed but had no caller: `drainDue` (the retry driver) and the
56
+ * connectors' reconcile sweeps.
57
+ *
58
+ * Robust because a scheduled pass must be: bounded concurrency, so one slow
59
+ * provider cannot delay the fleet, and a failure on any one scope or connection
60
+ * is recorded in the report and stepped over — never allowed to sink the pass.
61
+ *
62
+ * Provider-agnostic: connections are discovered via `listConnections` and
63
+ * dispatched to `sweepers[provider]`, so this imports no connector. A connection
64
+ * whose provider has no sweeper, or that is revoked, is skipped (and counted),
65
+ * not an error.
66
+ */
67
+ export declare function runPlatformSweep(host: ScopeHost, options: PlatformSweepOptions): Promise<PlatformSweepReport>;
68
+ /** A running sweeper; `stop()` prevents the next pass and cancels the pending timer. */
69
+ export interface PlatformSweeperHandle {
70
+ stop(): void;
71
+ }
72
+ export interface StartPlatformSweeperOptions extends PlatformSweepOptions {
73
+ /**
74
+ * Milliseconds between the END of one pass and the START of the next — a gap,
75
+ * not a fixed rate. Rescheduling only after a pass settles means two passes can
76
+ * never overlap, even when a pass runs longer than the interval.
77
+ */
78
+ intervalMs: number;
79
+ /** Observe each pass — for logging or a health metric. Never throws into the loop. */
80
+ onPass?: (outcome: PlatformSweepReport | {
81
+ error: string;
82
+ }) => void;
83
+ /** Injected for tests; default to the runtime's timer. */
84
+ setTimer?: (cb: () => void, ms: number) => unknown;
85
+ clearTimer?: (handle: unknown) => void;
86
+ }
87
+ /**
88
+ * Drive `runPlatformSweep` on a self-rescheduling timer — the node/long-lived
89
+ * runtime's trigger. (A Cloudflare deployment uses `scheduled()`/an alarm instead
90
+ * and calls `runPlatformSweep` directly; both share the one unit of work.)
91
+ *
92
+ * Non-overlapping by construction: the next pass is scheduled only once the
93
+ * current one settles, so a slow pass delays the next rather than stacking on it.
94
+ */
95
+ export declare function startPlatformSweeper(host: ScopeHost, options: StartPlatformSweeperOptions): PlatformSweeperHandle;
96
+ //# sourceMappingURL=platform-sweep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-sweep.d.ts","sourceRoot":"","sources":["../src/platform-sweep.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAQjF;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,CAAC,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,IAAI,EAAE;QAAE,KAAK,EAAE,SAAS,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7F;AAED,MAAM,WAAW,oBAAoB;IACnC,wFAAwF;IACxF,KAAK,EAAE,eAAe,CAAC;IACvB,0DAA0D;IAC1D,KAAK,EAAE,SAAS,CAAC;IACjB,+FAA+F;IAC/F,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC3C,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,uCAAuC;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,WAAW,EAAE,mBAAmB,CAAC;IACjC,qCAAqC;IACrC,gBAAgB,EAAE,MAAM,CAAC;IACzB,kFAAkF;IAClF,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oFAAoF;IACpF,MAAM,EAAE;QAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAClE;AAsBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,mBAAmB,CAAC,CA8C9B;AAED,wFAAwF;AACxF,MAAM,WAAW,qBAAqB;IACpC,IAAI,IAAI,IAAI,CAAC;CACd;AAED,MAAM,WAAW,2BAA4B,SAAQ,oBAAoB;IACvE;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,sFAAsF;IACtF,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACpE,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;IACnD,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,2BAA2B,GACnC,qBAAqB,CAuBvB"}
@@ -0,0 +1,114 @@
1
+ const message = (err) => (err instanceof Error ? err.message : String(err));
2
+ /**
3
+ * Run `fn` over `items` with at most `limit` in flight. `fn` owns its errors —
4
+ * this never rejects, so one unit's failure cannot abort the pass.
5
+ */
6
+ async function mapBounded(items, limit, fn) {
7
+ let next = 0;
8
+ const workers = Array.from({ length: Math.max(1, Math.min(limit, items.length)) }, async () => {
9
+ while (next < items.length) {
10
+ await fn(items[next++]);
11
+ }
12
+ });
13
+ await Promise.all(workers);
14
+ }
15
+ /**
16
+ * One pass of the platform's scheduled work: drain every active scope's due
17
+ * executor deliveries, then reconcile every live connection against its provider.
18
+ *
19
+ * This is the SCHEDULER'S UNIT OF WORK — a Cloudflare cron, a Durable Object
20
+ * alarm, or a node timer calls it; it holds no timer itself (see
21
+ * `startPlatformSweeper`, and docs/design/scheduler.md). Both halves are code
22
+ * that landed but had no caller: `drainDue` (the retry driver) and the
23
+ * connectors' reconcile sweeps.
24
+ *
25
+ * Robust because a scheduled pass must be: bounded concurrency, so one slow
26
+ * provider cannot delay the fleet, and a failure on any one scope or connection
27
+ * is recorded in the report and stepped over — never allowed to sink the pass.
28
+ *
29
+ * Provider-agnostic: connections are discovered via `listConnections` and
30
+ * dispatched to `sweepers[provider]`, so this imports no connector. A connection
31
+ * whose provider has no sweeper, or that is revoked, is skipped (and counted),
32
+ * not an error.
33
+ */
34
+ export async function runPlatformSweep(host, options) {
35
+ const concurrency = options.concurrency ?? 8;
36
+ const report = {
37
+ scopesDrained: 0,
38
+ drainTotals: { attempted: 0, delivered: 0, retrying: 0, deadLettered: 0 },
39
+ connectionsSwept: 0,
40
+ connectionsSkipped: 0,
41
+ errors: [],
42
+ };
43
+ if (options.drainRetries !== false) {
44
+ const scopes = await host.admin.listScopes(options.actor, { status: 'active' });
45
+ await mapBounded(scopes, concurrency, async (s) => {
46
+ try {
47
+ const r = await host.drainDue(s.tenantId, s.id);
48
+ report.scopesDrained += 1;
49
+ report.drainTotals.attempted += r.attempted;
50
+ report.drainTotals.delivered += r.delivered;
51
+ report.drainTotals.retrying += r.retrying;
52
+ report.drainTotals.deadLettered += r.deadLettered;
53
+ }
54
+ catch (err) {
55
+ report.errors.push({ kind: 'drain', id: s.id, error: message(err) });
56
+ }
57
+ });
58
+ }
59
+ const connections = await host.admin.listConnections(options.actor, {});
60
+ await mapBounded(connections, concurrency, async (c) => {
61
+ if (c.revokedAt !== null) {
62
+ report.connectionsSkipped += 1; // terminal — nothing to reconcile through it
63
+ return;
64
+ }
65
+ const sweeper = options.sweepers[c.provider];
66
+ if (!sweeper) {
67
+ report.connectionsSkipped += 1;
68
+ return;
69
+ }
70
+ try {
71
+ await sweeper(host, c.id, { fetch: options.fetch });
72
+ report.connectionsSwept += 1;
73
+ }
74
+ catch (err) {
75
+ report.errors.push({ kind: 'sweep', id: c.id, error: message(err) });
76
+ }
77
+ });
78
+ return report;
79
+ }
80
+ /**
81
+ * Drive `runPlatformSweep` on a self-rescheduling timer — the node/long-lived
82
+ * runtime's trigger. (A Cloudflare deployment uses `scheduled()`/an alarm instead
83
+ * and calls `runPlatformSweep` directly; both share the one unit of work.)
84
+ *
85
+ * Non-overlapping by construction: the next pass is scheduled only once the
86
+ * current one settles, so a slow pass delays the next rather than stacking on it.
87
+ */
88
+ export function startPlatformSweeper(host, options) {
89
+ const setTimer = options.setTimer ?? ((cb, ms) => setTimeout(cb, ms));
90
+ const clearTimer = options.clearTimer ?? ((h) => clearTimeout(h));
91
+ let stopped = false;
92
+ let handle;
93
+ const tick = async () => {
94
+ if (stopped)
95
+ return;
96
+ try {
97
+ options.onPass?.(await runPlatformSweep(host, options));
98
+ }
99
+ catch (err) {
100
+ options.onPass?.({ error: message(err) });
101
+ }
102
+ if (!stopped)
103
+ handle = setTimer(() => void tick(), options.intervalMs);
104
+ };
105
+ handle = setTimer(() => void tick(), options.intervalMs);
106
+ return {
107
+ stop() {
108
+ stopped = true;
109
+ if (handle !== undefined)
110
+ clearTimer(handle);
111
+ },
112
+ };
113
+ }
114
+ //# sourceMappingURL=platform-sweep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-sweep.js","sourceRoot":"","sources":["../src/platform-sweep.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { AdminAction, AccessLogEntry, BindHostnameInput, AdminLogEntry, CapabilityGrant, CreateTenantInput, Decision, DomainEvent, DomainEventInput, EntityRef, IdentityLink, IdentityPool, Jurisdiction, ModuleManifest, CreateOrgInput, Node, Org, OrgId, OrgMembership, PermissionKey, PlatformActorId, ChannelName, HostnameBinding, HostnameStatus, PromotionAcknowledgement, PublishVersionInput, RegisterVerticalInput, RouteTarget, PrincipalId, ResolvedIdentity, RoleAssignment, RoleDefinition, Scope, ScopeId, ScopeStatus, StorageShape, Tenant, TenantId, TenantRole, Vertical, VerticalChannel, VerticalVersion, TenantStatus } from '@substrat-run/contracts';
1
+ import type { AdminAction, Connection, ConnectionFilter, ConnectionId, ConnectionGrant, ConnectionSecret, CreateConnectionInput, OpenConnection, AccessLogEntry, BindHostnameInput, AdminLogEntry, CapabilityGrant, CreateTenantInput, Decision, DomainEvent, DomainEventInput, EntityRef, IdentityLink, IdentityPool, Jurisdiction, ModuleManifest, CreateOrgInput, Node, Org, OrgId, OrgMembership, PermissionKey, PlatformActorId, ChannelName, HostnameBinding, HostnameStatus, PromotionAcknowledgement, PublishVersionInput, RegisterVerticalInput, RouteTarget, PrincipalId, ResolvedIdentity, RoleAssignment, RoleDefinition, Scope, ScopeId, ScopeStatus, StorageShape, Tenant, TenantId, TenantRole, Vertical, VerticalChannel, VerticalVersion, TenantStatus } from '@substrat-run/contracts';
2
2
  /**
3
3
  * The scope-host contract — the adapter seam (§5.1 of the design doc).
4
4
  *
@@ -86,6 +86,138 @@ export type ConsumerHandler = (ctx: OperationContext, event: DomainEvent) => voi
86
86
  * the causing event's id (`causedBy`), so the split trail joins.
87
87
  */
88
88
  export type ExecutorHandler = (admin: HostAdmin, event: DomainEvent) => void | Promise<void>;
89
+ /**
90
+ * How hard the host tries before it gives up on one delivery (#100).
91
+ *
92
+ * Defaults suit a directory write. A connector making an outbound HTTP call
93
+ * wants a longer tail — that is the whole reason this is per-executor rather
94
+ * than a host-wide constant.
95
+ */
96
+ export interface ExecutorRetryPolicy {
97
+ /** Total attempts including the first. Reaching it dead-letters. Default 5. */
98
+ maxAttempts?: number;
99
+ /** First backoff step; doubles per attempt. Default 1000ms. `0` retries at once. */
100
+ baseDelayMs?: number;
101
+ /** Ceiling on the doubling. Default 300_000ms (5 min). */
102
+ maxDelayMs?: number;
103
+ }
104
+ /**
105
+ * What one drain pass did. `retrying` and `deadLettered` are the numbers a
106
+ * health surface reports; a caller that ignores them learns nothing, which is
107
+ * the failure mode the old silent path had.
108
+ */
109
+ export interface ExecutorDrainReport {
110
+ attempted: number;
111
+ delivered: number;
112
+ /** Failed, still under `maxAttempts` — scheduled for a later pass. */
113
+ retrying: number;
114
+ /** Failed at `maxAttempts` — terminal, and the row keeps the last error. */
115
+ deadLettered: number;
116
+ }
117
+ /**
118
+ * The web-standard fetch surface, structurally typed.
119
+ *
120
+ * Declared rather than imported: the kernel depends on no platform typings, and
121
+ * `RequestInit`/`Response` come from DOM lib in Node and from workers-types in
122
+ * Workers. Structural typing means both satisfy this without either being
123
+ * required — the same reason `crypto` and `TextEncoder` are declared locally.
124
+ */
125
+ export interface FetchLike {
126
+ (input: string, init?: ConnectorRequestInit): Promise<ConnectorResponse>;
127
+ }
128
+ export interface ConnectorRequestInit {
129
+ method?: string;
130
+ headers?: Record<string, string>;
131
+ /**
132
+ * `Uint8Array` as well as `string` because a real provider upload is binary:
133
+ * Scrive's `setfile` is `multipart/form-data`, whose body is a byte sequence a
134
+ * string cannot carry without corrupting the file. Web `fetch` accepts both, so
135
+ * this only widens the declared surface — the adapter passes it straight
136
+ * through.
137
+ */
138
+ body?: string | Uint8Array;
139
+ signal?: unknown;
140
+ }
141
+ export interface ConnectorResponse {
142
+ readonly ok: boolean;
143
+ readonly status: number;
144
+ text(): Promise<string>;
145
+ json(): Promise<unknown>;
146
+ }
147
+ /**
148
+ * A connection with its credential opened, plus egress bound to it.
149
+ *
150
+ * `fetch` is bound to the connection rather than sitting on the context because
151
+ * health has to land on the right row by construction. An ambient
152
+ * `ctx.fetch` would need the runtime to guess which connection a call belonged
153
+ * to, and it would guess wrong the first time a connector talked to two.
154
+ */
155
+ export interface ConnectorConnection extends OpenConnection {
156
+ /**
157
+ * Sanctioned egress: a timeout, and success/failure recorded against THIS
158
+ * connection.
159
+ *
160
+ * The connector is handed its `fetch` rather than importing one — the same
161
+ * move `ctx.sql` makes for module code, and for the same reason. Egress
162
+ * policy, timeouts and health become properties of the seam instead of
163
+ * conventions a connector author has to remember. Module code still cannot
164
+ * reach any of this: boundary-lint R3 bans `fetch` outright, and a connector
165
+ * is host code.
166
+ */
167
+ fetch(input: string, init?: ConnectorRequestInit): Promise<ConnectorResponse>;
168
+ }
169
+ /**
170
+ * What a connector sees. Strictly more than an executor: an executor effects
171
+ * something in the DIRECTORY, a connector effects something in the OUTSIDE
172
+ * WORLD, and only the second needs a per-tenant credential and egress.
173
+ */
174
+ export interface ConnectorContext {
175
+ readonly admin: HostAdmin;
176
+ readonly tenantId: TenantId;
177
+ readonly scopeId: ScopeId;
178
+ /** The scope's vertical — half the key a connection is stored under. */
179
+ readonly vertical: string;
180
+ /**
181
+ * The live connection for this provider, opened.
182
+ *
183
+ * Resolved as (this event's tenant, this scope's vertical, provider), so a
184
+ * connector cannot reach a credential another vertical connected even by
185
+ * accident — the tenant and vertical are ambient, not arguments. Throws when
186
+ * there is none: a connector that runs without a credential would otherwise
187
+ * fail later, further from the cause.
188
+ */
189
+ connection(provider: string): Promise<ConnectorConnection>;
190
+ }
191
+ export type ConnectorHandler = (ctx: ConnectorContext, event: DomainEvent) => void | Promise<void>;
192
+ /** Tuning for one connector's egress. */
193
+ export interface ConnectorOptions extends ExecutorRetryPolicy {
194
+ /** Per-request timeout. Default 30s. */
195
+ timeoutMs?: number;
196
+ }
197
+ /** A delivery that exhausted its attempts. The evidence, not a silent drop. */
198
+ export interface ExecutorDeadLetter {
199
+ eventId: string;
200
+ executorId: string;
201
+ eventType: string;
202
+ attempts: number;
203
+ error: string;
204
+ lastAttemptAt: string;
205
+ }
206
+ /**
207
+ * Retry defaults (#100). Tuned for the directory write the first executor does;
208
+ * a connector making an outbound call should raise `maxAttempts` explicitly,
209
+ * which is why the policy is per-executor rather than a host constant.
210
+ */
211
+ export declare function resolveRetryPolicy(retry?: ExecutorRetryPolicy): Required<ExecutorRetryPolicy>;
212
+ /**
213
+ * When attempt `attempts` should next be tried: exponential, capped, jittered.
214
+ *
215
+ * Jitter is ±20% and is skipped entirely at zero delay, so a test setting
216
+ * `baseDelayMs: 0` gets deterministic immediate retries rather than a race. It
217
+ * matters at real delays because every scope in a fleet retries a downed
218
+ * provider on the same schedule otherwise.
219
+ */
220
+ export declare function backoffAt(attempts: number, retry: Required<ExecutorRetryPolicy>, from: Date): string;
89
221
  /**
90
222
  * A named, manifest-wired pre-condition on an operation (K-17; engine-protocol
91
223
  * §6, open question 11). One module CONTRIBUTES a predicate under a name; a
@@ -157,6 +289,17 @@ export interface HostAdmin {
157
289
  assignRole(actor: PlatformActorId, assignment: RoleAssignment): Promise<void>;
158
290
  grant(actor: PlatformActorId, grant: CapabilityGrant): Promise<void>;
159
291
  /** Grant to an organization (portal customers); members reach it via membership tuples. */
292
+ /**
293
+ * Grant a permission to a CONNECTION (#97) — how a connector is allowed to
294
+ * write back into a scope.
295
+ *
296
+ * Deliberately the same shape as every other grant: tuples, tombstoned on
297
+ * revoke (K-21), visible to `listRoles`-style reads and to the permission
298
+ * diff. A separate "allowed operations" list on the connection was the
299
+ * alternative and was rejected — two mechanisms for one gate is worse than
300
+ * either, and only one of them would have shown up in a review.
301
+ */
302
+ grantToConnection(actor: PlatformActorId, grant: ConnectionGrant): Promise<void>;
160
303
  grantToOrg(actor: PlatformActorId, orgId: OrgId, permission: PermissionKey, node: Node, entity?: EntityRef): Promise<void>;
161
304
  addMember(actor: PlatformActorId, tenantId: TenantId, principal: PrincipalId, orgId: OrgId): Promise<void>;
162
305
  /**
@@ -337,6 +480,92 @@ export interface HostAdmin {
337
480
  * DIFFERENT principal **throws** — it means two subjects collided, and silently
338
481
  * ignoring it would resolve the second person as the first.
339
482
  */
483
+ /**
484
+ * Store a tenant's authorization for one provider, held by one vertical.
485
+ *
486
+ * The credential is sealed by the host's `SecretBox` before it touches the
487
+ * directory, and the admin-log row carries **metadata only** — provider,
488
+ * label, scopes. That is structural, not careful: `_substrat_admin_log` is
489
+ * append-only, so a secret written into it could never be removed.
490
+ *
491
+ * Takes a `PlatformActorId` today. Connecting a provider is really a tenant
492
+ * admin's act, and routing it through a platform actor is the same defect
493
+ * D-31 named for `addMember` — so this is a deliberate deferral, recorded in
494
+ * connections.md §3.5, not an answer. No console flow should be built on this
495
+ * signature until the question is settled together with membership's.
496
+ */
497
+ createConnection(actor: PlatformActorId, input: CreateConnectionInput): Promise<void>;
498
+ /** Metadata only — never the credential, at any privilege level. */
499
+ listConnections(actor: PlatformActorId, filter?: ConnectionFilter): Promise<Connection[]>;
500
+ /** Replace the sealed credential — the OAuth refresh path. */
501
+ updateConnectionSecret(actor: PlatformActorId, id: ConnectionId, secret: ConnectionSecret, expiresAt?: string): Promise<void>;
502
+ /**
503
+ * Withdraw a connection. Tombstones like K-21 rather than deleting: a
504
+ * credential that once had access is evidence of why an access was allowed.
505
+ * Terminal — a replacement is a new connection, which is why the uniqueness
506
+ * constraint ignores revoked rows.
507
+ */
508
+ revokeConnection(actor: PlatformActorId, id: ConnectionId): Promise<void>;
509
+ /**
510
+ * Open the credential for one (tenant, vertical, provider) — the connector's
511
+ * read, and the only path in the system that yields plaintext.
512
+ *
513
+ * **Takes no actor and is not audited**, the same exemption `resolveHostname`
514
+ * and `resolveIdentity` hold and for the same reason: it is a machine read on
515
+ * the request path, and an audit row per outbound HTTP call would drown the
516
+ * log that matters. What *is* recorded is health — `recordConnectionUse` below
517
+ * — which is the signal an operator can actually act on.
518
+ */
519
+ openConnection(tenantId: TenantId, vertical: string, provider: string): Promise<OpenConnection | undefined>;
520
+ /**
521
+ * Record that a connection worked, or did not (§3.7). Written by the connector
522
+ * runtime; read by a console. Not audited — it is telemetry about a machine
523
+ * read, not a control-plane mutation.
524
+ */
525
+ recordConnectionUse(id: ConnectionId, outcome: {
526
+ ok: true;
527
+ } | {
528
+ ok: false;
529
+ error: string;
530
+ }): Promise<void>;
531
+ /**
532
+ * Durable, connection-scoped state a connector keeps for itself — the home a
533
+ * connector's bookkeeping never had.
534
+ *
535
+ * The load-bearing use is **dispatch idempotency**. A connector runs from the
536
+ * outbox at-least-once, so a redelivery must not repeat an outward effect —
537
+ * and it cannot record "already did this" in the scope, because a connector
538
+ * runs *inside* the scope's dispatch and re-entering the scope actor
539
+ * deadlocks. This lives in the DIRECTORY instead, which the connector reaches
540
+ * through `ctx.admin` without touching the scope: before it creates a document
541
+ * at the provider it checks for prior state under a deterministic key, and
542
+ * skips if it is there.
543
+ *
544
+ * `value` is arbitrary JSON, opaque to the kernel — a `{ documentId, … }` map
545
+ * the connector interprets. NOT audited: this is high-frequency machine state,
546
+ * one write per dispatch, the same class as `recordConnectionUse`. Rows die
547
+ * with the connection (revoke cascades).
548
+ */
549
+ putConnectorState(id: ConnectionId, key: string, value: unknown): Promise<void>;
550
+ getConnectorState(id: ConnectionId, key: string): Promise<unknown | undefined>;
551
+ /**
552
+ * Every state row for a connection, optionally narrowed to keys under a
553
+ * `prefix`, ordered by key.
554
+ *
555
+ * `getConnectorState` answers "did I already do THIS one" from a deterministic
556
+ * key — the dispatch path. This answers "what is still outstanding" without
557
+ * knowing the keys up front, which is what a **poll driver** needs: a connector
558
+ * records one row per dispatch under `<provider>:dispatch:<id>`, and a
559
+ * scheduled sweep enumerates them (`prefix = '<provider>:dispatch:'`) to
560
+ * reconcile each against the provider. Without it a sweep would have to be told
561
+ * every id it might reconcile — which defeats the point of a sweep.
562
+ *
563
+ * A read of directory-local machine state, like get/put; not audited.
564
+ */
565
+ listConnectorState(id: ConnectionId, prefix?: string): Promise<{
566
+ key: string;
567
+ value: unknown;
568
+ }[]>;
340
569
  linkIdentity(actor: PlatformActorId, input: IdentityLink): Promise<void>;
341
570
  /**
342
571
  * Register an identity pool and its topology (K-23). A provider must be registered
@@ -498,8 +727,65 @@ export interface ScopeHost {
498
727
  * is what makes it correct under crash — but the common case completes inside the
499
728
  * originating request, so "requested but not yet effected" is a rare-case fallback
500
729
  * rather than the normal experience.
730
+ *
731
+ * **A failing handler never fails the operation** (#100). The operation already
732
+ * committed; the delivery did not. Those are different facts, and reporting the
733
+ * second as the first told a caller their work had been rolled back when it had
734
+ * not. A failure is retried with backoff, dead-lettered at `maxAttempts`, and
735
+ * surfaced through `drainDue`/`executorDeadLetters` — never thrown at whoever happened
736
+ * to be holding the request.
737
+ */
738
+ registerExecutor(id: string, eventType: string, handler: ExecutorHandler, retry?: ExecutorRetryPolicy): void;
739
+ /**
740
+ * A scope stub whose authority is a CONNECTION rather than a person (#97).
741
+ *
742
+ * This is the inbound half of the connector seam: the path by which a
743
+ * provider's callback, or a poll of a provider's state, writes back into a
744
+ * scope. `getScope` demands a `PrincipalId` and a provider is not one, which
745
+ * is why a connector could dispatch a document and then not record that it
746
+ * had — and why an at-least-once retry would send a second copy.
747
+ *
748
+ * **Authority is inherited, not re-declared.** A connection is keyed
749
+ * (tenant, vertical, provider), so this refuses any scope outside that
750
+ * tenant, and any scope not running that vertical. What the connection may
751
+ * then DO is an ordinary permission check against `connection:<id>` grants —
752
+ * one enforcement path, one place to read, one way to revoke.
753
+ *
754
+ * `ctx.principal` on the resulting stub carries the connection id so the type
755
+ * holds, but it is **not a person**: an operation invoked this way should read
756
+ * the event actor (`{ connection }`), and a module that attributes domain
757
+ * data to `ctx.principal` will be recording a connector.
758
+ */
759
+ getConnectorScope(connectionId: ConnectionId, scopeId: ScopeId): Promise<ScopeStub>;
760
+ /**
761
+ * Register a connector — an executor that also gets a per-tenant credential
762
+ * and sanctioned egress (#101, design/connections.md §4.1).
763
+ *
764
+ * Rides the same hardened dispatch, journal and retry policy as
765
+ * `registerExecutor`; the difference is only what the handler is handed. Kept
766
+ * as a second registration rather than widening `ExecutorHandler` because the
767
+ * two really are different capabilities, and a membership executor should not
768
+ * be handed the machinery to call the internet.
769
+ */
770
+ registerConnector(id: string, eventType: string, handler: ConnectorHandler, options?: ConnectorOptions): void;
771
+ /**
772
+ * Run every executor delivery that is due for this scope — the retry driver.
773
+ *
774
+ * Inline dispatch after an operation covers the common case, but a delivery
775
+ * that failed has no way back on its own: before this existed, retry happened
776
+ * only if someone happened to invoke another operation on the same scope, so a
777
+ * quiet scope could hold a failed effect forever with nothing reporting it.
778
+ *
779
+ * Call it from whatever scheduling the deployment has — a cron trigger, a
780
+ * Durable Object alarm, a dev-server timer. Idempotent and safe to call when
781
+ * nothing is due.
782
+ */
783
+ drainDue(tenantId: TenantId, scopeId: ScopeId): Promise<ExecutorDrainReport>;
784
+ /**
785
+ * Executor deliveries that exhausted their attempts, oldest first — the evidence a
786
+ * dead-letter is a decision rather than a disappearance.
501
787
  */
502
- registerExecutor(id: string, eventType: string, handler: ExecutorHandler): void;
788
+ executorDeadLetters(tenantId: TenantId, scopeId: ScopeId): Promise<ExecutorDeadLetter[]>;
503
789
  /** Bare operation registration (tests, glue). Names are module-namespaced: 'workorder/create'. */
504
790
  defineOperation<I, O>(name: string, handler: OperationHandler<I, O>): void;
505
791
  close(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"scope-host.d.ts","sourceRoot":"","sources":["../src/scope-host.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scope-host.d.ts","sourceRoot":"","sources":["../src/scope-host.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,26 @@
1
- export {};
1
+ /**
2
+ * Retry defaults (#100). Tuned for the directory write the first executor does;
3
+ * a connector making an outbound call should raise `maxAttempts` explicitly,
4
+ * which is why the policy is per-executor rather than a host constant.
5
+ */
6
+ export function resolveRetryPolicy(retry) {
7
+ return {
8
+ maxAttempts: retry?.maxAttempts ?? 5,
9
+ baseDelayMs: retry?.baseDelayMs ?? 1_000,
10
+ maxDelayMs: retry?.maxDelayMs ?? 300_000,
11
+ };
12
+ }
13
+ /**
14
+ * When attempt `attempts` should next be tried: exponential, capped, jittered.
15
+ *
16
+ * Jitter is ±20% and is skipped entirely at zero delay, so a test setting
17
+ * `baseDelayMs: 0` gets deterministic immediate retries rather than a race. It
18
+ * matters at real delays because every scope in a fleet retries a downed
19
+ * provider on the same schedule otherwise.
20
+ */
21
+ export function backoffAt(attempts, retry, from) {
22
+ const raw = Math.min(retry.baseDelayMs * 2 ** (attempts - 1), retry.maxDelayMs);
23
+ const jittered = raw === 0 ? 0 : raw * (0.8 + Math.random() * 0.4);
24
+ return new Date(from.getTime() + jittered).toISOString();
25
+ }
2
26
  //# sourceMappingURL=scope-host.js.map
@@ -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":"AAmRA;;;;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"}
@@ -1 +1 @@
1
- {"version":3,"file":"scope-record.d.ts","sourceRoot":"","sources":["../src/scope-record.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,mFAAmF;AACnF,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,YAAY,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,mBAAmB,GAAG,mBAAmB,CAYlF"}
1
+ {"version":3,"file":"scope-record.d.ts","sourceRoot":"","sources":["../src/scope-record.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,mFAAmF;AACnF,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,YAAY,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,mBAAmB,GAAG,mBAAmB,CAgBlF"}
@@ -23,7 +23,11 @@ export function resolveScopeRecord(input) {
23
23
  name: input.name ?? slug,
24
24
  vertical: input.vertical ?? null,
25
25
  storageShape: input.storageShape ?? 'A',
26
- jurisdiction: input.jurisdiction ?? null,
26
+ // No jurisdiction stated means `global` — unconstrained, the honest name for
27
+ // what an un-pinned scope already is (K-32). The old default was `null`, which
28
+ // also meant "nobody decided"; `global` is a decision, and the only one the
29
+ // provisioning boundary accepts until `eu`/`us` enforcement exists.
30
+ jurisdiction: input.jurisdiction ?? 'global',
27
31
  };
28
32
  }
29
33
  //# sourceMappingURL=scope-record.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scope-record.js","sourceRoot":"","sources":["../src/scope-record.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAc7D;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAA0B;IAC3D,8EAA8E;IAC9E,wEAAwE;IACxE,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IACzE,OAAO;QACL,IAAI;QACJ,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,OAAO;QAC3B,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,IAAI;QACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,IAAI;QAChC,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,GAAG;QACvC,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,IAAI;KACzC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"scope-record.js","sourceRoot":"","sources":["../src/scope-record.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAc7D;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAA0B;IAC3D,8EAA8E;IAC9E,wEAAwE;IACxE,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IACzE,OAAO;QACL,IAAI;QACJ,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,OAAO;QAC3B,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,IAAI;QACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,IAAI;QAChC,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,GAAG;QACvC,6EAA6E;QAC7E,+EAA+E;QAC/E,4EAA4E;QAC5E,oEAAoE;QACpE,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,QAAQ;KAC7C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * `SecretBox` — the seal/open adapter the connection store rests on (#101,
3
+ * design/connections.md §3.3).
4
+ *
5
+ * **Bucket 2 in D-18's triage**, which names the KMS as an adapter explicitly.
6
+ * The kernel decides that per-tenant credentials are encrypted at rest and that
7
+ * plaintext never touches the directory; *what* does the encrypting is swappable
8
+ * — Web Crypto locally, a Cloudflare Secrets Store binding or an external KMS
9
+ * when hosted.
10
+ *
11
+ * Before this existed there was no encryption primitive in the codebase at all:
12
+ * every `crypto.subtle` call was a one-way digest, and every secret was a
13
+ * plaintext Worker binding. Nothing was per-tenant, nothing was rotatable.
14
+ */
15
+ /**
16
+ * Sealed bytes plus the id of the key that sealed them.
17
+ *
18
+ * `keyId` is what makes rotation possible: a new key seals new writes while old
19
+ * blobs stay openable, so re-sealing is a background sweep rather than a
20
+ * flag-day. A `SecretBox` that cannot name its key can only ever have one.
21
+ */
22
+ export interface SealedSecret {
23
+ keyId: string;
24
+ /** Opaque to everything above this interface. Base64 for the Web Crypto impl. */
25
+ ciphertext: string;
26
+ }
27
+ export interface SecretBox {
28
+ seal(plaintext: string): Promise<SealedSecret>;
29
+ /** Throws if the blob was sealed by a key this box does not hold. */
30
+ open(sealed: SealedSecret): Promise<string>;
31
+ }
32
+ /**
33
+ * AES-256-GCM over Web Crypto — the default for dev, CI and self-hosting.
34
+ *
35
+ * `key` is 32 raw bytes. A fresh 96-bit IV per seal is prepended to the
36
+ * ciphertext, which is what makes it safe to seal the same credential twice;
37
+ * GCM with a reused IV is catastrophic rather than merely weak.
38
+ *
39
+ * **Fails closed when unconfigured.** A host built without a `SecretBox` cannot
40
+ * store a credential at all, rather than storing one in the clear. That is the
41
+ * rule `assertPlatformCall` already states — *"an unset secret is a failure, not
42
+ * a bypass"* — applied to the thing it most obviously protects. Note the router
43
+ * secret does the opposite; it is not a precedent to copy here.
44
+ */
45
+ export declare function webCryptoSecretBox(keyId: string, key: Uint8Array): SecretBox;
46
+ /**
47
+ * The box a host gets when none was configured: every call throws.
48
+ *
49
+ * Deliberately not "store it in the clear" and not "silently disable
50
+ * connections" — either would make a misconfiguration invisible until a
51
+ * credential leaked. Reading the error tells an operator exactly what to set.
52
+ */
53
+ export declare const unconfiguredSecretBox: SecretBox;
54
+ //# sourceMappingURL=secret-box.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-box.d.ts","sourceRoot":"","sources":["../src/secret-box.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/C,qEAAqE;IACrE,IAAI,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7C;AAkDD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,SAAS,CAqC5E;AAED;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,EAAE,SAanC,CAAC"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * `SecretBox` — the seal/open adapter the connection store rests on (#101,
3
+ * design/connections.md §3.3).
4
+ *
5
+ * **Bucket 2 in D-18's triage**, which names the KMS as an adapter explicitly.
6
+ * The kernel decides that per-tenant credentials are encrypted at rest and that
7
+ * plaintext never touches the directory; *what* does the encrypting is swappable
8
+ * — Web Crypto locally, a Cloudflare Secrets Store binding or an external KMS
9
+ * when hosted.
10
+ *
11
+ * Before this existed there was no encryption primitive in the codebase at all:
12
+ * every `crypto.subtle` call was a one-way digest, and every secret was a
13
+ * plaintext Worker binding. Nothing was per-tenant, nothing was rotatable.
14
+ */
15
+ const toBase64 = (bytes) => {
16
+ let s = '';
17
+ for (const b of bytes)
18
+ s += String.fromCharCode(b);
19
+ return btoa(s);
20
+ };
21
+ const fromBase64 = (b64) => {
22
+ const s = atob(b64);
23
+ const out = new Uint8Array(s.length);
24
+ for (let i = 0; i < s.length; i += 1)
25
+ out[i] = s.charCodeAt(i);
26
+ return out;
27
+ };
28
+ /**
29
+ * AES-256-GCM over Web Crypto — the default for dev, CI and self-hosting.
30
+ *
31
+ * `key` is 32 raw bytes. A fresh 96-bit IV per seal is prepended to the
32
+ * ciphertext, which is what makes it safe to seal the same credential twice;
33
+ * GCM with a reused IV is catastrophic rather than merely weak.
34
+ *
35
+ * **Fails closed when unconfigured.** A host built without a `SecretBox` cannot
36
+ * store a credential at all, rather than storing one in the clear. That is the
37
+ * rule `assertPlatformCall` already states — *"an unset secret is a failure, not
38
+ * a bypass"* — applied to the thing it most obviously protects. Note the router
39
+ * secret does the opposite; it is not a precedent to copy here.
40
+ */
41
+ export function webCryptoSecretBox(keyId, key) {
42
+ if (key.length !== 32) {
43
+ throw new Error(`SecretBox key must be 32 bytes (AES-256), got ${key.length}`);
44
+ }
45
+ const imported = crypto.subtle.importKey('raw', key, 'AES-GCM', false, ['encrypt', 'decrypt']);
46
+ return {
47
+ async seal(plaintext) {
48
+ const iv = crypto.getRandomValues(new Uint8Array(12));
49
+ const body = new Uint8Array(await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, await imported, new TextEncoder().encode(plaintext)));
50
+ const joined = new Uint8Array(iv.length + body.length);
51
+ joined.set(iv, 0);
52
+ joined.set(body, iv.length);
53
+ return { keyId, ciphertext: toBase64(joined) };
54
+ },
55
+ async open(sealed) {
56
+ if (sealed.keyId !== keyId) {
57
+ // Naming the ids is safe and is the only way an operator can tell
58
+ // "wrong key configured" from "corrupt blob".
59
+ throw new Error(`SecretBox cannot open a secret sealed by key '${sealed.keyId}' (holding '${keyId}')`);
60
+ }
61
+ const joined = fromBase64(sealed.ciphertext);
62
+ const plain = await crypto.subtle.decrypt({ name: 'AES-GCM', iv: joined.slice(0, 12) }, await imported, joined.slice(12));
63
+ return new TextDecoder().decode(new Uint8Array(plain));
64
+ },
65
+ };
66
+ }
67
+ /**
68
+ * The box a host gets when none was configured: every call throws.
69
+ *
70
+ * Deliberately not "store it in the clear" and not "silently disable
71
+ * connections" — either would make a misconfiguration invisible until a
72
+ * credential leaked. Reading the error tells an operator exactly what to set.
73
+ */
74
+ export const unconfiguredSecretBox = {
75
+ seal() {
76
+ return Promise.reject(new Error('no SecretBox configured: this host cannot store credentials. ' +
77
+ 'Pass one to the host (webCryptoSecretBox with a 32-byte key) — ' +
78
+ 'storing a credential unsealed is not an option.'));
79
+ },
80
+ open() {
81
+ return Promise.reject(new Error('no SecretBox configured: cannot open a stored credential'));
82
+ },
83
+ };
84
+ //# sourceMappingURL=secret-box.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-box.js","sourceRoot":"","sources":["../src/secret-box.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.9.0",
3
+ "version": "0.11.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.9.0"
25
+ "@substrat-run/contracts": "^0.11.0"
26
26
  },
27
27
  "devDependencies": {
28
28
  "typescript": "^5.6.0",