@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,46 @@
1
+ import { TrellisHttpError } from "../http_error.ts";
2
+ import type { TrellisAuth } from "../session_auth.ts";
3
+ import type { AuthorizationContextCache } from "./client_context.ts";
4
+ import type { AuthorizationContextRefreshResponse, AuthorizationContextRefreshResult, VerifiedAuthorizationContext } from "./types.ts";
5
+ /** HTTP refresh failure with terminal-state classification. */
6
+ export declare class AuthorizationContextRefreshError extends TrellisHttpError {
7
+ readonly terminal: boolean;
8
+ readonly loginInvalid: boolean;
9
+ constructor(status: number, code: string);
10
+ }
11
+ /** Refresh a context after proving possession of its bound session key. */
12
+ export declare function refreshAuthorizationContextWithMetadata(args: {
13
+ trellisUrl: string;
14
+ sessionId: string;
15
+ auth: TrellisAuth;
16
+ sessionKey?: string;
17
+ cache: AuthorizationContextCache;
18
+ fetch?: typeof globalThis.fetch;
19
+ shouldInstall?: () => boolean;
20
+ requiredTransport?: "native" | "websocket";
21
+ prepareInstall?: (response: AuthorizationContextRefreshResponse) => Promise<(verified: VerifiedAuthorizationContext) => void>;
22
+ prepareOnly?: boolean;
23
+ }): Promise<AuthorizationContextRefreshResult>;
24
+ /** Refresh a context and return only its verified projection. */
25
+ export declare function refreshAuthorizationContext(args: {
26
+ trellisUrl: string;
27
+ sessionId: string;
28
+ auth: TrellisAuth;
29
+ sessionKey?: string;
30
+ cache: AuthorizationContextCache;
31
+ fetch?: typeof globalThis.fetch;
32
+ shouldInstall?: () => boolean;
33
+ }): Promise<VerifiedAuthorizationContext>;
34
+ /** Start proactive refresh using the context's distributed refresh time. */
35
+ export declare function startAuthorizationContextRefresh(args: {
36
+ trellisUrl: string;
37
+ sessionId: string;
38
+ auth: TrellisAuth;
39
+ sessionKey?: string;
40
+ cache: AuthorizationContextCache;
41
+ fetch?: typeof globalThis.fetch;
42
+ refresh?: (shouldInstall: () => boolean) => Promise<VerifiedAuthorizationContext>;
43
+ onTerminalFailure?: (error: unknown) => void | Promise<void>;
44
+ onTransientFailure?: (error: unknown) => void | Promise<void>;
45
+ onRefresh?: (context: VerifiedAuthorizationContext) => void | Promise<void>;
46
+ }): () => void;
@@ -0,0 +1,246 @@
1
+ import { Value } from "typebox/value";
2
+ import { ulid } from "ulid";
3
+ import { decodeTrellisHttpError, TrellisHttpError } from "../http_error.js";
4
+ import { AuthorizationContextRefreshResponseSchema as ResponseSchema } from "./types.js";
5
+ /** HTTP refresh failure with terminal-state classification. */
6
+ export class AuthorizationContextRefreshError extends TrellisHttpError {
7
+ terminal;
8
+ loginInvalid;
9
+ constructor(status, code) {
10
+ super(status, code);
11
+ this.name = "AuthorizationContextRefreshError";
12
+ this.terminal = [
13
+ "session_not_found",
14
+ "session_expired",
15
+ "session_revoked",
16
+ "identity_not_found",
17
+ "identity_inactive",
18
+ "user_not_found",
19
+ "user_inactive",
20
+ "login_not_found",
21
+ "participant_not_found",
22
+ "participant_changed",
23
+ "contract_changed",
24
+ "authority_not_found",
25
+ "authority_rejected",
26
+ "authority_revoked",
27
+ "authority_expired",
28
+ "context_owner_mismatch",
29
+ "deployment_inactive",
30
+ "instance_inactive",
31
+ "device_inactive",
32
+ "activation_required",
33
+ "delegation_expired",
34
+ "context_refresh_mismatch",
35
+ "invalid_proof",
36
+ ].includes(code);
37
+ this.loginInvalid = [
38
+ "session_not_found",
39
+ "session_expired",
40
+ "session_revoked",
41
+ "identity_not_found",
42
+ "identity_inactive",
43
+ "user_not_found",
44
+ "user_inactive",
45
+ "login_not_found",
46
+ ].includes(code);
47
+ }
48
+ }
49
+ /** Refresh a context after proving possession of its bound session key. */
50
+ export async function refreshAuthorizationContextWithMetadata(args) {
51
+ const fetch = args.fetch ?? globalThis.fetch;
52
+ const currentDigest = args.cache.storedContextDigest();
53
+ let runtime;
54
+ try {
55
+ runtime = args.cache.runtimeBinding();
56
+ }
57
+ catch {
58
+ runtime = undefined;
59
+ }
60
+ if (runtime?.loginSessionId && runtime.loginSessionId !== args.sessionId) {
61
+ throw new Error("authorization recovery session mismatch");
62
+ }
63
+ const requestStartedAt = args.cache.nowMilliseconds();
64
+ const unsignedRequest = {
65
+ requestId: ulid(),
66
+ issuedAt: Math.trunc(args.auth.currentIat() * 1_000),
67
+ loginSessionId: args.sessionId,
68
+ connectionId: runtime?.connectionId ?? ulid(),
69
+ sessionKey: args.sessionKey ?? args.auth.sessionKey,
70
+ currentContextDigest: currentDigest ?? null,
71
+ };
72
+ const proof = await args.auth.signSessionProof({
73
+ purpose: "authorizationContextRefresh",
74
+ origin: new URL(args.trellisUrl).origin,
75
+ sessionPublicKey: args.auth.sessionKey,
76
+ unsignedRequest,
77
+ });
78
+ const response = await fetch(new URL("/auth/context/refresh", args.trellisUrl), {
79
+ method: "POST",
80
+ headers: { "content-type": "application/json" },
81
+ body: JSON.stringify({ ...unsignedRequest, proof }),
82
+ });
83
+ if (!response.ok) {
84
+ const error = await decodeTrellisHttpError(response);
85
+ throw new AuthorizationContextRefreshError(error.status, error.code);
86
+ }
87
+ const next = Value.Parse(ResponseSchema, await response.json());
88
+ if (args.requiredTransport &&
89
+ !next.transports[args.requiredTransport]?.natsServers.length) {
90
+ throw new Error(`authorization refresh has no ${args.requiredTransport} NATS endpoints`);
91
+ }
92
+ const serverClockOffsetMs = next.serverNow - Math.trunc((requestStartedAt + args.cache.nowMilliseconds()) / 2);
93
+ args.cache.setServerClockOffsetMs(serverClockOffsetMs);
94
+ args.auth.setServerClockOffsetMs(serverClockOffsetMs);
95
+ if (args.shouldInstall?.() === false) {
96
+ throw new Error("authorization context refresh stopped");
97
+ }
98
+ const nextRuntime = runtimeBindingFromResponse(next);
99
+ const context = await args.cache[args.prepareOnly ? "prepare" : "install"](next.authorizationContext, {
100
+ bootstrapJwt: next.routing.bootstrapJwt,
101
+ bootstrapJwtExpiresAt: next.routing.bootstrapJwtExpiresAt,
102
+ }, Math.floor(next.serverNow / 1_000), args.shouldInstall, nextRuntime, async (verified) => {
103
+ const installAdditional = await args.prepareInstall?.(next);
104
+ return installAdditional ? () => installAdditional(verified) : undefined;
105
+ });
106
+ return { context, response: next };
107
+ }
108
+ /** Refresh a context and return only its verified projection. */
109
+ export async function refreshAuthorizationContext(args) {
110
+ const result = await refreshAuthorizationContextWithMetadata(args);
111
+ return result.context;
112
+ }
113
+ /** Start proactive refresh using the context's distributed refresh time. */
114
+ export function startAuthorizationContextRefresh(args) {
115
+ let stopped = false;
116
+ let timer;
117
+ let failures = 0;
118
+ let running = false;
119
+ let wakePending = false;
120
+ const schedule = (delayMs) => {
121
+ if (!stopped)
122
+ timer = setTimeout(run, delayMs);
123
+ };
124
+ const run = async () => {
125
+ if (running) {
126
+ wakePending = true;
127
+ return;
128
+ }
129
+ running = true;
130
+ const clearGuard = args.cache.clearGuard();
131
+ try {
132
+ let before;
133
+ try {
134
+ before = args.cache.storedContextDigest();
135
+ }
136
+ catch {
137
+ before = undefined;
138
+ }
139
+ const context = args.refresh
140
+ ? await args.refresh(() => !stopped)
141
+ : (await refreshAuthorizationContextWithMetadata({
142
+ ...args,
143
+ shouldInstall: () => !stopped,
144
+ prepareOnly: true,
145
+ })).context;
146
+ if (stopped)
147
+ return;
148
+ failures = 0;
149
+ await args.onRefresh?.(context);
150
+ schedule(refreshDelay(args.cache, before === context.contextDigest ? 5_000 : 1_000));
151
+ }
152
+ catch (error) {
153
+ if (stopped)
154
+ return;
155
+ if (error instanceof AuthorizationContextRefreshError && error.terminal) {
156
+ if (!(await args.cache.clearIfCurrent(clearGuard))) {
157
+ failures = 0;
158
+ schedule(refreshDelay(args.cache, 1_000));
159
+ return;
160
+ }
161
+ await args.onTerminalFailure?.(error);
162
+ return;
163
+ }
164
+ failures += 1;
165
+ let current;
166
+ try {
167
+ current = args.cache.current();
168
+ }
169
+ catch {
170
+ current = undefined;
171
+ }
172
+ await args.onTransientFailure?.(error);
173
+ const beforeExpiry = current
174
+ ? Math.max(1_000, (current.context.expiresAt - args.cache.correctedNowSeconds()) *
175
+ 1_000)
176
+ : Number.POSITIVE_INFINITY;
177
+ schedule(Math.min(beforeExpiry, 5_000 * 2 ** Math.min(failures - 1, 3)));
178
+ }
179
+ finally {
180
+ running = false;
181
+ if (wakePending && !stopped) {
182
+ wakePending = false;
183
+ if (timer !== undefined)
184
+ clearTimeout(timer);
185
+ schedule(0);
186
+ }
187
+ }
188
+ };
189
+ schedule(refreshDelay(args.cache));
190
+ let unregisterRefreshRequest;
191
+ try {
192
+ unregisterRefreshRequest = args.cache.registerRefreshRequest(() => {
193
+ if (running) {
194
+ wakePending = true;
195
+ return;
196
+ }
197
+ if (timer !== undefined)
198
+ clearTimeout(timer);
199
+ schedule(0);
200
+ });
201
+ }
202
+ catch (error) {
203
+ stopped = true;
204
+ if (timer !== undefined)
205
+ clearTimeout(timer);
206
+ throw error;
207
+ }
208
+ return () => {
209
+ stopped = true;
210
+ unregisterRefreshRequest();
211
+ if (timer !== undefined)
212
+ clearTimeout(timer);
213
+ };
214
+ }
215
+ function refreshDelay(cache, minimumMs = 1_000) {
216
+ try {
217
+ return Math.max(minimumMs, (cache.routingRefreshAt() - cache.correctedNowSeconds()) * 1_000);
218
+ }
219
+ catch {
220
+ return minimumMs;
221
+ }
222
+ }
223
+ function runtimeBindingFromResponse(response) {
224
+ if (!response.transports.native &&
225
+ !response.transports.websocket) {
226
+ throw new Error("authorization refresh returned no NATS transport");
227
+ }
228
+ return {
229
+ connectionId: response.runtime.connectionId,
230
+ loginSessionId: response.runtime.loginSessionId,
231
+ participantId: response.runtime.participantId,
232
+ inboxPrefix: response.runtime.inboxPrefix,
233
+ transports: {
234
+ ...(response.transports.native === undefined ? {} : {
235
+ native: {
236
+ natsServers: [...response.transports.native.natsServers],
237
+ },
238
+ }),
239
+ ...(response.transports.websocket === undefined ? {} : {
240
+ websocket: {
241
+ natsServers: [...response.transports.websocket.natsServers],
242
+ },
243
+ }),
244
+ },
245
+ };
246
+ }
@@ -0,0 +1,207 @@
1
+ import { type Static, Type } from "typebox";
2
+ import type { AuthorizationContextVerificationPolicy, PermissionAtom, VerifiedAuthorizationContextTokenProjection } from "../protocol_wasm.ts";
3
+ /** Pinned root and connected NATS KV registry binding. */
4
+ export declare const AuthorizationRegistryBindingSchema: Type.TObject<{
5
+ contextBucket: Type.TString;
6
+ }>;
7
+ /** Wire binding for Trellis' internal authorization registry. */
8
+ export type AuthorizationRegistryBinding = Static<typeof AuthorizationRegistryBindingSchema>;
9
+ /** Wire schema for one published authorization context bundle. */
10
+ export declare const AuthorizationContextBundleSchema: Type.TObject<{
11
+ context: Type.TUnknown;
12
+ issuer: Type.TObject<{
13
+ keyId: Type.TString;
14
+ publicKey: Type.TString;
15
+ state: Type.TUnion<[Type.TLiteral<"active">, Type.TLiteral<"retired">, Type.TLiteral<"revoked">]>;
16
+ }>;
17
+ authorizationRegistry: Type.TObject<{
18
+ contextBucket: Type.TString;
19
+ }>;
20
+ policy: Type.TObject<{
21
+ allowedClockSkewSeconds: Type.TInteger;
22
+ maximumContextLifetimeSeconds: Type.TInteger;
23
+ maximumContextBytes: Type.TInteger;
24
+ maximumPermissions: Type.TInteger;
25
+ refreshLeadSeconds: Type.TInteger;
26
+ refreshJitterSeconds: Type.TInteger;
27
+ }>;
28
+ }>;
29
+ /** Published signed context and the trust information needed to verify it. */
30
+ export type AuthorizationContextBundle = Static<typeof AuthorizationContextBundleSchema>;
31
+ /** Route-selection JWT installed atomically with a context. */
32
+ export type AuthorizationRoutingMaterial = {
33
+ bootstrapJwt: string;
34
+ bootstrapJwtExpiresAt: number;
35
+ };
36
+ /** Transport endpoints retained for reconnect recovery. */
37
+ export type AuthorizationRuntimeTransports = {
38
+ native?: {
39
+ natsServers: string[];
40
+ };
41
+ websocket?: {
42
+ natsServers: string[];
43
+ };
44
+ };
45
+ /** Transport metadata retained for reconnect recovery. */
46
+ export type AuthorizationRuntimeBinding = {
47
+ connectionId: string;
48
+ loginSessionId: string | null;
49
+ participantId: string;
50
+ inboxPrefix: string;
51
+ transports: AuthorizationRuntimeTransports;
52
+ };
53
+ /** Trusted context projection returned by the Rust/WASM verifier. */
54
+ export type VerifiedAuthorizationContext = VerifiedAuthorizationContextTokenProjection;
55
+ /** Installed trust material that a provider-side verifier may reuse. */
56
+ export type AuthorizationContextVerificationMaterial = {
57
+ issuer: AuthorizationContextBundle["issuer"];
58
+ context: unknown;
59
+ contextDigest: string;
60
+ policy: AuthorizationContextVerificationPolicy;
61
+ verified: VerifiedAuthorizationContext;
62
+ };
63
+ /** Presented request proof data supplied by a provider transport adapter. */
64
+ export type AuthorizationProviderRequest = {
65
+ contextDigest: string;
66
+ sessionKey: string;
67
+ subject: string;
68
+ reply: string | null;
69
+ payload: Uint8Array;
70
+ iat: number;
71
+ requestId: string;
72
+ proof: string;
73
+ requiredPermissions: PermissionAtom[];
74
+ requiredCapabilities: string[];
75
+ };
76
+ /** Presented event proof data supplied by a provider event adapter. */
77
+ export type AuthorizationProviderEvent = {
78
+ contextDigest: string;
79
+ sessionKey: string;
80
+ descriptorIdentity: string;
81
+ subject: string;
82
+ payload: Uint8Array;
83
+ eventId: string;
84
+ eventTime: string;
85
+ proof: string;
86
+ requiredCapabilities: string[];
87
+ };
88
+ /** Proactive refresh response returned by the Rust auth service. */
89
+ export declare const AuthorizationContextRefreshResponseSchema: Type.TObject<{
90
+ serverNow: Type.TInteger;
91
+ authorizationContext: Type.TObject<{
92
+ context: Type.TUnknown;
93
+ issuer: Type.TObject<{
94
+ keyId: Type.TString;
95
+ publicKey: Type.TString;
96
+ state: Type.TUnion<[Type.TLiteral<"active">, Type.TLiteral<"retired">, Type.TLiteral<"revoked">]>;
97
+ }>;
98
+ authorizationRegistry: Type.TObject<{
99
+ contextBucket: Type.TString;
100
+ }>;
101
+ policy: Type.TObject<{
102
+ allowedClockSkewSeconds: Type.TInteger;
103
+ maximumContextLifetimeSeconds: Type.TInteger;
104
+ maximumContextBytes: Type.TInteger;
105
+ maximumPermissions: Type.TInteger;
106
+ refreshLeadSeconds: Type.TInteger;
107
+ refreshJitterSeconds: Type.TInteger;
108
+ }>;
109
+ }>;
110
+ routing: Type.TObject<{
111
+ bootstrapJwt: Type.TString;
112
+ bootstrapJwtExpiresAt: Type.TInteger;
113
+ }>;
114
+ runtime: Type.TObject<{
115
+ connectionId: Type.TString;
116
+ loginSessionId: Type.TUnion<[Type.TString, Type.TNull]>;
117
+ participantId: Type.TString;
118
+ inboxPrefix: Type.TString;
119
+ }>;
120
+ apiBindings: Type.TRecord<"^.*$", Type.TObject<{
121
+ providerDeploymentId: Type.TString;
122
+ }>>;
123
+ transports: Type.TObject<{
124
+ native: Type.TOptional<Type.TObject<{
125
+ natsServers: Type.TArray<Type.TString>;
126
+ }>>;
127
+ websocket: Type.TOptional<Type.TObject<{
128
+ natsServers: Type.TArray<Type.TString>;
129
+ }>>;
130
+ }>;
131
+ authorization: Type.TObject<{
132
+ participantId: Type.TString;
133
+ participantDigest: Type.TString;
134
+ resourceRuntime: Type.TObject<{
135
+ kv: Type.TOptional<Type.TRecord<"^.*$", Type.TObject<{
136
+ bucket: Type.TString;
137
+ history: Type.TInteger;
138
+ ttlMs: Type.TInteger;
139
+ maxValueBytes: Type.TOptional<Type.TInteger>;
140
+ }>>>;
141
+ store: Type.TOptional<Type.TRecord<"^.*$", Type.TObject<{
142
+ name: Type.TString;
143
+ ttlMs: Type.TInteger;
144
+ maxObjectBytes: Type.TOptional<Type.TInteger>;
145
+ maxTotalBytes: Type.TOptional<Type.TInteger>;
146
+ }>>>;
147
+ jobs: Type.TOptional<Type.TObject<{
148
+ serviceName: Type.TString;
149
+ namespace: Type.TString;
150
+ workStream: Type.TOptional<Type.TString>;
151
+ queues: Type.TRecord<"^.*$", Type.TObject<{
152
+ queueType: Type.TString;
153
+ publishPrefix: Type.TString;
154
+ workSubject: Type.TString;
155
+ consumerName: Type.TString;
156
+ payload: Type.TObject<{
157
+ schema: Type.TString;
158
+ }>;
159
+ update: Type.TOptional<Type.TObject<{
160
+ schema: Type.TString;
161
+ }>>;
162
+ updatesPrefix: Type.TOptional<Type.TString>;
163
+ result: Type.TOptional<Type.TObject<{
164
+ schema: Type.TString;
165
+ }>>;
166
+ maxDeliver: Type.TInteger;
167
+ backoffMs: Type.TArray<Type.TInteger>;
168
+ ackWaitMs: Type.TInteger;
169
+ defaultDeadlineMs: Type.TOptional<Type.TInteger>;
170
+ keyConcurrency: Type.TOptional<Type.TObject<{
171
+ key: Type.TArray<Type.TString>;
172
+ maxActive: Type.TInteger;
173
+ heartbeatIntervalMs: Type.TInteger;
174
+ heartbeatTtlMs: Type.TInteger;
175
+ stalePolicy: Type.TUnion<[Type.TLiteral<"fail-stale">, Type.TLiteral<"block">]>;
176
+ }>>;
177
+ queue: Type.TOptional<Type.TObject<{
178
+ maxQueuedPerKey: Type.TInteger;
179
+ whenFull: Type.TUnion<[Type.TLiteral<"reject">, Type.TLiteral<"coalesce">, Type.TLiteral<"replace-oldest">]>;
180
+ }>>;
181
+ }>>;
182
+ }>>;
183
+ eventConsumers: Type.TOptional<Type.TRecord<"^.*$", Type.TObject<{
184
+ resourceId: Type.TString;
185
+ stream: Type.TString;
186
+ consumerName: Type.TString;
187
+ filterSubjects: Type.TArray<Type.TString>;
188
+ replay: Type.TUnion<[Type.TLiteral<"new">, Type.TLiteral<"all">]>;
189
+ concurrency: Type.TInteger;
190
+ ackWaitMs: Type.TInteger;
191
+ maxDeliver: Type.TInteger;
192
+ backoffMs: Type.TArray<Type.TInteger>;
193
+ replayBinding: Type.TObject<{
194
+ stream: Type.TString;
195
+ consumerName: Type.TString;
196
+ }>;
197
+ }>>>;
198
+ }>;
199
+ }>;
200
+ }>;
201
+ /** Proactive refresh response with its verified installed context. */
202
+ export type AuthorizationContextRefreshResponse = Static<typeof AuthorizationContextRefreshResponseSchema>;
203
+ /** Result returned by the metadata-preserving refresh helper. */
204
+ export type AuthorizationContextRefreshResult = {
205
+ context: VerifiedAuthorizationContext;
206
+ response: AuthorizationContextRefreshResponse;
207
+ };
@@ -0,0 +1,60 @@
1
+ import { Type } from "typebox";
2
+ import { ContractResourceBindingsSchema } from "../../participant.js";
3
+ /** Pinned root and connected NATS KV registry binding. */
4
+ export const AuthorizationRegistryBindingSchema = Type.Object({
5
+ contextBucket: Type.String({ minLength: 1 }),
6
+ });
7
+ /** Wire schema for one published authorization context bundle. */
8
+ export const AuthorizationContextBundleSchema = Type.Object({
9
+ context: Type.Unknown(),
10
+ issuer: Type.Object({
11
+ keyId: Type.String({ minLength: 1 }),
12
+ publicKey: Type.String({ minLength: 1 }),
13
+ state: Type.Union([
14
+ Type.Literal("active"),
15
+ Type.Literal("retired"),
16
+ Type.Literal("revoked"),
17
+ ]),
18
+ }),
19
+ authorizationRegistry: AuthorizationRegistryBindingSchema,
20
+ policy: Type.Object({
21
+ allowedClockSkewSeconds: Type.Integer({ minimum: 0 }),
22
+ maximumContextLifetimeSeconds: Type.Integer({ minimum: 1 }),
23
+ // Canonical signed-context JSON size in UTF-8 bytes.
24
+ maximumContextBytes: Type.Integer({ minimum: 1 }),
25
+ maximumPermissions: Type.Integer({ minimum: 1 }),
26
+ refreshLeadSeconds: Type.Integer({ minimum: 1 }),
27
+ refreshJitterSeconds: Type.Integer({ minimum: 0 }),
28
+ }),
29
+ });
30
+ /** Proactive refresh response returned by the Rust auth service. */
31
+ export const AuthorizationContextRefreshResponseSchema = Type.Object({
32
+ serverNow: Type.Integer({ minimum: 0 }),
33
+ authorizationContext: AuthorizationContextBundleSchema,
34
+ routing: Type.Object({
35
+ bootstrapJwt: Type.String({ minLength: 1 }),
36
+ bootstrapJwtExpiresAt: Type.Integer({ minimum: 1 }),
37
+ }),
38
+ runtime: Type.Object({
39
+ connectionId: Type.String({ minLength: 1 }),
40
+ loginSessionId: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
41
+ participantId: Type.String({ minLength: 1 }),
42
+ inboxPrefix: Type.String({ minLength: 1 }),
43
+ }),
44
+ apiBindings: Type.Record(Type.String({ minLength: 1 }), Type.Object({
45
+ providerDeploymentId: Type.String({ minLength: 1 }),
46
+ })),
47
+ transports: Type.Object({
48
+ native: Type.Optional(Type.Object({
49
+ natsServers: Type.Array(Type.String({ minLength: 1 }), { minItems: 1 }),
50
+ })),
51
+ websocket: Type.Optional(Type.Object({
52
+ natsServers: Type.Array(Type.String({ minLength: 1 }), { minItems: 1 }),
53
+ })),
54
+ }),
55
+ authorization: Type.Object({
56
+ participantId: Type.String({ minLength: 1 }),
57
+ participantDigest: Type.String({ minLength: 1 }),
58
+ resourceRuntime: ContractResourceBindingsSchema,
59
+ }),
60
+ });
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Authorization context facade.
3
+ *
4
+ * The implementation is split by responsibility under `auth/authorization/`;
5
+ * this module preserves the existing import surface for Trellis clients.
6
+ */
7
+ export { AuthorizationContextCache, authorizationContextVerificationPolicy, verifyAuthorizationContext, } from "./authorization/client_context.ts";
8
+ export { AuthorizationProviderCache, type AuthorizationProviderCacheHealth, type AuthorizationProviderCacheOptions, type AuthorizationProviderIoCounters, } from "./authorization/provider_cache.ts";
9
+ export { AuthorizationContextRefreshError, refreshAuthorizationContext, refreshAuthorizationContextWithMetadata, startAuthorizationContextRefresh, } from "./authorization/refresh.ts";
10
+ export type { AuthorizationContextBundle, AuthorizationContextRefreshResponse, AuthorizationContextRefreshResult, AuthorizationContextVerificationMaterial, AuthorizationProviderEvent, AuthorizationProviderRequest, AuthorizationRoutingMaterial, AuthorizationRuntimeBinding, AuthorizationRuntimeTransports, VerifiedAuthorizationContext, } from "./authorization/types.ts";
11
+ export { AuthorizationContextBundleSchema, AuthorizationContextRefreshResponseSchema, } from "./authorization/types.ts";
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Authorization context facade.
3
+ *
4
+ * The implementation is split by responsibility under `auth/authorization/`;
5
+ * this module preserves the existing import surface for Trellis clients.
6
+ */
7
+ export { AuthorizationContextCache, authorizationContextVerificationPolicy, verifyAuthorizationContext, } from "./authorization/client_context.js";
8
+ export { AuthorizationProviderCache, } from "./authorization/provider_cache.js";
9
+ export { AuthorizationContextRefreshError, refreshAuthorizationContext, refreshAuthorizationContextWithMetadata, startAuthorizationContextRefresh, } from "./authorization/refresh.js";
10
+ export { AuthorizationContextBundleSchema, AuthorizationContextRefreshResponseSchema, } from "./authorization/types.js";
@@ -0,0 +1,84 @@
1
+ import type { StaticDecode } from "typebox";
2
+ import { Type } from "typebox";
3
+ export declare const PortalFlowStateSchema: Type.TUnion<[Type.TObject<{
4
+ status: Type.TLiteral<"choose_provider">;
5
+ flowId: Type.TString;
6
+ providers: Type.TArray<Type.TObject<{
7
+ id: Type.TString;
8
+ displayName: Type.TString;
9
+ }>>;
10
+ app: Type.TObject<{
11
+ displayName: Type.TString;
12
+ }>;
13
+ portal: Type.TOptional<Type.TObject<{}>>;
14
+ registration: Type.TOptional<Type.TObject<{}>>;
15
+ }>, Type.TObject<{
16
+ status: Type.TLiteral<"processing">;
17
+ flowId: Type.TString;
18
+ }>, Type.TObject<{
19
+ status: Type.TLiteral<"approval_required">;
20
+ flowId: Type.TString;
21
+ consentViewDigest: Type.TString;
22
+ optionalBundles: Type.TArray<Type.TObject<{}>>;
23
+ user: Type.TObject<{
24
+ origin: Type.TString;
25
+ id: Type.TString;
26
+ name: Type.TOptional<Type.TString>;
27
+ email: Type.TOptional<Type.TString>;
28
+ image: Type.TOptional<Type.TString>;
29
+ }>;
30
+ approval: Type.TObject<{
31
+ contractId: Type.TString;
32
+ contractDigest: Type.TString;
33
+ displayName: Type.TString;
34
+ description: Type.TString;
35
+ capabilities: Type.TRecord<"^.*$", Type.TObject<{
36
+ displayName: Type.TString;
37
+ description: Type.TString;
38
+ }>>;
39
+ }>;
40
+ }>, Type.TObject<{
41
+ status: Type.TLiteral<"approval_denied">;
42
+ flowId: Type.TString;
43
+ approval: Type.TObject<{
44
+ contractId: Type.TString;
45
+ contractDigest: Type.TString;
46
+ displayName: Type.TString;
47
+ description: Type.TString;
48
+ capabilities: Type.TRecord<"^.*$", Type.TObject<{
49
+ displayName: Type.TString;
50
+ description: Type.TString;
51
+ }>>;
52
+ }>;
53
+ returnLocation: Type.TOptional<Type.TString>;
54
+ }>, Type.TObject<{
55
+ status: Type.TLiteral<"insufficient_capabilities">;
56
+ flowId: Type.TString;
57
+ user: Type.TOptional<Type.TObject<{
58
+ origin: Type.TString;
59
+ id: Type.TString;
60
+ name: Type.TOptional<Type.TString>;
61
+ email: Type.TOptional<Type.TString>;
62
+ image: Type.TOptional<Type.TString>;
63
+ }>>;
64
+ approval: Type.TObject<{
65
+ contractId: Type.TString;
66
+ contractDigest: Type.TString;
67
+ displayName: Type.TString;
68
+ description: Type.TString;
69
+ capabilities: Type.TRecord<"^.*$", Type.TObject<{
70
+ displayName: Type.TString;
71
+ description: Type.TString;
72
+ }>>;
73
+ }>;
74
+ missingCapabilities: Type.TArray<Type.TString>;
75
+ userCapabilities: Type.TArray<Type.TString>;
76
+ returnLocation: Type.TOptional<Type.TString>;
77
+ }>, Type.TObject<{
78
+ status: Type.TLiteral<"redirect">;
79
+ location: Type.TString;
80
+ }>, Type.TObject<{
81
+ status: Type.TLiteral<"expired">;
82
+ returnLocation: Type.TOptional<Type.TString>;
83
+ }>]>;
84
+ export type PortalFlowState = StaticDecode<typeof PortalFlowStateSchema>;