@oatscenter/trellis 0.100.0-rc.1

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 (264) hide show
  1. package/README.md +59 -0
  2. package/auth/authorization/client_context.d.ts +61 -0
  3. package/auth/authorization/client_context.js +266 -0
  4. package/auth/authorization/nats_registry.d.ts +41 -0
  5. package/auth/authorization/nats_registry.js +283 -0
  6. package/auth/authorization/provider_cache.d.ts +90 -0
  7. package/auth/authorization/provider_cache.js +783 -0
  8. package/auth/authorization/refresh.d.ts +46 -0
  9. package/auth/authorization/refresh.js +246 -0
  10. package/auth/authorization/types.d.ts +207 -0
  11. package/auth/authorization/types.js +60 -0
  12. package/auth/authorization_context.d.ts +11 -0
  13. package/auth/authorization_context.js +10 -0
  14. package/auth/browser/flow_types.d.ts +84 -0
  15. package/auth/browser/flow_types.js +70 -0
  16. package/auth/browser/portal.d.ts +21 -0
  17. package/auth/browser/portal.js +307 -0
  18. package/auth/browser/storage.d.ts +26 -0
  19. package/auth/browser/storage.js +224 -0
  20. package/auth/browser.d.ts +11 -0
  21. package/auth/browser.js +10 -0
  22. package/auth/browser_recovery.d.ts +13 -0
  23. package/auth/browser_recovery.js +38 -0
  24. package/auth/device_activation.d.ts +134 -0
  25. package/auth/device_activation.js +376 -0
  26. package/auth/http_error.d.ts +12 -0
  27. package/auth/http_error.js +32 -0
  28. package/auth/keys.d.ts +5 -0
  29. package/auth/keys.js +63 -0
  30. package/auth/mod.d.ts +16 -0
  31. package/auth/mod.js +16 -0
  32. package/auth/proof.d.ts +31 -0
  33. package/auth/proof.js +95 -0
  34. package/auth/protocol_wasm/trellis_protocol_wasm.d.ts +138 -0
  35. package/auth/protocol_wasm/trellis_protocol_wasm.js +605 -0
  36. package/auth/protocol_wasm/trellis_protocol_wasm_bg.wasm +0 -0
  37. package/auth/protocol_wasm/trellis_protocol_wasm_bytes.d.ts +1 -0
  38. package/auth/protocol_wasm/trellis_protocol_wasm_bytes.js +2 -0
  39. package/auth/protocol_wasm.d.ts +179 -0
  40. package/auth/protocol_wasm.js +133 -0
  41. package/auth/session_auth.d.ts +30 -0
  42. package/auth/session_auth.js +77 -0
  43. package/auth/session_proof.d.ts +53 -0
  44. package/auth/session_proof.js +43 -0
  45. package/auth/time.d.ts +6 -0
  46. package/auth/time.js +7 -0
  47. package/auth/trellis_id.d.ts +1 -0
  48. package/auth/trellis_id.js +5 -0
  49. package/auth/utils.d.ts +10 -0
  50. package/auth/utils.js +69 -0
  51. package/auth.d.ts +1 -0
  52. package/auth.js +1 -0
  53. package/caller.d.ts +111 -0
  54. package/caller.js +85 -0
  55. package/client.d.ts +14 -0
  56. package/client.js +1 -0
  57. package/client_connect.d.ts +143 -0
  58. package/client_connect.js +1097 -0
  59. package/codec.d.ts +13 -0
  60. package/codec.js +192 -0
  61. package/connection.d.ts +107 -0
  62. package/connection.js +396 -0
  63. package/device/activation.d.ts +42 -0
  64. package/device/activation.js +319 -0
  65. package/device.d.ts +80 -0
  66. package/device.js +687 -0
  67. package/env.d.ts +2 -0
  68. package/env.js +10 -0
  69. package/errors/AuthError.d.ts +30 -0
  70. package/errors/AuthError.js +34 -0
  71. package/errors/KVError.d.ts +30 -0
  72. package/errors/KVError.js +36 -0
  73. package/errors/OperationLifecycleError.d.ts +110 -0
  74. package/errors/OperationLifecycleError.js +142 -0
  75. package/errors/RemoteError.d.ts +61 -0
  76. package/errors/RemoteError.js +72 -0
  77. package/errors/SchemaValidationError.d.ts +48 -0
  78. package/errors/SchemaValidationError.js +49 -0
  79. package/errors/StoreError.d.ts +21 -0
  80. package/errors/StoreError.js +31 -0
  81. package/errors/TransferError.d.ts +21 -0
  82. package/errors/TransferError.js +31 -0
  83. package/errors/TransportError.d.ts +29 -0
  84. package/errors/TransportError.js +33 -0
  85. package/errors/TrellisError.d.ts +15 -0
  86. package/errors/TrellisError.js +15 -0
  87. package/errors/ValidationError.d.ts +50 -0
  88. package/errors/ValidationError.js +59 -0
  89. package/errors/index.d.ts +254 -0
  90. package/errors/index.js +238 -0
  91. package/generated.d.ts +4 -0
  92. package/generated.js +3 -0
  93. package/generated_support.d.ts +120 -0
  94. package/generated_support.js +359 -0
  95. package/globals.d.ts +9 -0
  96. package/globals.js +16 -0
  97. package/health_transport.d.ts +18 -0
  98. package/health_transport.js +32 -0
  99. package/helpers.d.ts +11 -0
  100. package/helpers.js +53 -0
  101. package/index.d.ts +2 -0
  102. package/index.js +2 -0
  103. package/internal_sdk/generated/apis/auth/mod.d.ts +805 -0
  104. package/internal_sdk/generated/apis/auth/mod.js +958 -0
  105. package/internal_sdk/generated/apis/core/mod.d.ts +79 -0
  106. package/internal_sdk/generated/apis/core/mod.js +93 -0
  107. package/internal_sdk/generated/apis/events/mod.d.ts +224 -0
  108. package/internal_sdk/generated/apis/events/mod.js +313 -0
  109. package/internal_sdk/generated/apis/health/mod.d.ts +106 -0
  110. package/internal_sdk/generated/apis/health/mod.js +132 -0
  111. package/internal_sdk/generated/apis/index.d.ts +7 -0
  112. package/internal_sdk/generated/apis/index.js +8 -0
  113. package/internal_sdk/generated/apis/jobs/mod.d.ts +176 -0
  114. package/internal_sdk/generated/apis/jobs/mod.js +209 -0
  115. package/internal_sdk/generated/apis/state/mod.d.ts +104 -0
  116. package/internal_sdk/generated/apis/state/mod.js +139 -0
  117. package/internal_sdk/generated/index.d.ts +4 -0
  118. package/internal_sdk/generated/index.js +5 -0
  119. package/internal_sdk/generated/package.json +18 -0
  120. package/internal_sdk/generated/participants/cli/mod.d.ts +402 -0
  121. package/internal_sdk/generated/participants/cli/mod.js +460 -0
  122. package/internal_sdk/generated/participants/cli/types.d.ts +2 -0
  123. package/internal_sdk/generated/participants/cli/types.js +3 -0
  124. package/internal_sdk/generated/participants/console/mod.d.ts +489 -0
  125. package/internal_sdk/generated/participants/console/mod.js +579 -0
  126. package/internal_sdk/generated/participants/console/types.d.ts +2 -0
  127. package/internal_sdk/generated/participants/console/types.js +3 -0
  128. package/internal_sdk/generated/participants/eventsRuntime/mod.d.ts +64 -0
  129. package/internal_sdk/generated/participants/eventsRuntime/mod.js +42 -0
  130. package/internal_sdk/generated/participants/eventsRuntime/types.d.ts +2 -0
  131. package/internal_sdk/generated/participants/eventsRuntime/types.js +3 -0
  132. package/internal_sdk/generated/participants/healthRuntime/mod.d.ts +58 -0
  133. package/internal_sdk/generated/participants/healthRuntime/mod.js +36 -0
  134. package/internal_sdk/generated/participants/healthRuntime/types.d.ts +2 -0
  135. package/internal_sdk/generated/participants/healthRuntime/types.js +3 -0
  136. package/internal_sdk/generated/participants/index.d.ts +8 -0
  137. package/internal_sdk/generated/participants/index.js +9 -0
  138. package/internal_sdk/generated/participants/jobsRuntime/mod.d.ts +64 -0
  139. package/internal_sdk/generated/participants/jobsRuntime/mod.js +42 -0
  140. package/internal_sdk/generated/participants/jobsRuntime/types.d.ts +2 -0
  141. package/internal_sdk/generated/participants/jobsRuntime/types.js +3 -0
  142. package/internal_sdk/generated/participants/platform/mod.d.ts +164 -0
  143. package/internal_sdk/generated/participants/platform/mod.js +149 -0
  144. package/internal_sdk/generated/participants/platform/types.d.ts +7 -0
  145. package/internal_sdk/generated/participants/platform/types.js +5 -0
  146. package/internal_sdk/generated/participants/portal/mod.d.ts +131 -0
  147. package/internal_sdk/generated/participants/portal/mod.js +109 -0
  148. package/internal_sdk/generated/participants/portal/types.d.ts +2 -0
  149. package/internal_sdk/generated/participants/portal/types.js +3 -0
  150. package/internal_sdk/generated/types/_internal/p0.d.ts +13511 -0
  151. package/internal_sdk/generated/types/_internal/p0.js +6105 -0
  152. package/internal_sdk/generated/types/index.d.ts +2951 -0
  153. package/internal_sdk/generated/types/index.js +1477 -0
  154. package/jobs.d.ts +309 -0
  155. package/jobs.js +389 -0
  156. package/kv.d.ts +85 -0
  157. package/kv.js +330 -0
  158. package/operations.d.ts +189 -0
  159. package/operations.js +847 -0
  160. package/package.json +73 -0
  161. package/pagination.d.ts +25 -0
  162. package/pagination.js +117 -0
  163. package/participant.d.ts +6 -0
  164. package/participant.js +6 -0
  165. package/participant_runtime/api.d.ts +131 -0
  166. package/participant_runtime/api.js +42 -0
  167. package/participant_runtime/json.d.ts +16 -0
  168. package/participant_runtime/json.js +193 -0
  169. package/participant_runtime/metadata.d.ts +34 -0
  170. package/participant_runtime/metadata.js +4 -0
  171. package/participant_runtime/participant.d.ts +200 -0
  172. package/participant_runtime/participant.js +330 -0
  173. package/participant_runtime/schemas.d.ts +347 -0
  174. package/participant_runtime/schemas.js +211 -0
  175. package/participant_runtime/surface_names.d.ts +16 -0
  176. package/participant_runtime/surface_names.js +34 -0
  177. package/portable.d.ts +30 -0
  178. package/portable.js +14 -0
  179. package/provider.d.ts +69 -0
  180. package/provider.js +68 -0
  181. package/runtime_transport.d.ts +25 -0
  182. package/runtime_transport.js +48 -0
  183. package/service/mod.d.ts +14 -0
  184. package/service/mod.js +13 -0
  185. package/service/outbox_inbox.d.ts +259 -0
  186. package/service/outbox_inbox.js +908 -0
  187. package/service/runtime/bootstrap.d.ts +56 -0
  188. package/service/runtime/bootstrap.js +226 -0
  189. package/service/runtime/core.d.ts +46 -0
  190. package/service/runtime/core.js +1747 -0
  191. package/service/runtime/health.d.ts +97 -0
  192. package/service/runtime/health.js +153 -0
  193. package/service/runtime/health_schemas.d.ts +23 -0
  194. package/service/runtime/health_schemas.js +20 -0
  195. package/service/runtime/internal_jobs/active-job.d.ts +40 -0
  196. package/service/runtime/internal_jobs/active-job.js +91 -0
  197. package/service/runtime/internal_jobs/bindings.d.ts +40 -0
  198. package/service/runtime/internal_jobs/bindings.js +1 -0
  199. package/service/runtime/internal_jobs/cancellation-registry.d.ts +13 -0
  200. package/service/runtime/internal_jobs/cancellation-registry.js +55 -0
  201. package/service/runtime/internal_jobs/heartbeat.d.ts +33 -0
  202. package/service/runtime/internal_jobs/heartbeat.js +65 -0
  203. package/service/runtime/internal_jobs/job-manager.d.ts +126 -0
  204. package/service/runtime/internal_jobs/job-manager.js +821 -0
  205. package/service/runtime/internal_jobs/key-coordinator.d.ts +280 -0
  206. package/service/runtime/internal_jobs/key-coordinator.js +747 -0
  207. package/service/runtime/internal_jobs/projection.d.ts +3 -0
  208. package/service/runtime/internal_jobs/projection.js +42 -0
  209. package/service/runtime/internal_jobs/runtime-worker.d.ts +126 -0
  210. package/service/runtime/internal_jobs/runtime-worker.js +454 -0
  211. package/service/runtime/internal_jobs/types.d.ts +246 -0
  212. package/service/runtime/internal_jobs/types.js +163 -0
  213. package/service/runtime/logger.d.ts +2 -0
  214. package/service/runtime/logger.js +7 -0
  215. package/service/runtime/runtime.d.ts +16 -0
  216. package/service/runtime/runtime.js +1 -0
  217. package/service/runtime/service.d.ts +372 -0
  218. package/service/runtime/service.js +1896 -0
  219. package/service/runtime/transfer/download.d.ts +27 -0
  220. package/service/runtime/transfer/download.js +1 -0
  221. package/service/runtime/transfer/protocol.d.ts +15 -0
  222. package/service/runtime/transfer/protocol.js +46 -0
  223. package/service/runtime/transfer/queue.d.ts +18 -0
  224. package/service/runtime/transfer/queue.js +136 -0
  225. package/service/runtime/transfer/upload.d.ts +40 -0
  226. package/service/runtime/transfer/upload.js +27 -0
  227. package/service/runtime/transfer.d.ts +62 -0
  228. package/service/runtime/transfer.js +763 -0
  229. package/session.d.ts +862 -0
  230. package/session.js +3407 -0
  231. package/store.d.ts +71 -0
  232. package/store.js +412 -0
  233. package/store_entry.d.ts +20 -0
  234. package/store_entry.js +75 -0
  235. package/tasks.d.ts +10 -0
  236. package/tasks.js +28 -0
  237. package/telemetry/carrier.d.ts +8 -0
  238. package/telemetry/carrier.js +20 -0
  239. package/telemetry/core.d.ts +7 -0
  240. package/telemetry/core.js +14 -0
  241. package/telemetry/env.d.ts +2 -0
  242. package/telemetry/env.js +10 -0
  243. package/telemetry/init.d.ts +2 -0
  244. package/telemetry/init.js +7 -0
  245. package/telemetry/metrics.d.ts +81 -0
  246. package/telemetry/metrics.js +267 -0
  247. package/telemetry/mod.d.ts +13 -0
  248. package/telemetry/mod.js +8 -0
  249. package/telemetry/nats.d.ts +6 -0
  250. package/telemetry/nats.js +6 -0
  251. package/telemetry/result.d.ts +1 -0
  252. package/telemetry/result.js +18 -0
  253. package/telemetry/runtime.d.ts +1 -0
  254. package/telemetry/runtime.js +141 -0
  255. package/telemetry/trace.d.ts +4 -0
  256. package/telemetry/trace.js +26 -0
  257. package/telemetry/trellis.d.ts +1 -0
  258. package/telemetry/trellis.js +1 -0
  259. package/telemetry.d.ts +1 -0
  260. package/telemetry.js +1 -0
  261. package/transfer.d.ts +112 -0
  262. package/transfer.js +525 -0
  263. package/transfer_protocol.d.ts +1 -0
  264. package/transfer_protocol.js +13 -0
@@ -0,0 +1,56 @@
1
+ import type { NatsConnection } from "@nats-io/nats-core";
2
+ import { type TrellisAuth as SessionAuth } from "../../auth.ts";
3
+ import { type AuthorizationContextBundle } from "../../auth/authorization_context.ts";
4
+ import type { RuntimeApi } from "../../participant_runtime/api.ts";
5
+ import type { LoggerLike } from "../../globals.ts";
6
+ import type { TrellisServiceRuntimeDeps } from "./runtime.ts";
7
+ import type { GeneratedServiceParticipant, ResourceBindings } from "./service.ts";
8
+ type ServiceBootstrapConnectInfo = {
9
+ connectionId: string;
10
+ participantId: string;
11
+ participantDigest: string;
12
+ contractId: string;
13
+ contractDigest: string;
14
+ transports: {
15
+ native?: {
16
+ natsServers: string[];
17
+ };
18
+ websocket?: {
19
+ natsServers: string[];
20
+ };
21
+ };
22
+ jwt: string;
23
+ jwtExpiresAt: number;
24
+ authorizationContext: AuthorizationContextBundle;
25
+ };
26
+ /** Validated bootstrap material used to create a service runtime session. */
27
+ export type ServiceBootstrapResponse = {
28
+ status: "ready";
29
+ serverNow: number;
30
+ serverClockOffsetMs: number;
31
+ connectInfo: ServiceBootstrapConnectInfo;
32
+ binding: {
33
+ contractId: string;
34
+ digest: string;
35
+ resources: ResourceBindings;
36
+ apiBindings: Readonly<Record<string, unknown>>;
37
+ };
38
+ };
39
+ /** Loads the default transport and telemetry dependencies for service connection. */
40
+ export declare function loadDefaultServiceRuntimeDeps(): Promise<TrellisServiceRuntimeDeps>;
41
+ /** Fetches and validates service bootstrap material, retrying pending states. */
42
+ export declare function fetchServiceBootstrapInfo(args: {
43
+ trellisUrl: string;
44
+ serviceName: string;
45
+ name?: string;
46
+ contractId: string;
47
+ contractDigest: string;
48
+ contract: GeneratedServiceParticipant<RuntimeApi, RuntimeApi | undefined>;
49
+ identityAuth: SessionAuth;
50
+ sessionAuth: SessionAuth;
51
+ log: LoggerLike;
52
+ connectionId?: string;
53
+ }): Promise<ServiceBootstrapResponse>;
54
+ /** Closes a NATS connection created by an unsuccessful bootstrap attempt. */
55
+ export declare function closeFailedServiceBootstrapConnection(nc: NatsConnection): Promise<void>;
56
+ export {};
@@ -0,0 +1,226 @@
1
+ import { Type } from "typebox";
2
+ import { Value } from "typebox/value";
3
+ import { ulid } from "ulid";
4
+ import { base64urlDecode, base64urlEncode, estimateMidpointClockOffsetMs, sha256, } from "../../auth.js";
5
+ import {} from "../../auth/authorization_context.js";
6
+ import { AuthorizationContextRefreshResponseSchema } from "../../auth/authorization/types.js";
7
+ import { decodeTrellisHttpError, TrellisHttpError, } from "../../auth/http_error.js";
8
+ import { ContractResourceBindingsSchema } from "../../participant.js";
9
+ import { participantEvidence } from "../../participant_runtime/participant.js";
10
+ import { TransportError } from "../../errors/index.js";
11
+ import { loadDefaultRuntimeTransport } from "../../runtime_transport.js";
12
+ import { initTelemetry } from "../../telemetry/init.js";
13
+ const DEFAULT_BOOTSTRAP_UNAVAILABLE_INITIAL_RETRY_MS = 1_000;
14
+ const MAX_BOOTSTRAP_UNAVAILABLE_RETRY_MS = 30_000;
15
+ function getErrorCauseMessage(error) {
16
+ if (error && typeof error === "object") {
17
+ const context = error.context;
18
+ if (typeof context?.causeMessage === "string" &&
19
+ context.causeMessage.length > 0) {
20
+ return context.causeMessage;
21
+ }
22
+ }
23
+ return error instanceof Error ? error.message : String(error);
24
+ }
25
+ function delay(ms) {
26
+ return new Promise((resolve) => setTimeout(resolve, ms));
27
+ }
28
+ function bootstrapUnavailableRetryDelayMs(attempt) {
29
+ const exponent = Math.min(attempt, 10);
30
+ return Math.min(DEFAULT_BOOTSTRAP_UNAVAILABLE_INITIAL_RETRY_MS * 2 ** exponent, MAX_BOOTSTRAP_UNAVAILABLE_RETRY_MS);
31
+ }
32
+ class ServiceBootstrapEndpointUnavailableError extends Error {
33
+ constructor(cause) {
34
+ super("Service bootstrap endpoint is unavailable.", { cause });
35
+ this.name = "ServiceBootstrapEndpointUnavailableError";
36
+ }
37
+ }
38
+ /** Loads the default transport and telemetry dependencies for service connection. */
39
+ export async function loadDefaultServiceRuntimeDeps() {
40
+ const transport = await loadDefaultRuntimeTransport();
41
+ return {
42
+ initTelemetry,
43
+ connect: ({ servers, token, authenticator, inboxPrefix, ...extraOptions }) => transport.connect({
44
+ servers,
45
+ ...extraOptions,
46
+ ...(token ? { token } : {}),
47
+ ...(authenticator ? { authenticator: authenticator } : {}),
48
+ ...(inboxPrefix ? { inboxPrefix } : {}),
49
+ }),
50
+ };
51
+ }
52
+ const ServiceBootstrapReadySchema = Type.Object({
53
+ ...AuthorizationContextRefreshResponseSchema.properties,
54
+ authorization: Type.Object({
55
+ participantId: Type.String({ minLength: 1 }),
56
+ participantDigest: Type.String({ minLength: 1 }),
57
+ resourceRuntime: ContractResourceBindingsSchema,
58
+ }),
59
+ });
60
+ async function fetchServiceBootstrapInfoOnce(args) {
61
+ const requestStartedAtMs = Date.now();
62
+ const requestId = ulid();
63
+ const issuedAt = args.identityAuth.currentIat() * 1_000;
64
+ const provisionedIdentityKeyId = base64urlEncode(await sha256(base64urlDecode(args.identityAuth.sessionKey)));
65
+ const unsigned = {
66
+ identityKeyId: provisionedIdentityKeyId,
67
+ sessionKey: args.sessionAuth.sessionKey,
68
+ connectionId: args.connectionId,
69
+ requestId,
70
+ iat: issuedAt,
71
+ ...participantEvidence(args.contract),
72
+ ...(args.name === undefined ? {} : { name: args.name }),
73
+ };
74
+ const body = JSON.stringify({
75
+ ...unsigned,
76
+ proof: await args.identityAuth.signSessionProof({
77
+ purpose: "serviceBootstrap",
78
+ origin: args.bootstrapUrl.origin,
79
+ unsignedRequest: unsigned,
80
+ }),
81
+ });
82
+ let response;
83
+ try {
84
+ response = await fetch(args.bootstrapUrl, {
85
+ method: "POST",
86
+ headers: { "Content-Type": "application/json" },
87
+ body,
88
+ });
89
+ }
90
+ catch (cause) {
91
+ throw new ServiceBootstrapEndpointUnavailableError(cause);
92
+ }
93
+ const responseReceivedAtMs = Date.now();
94
+ if (!response.ok)
95
+ throw await decodeTrellisHttpError(response);
96
+ let payload;
97
+ try {
98
+ payload = await response.json();
99
+ }
100
+ catch {
101
+ payload = undefined;
102
+ }
103
+ return {
104
+ response,
105
+ payload,
106
+ requestStartedAtMs,
107
+ responseReceivedAtMs,
108
+ };
109
+ }
110
+ /** Fetches and validates service bootstrap material, retrying pending states. */
111
+ export async function fetchServiceBootstrapInfo(args) {
112
+ const bootstrapUrl = new URL("/bootstrap/service", args.trellisUrl);
113
+ const connectionId = args.connectionId ?? ulid();
114
+ let unavailableAttempt = 0;
115
+ while (true) {
116
+ let settled;
117
+ try {
118
+ settled = await fetchServiceBootstrapInfoOnce({
119
+ ...args,
120
+ bootstrapUrl,
121
+ connectionId,
122
+ });
123
+ unavailableAttempt = 0;
124
+ }
125
+ catch (cause) {
126
+ if (cause instanceof TrellisHttpError && cause.code === "resource_pending") {
127
+ await delay(bootstrapUnavailableRetryDelayMs(unavailableAttempt));
128
+ unavailableAttempt += 1;
129
+ continue;
130
+ }
131
+ if (!(cause instanceof ServiceBootstrapEndpointUnavailableError)) {
132
+ throw cause;
133
+ }
134
+ const retryDelayMs = bootstrapUnavailableRetryDelayMs(unavailableAttempt);
135
+ unavailableAttempt += 1;
136
+ args.log.warn({
137
+ service: args.serviceName,
138
+ trellisUrl: args.trellisUrl,
139
+ contractId: args.contractId,
140
+ contractDigest: args.contractDigest,
141
+ attempt: unavailableAttempt,
142
+ retryDelayMs,
143
+ causeMessage: getErrorCauseMessage(cause.cause),
144
+ }, "Service bootstrap endpoint unavailable; retrying");
145
+ await delay(retryDelayMs);
146
+ continue;
147
+ }
148
+ if (settled.payload === undefined) {
149
+ throw new TransportError({
150
+ code: "trellis.bootstrap.invalid_response",
151
+ message: "Service bootstrap returned invalid JSON.",
152
+ hint: "Retry the connection. If it keeps happening, check the Trellis deployment.",
153
+ context: {
154
+ trellisUrl: args.trellisUrl,
155
+ contractId: args.contractId,
156
+ contractDigest: args.contractDigest,
157
+ },
158
+ });
159
+ }
160
+ const response = Value.Parse(ServiceBootstrapReadySchema, settled.payload);
161
+ const serverClockOffsetMs = estimateMidpointClockOffsetMs({
162
+ requestStartedAtMs: settled.requestStartedAtMs,
163
+ responseReceivedAtMs: settled.responseReceivedAtMs,
164
+ serverNowSeconds: response.serverNow / 1_000,
165
+ });
166
+ args.identityAuth.setServerClockOffsetMs(serverClockOffsetMs);
167
+ args.sessionAuth.setServerClockOffsetMs(serverClockOffsetMs);
168
+ const native = response.transports.native;
169
+ if (!native) {
170
+ throw new TransportError({
171
+ code: "trellis.bootstrap.invalid_response",
172
+ message: "Service bootstrap returned no native NATS transport.",
173
+ hint: "Configure native NATS endpoints for the Trellis runtime.",
174
+ });
175
+ }
176
+ return {
177
+ status: "ready",
178
+ serverNow: response.serverNow / 1_000,
179
+ serverClockOffsetMs,
180
+ connectInfo: {
181
+ connectionId: response.runtime.connectionId,
182
+ participantId: response.runtime.participantId,
183
+ participantDigest: response.authorization.participantDigest,
184
+ contractId: args.contractId,
185
+ contractDigest: args.contractDigest,
186
+ transports: { native: { natsServers: native.natsServers } },
187
+ jwt: response.routing.bootstrapJwt,
188
+ jwtExpiresAt: response.routing.bootstrapJwtExpiresAt,
189
+ authorizationContext: response.authorizationContext,
190
+ },
191
+ binding: {
192
+ contractId: args.contractId,
193
+ digest: response.authorization.participantDigest,
194
+ apiBindings: response.apiBindings,
195
+ resources: {
196
+ kv: response.authorization.resourceRuntime.kv ?? {},
197
+ store: response.authorization.resourceRuntime.store ?? {},
198
+ ...(response.authorization.resourceRuntime.jobs === undefined
199
+ ? {}
200
+ : { jobs: response.authorization.resourceRuntime.jobs }),
201
+ ...(response.authorization.resourceRuntime.eventConsumers ===
202
+ undefined
203
+ ? {}
204
+ : {
205
+ eventConsumers: response.authorization.resourceRuntime.eventConsumers,
206
+ }),
207
+ },
208
+ },
209
+ };
210
+ }
211
+ }
212
+ /** Closes a NATS connection created by an unsuccessful bootstrap attempt. */
213
+ export async function closeFailedServiceBootstrapConnection(nc) {
214
+ const closed = nc.closed().catch(() => undefined);
215
+ if (nc.isClosed()) {
216
+ await closed;
217
+ return;
218
+ }
219
+ try {
220
+ await nc.close();
221
+ }
222
+ catch {
223
+ // The connection closure is the lifecycle result, including auth revocation.
224
+ }
225
+ await closed;
226
+ }
@@ -0,0 +1,46 @@
1
+ import { type NatsConnection } from "@nats-io/nats-core";
2
+ import { type PermissionAtom, type RuntimeApi } from "../../participant_runtime/api.ts";
3
+ import { AsyncResult, BaseError } from "@oatscenter/result";
4
+ import { TransferError } from "../../errors/index.ts";
5
+ import { type HandlerFn, type MethodsOf, type OperationInputOf, type OperationOutputOf, type OperationProgressOf, type OperationRegistration, type OperationsOf, type OperationTransferContextOf, type OperationTransferHandle, type OperationUpdateOf, type RuntimeOperationController, Trellis, type TrellisAuth, type TrellisMode, type TrellisOpts } from "../../session.ts";
6
+ import { type FileInfo, type SendTransferGrant } from "../../transfer.ts";
7
+ type TrellisServiceRuntimeOpts<TA extends RuntimeApi> = Omit<TrellisOpts<TA>, "api"> & {
8
+ api: TA;
9
+ transferSupport?: RuntimeOperationTransferSupport;
10
+ version?: string;
11
+ operationDeploymentId?: string;
12
+ operationConnectionId?: string;
13
+ feedOwnerId?: string;
14
+ };
15
+ export type TrellisServiceRuntimeFor<TA extends RuntimeApi = RuntimeApi> = Omit<TrellisServiceRuntime, "mount" | "operationHandle"> & {
16
+ mount<M extends MethodsOf<TA>>(method: M, fn: HandlerFn<TA, M>): Promise<void>;
17
+ operationHandle<O extends OperationsOf<TA>>(operation: O): OperationRegistration<OperationInputOf<TA, O>, OperationProgressOf<TA, O>, OperationOutputOf<TA, O>, OperationTransferContextOf<TA, O>, BaseError, OperationUpdateOf<TA, O>>;
18
+ };
19
+ type RuntimeOperationTransferSession = {
20
+ grant: SendTransferGrant;
21
+ transfer: OperationTransferHandle;
22
+ };
23
+ type RuntimeOperationTransferSupport = {
24
+ openOperationTransfer(args: {
25
+ sessionKey: string;
26
+ permission: PermissionAtom | undefined;
27
+ requiredCapabilities: readonly string[];
28
+ store: string;
29
+ key: string;
30
+ expiresInMs: number;
31
+ maxBytes?: number;
32
+ contentType?: string;
33
+ metadata?: Record<string, string>;
34
+ onComplete?: (info: FileInfo) => Promise<void>;
35
+ }): AsyncResult<RuntimeOperationTransferSession, TransferError>;
36
+ };
37
+ export declare class TrellisServiceRuntime extends Trellis<RuntimeApi, TrellisMode> {
38
+ #private;
39
+ readonly operations: RuntimeOperationController;
40
+ private constructor();
41
+ mountRuntime(method: string, fn: Parameters<Trellis<RuntimeApi, TrellisMode>["mount"]>[1]): Promise<void>;
42
+ static create<TA extends RuntimeApi>(name: string, nats: NatsConnection, auth: TrellisAuth, opts: TrellisServiceRuntimeOpts<TA>): TrellisServiceRuntimeFor<TA>;
43
+ operationHandle(operation: string): OperationRegistration<unknown, unknown, unknown, undefined, BaseError>;
44
+ stop(): Promise<void>;
45
+ }
46
+ export {};