@substrat-run/kernel 0.147.0 → 0.149.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/attachment-sweep.d.ts +208 -0
- package/dist/attachment-sweep.d.ts.map +1 -0
- package/dist/attachment-sweep.js +318 -0
- package/dist/attachment-sweep.js.map +1 -0
- package/dist/audit-outcome.d.ts +1 -1
- package/dist/audit-outcome.d.ts.map +1 -1
- package/dist/audit-outcome.js +4 -2
- package/dist/audit-outcome.js.map +1 -1
- package/dist/export-break.d.ts +137 -0
- package/dist/export-break.d.ts.map +1 -0
- package/dist/export-break.js +219 -0
- package/dist/export-break.js.map +1 -0
- package/dist/index.d.ts +24 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -7
- package/dist/index.js.map +1 -1
- package/dist/install-receipts.d.ts +116 -0
- package/dist/install-receipts.d.ts.map +1 -0
- package/dist/install-receipts.js +162 -0
- package/dist/install-receipts.js.map +1 -0
- package/dist/invocation-line.d.ts +85 -0
- package/dist/invocation-line.d.ts.map +1 -1
- package/dist/invocation-line.js +43 -0
- package/dist/invocation-line.js.map +1 -1
- package/dist/map-bounded.d.ts +8 -0
- package/dist/map-bounded.d.ts.map +1 -0
- package/dist/map-bounded.js +16 -0
- package/dist/map-bounded.js.map +1 -0
- package/dist/migration-digest.d.ts +56 -0
- package/dist/migration-digest.d.ts.map +1 -1
- package/dist/migration-digest.js +92 -0
- package/dist/migration-digest.js.map +1 -1
- package/dist/migration-fence.d.ts +14 -0
- package/dist/migration-fence.d.ts.map +1 -0
- package/dist/migration-fence.js +515 -0
- package/dist/migration-fence.js.map +1 -0
- package/dist/migration-replay.d.ts +52 -0
- package/dist/migration-replay.d.ts.map +1 -0
- package/dist/migration-replay.js +140 -0
- package/dist/migration-replay.js.map +1 -0
- package/dist/module-migrations.d.ts +3 -3
- package/dist/module-migrations.js +3 -3
- package/dist/peer.d.ts +32 -2
- package/dist/peer.d.ts.map +1 -1
- package/dist/peer.js +100 -4
- package/dist/peer.js.map +1 -1
- package/dist/permission-eval.d.ts +8 -0
- package/dist/permission-eval.d.ts.map +1 -1
- package/dist/permission-eval.js +14 -0
- package/dist/permission-eval.js.map +1 -1
- package/dist/platform-sweep.d.ts +114 -361
- package/dist/platform-sweep.d.ts.map +1 -1
- package/dist/platform-sweep.js +134 -561
- package/dist/platform-sweep.js.map +1 -1
- package/dist/promote-review.d.ts +125 -0
- package/dist/promote-review.d.ts.map +1 -0
- package/dist/promote-review.js +181 -0
- package/dist/promote-review.js.map +1 -0
- package/dist/schedule-state.d.ts +91 -0
- package/dist/schedule-state.d.ts.map +1 -0
- package/dist/schedule-state.js +118 -0
- package/dist/schedule-state.js.map +1 -0
- package/dist/scope-copy-ledger.d.ts +29 -0
- package/dist/scope-copy-ledger.d.ts.map +1 -1
- package/dist/scope-copy-ledger.js +23 -0
- package/dist/scope-copy-ledger.js.map +1 -1
- package/dist/scope-copy.d.ts.map +1 -1
- package/dist/scope-copy.js +3 -2
- package/dist/scope-copy.js.map +1 -1
- package/dist/scope-host.d.ts +303 -11
- package/dist/scope-host.d.ts.map +1 -1
- package/dist/scope-host.js.map +1 -1
- package/dist/scope-identity.d.ts +68 -0
- package/dist/scope-identity.d.ts.map +1 -0
- package/dist/scope-identity.js +75 -0
- package/dist/scope-identity.js.map +1 -0
- package/dist/scope-store.d.ts +9 -6
- package/dist/scope-store.d.ts.map +1 -1
- package/dist/scope-store.js.map +1 -1
- package/dist/spine-restore.d.ts +2 -0
- package/dist/spine-restore.d.ts.map +1 -1
- package/dist/spine-restore.js +6 -1
- package/dist/spine-restore.js.map +1 -1
- package/dist/store-driver-releases.d.ts +306 -0
- package/dist/store-driver-releases.d.ts.map +1 -0
- package/dist/store-driver-releases.js +581 -0
- package/dist/store-driver-releases.js.map +1 -0
- package/dist/table-ownership.d.ts +5 -2
- package/dist/table-ownership.d.ts.map +1 -1
- package/dist/table-ownership.js +19 -10
- package/dist/table-ownership.js.map +1 -1
- package/dist/testing.d.ts +2 -0
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +2 -0
- package/dist/testing.js.map +1 -1
- package/dist/upload-link.d.ts +142 -0
- package/dist/upload-link.d.ts.map +1 -0
- package/dist/upload-link.js +441 -0
- package/dist/upload-link.js.map +1 -0
- package/dist/version-migrations.d.ts +63 -1
- package/dist/version-migrations.d.ts.map +1 -1
- package/dist/version-migrations.js +174 -8
- package/dist/version-migrations.js.map +1 -1
- package/dist/vertical-scope-stores.d.ts +43 -0
- package/dist/vertical-scope-stores.d.ts.map +1 -0
- package/dist/vertical-scope-stores.js +195 -0
- package/dist/vertical-scope-stores.js.map +1 -0
- package/package.json +2 -2
package/dist/scope-host.d.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
+
import type { OrphanSweepReport, OrphanSweepRequest } from './attachment-sweep.js';
|
|
1
2
|
import type { ScopeStoreStubOptions, StoreErasureReplay, StoreStub } from './scope-store.js';
|
|
2
3
|
import type { ModuleLog } from './module-log.js';
|
|
3
4
|
import type { BoundOperations } from './module-operations.js';
|
|
4
5
|
import type { DeliveryRefusal } from './delivery-refusal.js';
|
|
5
6
|
import type { ScopeRoleHolder } from './scope-role-admin.js';
|
|
6
|
-
import type { ScopeCopyBackfillResult } from './scope-copy-ledger.js';
|
|
7
|
+
import type { ScopeCopyBackfillResult, SubjectErasureFence } from './scope-copy-ledger.js';
|
|
8
|
+
import type { VerticalScopeStore } from './vertical-scope-stores.js';
|
|
9
|
+
import type { StoreDriverHoldMode, StoreDriverRebuildFailure, StoreDriverRebuildRecord, StoreDriverReleaseRecord, StoreDriverRolloutAction, StoreDriverRolloutRecord, StoreDriverRolloutState, StoreDriverRolloutTarget, StoreDriverState } from './store-driver-releases.js';
|
|
7
10
|
import type { SubjectRedactionCounts } from './subject-redaction.js';
|
|
8
|
-
import type { OnBehalfOf, ExportReadInput, ExportedBatch, ImportBatch, ImportedEvent, ImportResult, ImportState, ImportCursorMove, ImportCursorMoved, AdminAction, BecomeCapabilityInput, CapabilityExchange, CapabilityFilter, CapabilityId, CapabilityPage, MintedCapability, ListPage, ConnectLink, ConnectLinkConsume, ConnectLinkFilter, ConnectLinkKey, ConsumeConnectLinkInput, MintConnectLinkInput, Connection, ConnectionFilter, ConnectionId, ConnectionGrant, ConnectionGrantRecord, ConnectionSecret, CreateConnectionInput, OpenConnection, ProjectedConnectionGrant, ProjectedConnectionKey, AccessLogEntry, DelegatedReadRecord, OwnerTransferAudit, MemberChangeAudit, PeerBindingAudit, CopyMarkAudit, BindHostnameInput, AdminLogEntry, OpsFailureEntry, PlatformRequestDrainTotalsEntry, SweepRunEntry, SweepRunKind, SweepRunOutcome, ModelUsageEntry, ModelUsageSummary, CapabilityGrant, CreateTenantInput, Decision, Instant, DomainEvent, DomainEventInput, PlatformRequestInput, PlatformRequestId, PlatformRequestEntry, PlatformRequestFilter, PlatformRequestStatus, PlatformRequestFailure, PlatformOutcomeEvent, EntitlementGrant, EntitlementGrantInput, EntitlementView, MeterReading, ScopeStorageSample, EntityRef, IdentityLink, IdentityPool, Jurisdiction, ModuleId, ModuleManifest, ScheduleSpec, SystemGrant, PeerGrantsStatusEntry, SystemGrantsStatusEntry, SystemSwitchRecord, SystemSwitch, SystemSwitchResult, PeerCoverage, PeerSwitch, PeerSwitchResult, VerticalCaller, VerticalResolution, PeerBinding, PeerInstanceResolution, CreateOrgInput, Node, Org, OrgId, OrgMembership, PermissionKey, PlatformActorId, ChannelName, ExportBreak, ChannelHistoryEntry, DnsRecord, HostnameBinding, HostnameStatus, PromotionAcknowledgement, BindAcknowledgement, PublishVersionInput, RegisterVerticalInput, VerticalServingState, RouteTarget, DirectoryDump, IdentityMembership, PrincipalId, ResolvedIdentity, RoleAssignment, RoleDefinition, QueryScopeInput, ReadScopeTableInput, Scope, ScopeDump, ScopeDumpInput, SubjectShredReceipt, ScopeQueryResult, ScopeId, ScopeStatus, ScopeTable, DenialFilter, DenialSummary, RefusalFilter, RefusalRecord, PermissionDenial, Coverage, BeginImpersonationInput, ImpersonationFilter, ImpersonationSession, ImpersonationSessionId, ScopeTablePage, StorageShape, Tenant, TenantId, TenantRole, TenantStoreHandle, AttachmentRecord, BlobStoreHandle, Visibility, Vertical, VerticalChannel, VerticalVersion, TenantStatus, Page, CountedPage, FreshnessSpec, EntityHistoryInput, EventFacetInput, EventCauseInput, EventEffectsInput, EffectsTree, InvocationEventsInput, InvocationEvents, DeadLettersInput, DeadLetter, LifecycleFlowInput, LifecycleFlowResult, OperationSeriesInput, OperationSeriesResult, CauseChain, EventFacetResult, HistoryEntry, ErrorCode, PlatformRequestFailureOrigin, IssueEntry, IssueStatus, IssueStatusInput, FindingEntry, FindingFilter, FindingRuleEntry, FindingRuleInput, FindingStatusInput, DeclaredMigration, CheckSubject, EntityGrantShape } from '@substrat-run/contracts';
|
|
11
|
+
import type { OnBehalfOf, ExportReadInput, ExportedBatch, ImportBatch, ImportedEvent, ImportResult, ImportState, ImportCursorMove, ImportCursorMoved, AdminAction, BecomeCapabilityInput, CapabilityExchange, CapabilityFilter, CapabilityId, CapabilityPage, MintedCapability, ListPage, ConnectLink, ConnectLinkConsume, ConnectLinkFilter, ConnectLinkKey, ConsumeConnectLinkInput, MintConnectLinkInput, Connection, ConnectionFilter, ConnectionId, ConnectionGrant, ConnectionGrantRecord, ConnectionSecret, CreateConnectionInput, OpenConnection, ProjectedConnectionGrant, ProjectedConnectionKey, AccessLogEntry, DelegatedReadRecord, OwnerTransferAudit, MemberChangeAudit, PeerBindingAudit, ConnectionBindingAudit, CopyMarkAudit, OrphanSweepAudit, BindHostnameInput, AdminLogEntry, OpsFailureEntry, PlatformRequestDrainTotalsEntry, SweepRunEntry, SweepRunKind, SweepRunOutcome, ModelUsageEntry, ModelUsageSummary, CapabilityGrant, CreateTenantInput, Decision, Instant, DomainEvent, DomainEventInput, PlatformRequestInput, PlatformRequestId, PlatformRequestEntry, PlatformRequestFilter, PlatformRequestStatus, PlatformRequestFailure, PlatformOutcomeEvent, EntitlementGrant, EntitlementGrantInput, EntitlementView, MeterReading, ScopeStorageSample, EntityRef, IdentityLink, IdentityPool, Jurisdiction, ModuleId, ModuleManifest, ScheduleSpec, SystemGrant, PeerGrantsStatusEntry, SystemGrantsStatusEntry, SystemSwitchRecord, SystemSwitch, SystemSwitchResult, PeerCoverage, PeerSwitch, PeerSwitchResult, VerticalCaller, VerticalResolution, PeerBinding, PeerInstanceResolution, CreateOrgInput, Node, Org, OrgId, OrgMembership, PermissionKey, PlatformActorId, ChannelName, ExportBreak, ChannelHistoryEntry, DnsRecord, HostnameBinding, HostnameStatus, PromotionAcknowledgement, BindAcknowledgement, PublishVersionInput, RegisterVerticalInput, VerticalServingState, RouteTarget, DirectoryDump, IdentityMembership, PrincipalId, ResolvedIdentity, RoleAssignment, RoleDefinition, QueryScopeInput, ReadScopeTableInput, Scope, ScopeDump, ScopeDumpInput, SubjectShredReceipt, ScopeQueryResult, ScopeId, ScopeStatus, ScopeTable, DenialFilter, DenialSummary, RefusalFilter, RefusalRecord, PermissionDenial, Coverage, BeginImpersonationInput, ImpersonationFilter, ImpersonationSession, ImpersonationSessionId, ScopeTablePage, StorageShape, Tenant, TenantId, TenantRole, TenantStoreHandle, AttachmentRecord, UploadLinkView, BlobStoreHandle, Visibility, Vertical, VerticalChannel, VerticalVersion, TenantStatus, Page, CountedPage, FreshnessSpec, EntityHistoryInput, EventFacetInput, EventCauseInput, EventEffectsInput, EffectsTree, InvocationEventsInput, InvocationEvents, DeadLettersInput, DeadLetter, LifecycleFlowInput, LifecycleFlowResult, OperationSeriesInput, OperationSeriesResult, CauseChain, EventFacetResult, HistoryEntry, ErrorCode, PlatformRequestFailureOrigin, IssueEntry, IssueStatus, IssueStatusInput, FindingEntry, FindingFilter, FindingRuleEntry, FindingRuleInput, FindingStatusInput, DeclaredMigration, CheckSubject, EntityGrantShape } from '@substrat-run/contracts';
|
|
9
12
|
import type { ConnectionUseOutcome } from './connector-calls.js';
|
|
10
13
|
import type { CapabilityVerbs } from './capability.js';
|
|
14
|
+
import type { AttachmentVerbs } from './upload-link.js';
|
|
11
15
|
import type { AuditedOperationRef, AuditedOperationRow } from './audit-outcome.js';
|
|
12
16
|
import { type EntityStateName } from '@substrat-run/contracts';
|
|
13
17
|
import type { ModelUsageFilter, ModelUsageInput, ModelUsageWindow } from './model-usage.js';
|
|
@@ -577,6 +581,14 @@ export interface OperationContext {
|
|
|
577
581
|
* like `ctx.grant`.
|
|
578
582
|
*/
|
|
579
583
|
readonly capabilities: CapabilityVerbs;
|
|
584
|
+
/**
|
|
585
|
+
* Attachment verbs an operation may use — today, minting a single-use URL through which a
|
|
586
|
+
* caller with no session uploads ONE file to an entity (`mintUploadUrl`). The bytes
|
|
587
|
+
* themselves never ride an operation: they go to the redemption route, which writes them
|
|
588
|
+
* through `ScopeHost.attachments`' own upload as the principal who minted the link.
|
|
589
|
+
* See {@link AttachmentVerbs}.
|
|
590
|
+
*/
|
|
591
|
+
readonly attachments: AttachmentVerbs;
|
|
580
592
|
/**
|
|
581
593
|
* Run `fn` as a SUB-TRANSACTION of this operation (#770,
|
|
582
594
|
* docs/architecture/sub-transactions.md) — the boundary that makes catching an
|
|
@@ -800,6 +812,23 @@ export interface SqlMigration {
|
|
|
800
812
|
/** Ordered, unique per module, e.g. '0001-init'. Journaled per (module, version). */
|
|
801
813
|
version: string;
|
|
802
814
|
sql: string;
|
|
815
|
+
/**
|
|
816
|
+
* Data this migration MOVES, verified (#115): `{ source: target }`, both `table` or both
|
|
817
|
+
* `table.column`. The kernel refuses a migration that loses rows or values a scope holds
|
|
818
|
+
* (`migration-fence.ts`); a move excuses the source's loss only when the target gained at least
|
|
819
|
+
* what the source held, and a table moved whole only when each of its columns that held values
|
|
820
|
+
* arrives under the same name or is declared by name. Reviewed in the migration diff beside the SQL, and not part of the
|
|
821
|
+
* SQL's digest. The planner never writes it: a generated migration loses nothing.
|
|
822
|
+
*/
|
|
823
|
+
moves?: Readonly<Record<string, string>>;
|
|
824
|
+
/**
|
|
825
|
+
* Data this migration deliberately LOSES (#115): `{ target: why }`, where target is `table`
|
|
826
|
+
* (its rows, or the table itself) or `table.column` (its values, or their storage class — a
|
|
827
|
+
* deliberate retype, a widening included, is declared here). The
|
|
828
|
+
* reason is required and is what a reviewer reads. Anything lost and not declared here or in
|
|
829
|
+
* `moves` refuses the migration in a scope that holds it.
|
|
830
|
+
*/
|
|
831
|
+
discards?: Readonly<Record<string, string>>;
|
|
803
832
|
}
|
|
804
833
|
/**
|
|
805
834
|
* The deployed migration frontier — what "up to date" means for THIS host build
|
|
@@ -2058,6 +2087,9 @@ export interface HostAdmin {
|
|
|
2058
2087
|
* permission diffs are the admission gates, and binding a scope is a separate step
|
|
2059
2088
|
* (`bindScopeVersion`), so the two human checkpoints fire where the blast radius is
|
|
2060
2089
|
* rather than where the typing was.
|
|
2090
|
+
*
|
|
2091
|
+
* Refuses (`conflict`) a version that declares a scope-store binding the vertical already
|
|
2092
|
+
* declared as another driver (#2286): see `verticalScopeStores`.
|
|
2061
2093
|
*/
|
|
2062
2094
|
publishVersion(actor: PlatformActorId, input: PublishVersionInput): Promise<void>;
|
|
2063
2095
|
/** Ordered by id (ULID = publish order), `asc` unless `page.order` says otherwise. */
|
|
@@ -2203,6 +2235,16 @@ export interface HostAdmin {
|
|
|
2203
2235
|
* (`bindExportBreaksOf`), asked of one install. Judged on what the scope RUNS before and
|
|
2204
2236
|
* after, so re-pointing a scope that runs its vertical's serving script, a fork, a preview,
|
|
2205
2237
|
* or a first bind is never refused. `bindingImpact` is the listing.
|
|
2238
|
+
*
|
|
2239
|
+
* **#2347: a rebind across lineages moves the route and the pointer in ONE write.**
|
|
2240
|
+
* `opts.servingRef` routes the scope onto that serving script in the same write as the bind
|
|
2241
|
+
* (judged for what the scope runs there, as `bindingImpact` with `servingRef` is), and
|
|
2242
|
+
* `opts.expectedServing` makes that write conditional on the target lineage's serving script
|
|
2243
|
+
* still running the version the rebind was judged against. Two writes would leave a window
|
|
2244
|
+
* where a promote on the target lands between them: the route on the new script, the pointer
|
|
2245
|
+
* on the old lineage. When `expectedServing` is given, losing either compare-and-set (it, or
|
|
2246
|
+
* `expectedVersionId`) is refused as `rebind_review_stale`. Both options are additive: a
|
|
2247
|
+
* caller that sends neither binds exactly as before.
|
|
2206
2248
|
*/
|
|
2207
2249
|
bindScopeVersion(actor: PlatformActorId, tenantId: TenantId, scopeId: ScopeId, versionId: string, opts?: {
|
|
2208
2250
|
snapshot?: boolean;
|
|
@@ -2211,6 +2253,14 @@ export interface HostAdmin {
|
|
|
2211
2253
|
expectedErasureEpoch?: number;
|
|
2212
2254
|
/** #1722: the copy move this bind routes the scope onto, confirmed in the same write. */
|
|
2213
2255
|
confirmMove?: ScopeCopyMoveConfirmation;
|
|
2256
|
+
/** #2347: the serving script the scope routes to from this same write. */
|
|
2257
|
+
servingRef?: string;
|
|
2258
|
+
/** #2347: what the target lineage's serving script must still run for the write to land. */
|
|
2259
|
+
expectedServing?: {
|
|
2260
|
+
vertical: string;
|
|
2261
|
+
ref: string;
|
|
2262
|
+
versionId: string;
|
|
2263
|
+
};
|
|
2214
2264
|
}): Promise<void>;
|
|
2215
2265
|
/**
|
|
2216
2266
|
* Which apps in the scope's tenant binding `versionId` would break (#1756): the answer
|
|
@@ -2269,13 +2319,24 @@ export interface HostAdmin {
|
|
|
2269
2319
|
* version can be bound per-version but never served in place.
|
|
2270
2320
|
*/
|
|
2271
2321
|
versionManifest(actor: PlatformActorId, verticalSlug: string, versionId: string): Promise<string | null>;
|
|
2322
|
+
/**
|
|
2323
|
+
* Every scope-store binding any version of the vertical has declared, with its driver (#2286,
|
|
2324
|
+
* RFC scope-stores L17): what export, wipe, erasure and the meter reach, so an object under a
|
|
2325
|
+
* binding a later version dropped is still reached. Read by its keys, with no per-version work
|
|
2326
|
+
* once the vertical is indexed. A binding keeps its driver for the life of the vertical:
|
|
2327
|
+
* `publishVersion` refuses a version that moves one to another driver, or declares one twice (`conflict`).
|
|
2328
|
+
* Refuses (`unavailable`) when a version's manifest cannot be read, since that version may
|
|
2329
|
+
* declare a store nobody can name. Empty for an unknown vertical.
|
|
2330
|
+
*/
|
|
2331
|
+
verticalScopeStores(actor: PlatformActorId, verticalSlug: string): Promise<VerticalScopeStore[]>;
|
|
2272
2332
|
/**
|
|
2273
2333
|
* One version's SQL migrations (#1764), in the order the host runs them. They are stored
|
|
2274
2334
|
* apart from the manifest, which `versionManifest` returns without them. Null for a version
|
|
2275
2335
|
* that carries none that can be shown (pushed before #1677, or over the push's caps), which
|
|
2276
2336
|
* a reader must show as "not available", never as "no migrations". `[]` is a version whose
|
|
2277
2337
|
* modules ship none. Refuses a version of another vertical, like `versionManifest`.
|
|
2278
|
-
* Access-logged
|
|
2338
|
+
* Access-logged. Read by the promote review, and by every serving upload, which injects the
|
|
2339
|
+
* digest of the served version's migrations (#2349) — one read per upload, never a scan.
|
|
2279
2340
|
*/
|
|
2280
2341
|
versionMigrations(actor: PlatformActorId, verticalSlug: string, versionId: string): Promise<DeclaredMigration[] | null>;
|
|
2281
2342
|
/**
|
|
@@ -2461,8 +2522,15 @@ export interface HostAdmin {
|
|
|
2461
2522
|
* the append-only admin log (K-21 protects tuples, not the route table).
|
|
2462
2523
|
* Idempotent: unbinding an unknown hostname is a silent no-op, not an error —
|
|
2463
2524
|
* so a cleanup pass can re-run over a partial failure.
|
|
2525
|
+
*
|
|
2526
|
+
* `owner` (#2285): remove the binding only while it still names this tenant and scope,
|
|
2527
|
+
* decided by the delete itself. A name rebound to another scope since the caller listed it
|
|
2528
|
+
* is left bound to that scope, and the call is a silent no-op, as for an unknown name.
|
|
2464
2529
|
*/
|
|
2465
|
-
unbindHostname(actor: PlatformActorId, hostname: string
|
|
2530
|
+
unbindHostname(actor: PlatformActorId, hostname: string, owner?: {
|
|
2531
|
+
tenantId: TenantId;
|
|
2532
|
+
scopeId: ScopeId;
|
|
2533
|
+
}): Promise<void>;
|
|
2466
2534
|
/**
|
|
2467
2535
|
* Ordered by hostname; the cursor is a hostname.
|
|
2468
2536
|
*
|
|
@@ -2587,6 +2655,154 @@ export interface HostAdmin {
|
|
|
2587
2655
|
tenantId?: TenantId;
|
|
2588
2656
|
vertical?: string;
|
|
2589
2657
|
}): Promise<BlobStoreRecord[]>;
|
|
2658
|
+
/**
|
|
2659
|
+
* Record that a store driver's release bytes are stored, keyed by their sha256 (D-63, #2300).
|
|
2660
|
+
* Insert-only: the same sha256 again answers the row as it stands, and from another source
|
|
2661
|
+
* commit is refused (`conflict`). Audited `uploadStoreDriverRelease` when it writes.
|
|
2662
|
+
*/
|
|
2663
|
+
recordStoreDriverRelease(actor: PlatformActorId, input: {
|
|
2664
|
+
driver: string;
|
|
2665
|
+
sha256: string;
|
|
2666
|
+
sourceCommit: string;
|
|
2667
|
+
}): Promise<StoreDriverReleaseRecord>;
|
|
2668
|
+
/** One stored release, or undefined. */
|
|
2669
|
+
getStoreDriverRelease(actor: PlatformActorId, driver: string, sha256: string): Promise<StoreDriverReleaseRecord | undefined>;
|
|
2670
|
+
/**
|
|
2671
|
+
* A driver's current good release, every rollout of it, oldest first, and where a rollback goes.
|
|
2672
|
+
* A `rolling` row whose holder holds the driver no longer reads as `diverged`.
|
|
2673
|
+
*/
|
|
2674
|
+
storeDriverState(actor: PlatformActorId, driver: string): Promise<StoreDriverState>;
|
|
2675
|
+
/**
|
|
2676
|
+
* Every vertical any version of which declared a store of `driver`, with those bindings: the
|
|
2677
|
+
* scripts a rollout reaches, and in `unreadable` every vertical that cannot say (a manifest that
|
|
2678
|
+
* does not parse, or versions from before the record that moved a binding to another driver): the caller that
|
|
2679
|
+
* must reach every script refuses while it is not empty.
|
|
2680
|
+
*/
|
|
2681
|
+
storeDriverDeclarations(actor: PlatformActorId, driver: string): Promise<{
|
|
2682
|
+
verticals: {
|
|
2683
|
+
vertical: string;
|
|
2684
|
+
stores: VerticalScopeStore[];
|
|
2685
|
+
}[];
|
|
2686
|
+
unreadable: string[];
|
|
2687
|
+
}>;
|
|
2688
|
+
/**
|
|
2689
|
+
* What the next request of a rollout of `sha256` (or a rollback to it) walks (#2312): the first
|
|
2690
|
+
* `limit` verticals, in (vertical, binding) order, holding a declaration of the driver the attempt
|
|
2691
|
+
* it would continue has not walked yet; `pending` counts them all and `walked` the verticals that
|
|
2692
|
+
* attempt walked. A request that continues no attempt (the rows before it are not `paused` at the
|
|
2693
|
+
* same release and action) walks every declaration. `unreadable` as `storeDriverDeclarations`.
|
|
2694
|
+
*/
|
|
2695
|
+
storeDriverRolloutPending(actor: PlatformActorId, input: {
|
|
2696
|
+
driver: string;
|
|
2697
|
+
sha256: string;
|
|
2698
|
+
action: StoreDriverRolloutAction;
|
|
2699
|
+
limit: number;
|
|
2700
|
+
}): Promise<{
|
|
2701
|
+
verticals: StoreDriverRolloutTarget[];
|
|
2702
|
+
pending: number;
|
|
2703
|
+
walked: number;
|
|
2704
|
+
unreadable: string[];
|
|
2705
|
+
}>;
|
|
2706
|
+
/**
|
|
2707
|
+
* What the attempt of the rollout at `seq` walked in its earlier requests, in (vertical, binding)
|
|
2708
|
+
* order, at most `limit` (#2312): what a failure part way returns besides its own request's.
|
|
2709
|
+
*/
|
|
2710
|
+
storeDriverRolloutWalked(actor: PlatformActorId, input: {
|
|
2711
|
+
driver: string;
|
|
2712
|
+
seq: number;
|
|
2713
|
+
limit: number;
|
|
2714
|
+
}): Promise<{
|
|
2715
|
+
verticals: StoreDriverRolloutTarget[];
|
|
2716
|
+
walked: number;
|
|
2717
|
+
}>;
|
|
2718
|
+
/**
|
|
2719
|
+
* Take or renew a lease on a driver (#2300): `exclusive` for a rollout or rollback, `shared` for
|
|
2720
|
+
* a push or serve rebuilding a script. False when a live hold of another holder excludes it.
|
|
2721
|
+
* `renew` extends only a hold the holder still holds (a lapsed one answers false, never a fresh
|
|
2722
|
+
* hold), and `rolloutSeq` also needs that rollout to be `rolling` still.
|
|
2723
|
+
*/
|
|
2724
|
+
holdStoreDriver(actor: PlatformActorId, input: {
|
|
2725
|
+
driver: string;
|
|
2726
|
+
holder: string;
|
|
2727
|
+
mode: StoreDriverHoldMode;
|
|
2728
|
+
ttlMs: number;
|
|
2729
|
+
renew?: boolean;
|
|
2730
|
+
rolloutSeq?: number;
|
|
2731
|
+
}): Promise<boolean>;
|
|
2732
|
+
releaseStoreDriverHold(actor: PlatformActorId, input: {
|
|
2733
|
+
driver: string;
|
|
2734
|
+
holder: string;
|
|
2735
|
+
}): Promise<void>;
|
|
2736
|
+
/**
|
|
2737
|
+
* Begin a rollout (or a rollback) of a stored release, as the driver's exclusive holder; refused
|
|
2738
|
+
* (`conflict`) otherwise. A rollback must name `storeDriverState`'s `rollbackTarget`. Audited
|
|
2739
|
+
* under `rollOutStoreDriver` / `rollBackStoreDriver`.
|
|
2740
|
+
*/
|
|
2741
|
+
beginStoreDriverRollout(actor: PlatformActorId, input: {
|
|
2742
|
+
driver: string;
|
|
2743
|
+
sha256: string;
|
|
2744
|
+
action: StoreDriverRolloutAction;
|
|
2745
|
+
holder: string;
|
|
2746
|
+
}): Promise<StoreDriverRolloutRecord>;
|
|
2747
|
+
/**
|
|
2748
|
+
* End a rollout as its exclusive holder; a `good` end makes its release current. Audited as its
|
|
2749
|
+
* begin. A `paused` end records `walked`, what its request walked, in the attempt's ledger, in
|
|
2750
|
+
* the same transaction (#2312); any other end drops the ledger, and `walked` with it is refused.
|
|
2751
|
+
*/
|
|
2752
|
+
finishStoreDriverRollout(actor: PlatformActorId, input: {
|
|
2753
|
+
driver: string;
|
|
2754
|
+
seq: number;
|
|
2755
|
+
holder: string;
|
|
2756
|
+
state: Exclude<StoreDriverRolloutState, 'rolling'>;
|
|
2757
|
+
detail: string | null;
|
|
2758
|
+
walked?: readonly StoreDriverRolloutTarget[];
|
|
2759
|
+
}): Promise<StoreDriverRolloutRecord>;
|
|
2760
|
+
/** The platform's rebuild of every script of a driver (#2309), or undefined before its first. */
|
|
2761
|
+
storeDriverRebuild(actor: PlatformActorId, driver: string): Promise<StoreDriverRebuildRecord | undefined>;
|
|
2762
|
+
/**
|
|
2763
|
+
* Take the lease on a driver's fleet rebuild towards `fingerprint` (#2309): the rebuild as it
|
|
2764
|
+
* stands, started over when it was towards another fingerprint (or, with `restart`, when it is
|
|
2765
|
+
* done; with `attestedBy`, always, carrying that attestation), or null while another holder's
|
|
2766
|
+
* lease is live.
|
|
2767
|
+
*/
|
|
2768
|
+
claimStoreDriverRebuild(actor: PlatformActorId, input: {
|
|
2769
|
+
driver: string;
|
|
2770
|
+
fingerprint: string;
|
|
2771
|
+
holder: string;
|
|
2772
|
+
ttlMs: number;
|
|
2773
|
+
restart?: boolean;
|
|
2774
|
+
attestedBy?: string;
|
|
2775
|
+
}): Promise<StoreDriverRebuildRecord | null>;
|
|
2776
|
+
/**
|
|
2777
|
+
* Record the lease holder's progress and renew its lease (or drop it with `release`); refused
|
|
2778
|
+
* (`conflict`) once another pass claimed the row or it was restarted at another fingerprint.
|
|
2779
|
+
*/
|
|
2780
|
+
advanceStoreDriverRebuild(actor: PlatformActorId, input: {
|
|
2781
|
+
driver: string;
|
|
2782
|
+
fingerprint: string;
|
|
2783
|
+
holder: string;
|
|
2784
|
+
cursor: string | null;
|
|
2785
|
+
failures: readonly StoreDriverRebuildFailure[];
|
|
2786
|
+
done: boolean;
|
|
2787
|
+
/** With `done`: the walk proved every script current. */
|
|
2788
|
+
verified?: boolean;
|
|
2789
|
+
ttlMs: number;
|
|
2790
|
+
release?: boolean;
|
|
2791
|
+
}): Promise<StoreDriverRebuildRecord>;
|
|
2792
|
+
/**
|
|
2793
|
+
* Audit a staff-run pass of a driver's fleet rebuild (#2309) as `rebuildStoreDriver`: the driver,
|
|
2794
|
+
* how the pass ended and what it walked, and `deployFinished` when the person attested that no
|
|
2795
|
+
* control-plane deploy was rolling out. The scheduled pass writes no admin row; its failures are
|
|
2796
|
+
* ops-failure rows.
|
|
2797
|
+
*/
|
|
2798
|
+
recordStoreDriverRebuildRun(actor: PlatformActorId, entry: {
|
|
2799
|
+
driver: string;
|
|
2800
|
+
outcome: string;
|
|
2801
|
+
walked: readonly string[];
|
|
2802
|
+
uploaded: readonly string[];
|
|
2803
|
+
error?: string;
|
|
2804
|
+
deployFinished?: true;
|
|
2805
|
+
}): Promise<void>;
|
|
2590
2806
|
/**
|
|
2591
2807
|
* One scope's directory record. Cross-checks the (tenantId, scopeId) pair and
|
|
2592
2808
|
* returns undefined on a mismatch rather than another tenant's scope (K-3) —
|
|
@@ -3019,8 +3235,13 @@ export interface HostAdmin {
|
|
|
3019
3235
|
* A scope store is reached, by `substrat.erase`, after the scope-side redaction and
|
|
3020
3236
|
* before the key is destroyed. A store that answers with an error throws, and the key
|
|
3021
3237
|
* stays, so a retry converges. The receipt's `storeErasures` names each binding.
|
|
3238
|
+
*
|
|
3239
|
+
* `fence` (#2285): the scope state the caller read before it erased the platform's stores. Given,
|
|
3240
|
+
* the shred takes the same claim `finalizeSubjectShred` takes, just before the key goes, and
|
|
3241
|
+
* refuses (`precondition_failed`) with the key kept when the scope moved. Omitted, nothing is
|
|
3242
|
+
* claimed: the caller reached no store outside this host.
|
|
3022
3243
|
*/
|
|
3023
|
-
shredSubject(actor: PlatformActorId, tenantId: TenantId, scopeId: ScopeId, subjectId: string): Promise<SubjectShredReceipt>;
|
|
3244
|
+
shredSubject(actor: PlatformActorId, tenantId: TenantId, scopeId: ScopeId, subjectId: string, fence?: SubjectErasureFence): Promise<SubjectShredReceipt>;
|
|
3024
3245
|
/**
|
|
3025
3246
|
* Subjects whose key row is tombstoned (`shredded_at` set), in subject-id order.
|
|
3026
3247
|
* A page is at most 100. `cursor` is the last id the caller already has.
|
|
@@ -3034,12 +3255,7 @@ export interface HostAdmin {
|
|
|
3034
3255
|
/** Finish an orchestrated erasure only after every script holding a copy has redacted it.
|
|
3035
3256
|
* The copy count fences a move that was recorded after the coordinator listed scripts;
|
|
3036
3257
|
* ledger rows are append-only, so a changed count means that inventory is stale. */
|
|
3037
|
-
finalizeSubjectShred(actor: PlatformActorId, tenantId: TenantId, scopeId: ScopeId, subjectId: string, redactions: readonly SubjectRedactionCounts[], expected:
|
|
3038
|
-
versionId: string | null;
|
|
3039
|
-
servingRef: string | null;
|
|
3040
|
-
epoch: number;
|
|
3041
|
-
copyCount: number;
|
|
3042
|
-
},
|
|
3258
|
+
finalizeSubjectShred(actor: PlatformActorId, tenantId: TenantId, scopeId: ScopeId, subjectId: string, redactions: readonly SubjectRedactionCounts[], expected: SubjectErasureFence,
|
|
3043
3259
|
/**
|
|
3044
3260
|
* What the serving script's stores erased (#2068). The coordinator calls
|
|
3045
3261
|
* `substrat.erase` once — store objects are per vertical, not per script copy —
|
|
@@ -3565,6 +3781,14 @@ export interface HostAdmin {
|
|
|
3565
3781
|
* cannot be written.
|
|
3566
3782
|
*/
|
|
3567
3783
|
recordCopyMark(actor: PlatformActorId, entry: CopyMarkAudit): Promise<void>;
|
|
3784
|
+
/**
|
|
3785
|
+
* Record one pass of the platform's orphan-attachment sweep over one scope (#2314) on the admin
|
|
3786
|
+
* log, as `sweepOrphanAttachments`. The pass runs in the vertical's deployment, so the platform's
|
|
3787
|
+
* sweep writes this after it, when the pass found or deleted an orphan. A dry-run row is also
|
|
3788
|
+
* what licenses a later destructive pass on the scope (`OrphanAttachmentSweepOptions`).
|
|
3789
|
+
* `recordCopyMark`'s shape. Throws when the row cannot be written.
|
|
3790
|
+
*/
|
|
3791
|
+
recordOrphanSweep(actor: PlatformActorId, entry: OrphanSweepAudit): Promise<void>;
|
|
3568
3792
|
/**
|
|
3569
3793
|
* Record one phase of a dashboard member change (#1150) — an invite, a role move or a removal
|
|
3570
3794
|
* on an installed vertical's scope — as `manageScopeMember`. The change runs in the vertical's
|
|
@@ -3574,6 +3798,7 @@ export interface HostAdmin {
|
|
|
3574
3798
|
*/
|
|
3575
3799
|
recordMemberChange(actor: PlatformActorId, entry: MemberChangeAudit): Promise<void>;
|
|
3576
3800
|
/** One intent or outcome of a tenant's peer-instance binding change (#1720). */
|
|
3801
|
+
recordConnectionBindingChange(actor: PlatformActorId, entry: ConnectionBindingAudit): Promise<void>;
|
|
3577
3802
|
recordPeerBindingChange(actor: PlatformActorId, entry: PeerBindingAudit): Promise<void>;
|
|
3578
3803
|
/**
|
|
3579
3804
|
* Close one audited change whose intent has no outcome (#2064): in ONE transaction, read the
|
|
@@ -3863,6 +4088,28 @@ export interface AttachmentUploadInput {
|
|
|
3863
4088
|
visibility: Visibility;
|
|
3864
4089
|
body: Uint8Array;
|
|
3865
4090
|
}
|
|
4091
|
+
/**
|
|
4092
|
+
* Input to `ScopeHost.redeemUploadLink`. No `visibility`: the link carries it, as it carries
|
|
4093
|
+
* the author. `entity` is what the URL named, and must be the link's own.
|
|
4094
|
+
*/
|
|
4095
|
+
export interface UploadLinkRedeemInput {
|
|
4096
|
+
entity: EntityRef;
|
|
4097
|
+
filename: string;
|
|
4098
|
+
contentType: string;
|
|
4099
|
+
body: Uint8Array;
|
|
4100
|
+
/**
|
|
4101
|
+
* #2315: the redeemer's own id for this redemption (the route reads `Idempotency-Key`). The
|
|
4102
|
+
* spend records its hash; a later redemption of the SAME link with the same key, the same
|
|
4103
|
+
* bytes and inside the link's lifetime plus `UPLOAD_LINK_REPLAY_GRACE_SECONDS` gets the stored
|
|
4104
|
+
* record back (`replayed: true`) and writes nothing. Without it, a spent link is 410 forever.
|
|
4105
|
+
*/
|
|
4106
|
+
idempotencyKey?: string;
|
|
4107
|
+
}
|
|
4108
|
+
/** What `ScopeHost.redeemUploadLink` answers: the record, and whether it was stored by an earlier request. */
|
|
4109
|
+
export type RedeemedUploadLink = AttachmentRecord & {
|
|
4110
|
+
/** Present only on a replay (#2315): the file was stored by the request that spent the link, and nothing was written now. */
|
|
4111
|
+
replayed?: true;
|
|
4112
|
+
};
|
|
3866
4113
|
/** An opened attachment: the metadata fact plus the bytes it witnesses. */
|
|
3867
4114
|
export interface OpenedAttachment {
|
|
3868
4115
|
record: AttachmentRecord;
|
|
@@ -4392,6 +4639,51 @@ export interface ScopeHost {
|
|
|
4392
4639
|
* extraction job has no reason to mutate attachment metadata or bytes.
|
|
4393
4640
|
*/
|
|
4394
4641
|
getSystemAttachments(moduleId: ModuleId, tenantId: TenantId, scopeId: ScopeId): Promise<Pick<ScopeAttachments, 'open'>>;
|
|
4642
|
+
/**
|
|
4643
|
+
* Look an upload link up WITHOUT spending it, so the route can refuse an oversize body or a
|
|
4644
|
+
* wrong type before it reads a byte. `not_found` for a secret that names nothing (and for
|
|
4645
|
+
* one that cannot be ours); `not_found` with reason `upload_link_wrong_target` when `target`
|
|
4646
|
+
* is given and the link was minted for another, judged before its state, so a wrong path is
|
|
4647
|
+
* the same 404 for a pending link and a spent one; `conflict` with reason `upload_link_gone`
|
|
4648
|
+
* for one that is used, expired or revoked. The mint is `ctx.attachments.mintUploadUrl`.
|
|
4649
|
+
*
|
|
4650
|
+
* Optional, like `getCapabilityAttachments`: a host that has not wired the link table says so
|
|
4651
|
+
* by leaving it out, and `mountUploadLinkRedeem` refuses to mount over one.
|
|
4652
|
+
*/
|
|
4653
|
+
inspectUploadLink?(tenantId: TenantId, scopeId: ScopeId, secret: string, target?: EntityRef, idempotencyKey?: string): Promise<UploadLinkView>;
|
|
4654
|
+
/**
|
|
4655
|
+
* Redeem an upload link: write the bytes as ONE attachment, AS the principal who minted the
|
|
4656
|
+
* link — the target's `writePermission` is checked as them now, they are the author, and
|
|
4657
|
+
* `attachment.added` is emitted exactly as for any upload. The link is spent in the same
|
|
4658
|
+
* transaction as the attachment row, so a redemption that fails anywhere leaves it unspent;
|
|
4659
|
+
* the size and the type are the LINK's to refuse (`validation_failed`, reasons
|
|
4660
|
+
* `upload_link_too_large` / `upload_link_type_refused`) and a link used by another request
|
|
4661
|
+
* first is `conflict` / `upload_link_gone`. The bytes are written to the blob store before
|
|
4662
|
+
* the row, as an upload's are, and removed again if the row is refused.
|
|
4663
|
+
*
|
|
4664
|
+
* #2315: with `input.idempotencyKey`, a link spent by a redemption that carried the same key
|
|
4665
|
+
* is a REPLAY — `inspectUploadLink` with that key answers the view instead of 410, and this
|
|
4666
|
+
* answers the stored record with `replayed: true` once the body matches it by size and
|
|
4667
|
+
* SHA-256 (`conflict` / `upload_link_replay_mismatch` when it does not). A replay puts no
|
|
4668
|
+
* bytes, writes no row and emits nothing. A retry that races the first request and loses the
|
|
4669
|
+
* spend has its own bytes removed and is answered as a replay too.
|
|
4670
|
+
*/
|
|
4671
|
+
redeemUploadLink?(tenantId: TenantId, scopeId: ScopeId, secret: string, input: UploadLinkRedeemInput): Promise<RedeemedUploadLink>;
|
|
4672
|
+
/**
|
|
4673
|
+
* One orphan-sweep pass over a scope's attachment bytes (#2314): delete the objects under the
|
|
4674
|
+
* scope's attachment prefix that no `_substrat_attachments` row names, once they are older than
|
|
4675
|
+
* the grace period and the scope is clear of its restore fence. The scope tombstones each id
|
|
4676
|
+
* before its object is deleted, and the attachment insert refuses a tombstoned id, so a row
|
|
4677
|
+
* that commits never loses its bytes (`sweepOrphanAttachments`, attachment-sweep.ts).
|
|
4678
|
+
*
|
|
4679
|
+
* Platform-only, and judged by THIS host's copy of the scope: only an active primary of
|
|
4680
|
+
* `tenantId` that this host holds is swept, and anything else refuses (`conflict`), as does a
|
|
4681
|
+
* scope with an unsettled copy in another script. On a host whose scopes live in several
|
|
4682
|
+
* deployments, the caller asks only the deployment serving the scope. The age floor and the
|
|
4683
|
+
* fence are judged against the host's own clock, never the caller's.
|
|
4684
|
+
* Optional: a host that has not wired the sweep leaves it out.
|
|
4685
|
+
*/
|
|
4686
|
+
sweepOrphanAttachments?(tenantId: TenantId, scopeId: ScopeId, request?: OrphanSweepRequest): Promise<OrphanSweepReport>;
|
|
4395
4687
|
/**
|
|
4396
4688
|
* Provision a NEW scope and load a `ScopeDump` into it — the write side of
|
|
4397
4689
|
* `exportScope` and the fork primitive (docs/architecture/preview-and-snapshots.md §3):
|