@volter/world-core 2.0.37 → 3.0.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.
Files changed (205) hide show
  1. package/README.md +4 -5
  2. package/app-route.cjs +12 -6
  3. package/app-route.d.cts +1 -1
  4. package/dist/app-route.cjs +12 -6
  5. package/dist/app-route.d.cts +1 -1
  6. package/dist/generated/pack-facts.json +1410 -3069
  7. package/dist/inject.cjs +64 -9
  8. package/dist/pack-facts.cjs +44 -0
  9. package/dist/src/actions.d.ts +3 -3
  10. package/dist/src/actions.js +22 -16
  11. package/dist/src/ancestry.d.ts +14 -2
  12. package/dist/src/ancestry.js +92 -2
  13. package/dist/src/anthropic-wire.d.ts +39 -0
  14. package/dist/src/anthropic-wire.js +136 -0
  15. package/dist/src/bytes.d.ts +7 -0
  16. package/dist/src/bytes.js +35 -0
  17. package/dist/src/changeset.d.ts +1 -1
  18. package/dist/src/changeset.js +0 -0
  19. package/dist/src/clickhouse/index.d.ts +3 -0
  20. package/dist/src/clickhouse/index.js +6 -0
  21. package/dist/src/clickhouse/sql.d.ts +233 -0
  22. package/dist/src/clickhouse/sql.js +4329 -0
  23. package/dist/src/clickhouse/types.d.ts +18 -0
  24. package/dist/src/clickhouse/types.js +47 -0
  25. package/dist/src/clickhouse/values.d.ts +146 -0
  26. package/dist/src/clickhouse/values.js +858 -0
  27. package/dist/src/client-bundle.js +2 -3
  28. package/dist/src/cors.d.ts +15 -0
  29. package/dist/src/cors.js +31 -0
  30. package/dist/src/derived-core.d.ts +487 -24
  31. package/dist/src/derived-core.js +788 -144
  32. package/dist/src/derived-real.d.ts +13 -0
  33. package/dist/src/derived-real.js +518 -0
  34. package/dist/src/derived.d.ts +35 -1
  35. package/dist/src/derived.js +61 -9
  36. package/dist/src/emit.js +1 -2
  37. package/dist/src/events.d.ts +206 -0
  38. package/dist/src/events.js +341 -0
  39. package/dist/src/executor.d.ts +3 -0
  40. package/dist/src/executor.js +19 -2
  41. package/dist/src/file-response.d.ts +6 -0
  42. package/dist/src/file-response.js +30 -0
  43. package/dist/src/fork.js +3 -2
  44. package/dist/src/git/history.d.ts +7 -0
  45. package/dist/src/git/history.js +24 -0
  46. package/dist/src/git/index.d.ts +1 -0
  47. package/dist/src/git/index.js +1 -0
  48. package/dist/src/git/lfs.d.ts +28 -0
  49. package/dist/src/git/lfs.js +66 -0
  50. package/dist/src/git/objects.js +3 -8
  51. package/dist/src/git/smart-http.d.ts +3 -1
  52. package/dist/src/git/smart-http.js +67 -6
  53. package/dist/src/graphql-wire.d.ts +29 -0
  54. package/dist/src/graphql-wire.js +101 -0
  55. package/dist/src/grpc-wire.d.ts +67 -0
  56. package/dist/src/grpc-wire.js +170 -0
  57. package/dist/src/h2.d.ts +40 -0
  58. package/dist/src/h2.js +656 -0
  59. package/dist/src/head.d.ts +32 -3
  60. package/dist/src/head.js +161 -40
  61. package/dist/src/history.d.ts +1 -1
  62. package/dist/src/history.js +6 -6
  63. package/dist/src/hpack.json +1 -0
  64. package/dist/src/index.d.ts +64 -75
  65. package/dist/src/index.js +58 -101
  66. package/dist/src/log.js +28 -19
  67. package/dist/src/machines.d.ts +50 -0
  68. package/dist/src/machines.js +151 -0
  69. package/dist/src/managed-database.d.ts +86 -0
  70. package/dist/src/managed-database.js +283 -0
  71. package/dist/src/multipart.d.ts +11 -0
  72. package/dist/src/multipart.js +51 -0
  73. package/dist/src/observe.d.ts +15 -5
  74. package/dist/src/observe.js +23 -9
  75. package/dist/src/openai-wire.d.ts +108 -0
  76. package/dist/src/openai-wire.js +337 -0
  77. package/dist/src/pack-assets.d.ts +3 -4
  78. package/dist/src/pack-assets.js +15 -10
  79. package/dist/src/pack-fetch.d.ts +77 -0
  80. package/dist/src/pack-fetch.js +449 -0
  81. package/dist/src/pack-paths.d.ts +12 -0
  82. package/dist/src/pack-paths.js +86 -0
  83. package/dist/src/packRegistry.d.ts +69 -162
  84. package/dist/src/packRegistry.js +55 -20
  85. package/dist/src/people.d.ts +13 -0
  86. package/dist/src/people.js +18 -0
  87. package/dist/src/placeholder-image.d.ts +5 -0
  88. package/dist/src/placeholder-image.js +114 -0
  89. package/dist/src/protobuf.d.ts +28 -0
  90. package/dist/src/protobuf.js +332 -0
  91. package/dist/src/redis/engine.js +1 -1
  92. package/dist/src/request-scope.d.ts +1 -1
  93. package/dist/src/request-scope.js +6 -4
  94. package/dist/src/resource-blob.d.ts +5 -0
  95. package/dist/src/resource-blob.js +11 -0
  96. package/dist/src/runtime.d.ts +85 -0
  97. package/dist/src/runtime.js +104 -0
  98. package/dist/src/s3/wire.d.ts +60 -0
  99. package/dist/src/s3/wire.js +157 -0
  100. package/dist/src/scenario.d.ts +3 -0
  101. package/dist/src/scenario.js +2 -0
  102. package/dist/src/schema-sample.d.ts +1 -0
  103. package/dist/src/schema-sample.js +21 -0
  104. package/dist/src/sealed-box.d.ts +14 -0
  105. package/dist/src/sealed-box.js +225 -0
  106. package/dist/src/serve-http.d.ts +14 -0
  107. package/dist/src/serve-http.js +27 -3
  108. package/dist/src/serve.d.ts +6 -0
  109. package/dist/src/serve.js +69 -14
  110. package/dist/src/signing.d.ts +135 -0
  111. package/dist/src/signing.js +222 -0
  112. package/dist/src/sigv4.d.ts +48 -0
  113. package/dist/src/sigv4.js +167 -0
  114. package/dist/src/smtp.d.ts +16 -0
  115. package/dist/src/smtp.js +72 -0
  116. package/dist/src/sockets.d.ts +51 -0
  117. package/dist/src/sockets.js +90 -0
  118. package/dist/src/state-system.d.ts +1 -0
  119. package/dist/src/state-system.js +1 -1
  120. package/dist/src/storage.d.ts +1 -1
  121. package/dist/src/storage.js +3 -3
  122. package/dist/src/trace-context.js +1 -1
  123. package/dist/src/twin-fetch.d.ts +0 -7
  124. package/dist/src/twin-fetch.js +0 -14
  125. package/dist/src/vendor-call.d.ts +6 -0
  126. package/dist/src/vendor-call.js +41 -0
  127. package/dist/src/world-store.js +1 -1
  128. package/dist/vendor-hosts.cjs +36 -125
  129. package/dist/vendor-hosts.d.cts +8 -0
  130. package/generated/pack-facts.json +1410 -3069
  131. package/inject.cjs +64 -9
  132. package/pack-facts.cjs +44 -0
  133. package/package.json +17 -3
  134. package/src/actions.ts +23 -16
  135. package/src/ancestry.ts +74 -2
  136. package/src/anthropic-wire.ts +137 -0
  137. package/src/bytes.ts +42 -0
  138. package/src/changeset.ts +5 -5
  139. package/src/clickhouse/index.ts +6 -0
  140. package/src/clickhouse/sql.ts +3059 -0
  141. package/src/clickhouse/types.ts +44 -0
  142. package/src/clickhouse/values.ts +697 -0
  143. package/src/client-bundle.ts +2 -3
  144. package/src/cors.ts +34 -0
  145. package/src/derived-core.ts +1013 -146
  146. package/src/derived-real.ts +434 -0
  147. package/src/derived.ts +73 -3
  148. package/src/emit.ts +1 -2
  149. package/src/events.ts +449 -0
  150. package/src/executor.ts +24 -2
  151. package/src/file-response.ts +27 -0
  152. package/src/fork.ts +3 -2
  153. package/src/git/history.ts +19 -0
  154. package/src/git/index.ts +1 -0
  155. package/src/git/lfs.ts +67 -0
  156. package/src/git/objects.ts +3 -5
  157. package/src/git/smart-http.ts +56 -6
  158. package/src/graphql-wire.ts +106 -0
  159. package/src/grpc-wire.ts +159 -0
  160. package/src/h2.ts +627 -0
  161. package/src/head.ts +132 -41
  162. package/src/history.ts +6 -6
  163. package/src/hpack.json +1 -0
  164. package/src/index.ts +82 -329
  165. package/src/log.ts +27 -18
  166. package/src/machines.ts +151 -0
  167. package/src/managed-database.ts +299 -0
  168. package/src/multipart.ts +51 -0
  169. package/src/observe.ts +31 -15
  170. package/src/openai-wire.ts +371 -0
  171. package/src/pack-assets.ts +15 -11
  172. package/src/pack-fetch.ts +458 -0
  173. package/src/pack-paths.ts +72 -0
  174. package/src/packRegistry.ts +79 -167
  175. package/src/people.ts +31 -0
  176. package/src/placeholder-image.ts +88 -0
  177. package/src/protobuf.ts +251 -0
  178. package/src/redis/engine.ts +1 -1
  179. package/src/request-scope.ts +8 -4
  180. package/src/resource-blob.ts +13 -0
  181. package/src/runtime.ts +344 -0
  182. package/src/s3/wire.ts +172 -0
  183. package/src/scenario.ts +4 -0
  184. package/src/schema-sample.ts +24 -0
  185. package/src/sealed-box.ts +182 -0
  186. package/src/serve-http.ts +31 -3
  187. package/src/serve.ts +58 -14
  188. package/src/signing.ts +231 -0
  189. package/src/sigv4.ts +158 -0
  190. package/src/smtp.ts +76 -0
  191. package/src/sockets.ts +140 -0
  192. package/src/state-system.ts +2 -2
  193. package/src/storage.ts +3 -3
  194. package/src/trace-context.ts +1 -1
  195. package/src/twin-fetch.ts +0 -20
  196. package/src/vendor-call.ts +41 -0
  197. package/src/world-store.ts +1 -1
  198. package/vendor-hosts.cjs +36 -125
  199. package/vendor-hosts.d.cts +8 -0
  200. package/dist/src/mirror-shell.d.ts +0 -2
  201. package/dist/src/mirror-shell.js +0 -13
  202. package/dist/src/v1-removed.d.ts +0 -159
  203. package/dist/src/v1-removed.js +0 -124
  204. package/src/mirror-shell.ts +0 -15
  205. package/src/v1-removed.ts +0 -172
package/dist/src/index.js CHANGED
@@ -1,102 +1,59 @@
1
- // @volter/world-core — the shared state kernel and vendor-independent runtime libraries.
2
- // Protocol-2 packs read the checkpointed tree and write through the head's state system.
3
- // The kernel owns logs, branches, landing and receipts; each pack owns its vendor's wire
4
- // and resource semantics. See docs/concepts/the-model.md and docs/contributing/architecture.md.
5
- // Compatibility exports below are not a second state model. Refer to their implementations
6
- // before using older operator helpers; removed v1 entry points fail explicitly.
7
- // Conformance/validation tooling (capability + spec + recorded-diff + UI harnesses and
8
- // the spec derivers) is NOT part of the runtime kernel — it lives in @volter/world-tooling,
9
- // a dev dependency. A twin runs without it; only tests and the conformance scripts use it.
10
- // Pack registry — vendor twins self-describe (TwinPack) so tooling discovers them.
11
- export { clearRegistry, getPack, hasPack, listPacks, registerPack, pullPosture, assertContinuousPullAllowed, pullOnSchedule, resolvePullVendor, DEFAULT_PULL_POSTURE, DEFAULT_PULL_TRIGGER, PROTOCOL_VERSION, PROTOCOL_MAJOR, protocolStanding } from "./packRegistry.js";
12
- // The DELIVER verb (`emit`) — vendor-agnostic engine + CLI glue; packs declare a TwinEmitter
13
- // (their event catalog, endpoints-from-state, and signed synthesis) on `TwinPack.emitter`.
14
- export { parseScenarioDocument, scenarioFaultResult, ScenarioEngine, ScenarioError, statefulTwinManifest, twinManifest } from "./scenario.js";
15
- export { WORLD_CLOCK_ENV, worldNow } from "./world-clock.js";
16
- export { WORLD_ENV_NAMES_ENV, worldEnvValue } from "./world-env.js";
17
- export { createTwinFetchFromHandler, TWIN_PREFIX_HEADER, TWIN_REQUEST_SCOPES, twinPublicBase, withRequestScopes } from "./twin-fetch.js";
18
- export { isReadOnlyRequest, READ_ONLY_REQUEST_HEADER, ReadOnlyRequestError, runAsReadOnlyRequest, runAsVendorMove, writesRefused } from "./request-scope.js";
19
- export { compileSurface, createDerivedFetch, matchOperation } from "./derived.js";
20
- export { currentTraceparent, deliveryTraceHeaders, newTraceparent, parseTraceparent, runWithRequestTrace, runWithTraceparent, TRACEPARENT_HEADER, traceparentForDelivery, validTraceparent } from "./trace-context.js";
21
- export { bindSemantics, coreFor, crossCutting, derivedRequestScopes, observeTransitions, resourcesOfType as twinResourcesOfType, semanticsContext, stateOf, transitionFor, parseBracketForm, readParams, render as renderDerived, serveCore, sse, vendorError } from "./derived-core.js";
22
- export { emitTwinEvent, eventSubscriptionMatches, listEmittable, runEmitCli } from "./emit.js";
23
- // The vendor-agnostic CLIENT-SIDE RATE BUDGET — the fail-closed backstop a pack's guarded client
24
- // routes every live vendor call through. The MECHANISM is here; the per-vendor ceiling/window/
25
- // weights are DATA the pack declares (`TwinPack.rateBudget` / `declareRateBudget`). Exported so an
26
- // operator can inspect spend (`snapshot`) and a caller can catch `RateBudgetError` by type; there
27
- // is deliberately no export that disables the guard, and a vendor with no declaration falls back
28
- // to `DEFAULT_RATE_BUDGET` rather than to no limit at all.
29
- export { DEFAULT_RATE_BUDGET, MAX_RATE_BUDGET_CEILING, MAX_RATE_BUDGET_WINDOW_MS, MIN_RATE_BUDGET_WEIGHT, MIN_RATE_BUDGET_WINDOW_MS, RateBudget, RateBudgetError, declareRateBudget, hasRateBudgetDeclaration, listRateBudgets, priceCall, rateBudgetPath, rateBudgetPolicy, rateBudgetWeight, resetToSeconds, assertBudgetGuardIntact, } from "./rateBudget.js";
30
- export { GenericWorldStateSchema, WorldActorSchema, WorldExternalRefSchema, WorldServiceEventSchema, WorldSubjectSchema, } from "./schemas.js";
31
- // NOTE: source books (event→tracker-source mapping) moved OUT of the world — it was
32
- // the last tracker coupling. It now lives at `@volter/tracker/world-source-books`,
33
- // so `@volter/world-core` is a pure twin runtime.
34
- export { loadWorldConfig, } from "./worldConfig.js";
35
- export { DELTA_TYPE_SUFFIX, diffSubjectFields, hashFieldValue, subjectKey, deltaAfterFields } from "./hash.js";
36
- export { appendDurable, appendEvent, createEvent, emptyGenericState, genericWorldReducer, listEvents, loadState, projectionLockPath, readJsonFile, rebuildGenericState, rebuildState,
37
- // Scrub: delete pulled data at rest (TWIN-45) — the honest, plain-`rm` counterpart to
38
- // sync pull's fold-into-the-log. See docs/concepts/data-and-keys.md for the full data-at-rest story.
39
- scrubService, scrubWorld, stateDirName,
40
- // Opt-in structured stderr logging (VOLTER_TWIN_LOG=1) for the audit trail. Public so a
41
- // CONNECTOR can say on the same stream when the vendor handed it a truncated page — a
42
- // silent shortfall is the one thing a pull must never pass off as the whole resource.
43
- twinLog,
44
- // The kernel's cross-process mutual-exclusion primitive (exclusive-create lockfile with
45
- // stale-holder reclaim). Public so world-runtime can guard concurrent `upWorld` claims of
46
- // one instance dir with the SAME lock semantics the event log uses (TWIN-36).
47
- withFileLock, worldPaths, worldStateRoot,
48
- // Where another pack's store is in a World (architecture A3), and the variable the runtime names its data directory in.
49
- ownerStoreRoots, WORLD_DATA_ENV, } from "./storage.js";
50
- // The pluggable persistence seam: the sync WorldStore interface, its fs (default) and
51
- // in-memory implementations, the active-store injection point, and the async
52
- // hydrate/flush boundary a serverless (Durable Object / KV / redis) entry uses.
53
- export { FsWorldStore, MemoryWorldStore, getActiveWorldStore, setActiveWorldStore, withWorldStore, hydrateInto, flushFrom, } from "./world-store.js";
54
- export { SqlWorldStore } from "./world-store-sql.js";
55
- // The blob seam (runtime contract R11): byte storage behind byte-carrying handlers, so a
56
- // serverless namespace puts bytes in object storage while local worlds keep today's layout.
57
- export { FsBlobStore, MemoryBlobStore, blobDigest, getActiveBlobStore, setActiveBlobStore, withBlobStore, readBlobRange, } from "./blob-store.js";
58
- export { applyTwinWrite, applyTwinWriteAtomic, createTwinServer, CALLER_HEADER, journalTwinRequest, twinRequestJournalFailures, twinRequestCredentials, readTwinRequestJournal, resolveTwinRead, twinRequestJournalEnabled, twinRequestJournalPath, readTwinRequestJournalFrom, twinResources, } from "./serve.js";
59
- export { createTwinProxy } from "./proxy.js";
60
- export { forkTwin, isFork, readForkMeta, } from "./fork.js";
61
- export { appendAction, appendTransactionCommit, checkPrecondition, confirmAction, listActions, listTransactionCommits, pendingActions, pushablePendingActions, isTwinBookkeeping, pendingTransactionCommits, projectResources, projectOwnerResources, OwnerStoreAmbiguousError, revertAction, TwinActionPreconditionError, subjectAliases, resolveSubjectId, runWithCorrelationId, currentCorrelationId } from "./actions.js";
62
- // ── Operator control plane (R19/R20): remote refs, queue lifecycle, push ledger,
63
- // apply leases, plan, status. (the twins architecture notes)
64
- // The CHANGESET primitive + the ledger DIFF (docs/concepts/the-model.md v0) — "commit" and
65
- // "diff" for operational reality: a cross-service base marker, the ledger delta since it, and
66
- // the content-addressed, replayable changeset over that delta. State-level by construction
67
- // (it reads the same per-service action ledgers `actions.ts` writes); `volter-world` supplies
68
- // world discovery and thin verbs on top.
69
- export { approveChangeset, assertMarkerBelongsTo, assertSafeChangesetName, assertValidVerifiers, buildChangeset, captureMarker, changesetContentHash, changesetHashMatches, changesetReadiness, approverOf, CHANGESET_KIND, diffLedgers, formatApplication, formatChangeset, formatRebaseReport, narrateActions, narrationDrift, rebaseChangeset, formatChangesetStatus, formatLedgerDelta, formatReplayReport, formatVerification, MARKER_KIND, normalizeChangeset, parseVerifierExpression, replayChangeset, runChangesetVerifiers, summarizeByVendor, twinWriteShape, withApplication, withVerification, worldBootMarker, WORLD_BOOT_MARKER_ID, } from "./changeset.js";
70
- export { getActivePackAssets, setActivePackAssets, packAsset, assetContentType, confinedAssetPath, LocalPackAssets, BindingPackAssets } from "./pack-assets.js";
71
- // The git plane (contract "The git plane is a kernel library"): objects, packs, refs, smart HTTP.
1
+ // @volter/world-core — the pack contract (docs/contributing/architecture.md, "The pack contract: the kernel's root").
2
+ // This root is everything a Protocol 3 pack may import from the kernel, and nothing else: the manifest's and the
3
+ // descriptor's types, the handler contract, the derived fetch and core a pack's fetch.ts builds, the serve factory's
4
+ // pieces, the kernel's deterministic helpers and the scenario grammar. The kernel itself (the log and the tree read
5
+ // and written directly, the head, the stores, the runtime's scopes) and the plugin contract's surfaces are
6
+ // `@volter/world-core/runtime`, which a pack never imports.
7
+ import { bindSemantics as bindAny } from "./derived-core.js";
8
+ import { packOf as packOfAny, registerPack as registerAny } from "./packRegistry.js";
9
+ /** The descriptor a manifest declares, with its vendor ("The descriptor"); given the pack's generated surface (a vendor of
10
+ * lanes: each lane's manifest and surface), with the real-system adapters the kernel derives from them. */
11
+ export const packOf = (manifest, surface) => packOfAny(manifest, surface);
12
+ /** The pack registered, so the World finds it. */
13
+ export const registerPack = (pack) => registerAny(pack);
14
+ export { verifyEvent } from "./events.js";
15
+ export { deriveStateSystem, deriveVendorStateSystem } from "./derived-real.js";
16
+ export { machinePool } from "./machines.js";
17
+ /** A pack's handlers, by operationId, bound to the manifest: each is answered over the contract's context. */
18
+ export const bindSemantics = (m, handlers, scope = {}) => bindAny(m, handlers, scope);
19
+ // ── the derived fetch ──────────────────────────────────────────────────────────────────────────
20
+ export { createPackFetch, createVendorFetch } from "./pack-fetch.js";
21
+ export { createDerivedFetch } from "./derived.js";
22
+ export { coreFor, crossCutting, derivedRequestScopes, vendorError } from "./derived-core.js";
23
+ export { answerVendorErrors, RefusedWriteError } from "./head.js";
24
+ // a GraphQL API's resolvers (`semantics/graphql.ts`), and the error one answers with the vendor's type
25
+ export { GraphqlError } from "./graphql-wire.js";
26
+ // what `ctx.vendorFetch` throws when the other vendor cannot be reached (a vendor's call to another as its own behaviour)
27
+ export { VendorUnreachableError } from "./vendor-call.js";
28
+ export { isReadOnlyRequest, READ_ONLY_REQUEST_HEADER } from "./request-scope.js";
29
+ // ── the serve factory ──────────────────────────────────────────────────────────────────────────
30
+ export { serveHttp, serveStream } from "./serve-http.js";
31
+ export { statefulTwinManifest, twinManifest } from "./scenario.js";
32
+ export { assetContentType, packAsset } from "./pack-assets.js";
33
+ export { bytesResponse, contentTypeOf, fileResponse } from "./file-response.js";
34
+ // ── the kernel's deterministic helpers ─────────────────────────────────────────────────────────
35
+ export { certificateOf, digest, digestBytes, equalSecrets, oauth1BaseString, oauth1Encode, oauth1Header, oauth1Signature, hmac, jwks, jwtDecode, jwtSign, jwtVerify, keyId, lettersFrom, md5, publicKeyOf, sha256, signWith, SIGNING_ALGORITHMS, uuidFrom, verifyWith } from "./signing.js";
36
+ export { blobDigest } from "./blob-store.js";
37
+ // compressed bytes a wire carries (a SARIF upload), over web streams
38
+ export { gunzip, gzip } from "./bytes.js";
39
+ // a row's own fields, where the tree's reserved ones (id, type, updatedAt) shadow the vendor's of the same name
40
+ export { ownFields } from "./log.js";
41
+ // the people a vendor's pages sign in (a `_person` row with its password's hash)
42
+ export { passwordHash, personOf, personWith, recordPerson } from "./people.js";
43
+ // the World's managed Postgres a handler reaches as `ctx.engine` (managed-database.ts), and a mail's route (`ctx.mail`)
44
+ export { EngineDatabaseError, EngineUnavailableError, quoteIdent, worldClockSql } from "./managed-database.js";
45
+ // S3's wire (contract "S3's wire is a kernel library too") and the git plane (contract "The git plane is a kernel library")
46
+ export * as s3 from "./s3/wire.js";
47
+ export * as clickhouse from "./clickhouse/index.js";
48
+ export { sampleFromSchema } from "./schema-sample.js";
49
+ export * as openaiWire from "./openai-wire.js";
50
+ export * as anthropicWire from "./anthropic-wire.js";
51
+ export * as protobuf from "./protobuf.js";
52
+ export * as grpc from "./grpc-wire.js";
53
+ export { acceptH2Connection } from "./h2.js";
54
+ export { placeholderPng } from "./placeholder-image.js";
55
+ export { presignSigV4, signSigV4, verifySigV4 } from "./sigv4.js";
56
+ export * as redis from "./redis/index.js";
72
57
  export * as git from "./git/index.js";
73
- // The push arm: the kernel's transaction over a pack's one `perform<Name>Action` (contract section of that name).
74
- // The placeholder remote (contract section of that name): the seed is a pull, never a pending write.
75
- export { PLACEHOLDER_REMOTE, beginPlaceholderPull, endPlaceholderPull, placeholderPullActive, placeholderPullMarkerPath, withPlaceholderPull, placeholderEventsFor } from "./placeholder-remote.js";
76
- export { ownFields, subjectHistory, rebaseBranch, cutCheckpoint, appendParentEntry, wholeLog, branchEntries, branchLogPath, branchMetaPath, CHECKPOINT_EVERY, dropCheckpoint, foldEntries, landedCopy, landedIds, parentEntries, parentLogPath, position, readBranchMeta, readTree, toEntry, toEvent, unpushedEntries, writeBranchMeta } from "./log.js";
77
- export { sealCredential, openSealedCredential, MemoryCredentialStorage, keySealer, transitSealer } from "./credential.js";
78
- export { validateRemoteOrigin, buildRemoteExecute } from "./executor.js";
79
- export { clearRoot, authStrategyFor, clearStateSystems, NO_SECRETS_CHECK, readRoot, registerAuthStrategy, registerStateSystem, rootPath, runChecks, stateSystemFor, writeRoot } from "./state-system.js";
80
- export { observeAppends } from "./actions.js";
81
- export { appendActionIfAbsent, appendActionOccurrence } from "./actions.js";
82
- // PROTOCOL 2 — the head and the fold (company contract "The head", "Refresh is the kernel's fold")
83
- export { answerVendorErrors, performEntries, performAtHead, deployableEntries, headOf, boundRoot, loadChecks, loadCheck, openRootCredential, resealRootCredential, destinationOf, openSealedRecord, sealsThroughVault, rootCustody, sealingKey, setCheckLoader, setSealingKeySource, setSealer, currentSealer, openSealedAt, userKek, userKekPath, vendorOf, worldRootOf, RefusedWriteError, VendorWriteError, HeadError } from "./head.js";
84
- export { observeResource, observeResources, collectObservations, foldObservations } from "./observe.js";
85
- export { readTreeMap, readParentTreeMap, treeStamp, treeChangesSince, originEntries, appendOriginEntry, originLogPath, isUrlParent, parentPosition, positionAt, splitsBatch, assertBatchBoundary } from "./log.js";
86
- // v1 left the kernel (contract "Just like Neon", 5): the names a protocol 1 pack still imports throw on
87
- // their first call, so the catalog stays importable and a pack out of date fails loudly.
88
- export * from "./v1-removed.js";
89
- export { referenceField, registerReferences, packReferences, resolveReferences } from "./references.js";
90
- // the HTTP server seam: the one place the serve path meets the runtime (Bun or Node)
91
- export { serveHttp, nodeBuiltin, WORLD_BOOT_PATH } from "./serve-http.js";
92
- // two runtime-neutral helpers for a pack's serve path: a file as a Response, a mirror's client bundle
93
- export { fileResponse, contentTypeOf } from "./file-response.js";
94
- export { bundleClient, filePathOf } from "./client-bundle.js";
95
- // the brand's tokens and faces for a Volter page (the console, the site, the UI kit), fetched at build
96
- export { brandTokensResponse } from "./brand-tokens.js";
97
- export { readResourceBlob, readResourceBlobRange, resourceBlobSize, resourceChain } from "./resource-blob.js";
98
- export { mirrorShellUnder } from "./mirror-shell.js";
99
- export { assertStateRemovable, checkParent, stateGeneration, withAncestryLock, withStateRemoval } from "./ancestry.js";
100
- export { captureHistory, captureParentHistory, historyChanges, historyAtInstant, historyDigest, historyEntries, historyLength, historyPrefix, inheritedHistory, originHead, publishOriginHistory, readHistoryView } from "./history.js";
101
- export { foldHistory } from "./log.js";
102
- export { volterHome } from "./volter-home.js";
58
+ // ── the scenario grammar (architecture, "Behaviour") ───────────────────────────────────────────
59
+ export { parseScenarioDocument, scenarioFaultResult, ScenarioEngine, ScenarioError } from "./scenario.js";
package/dist/src/log.js CHANGED
@@ -20,11 +20,11 @@
20
20
  // and the fold skips a branch entry whose id the parent already holds. Nothing is suppressed,
21
21
  // rebound or quarantined by a bookkeeping row; `unpushed` is the branch log minus what the parent
22
22
  // holds. The parent log accepts the v1 observed-event rows too (`toEntry` reads a delta event as
23
- // an entry; a non-delta observation folds nothing and is kept for `listEvents`), so a protocol 1
24
- // pack's own fold of the logs keeps working while it is deprecated.
23
+ // an entry; a non-delta observation folds nothing and is kept for `listEvents`), so a World whose
24
+ // log was written in that form still reads.
25
25
  import { captureHistory, historyChanges, historyEntryTime, historyEntries, historyLength, historyPrefix, inheritedHistory, inheritedHistoryKey, originHead, readHistoryView, replaceHistoryOrigin, saveHistoryView, validateHistoryOrigin } from "./history.js";
26
26
  import { dirname, join } from 'node:path';
27
- import { canonicalStatePath, checkParent, commitParentPin, pinParent, withAncestryLock } from "./ancestry.js";
27
+ import { canonicalStatePath, checkParent, commitParentPin, pinParent, withAncestryLock, withHistoryLock } from "./ancestry.js";
28
28
  import { resolveReferences } from "./references.js";
29
29
  import { hashFieldValue } from "./hash.js";
30
30
  import { worldPaths } from "./storage.js";
@@ -122,7 +122,9 @@ export function readBranchMeta(service, root) {
122
122
  return meta;
123
123
  }
124
124
  export function writeBranchMeta(service, meta, root) {
125
- withAncestryLock(() => {
125
+ // Under the branch's own history lock (a capture of its parent's nests inside it, child before ancestor); only the
126
+ // pin and the pointer's publication take the coordinator.
127
+ withHistoryLock(worldPaths(service, root).dir, () => {
126
128
  if (meta.parent && (!Number.isInteger(meta.parent.position) || meta.parent.position < 0))
127
129
  throw new Error('Invalid branch position');
128
130
  const path = branchMetaPath(service, root);
@@ -141,6 +143,7 @@ export function writeBranchMeta(service, meta, root) {
141
143
  previousParents.push({ directory: old.parent.directory, generation: old.parent.generation });
142
144
  if (previousParents.length)
143
145
  meta = { ...meta, previousParents: [...new Map(previousParents.map(p => [p.directory, p])).values()] };
146
+ let local;
144
147
  if (meta.parent && !isUrlParent(meta.parent.at)) {
145
148
  const directory = canonicalStatePath(worldPaths(service, meta.parent.at).dir);
146
149
  const view = meta.parent.view ?? captureHistory(service, meta.parent.at).view;
@@ -149,9 +152,8 @@ export function writeBranchMeta(service, meta, root) {
149
152
  throw new Error('Composed history view must belong to this branch');
150
153
  const descriptor = readHistoryView(viewDirectory, view);
151
154
  historyPrefix(descriptor, meta.parent.position);
152
- const parent = meta.parent;
153
- const generation = pinParent(directory, path, parent.generation);
154
- meta = { ...meta, parent: { ...parent, view, at: canonicalStatePath(parent.at), directory, generation } };
155
+ // the parent the view was captured from: a parent removed or re-created since is refused at the pin
156
+ local = { directory, view, generation: meta.parent.generation ?? (viewDirectory === directory ? descriptor.owner.generation : undefined) };
155
157
  }
156
158
  if (meta.parent && isUrlParent(meta.parent.at) && !meta.parent.view) {
157
159
  const head = originHead(service, root);
@@ -164,10 +166,17 @@ export function writeBranchMeta(service, meta, root) {
164
166
  else
165
167
  throw new Error('Origin has no completed immutable history view');
166
168
  }
167
- getActiveWorldStore().mkdir(dirname(path));
168
- getActiveWorldStore().writeAtomic(path, `${JSON.stringify(meta, null, 2)}\n`);
169
- if (meta.parent?.directory && !isUrlParent(meta.parent.at))
170
- commitParentPin(meta.parent.directory, path);
169
+ withAncestryLock(() => {
170
+ if (local && meta.parent) {
171
+ const parent = meta.parent;
172
+ const generation = pinParent(local.directory, path, local.generation);
173
+ meta = { ...meta, parent: { ...parent, view: local.view, at: canonicalStatePath(parent.at), directory: local.directory, generation } };
174
+ }
175
+ getActiveWorldStore().mkdir(dirname(path));
176
+ getActiveWorldStore().writeAtomic(path, `${JSON.stringify(meta, null, 2)}\n`);
177
+ if (meta.parent?.directory && !isUrlParent(meta.parent.at))
178
+ commitParentPin(meta.parent.directory, path);
179
+ });
171
180
  });
172
181
  }
173
182
  /** A v1 observed row as an entry: a delta event folds its `changed.*.after`; anything else folds
@@ -234,7 +243,7 @@ export function appendOriginEntry(entry, root) {
234
243
  const path = originLogPath(entry.service, root);
235
244
  const store = getActiveWorldStore();
236
245
  store.mkdir(dirname(path));
237
- return withAncestryLock(() => store.withLock(`${path}.lock`, () => {
246
+ return withHistoryLock(worldPaths(entry.service, root).dir, () => store.withLock(`${path}.lock`, () => {
238
247
  if (readRows(path).some((r) => r.id === entry.id))
239
248
  return { appended: false };
240
249
  store.append(path, `${JSON.stringify(entry)}\n`);
@@ -386,7 +395,7 @@ export function readTree(service, root, opts = {}) {
386
395
  /** The upstream view for observation diffing, without this root's local overlay. Inherited
387
396
  * history keeps its own layout: an ancestor's local writes are part of our pinned base. */
388
397
  export function readParentTreeMap(service, root) {
389
- return withAncestryLock(() => {
398
+ return withHistoryLock(worldPaths(service, root).dir, () => {
390
399
  const inherited = inheritedHistory(service, root);
391
400
  const own = ownParentEntries(service, root);
392
401
  return foldHistory([...(inherited ? historyEntries(inherited) : []), ...own], {
@@ -459,12 +468,12 @@ function currentTree(service, root) {
459
468
  treeMemos.set(store, memos);
460
469
  }
461
470
  const slot = `${service}\u0000${root ?? ''}`;
462
- // A hit needs no coordinator: a memo is only ever stored from a fold made under it, and while the
471
+ // A hit needs no lock: a memo is only ever stored from a fold made under the history lock, and while the
463
472
  // facts still match that fold, nothing was written since. A writer mid-batch has moved them.
464
473
  const unlocked = memos.get(slot);
465
474
  if (unlocked && unlocked.parentKey === parentKeyOf(service, root) && unlocked.branchKey === statKey(branchLogPath(service, root)))
466
475
  return { tree: unlocked.tree, memo: unlocked };
467
- return withAncestryLock(() => {
476
+ return withHistoryLock(worldPaths(service, root).dir, () => {
468
477
  const parentKey = parentKeyOf(service, root);
469
478
  const branchKey = statKey(branchLogPath(service, root));
470
479
  const held = memos.get(slot);
@@ -548,7 +557,7 @@ export function treeChangesSince(service, root, since) {
548
557
  return { stamp, changed: treeResources(present), removed, appended: [...order.keys()].filter((k) => tree.has(k)) };
549
558
  }
550
559
  function readTreeMapFull(service, root, opts = {}) {
551
- return withAncestryLock(() => {
560
+ return withHistoryLock(worldPaths(service, root).dir, () => {
552
561
  if (opts.at !== undefined || opts.view !== undefined) {
553
562
  const view = opts.view ? readHistoryView(worldPaths(service, root).dir, opts.view) : captureHistory(service, root).descriptor;
554
563
  const at = opts.at ?? historyLength(view.layout);
@@ -603,7 +612,7 @@ function readTreeMapFull(service, root, opts = {}) {
603
612
  });
604
613
  }
605
614
  export function cutCheckpoint(service, root) {
606
- return withAncestryLock(() => {
615
+ return withHistoryLock(worldPaths(service, root).dir, () => {
607
616
  dropCheckpoint(service, root);
608
617
  const subjects = [...readTreeMap(service, root).values()];
609
618
  const inherited = inheritedHistory(service, root);
@@ -691,7 +700,7 @@ export function appendParentEntry(entry, root) {
691
700
  const path = parentLogPath(entry.service, root);
692
701
  const store = getActiveWorldStore();
693
702
  store.mkdir(dirname(path));
694
- return withAncestryLock(() => store.withLock(`${path}.lock`, () => {
703
+ return withHistoryLock(worldPaths(entry.service, root).dir, () => store.withLock(`${path}.lock`, () => {
695
704
  let indexes = parentIdIndex.get(store);
696
705
  if (!indexes) {
697
706
  indexes = new Map();
@@ -724,7 +733,7 @@ export function wholeLog(service, root) {
724
733
  * result, never a stop. An unbranched world (no pointer) has nothing to rebase.
725
734
  */
726
735
  export function rebaseBranch(service, root, opts = {}) {
727
- return withAncestryLock(() => {
736
+ return withHistoryLock(worldPaths(service, root).dir, () => {
728
737
  const meta = readBranchMeta(service, root);
729
738
  if (!meta?.parent)
730
739
  return { moved: false, from: 0, to: 0, conflicts: [] };
@@ -0,0 +1,50 @@
1
+ export type MachineSpec = {
2
+ name: string;
3
+ image: string;
4
+ env?: Record<string, string>;
5
+ ports?: number[];
6
+ command?: string[];
7
+ };
8
+ export type MachineRun = {
9
+ ports: Array<{
10
+ internal: number;
11
+ host: number;
12
+ }>;
13
+ };
14
+ /** A process started in a machine: its pid, and what it writes and how it ends, as they happen. */
15
+ export type MachineProcess = {
16
+ pid: number;
17
+ events: AsyncIterable<{
18
+ stdout?: string;
19
+ } | {
20
+ stderr?: string;
21
+ } | {
22
+ exit: number;
23
+ }>;
24
+ };
25
+ export type ExecSpec = {
26
+ args: string[];
27
+ env?: Record<string, string>;
28
+ cwd?: string;
29
+ };
30
+ export type MachinePool = {
31
+ readonly kind: 'docker' | 'none' | 'fake';
32
+ /** runs the image; a failure (no container runtime, an image that will not start) rejects with the runtime's message */
33
+ run(spec: MachineSpec): Promise<MachineRun>;
34
+ /** starts a process in a running machine; a machine the pool does not run rejects */
35
+ exec(name: string, spec: ExecSpec): Promise<MachineProcess>;
36
+ stop(name: string): Promise<void>;
37
+ remove(name: string): Promise<void>;
38
+ /** the fake pool's record of what it was asked */
39
+ readonly asked?: Array<{
40
+ act: 'run' | 'exec' | 'stop' | 'remove';
41
+ name: string;
42
+ spec?: MachineSpec;
43
+ exec?: ExecSpec;
44
+ }>;
45
+ };
46
+ export declare const MACHINE_POOL = "_machine_pool";
47
+ export declare const POOL_KINDS: readonly ["docker", "none", "fake"];
48
+ /** The pool of a kind, for a World (`world`: the mark its containers carry). */
49
+ export declare function machinePool(kind: MachinePool['kind'], world?: string): MachinePool;
50
+ export declare function poolFor(service: string, root: string | undefined, kind: MachinePool['kind']): MachinePool;
@@ -0,0 +1,151 @@
1
+ // The World's machine pool (architecture, "Other wires: … machines"): what runs a vendor's customer's image when the
2
+ // vendor is one that runs images (Fly's Machines). It is a platform provider enrolled through the kernel's door
3
+ // `POST /_twin/machine-pool`, recorded in the pack's own tree; a handler reaches it as `ctx.machines`. `docker` runs
4
+ // each machine as a local container with its internal ports published on loopback; `none` runs nothing; `fake`
5
+ // records what it was asked (capability verification). Nothing here runs at module scope, and `node:child_process`
6
+ // is reached only when a docker pool is asked to act.
7
+ import { nodeBuiltin } from "./serve-http.js";
8
+ export const MACHINE_POOL = '_machine_pool';
9
+ export const POOL_KINDS = ['docker', 'none', 'fake'];
10
+ /** A container's name for a machine: the World's prefix, the World's own mark (a machine id repeats across Worlds and
11
+ * branches, which mint alike), then the vendor's machine name made safe for docker. */
12
+ const containerName = (world, name) => `volter-world-machine-${world}-${name.replace(/[^A-Za-z0-9_.-]/g, '-')}`;
13
+ // an image's pull is the slow step: a run may take two minutes before the pool gives up; anything else, thirty seconds
14
+ const RUN_TIMEOUT_MS = 120_000;
15
+ const STEP_TIMEOUT_MS = 30_000;
16
+ function dockerPool(world) {
17
+ // asynchronous, so a pull never holds the World's other requests (or a socket's heartbeats) behind it
18
+ const docker = (args, timeout = STEP_TIMEOUT_MS) => new Promise((resolve, reject) => {
19
+ const { execFile } = nodeBuiltin('node:child_process');
20
+ execFile('docker', args, { encoding: 'utf8', timeout }, (error, stdout, stderr) => (error ? reject(new Error(String(stderr || error.message).trim())) : resolve(String(stdout).trim())));
21
+ });
22
+ return {
23
+ kind: 'docker',
24
+ async run(spec) {
25
+ const name = containerName(world, spec.name);
26
+ await docker(['rm', '-f', name]).catch(() => undefined);
27
+ const env = Object.entries(spec.env ?? {}).flatMap(([k, v]) => ['-e', `${k}=${v}`]);
28
+ const ports = (spec.ports ?? []).flatMap((p) => ['-p', `127.0.0.1::${p}`]);
29
+ await docker(['run', '-d', '--name', name, ...env, ...ports, spec.image, ...(spec.command ?? [])], RUN_TIMEOUT_MS);
30
+ const published = [];
31
+ for (const internal of spec.ports ?? []) {
32
+ const line = (await docker(['port', name, String(internal)])).split('\n')[0] ?? '';
33
+ published.push({ internal, host: Number(line.split(':').at(-1)) });
34
+ }
35
+ return { ports: published };
36
+ },
37
+ async exec(name, spec) {
38
+ const { spawn } = nodeBuiltin('node:child_process');
39
+ const env = Object.entries(spec.env ?? {}).flatMap(([k, v]) => ['-e', `${k}=${v}`]);
40
+ // the shell names its own pid first, then becomes the process: its pid is the process's
41
+ const child = spawn('docker', ['exec', '-i', ...env, ...(spec.cwd ? ['-w', spec.cwd] : []), containerName(world, name), 'sh', '-c', 'echo "@pid $$"; exec "$@"', 'sh', ...spec.args], { stdio: ['ignore', 'pipe', 'pipe'] });
42
+ const queue = [];
43
+ let wake;
44
+ let done = false;
45
+ let pid;
46
+ let head = '';
47
+ let stderr = '';
48
+ let settle;
49
+ const pidKnown = new Promise((resolve, reject) => { settle = { resolve, reject }; child.on('error', reject); });
50
+ const push = (e) => { queue.push(e); wake?.(); };
51
+ child.stdout.setEncoding('utf8').on('data', (chunk) => {
52
+ if (pid === undefined) {
53
+ // the pid line may arrive split across chunks: nothing is output until its newline is read
54
+ head += chunk;
55
+ const nl = head.indexOf('\n');
56
+ if (nl < 0)
57
+ return;
58
+ const m = /^@pid (\d+)$/.exec(head.slice(0, nl));
59
+ if (!m) {
60
+ push({ stdout: head });
61
+ head = '';
62
+ return;
63
+ }
64
+ pid = Number(m[1]);
65
+ settle?.resolve(pid);
66
+ chunk = head.slice(nl + 1);
67
+ head = '';
68
+ }
69
+ if (chunk)
70
+ push({ stdout: chunk });
71
+ });
72
+ child.stderr.setEncoding('utf8').on('data', (chunk) => { if (pid === undefined)
73
+ stderr += chunk; push({ stderr: chunk }); });
74
+ child.on('close', (code, signal) => {
75
+ // a machine the pool does not run (docker exec fails before the shell starts) rejects, with docker's words
76
+ if (pid === undefined)
77
+ settle?.reject(new Error(stderr.trim() || `the process did not start (exit ${code ?? signal})`));
78
+ // a process ended by a signal exits as a shell reports it: 128 and the signal's number
79
+ const signals = { SIGHUP: 1, SIGINT: 2, SIGQUIT: 3, SIGKILL: 9, SIGTERM: 15 };
80
+ push({ exit: code ?? (signal ? 128 + (signals[signal] ?? 0) : 0) });
81
+ done = true;
82
+ wake?.();
83
+ });
84
+ const events = {
85
+ async *[Symbol.asyncIterator]() {
86
+ for (;;) {
87
+ while (queue.length) {
88
+ const e = queue.shift();
89
+ yield e;
90
+ if ('exit' in e)
91
+ return;
92
+ }
93
+ if (done)
94
+ return;
95
+ await new Promise((r) => { wake = r; });
96
+ }
97
+ },
98
+ };
99
+ let timer;
100
+ const timeout = new Promise((_, reject) => { timer = setTimeout(() => reject(new Error('the process did not start')), STEP_TIMEOUT_MS); });
101
+ try {
102
+ return { pid: await Promise.race([pidKnown, timeout]), events };
103
+ }
104
+ finally {
105
+ clearTimeout(timer);
106
+ }
107
+ },
108
+ async stop(name) { await docker(['stop', containerName(world, name)]).catch(() => undefined); },
109
+ async remove(name) { await docker(['rm', '-f', containerName(world, name)]).catch(() => undefined); },
110
+ };
111
+ }
112
+ /** The pool of a kind, for a World (`world`: the mark its containers carry). */
113
+ export function machinePool(kind, world = 'world') {
114
+ if (kind === 'docker')
115
+ return dockerPool(world);
116
+ if (kind === 'fake') {
117
+ const asked = [];
118
+ return {
119
+ kind, asked,
120
+ async run(spec) { asked.push({ act: 'run', name: spec.name, spec }); return { ports: (spec.ports ?? []).map((internal) => ({ internal, host: 40_000 + internal })) }; },
121
+ async exec(name, spec) {
122
+ asked.push({ act: 'exec', name, exec: spec });
123
+ // a fake process: its pid the count of processes asked, and it ends at once
124
+ const pid = asked.filter((a) => a.act === 'exec').length + 100;
125
+ return { pid, events: (async function* () { yield { exit: 0 }; })() };
126
+ },
127
+ async stop(name) { asked.push({ act: 'stop', name }); },
128
+ async remove(name) { asked.push({ act: 'remove', name }); },
129
+ };
130
+ }
131
+ return {
132
+ kind: 'none', async run() { return { ports: [] }; },
133
+ async exec() { throw new Error('no machine runs in this World: its machine pool is none'); },
134
+ async stop() { }, async remove() { },
135
+ };
136
+ }
137
+ /** A vendor's pool in a World, one per World and kind for the life of the process (a fake pool keeps what it was asked). */
138
+ const pools = new Map();
139
+ export function poolFor(service, root, kind) {
140
+ const key = `${service}\0${root ?? ''}\0${kind}`;
141
+ let pool = pools.get(key);
142
+ if (!pool) {
143
+ // the World's mark: a short digest of the vendor and the World's tree, so two Worlds' machines never share a name
144
+ let h = 0;
145
+ for (const ch of `${service}:${root ?? ''}`)
146
+ h = (Math.imul(h, 31) + ch.charCodeAt(0)) >>> 0;
147
+ pool = machinePool(kind, h.toString(16).padStart(8, '0'));
148
+ pools.set(key, pool);
149
+ }
150
+ return pool;
151
+ }
@@ -0,0 +1,86 @@
1
+ /** One statement of a batch; `values` travel as bind parameters (text, or null), never in the SQL text. */
2
+ export type Statement = {
3
+ text: string;
4
+ values?: ReadonlyArray<string | null>;
5
+ };
6
+ /** What one statement answered: its columns and rows in Postgres's text format, and its command tag. */
7
+ export type StatementResult = {
8
+ fields: string[];
9
+ rows: Array<Array<string | null>>;
10
+ command: string;
11
+ };
12
+ /** A Postgres error as the backend reported it (SQLSTATE and its fields), what a vendor's server passes through. */
13
+ export declare class EngineDatabaseError extends Error {
14
+ readonly code: string;
15
+ readonly detail: string | null;
16
+ readonly hint: string | null;
17
+ constructor(message: string, fields: {
18
+ code?: string;
19
+ detail?: string;
20
+ hint?: string;
21
+ });
22
+ }
23
+ /** The World's database cannot be reached: none is bound, or it does not answer. */
24
+ export declare class EngineUnavailableError extends Error {
25
+ constructor(message: string);
26
+ }
27
+ /** One transaction: as `role` (none: the twin's own login role, the vendor's servers' own work), with transaction-local
28
+ * `settings` (`request.jwt.claims`, `search_path`), READ ONLY when `readOnly` (a write is refused by Postgres itself,
29
+ * 25006), ended with ROLLBACK when `rollback` (a permission probe asked of Postgres and undone). */
30
+ export type Batch = {
31
+ role?: string;
32
+ settings?: Record<string, string>;
33
+ readOnly?: boolean;
34
+ rollback?: boolean;
35
+ statements: Statement[];
36
+ };
37
+ export interface ManagedDatabase {
38
+ /** Whether the World binds a database at all (a World with none refuses every batch). */
39
+ readonly bound: boolean;
40
+ /** One transaction as one pipeline and one Sync; the answer is the batch's own statements', in order. */
41
+ batch(batch: Batch): Promise<StatementResult[]>;
42
+ /** A whole SQL script as one simple Query (a vendor's migrations, several statements to a file). */
43
+ script(text: string): Promise<void>;
44
+ }
45
+ /** The transaction-local setting every batch a handler makes carries: the World clock at the call (ctx.occurredAt). */
46
+ export declare const WORLD_CLOCK_SETTING = "volter.world_clock";
47
+ /** The World clock inside the database, for the schemas a vendor lays (its migrations stamp rows with Postgres's
48
+ * `now()`, which reads the wall clock): `volter.now()`, the World clock the batch set or the wall clock where none is
49
+ * set, and every column default in `schemas` that reads `now()` or `CURRENT_TIMESTAMP` (alone or inside an expression,
50
+ * GoTrue's `timezone('utc', now())`) rewritten to read it. Run after the schemas are laid; running it again changes
51
+ * nothing. A trigger or function that calls `now()` itself is the pack's to redefine. */
52
+ export declare function worldClockSql(schemas: string[]): string;
53
+ /** Quote an identifier the way Postgres's quote_ident does for a name that needs it. */
54
+ export declare function quoteIdent(name: string): string;
55
+ /** The part of a Postgres driver the kernel uses: node-postgres's (`pg`) Pool and its clients. */
56
+ type PgClient = {
57
+ query(query: unknown): unknown;
58
+ release(error?: Error): void;
59
+ };
60
+ type PgPool = {
61
+ connect(): Promise<PgClient>;
62
+ end(): Promise<void>;
63
+ on(event: 'error', listener: (error: Error) => void): unknown;
64
+ };
65
+ export type DatabaseDriver = {
66
+ Pool: new (config: {
67
+ connectionString: string;
68
+ max: number;
69
+ idleTimeoutMillis: number;
70
+ connectionTimeoutMillis: number;
71
+ }) => PgPool;
72
+ };
73
+ /** A Postgres driver a host registers in place of node-postgres. */
74
+ export declare function useDatabaseDriver(given: DatabaseDriver): void;
75
+ /** The World's Postgres at `url` (the runtime's binding, never the environment); with `readOnly`, every transaction is
76
+ * READ ONLY whatever the batch asks (a read-only twin or request: Postgres itself refuses a write, 25006); with `clock`,
77
+ * every batch carries the World clock as `volter.world_clock`. */
78
+ export declare function managedDatabase(url: string, options?: {
79
+ readOnly?: boolean;
80
+ clock?: string;
81
+ }): ManagedDatabase;
82
+ /** A handler's database when the World binds none: every use is the refusal naming what to add. */
83
+ export declare function unboundDatabase(service: string): ManagedDatabase;
84
+ /** Close every connection this process holds (a test's teardown; a served twin's connections end with it). */
85
+ export declare function closeManagedDatabases(): Promise<void>;
86
+ export {};