@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,179 @@
1
+ import { type VerifiedAuthorizationContextHandle as WasmAuthorizationContextHandle } from "./protocol_wasm/trellis_protocol_wasm.js";
2
+ /** Verification policy accepted by the Rust authorization protocol. */
3
+ export type AuthorizationVerificationPolicy = {
4
+ nowUnixSeconds: number;
5
+ allowedClockSkewSeconds: number;
6
+ maximumContextLifetimeSeconds: number;
7
+ maximumContextBytes: number;
8
+ maximumPermissions: number;
9
+ };
10
+ /** Context verification policy fields used to schedule refresh. */
11
+ export type AuthorizationContextVerificationPolicy = AuthorizationVerificationPolicy & {
12
+ refreshLeadSeconds: number;
13
+ refreshJitterSeconds: number;
14
+ };
15
+ /** Online issuer entry and signed context supplied to a local verifier. */
16
+ export type AuthorizationContextVerificationInput = {
17
+ issuer: AuthorizationIssuerKey;
18
+ context: unknown;
19
+ };
20
+ /** Public issuer entry authenticated by the configured Trellis origin. */
21
+ export type AuthorizationIssuerKey = {
22
+ keyId: string;
23
+ publicKey: string;
24
+ state: "active" | "retired" | "revoked";
25
+ };
26
+ /** Meta-authority not represented by ordinary permission atoms. */
27
+ export type PlatformPrivilege = "trellis.auth::admin";
28
+ /** One exact API or participant-resource permission target. */
29
+ export type PermissionTarget = {
30
+ kind: "apiSurface";
31
+ api: string;
32
+ surface: "rpc" | "operation" | "event" | "feed" | "state";
33
+ name: string;
34
+ } | {
35
+ kind: "participantResource";
36
+ participant: string;
37
+ resource: "kv" | "store" | "jobQueue" | "eventConsumer" | "state";
38
+ name: string;
39
+ } | {
40
+ kind: "operationSignal";
41
+ api: string;
42
+ operation: string;
43
+ signal: string;
44
+ };
45
+ /** One exact machine-enforceable permission atom. */
46
+ export type PermissionAtom = {
47
+ target: PermissionTarget;
48
+ action: "call" | "invoke" | "observe" | "cancel" | "control" | "publish" | "subscribe" | "read" | "write" | "delete" | "submit" | "process" | "consume";
49
+ };
50
+ /** Grant set projection returned by local authorization verification. */
51
+ export type GrantSet = {
52
+ format: "trellis.grant-set.v1";
53
+ permissions: PermissionAtom[];
54
+ };
55
+ /** Verified request caller projection. */
56
+ export type VerifiedAuthorizationRequestProjection = {
57
+ contextDigest: string;
58
+ };
59
+ /** Verified event publisher projection. */
60
+ export type VerifiedAuthorizationEventPublisher = {
61
+ kind: "user" | "service" | "device";
62
+ deploymentId: string | null;
63
+ instanceId: string | null;
64
+ participantId: string;
65
+ connectionId: string;
66
+ loginSessionId: string | null;
67
+ };
68
+ /** Verified event publisher projection. */
69
+ export type VerifiedAuthorizationEventProjection = VerifiedAuthorizationRequestProjection & {
70
+ publisher: VerifiedAuthorizationEventPublisher;
71
+ };
72
+ /** Stable error categories returned by local authorization verification. */
73
+ export type AuthorizationVerificationErrorCode = "InvalidInput" | "SerializationError" | "InvalidFormat" | "UnsafeJsonInteger" | "InvalidEncoding" | "InvalidPublicKey" | "InvalidKeyId" | "InvalidSignature" | "UnknownCriticalExtension" | "NonCanonicalSet" | "InvalidValidityWindow" | "IssuerRevoked" | "IssuerRetired" | "HistoricalContext" | "ContextNotYetValid" | "ContextExpired" | "ContextLifetimeExceeded" | "InvalidSessionKey" | "PermissionDenied" | "ContextTooLarge" | "ProofIatOutOfRange" | "InvalidRequestProof" | "ReplySubjectMismatch" | "InvalidEventTime" | "InvalidEventProof" | "EventRevoked";
74
+ /** Stable structured local authorization failure. */
75
+ export type AuthorizationVerificationError = {
76
+ code: AuthorizationVerificationErrorCode;
77
+ path: string;
78
+ };
79
+ /** Result envelope returned by a local request authorization verifier. */
80
+ export type VerifyAuthorizationRequestResult = ({
81
+ ok: true;
82
+ } & VerifiedAuthorizationRequestProjection) | {
83
+ ok: false;
84
+ error: AuthorizationVerificationError;
85
+ };
86
+ /** Result envelope returned by a local event authorization verifier. */
87
+ export type VerifyAuthorizationEventResult = ({
88
+ ok: true;
89
+ } & VerifiedAuthorizationEventProjection) | {
90
+ ok: false;
91
+ error: AuthorizationVerificationError;
92
+ };
93
+ /** Arguments for local context-bound request authorization. */
94
+ export type VerifyAuthorizationRequestArgs = {
95
+ contextHandle: AuthorizationContextHandle;
96
+ subject: string;
97
+ reply: string | null;
98
+ payload: Uint8Array;
99
+ iat: number;
100
+ requestId: string;
101
+ proof: string;
102
+ requiredPermissions: PermissionAtom[];
103
+ policy: AuthorizationVerificationPolicy;
104
+ };
105
+ /** Arguments for local context-bound event authorization. */
106
+ export type VerifyAuthorizationEventArgs = {
107
+ contextHandle: AuthorizationContextHandle;
108
+ descriptorIdentity: string;
109
+ subject: string;
110
+ payload: Uint8Array;
111
+ eventId: string;
112
+ eventTime: string;
113
+ proof: string;
114
+ policy: AuthorizationVerificationPolicy;
115
+ revokedAt?: number | null;
116
+ };
117
+ /** Projection returned after verifying an online-issued context. */
118
+ export type VerifiedAuthorizationContextTokenProjection = {
119
+ issuer: AuthorizationIssuerKey;
120
+ contextDigest: string;
121
+ refreshAt: number;
122
+ context: Record<string, unknown> & {
123
+ ownerKind: "deployment" | "user";
124
+ ownerId: string;
125
+ grantRevision: number;
126
+ principalId: string;
127
+ principalKind: "user" | "service" | "device";
128
+ participantId: string;
129
+ identityKeyId: string | null;
130
+ loginSessionId: string | null;
131
+ deploymentId: string | null;
132
+ instanceId: string | null;
133
+ issuerKeyId: string;
134
+ connectionId: string;
135
+ sessionKey: string;
136
+ inboxPrefix: string;
137
+ issuedAt: number;
138
+ notBefore: number;
139
+ expiresAt: number;
140
+ grants: GrantSet;
141
+ platformPrivileges: PlatformPrivilege[];
142
+ };
143
+ };
144
+ /** Opaque Rust/WASM verification state for one authorization context. */
145
+ export type AuthorizationContextHandle = WasmAuthorizationContextHandle;
146
+ /** Initialize the shared Rust protocol implementation before asynchronous use. */
147
+ export declare function initializeProtocolWasm(): Promise<void>;
148
+ /** Initialize the shared Rust protocol implementation before synchronous use. */
149
+ export declare function initializeProtocolWasmSync(): void;
150
+ /** Derive an API-qualified event subject through the shared Rust protocol. */
151
+ export declare function eventSubjectWasm(apiId: string, action: string): Promise<string>;
152
+ /** Compute the shared query binding for an opaque pagination cursor. */
153
+ export declare function paginationQueryDigest(endpoint: string, query: unknown): Promise<string>;
154
+ /** Encode a value with the shared versioned pagination cursor codec. */
155
+ export declare function encodePaginationCursor(queryDigest: string, after: unknown): Promise<string>;
156
+ /** Decode and query-bind a value with the shared pagination cursor codec. */
157
+ export declare function decodePaginationCursor<T>(cursor: string, queryDigest: string): Promise<T>;
158
+ /** Verify a complete signed authorization context through Rust/WASM. */
159
+ export declare function verifyAuthorizationContextWasm(args: {
160
+ issuer: AuthorizationIssuerKey;
161
+ context: unknown;
162
+ policy: AuthorizationContextVerificationPolicy;
163
+ }): Promise<VerifiedAuthorizationContextTokenProjection>;
164
+ /** Verify and retain one authorization context for repeated proof checks. */
165
+ export declare function createAuthorizationContextHandleWasm(args: {
166
+ issuer: AuthorizationIssuerKey;
167
+ context: unknown;
168
+ policy: AuthorizationContextVerificationPolicy;
169
+ historical?: boolean;
170
+ }): Promise<{
171
+ handle: AuthorizationContextHandle;
172
+ verified: VerifiedAuthorizationContextTokenProjection;
173
+ }>;
174
+ /** Require an opaque verified context to be currently eligible. */
175
+ export declare function assertAuthorizationContextHandleCurrentWasm(handle: AuthorizationContextHandle, policy: AuthorizationContextVerificationPolicy): void;
176
+ /** Verify one context-bound request proof using actual received request bytes. */
177
+ export declare function verifyAuthorizationRequestWasm(args: VerifyAuthorizationRequestArgs): Promise<VerifyAuthorizationRequestResult>;
178
+ /** Verify one context-bound event proof, including historical time/revocation checks. */
179
+ export declare function verifyAuthorizationEventWasm(args: VerifyAuthorizationEventArgs): Promise<VerifyAuthorizationEventResult>;
@@ -0,0 +1,133 @@
1
+ import init, { initSync, } from "./protocol_wasm/trellis_protocol_wasm.js";
2
+ import * as protocolWasmModule from "./protocol_wasm/trellis_protocol_wasm.js";
3
+ import { PROTOCOL_WASM_BASE64 } from "./protocol_wasm/trellis_protocol_wasm_bytes.js";
4
+ import { base64urlDecode } from "./utils.js";
5
+ const protocolWasm = protocolWasmModule;
6
+ let initialized;
7
+ let initializedSync = false;
8
+ async function wasmBytes() {
9
+ const url = new URL("./protocol_wasm/trellis_protocol_wasm_bg.wasm", import.meta.url);
10
+ if (url.protocol === "file:") {
11
+ const { readFile } = await import("node:fs/promises");
12
+ return new Uint8Array(await readFile(url));
13
+ }
14
+ const response = await fetch(url);
15
+ if (!response.ok) {
16
+ throw new Error(`authorization protocol WASM returned HTTP ${response.status}`);
17
+ }
18
+ return new Uint8Array(await response.arrayBuffer());
19
+ }
20
+ /** Initialize the shared Rust protocol implementation before asynchronous use. */
21
+ export async function initializeProtocolWasm() {
22
+ initialized ??= (async () => {
23
+ await init({ module_or_path: await wasmBytes() });
24
+ })();
25
+ await initialized;
26
+ }
27
+ /** Initialize the shared Rust protocol implementation before synchronous use. */
28
+ export function initializeProtocolWasmSync() {
29
+ if (initializedSync)
30
+ return;
31
+ const url = new URL("./protocol_wasm/trellis_protocol_wasm_bg.wasm", import.meta.url);
32
+ const runtime = globalThis;
33
+ const process = runtime["pro" + "cess"];
34
+ if (process?.versions?.node && process.getBuiltinModule) {
35
+ initSync({
36
+ module: process.getBuiltinModule("node:fs").readFileSync(url),
37
+ });
38
+ initializedSync = true;
39
+ return;
40
+ }
41
+ const binary = atob(PROTOCOL_WASM_BASE64);
42
+ const bytes = new Uint8Array(binary.length);
43
+ for (let index = 0; index < binary.length; index += 1) {
44
+ bytes[index] = binary.charCodeAt(index);
45
+ }
46
+ initSync({ module: bytes });
47
+ initializedSync = true;
48
+ }
49
+ /** Derive an API-qualified event subject through the shared Rust protocol. */
50
+ export async function eventSubjectWasm(apiId, action) {
51
+ await initializeProtocolWasm();
52
+ return protocolWasm.event_subject(apiId, action);
53
+ }
54
+ /** Compute the shared query binding for an opaque pagination cursor. */
55
+ export async function paginationQueryDigest(endpoint, query) {
56
+ await initializeProtocolWasm();
57
+ return protocolWasm.pagination_query_digest(endpoint, JSON.stringify(query));
58
+ }
59
+ /** Encode a value with the shared versioned pagination cursor codec. */
60
+ export async function encodePaginationCursor(queryDigest, after) {
61
+ await initializeProtocolWasm();
62
+ return protocolWasm.encode_pagination_cursor(queryDigest, JSON.stringify(after));
63
+ }
64
+ /** Decode and query-bind a value with the shared pagination cursor codec. */
65
+ export async function decodePaginationCursor(cursor, queryDigest) {
66
+ await initializeProtocolWasm();
67
+ return JSON.parse(protocolWasm.decode_pagination_cursor(cursor, queryDigest));
68
+ }
69
+ /** Verify a complete signed authorization context through Rust/WASM. */
70
+ export async function verifyAuthorizationContextWasm(args) {
71
+ const { handle, verified } = await createAuthorizationContextHandleWasm(args);
72
+ handle.free();
73
+ return verified;
74
+ }
75
+ /** Verify and retain one authorization context for repeated proof checks. */
76
+ export async function createAuthorizationContextHandleWasm(args) {
77
+ await initializeProtocolWasm();
78
+ const handle = protocolWasm.create_authorization_context_handle(JSON.stringify(args.issuer), JSON.stringify(args.context), JSON.stringify(wasmVerificationPolicy(args.policy)), args.historical ?? false);
79
+ try {
80
+ const result = JSON.parse(handle.projection());
81
+ const jitter = contextJitter(result.contextDigest, args.policy.refreshJitterSeconds);
82
+ return {
83
+ handle,
84
+ verified: {
85
+ ...result,
86
+ refreshAt: result.context.expiresAt - args.policy.refreshLeadSeconds -
87
+ jitter,
88
+ },
89
+ };
90
+ }
91
+ catch (error) {
92
+ handle.free();
93
+ throw error;
94
+ }
95
+ }
96
+ /** Require an opaque verified context to be currently eligible. */
97
+ export function assertAuthorizationContextHandleCurrentWasm(handle, policy) {
98
+ handle.assert_current(JSON.stringify(wasmVerificationPolicy(policy)));
99
+ }
100
+ /** Verify one context-bound request proof using actual received request bytes. */
101
+ export async function verifyAuthorizationRequestWasm(args) {
102
+ await initializeProtocolWasm();
103
+ const { contextHandle, payload, ...input } = args;
104
+ return JSON.parse(protocolWasm.verify_authorization_request(contextHandle, JSON.stringify({
105
+ ...input,
106
+ policy: wasmVerificationPolicy(args.policy),
107
+ }), payload));
108
+ }
109
+ /** Verify one context-bound event proof, including historical time/revocation checks. */
110
+ export async function verifyAuthorizationEventWasm(args) {
111
+ await initializeProtocolWasm();
112
+ const { contextHandle, payload, ...input } = args;
113
+ return JSON.parse(protocolWasm.verify_authorization_event(contextHandle, JSON.stringify({
114
+ ...input,
115
+ policy: wasmVerificationPolicy(args.policy),
116
+ }), payload));
117
+ }
118
+ function wasmVerificationPolicy(policy) {
119
+ return {
120
+ nowUnixSeconds: policy.nowUnixSeconds,
121
+ allowedClockSkewSeconds: policy.allowedClockSkewSeconds,
122
+ maximumContextLifetimeSeconds: policy.maximumContextLifetimeSeconds,
123
+ maximumContextBytes: policy.maximumContextBytes,
124
+ maximumPermissions: policy.maximumPermissions,
125
+ };
126
+ }
127
+ function contextJitter(contextDigest, maximum) {
128
+ const bytes = base64urlDecode(contextDigest);
129
+ let value = 0n;
130
+ for (const byte of bytes.slice(0, 8))
131
+ value = (value << 8n) | BigInt(byte);
132
+ return Number(value % BigInt(maximum + 1));
133
+ }
@@ -0,0 +1,30 @@
1
+ import { type Authenticator } from "@nats-io/nats-core";
2
+ import type { AuthorizationProviderCache } from "./authorization_context.ts";
3
+ import { type SessionProof, type SessionProofInput } from "./session_proof.ts";
4
+ export type NatsConnectOptions = {
5
+ authenticator: Authenticator | Authenticator[];
6
+ inboxPrefix: string;
7
+ };
8
+ export type TrellisAuth = {
9
+ sessionKey: string;
10
+ sessionNkey: string;
11
+ sign: (data: Uint8Array) => Promise<Uint8Array>;
12
+ currentIat: () => number;
13
+ setServerClockOffsetMs: (clockOffsetMs: number) => void;
14
+ /** Current authorization-context digest bound into v1 request and event proofs. */
15
+ contextDigest: () => string;
16
+ /** Local verifier for received requests and events. */
17
+ authorizationProviderCache?: AuthorizationProviderCache;
18
+ createProof: (subject: string, payloadHash: Uint8Array, reply: string, requestId?: string, iat?: number) => Promise<string>;
19
+ signSessionProof: (input: SessionProofInput) => Promise<SessionProof>;
20
+ natsConnectOptions: (opts: {
21
+ sessionId: string;
22
+ contextDigest: string | (() => string);
23
+ jwt: string | (() => string);
24
+ authorizationUsable?: () => boolean;
25
+ }) => Promise<NatsConnectOptions>;
26
+ };
27
+ export declare function createAuth(opts: {
28
+ sessionKeySeed: string;
29
+ contextDigest?: string | (() => string);
30
+ }): Promise<TrellisAuth>;
@@ -0,0 +1,77 @@
1
+ import { jwtAuthenticator } from "@nats-io/nats-core";
2
+ import { fromSeed, Prefix } from "@nats-io/nkeys";
3
+ import { Codec } from "@nats-io/nkeys/lib/codec.js";
4
+ import { ulid } from "ulid";
5
+ import { importEd25519PrivateKeyFromSeedBase64url, publicKeyBase64urlFromSeed, } from "./keys.js";
6
+ import { createProof } from "./proof.js";
7
+ import { signSessionProof, } from "./session_proof.js";
8
+ import { correctedIatSeconds } from "./time.js";
9
+ import { base64urlDecode, base64urlEncode, canonicalizeJsonValue, sha256, toArrayBuffer, utf8, } from "./utils.js";
10
+ export async function createAuth(opts) {
11
+ const seed = base64urlDecode(opts.sessionKeySeed);
12
+ const privateKey = await importEd25519PrivateKeyFromSeedBase64url(opts.sessionKeySeed);
13
+ const sessionKey = publicKeyBase64urlFromSeed(seed);
14
+ const encodedSeed = Codec.encodeSeed(Prefix.User, seed);
15
+ const sessionNkey = fromSeed(encodedSeed).getPublicKey();
16
+ let serverClockOffsetMs = 0;
17
+ const resolveContextDigest = () => {
18
+ const digest = typeof opts.contextDigest === "function"
19
+ ? opts.contextDigest()
20
+ : opts.contextDigest;
21
+ if (digest === undefined) {
22
+ throw new Error("contextDigest is required to sign v1 request proofs");
23
+ }
24
+ return digest;
25
+ };
26
+ const sign = async (data) => {
27
+ const sig = await crypto.subtle.sign({ name: "Ed25519" }, privateKey, toArrayBuffer(data));
28
+ return new Uint8Array(sig);
29
+ };
30
+ const currentIat = () => correctedIatSeconds(Date.now(), serverClockOffsetMs);
31
+ return {
32
+ sessionKey,
33
+ sessionNkey,
34
+ sign,
35
+ currentIat,
36
+ setServerClockOffsetMs: (clockOffsetMs) => {
37
+ serverClockOffsetMs = clockOffsetMs;
38
+ },
39
+ contextDigest: resolveContextDigest,
40
+ createProof: (subject, payloadHash, reply, requestId, iat) => createProof(privateKey, {
41
+ contextDigest: resolveContextDigest(),
42
+ subject,
43
+ reply,
44
+ payloadHash,
45
+ iat: iat ?? currentIat(),
46
+ requestId: requestId ?? ulid(),
47
+ }),
48
+ signSessionProof: (input) => signSessionProof(input, privateKey, sessionKey),
49
+ natsConnectOptions: (options) => {
50
+ return Promise.resolve({
51
+ authenticator: [
52
+ jwtAuthenticator(options.jwt, encodedSeed),
53
+ (nonce) => {
54
+ if (options.authorizationUsable?.() === false) {
55
+ throw new Error("authorization context is suspended");
56
+ }
57
+ if (!nonce)
58
+ throw new Error("NATS server nonce is required");
59
+ const contextDigest = typeof options.contextDigest === "function"
60
+ ? options.contextDigest()
61
+ : options.contextDigest;
62
+ if (!contextDigest) {
63
+ throw new Error("contextDigest is required for NATS connect");
64
+ }
65
+ return {
66
+ auth_token: JSON.stringify({
67
+ format: "trellis.nats-connect-token.v1",
68
+ contextDigest,
69
+ }),
70
+ };
71
+ },
72
+ ],
73
+ inboxPrefix: `_INBOX.${options.sessionId}`,
74
+ });
75
+ },
76
+ };
77
+ }
@@ -0,0 +1,53 @@
1
+ /** Strict signature envelope shared by auth, bootstrap, and context refresh. */
2
+ export declare const SESSION_PROOF_FORMAT_V1: "trellis.session-proof.v1";
3
+ /** One protocol-owned signature purpose. */
4
+ export type SessionProofPurpose = "userAuthRequest" | "userAuthBind" | "serviceBootstrap" | "deviceBootstrap" | "deviceEnrollment" | "authorizationContextRefresh";
5
+ /** Inputs validated and encoded by the Rust session-proof protocol. */
6
+ export type SessionProofInput = {
7
+ purpose: "userAuthBind";
8
+ origin: string;
9
+ flowId: string;
10
+ sessionPublicKey: string;
11
+ unsignedRequest: Record<string, unknown> & {
12
+ issuedAt: number;
13
+ };
14
+ } | {
15
+ purpose: "userAuthRequest";
16
+ origin: string;
17
+ unsignedRequest: Record<string, unknown> & {
18
+ issuedAt: number;
19
+ };
20
+ } | {
21
+ purpose: "serviceBootstrap" | "deviceBootstrap" | "deviceEnrollment";
22
+ origin: string;
23
+ unsignedRequest: Record<string, unknown> & {
24
+ iat: number;
25
+ };
26
+ } | {
27
+ purpose: "authorizationContextRefresh";
28
+ origin: string;
29
+ sessionPublicKey: string;
30
+ unsignedRequest: Record<string, unknown> & {
31
+ issuedAt: number;
32
+ };
33
+ };
34
+ /** One strict session-proof signature envelope. */
35
+ export type SessionProof = {
36
+ format: typeof SESSION_PROOF_FORMAT_V1;
37
+ signature: string;
38
+ };
39
+ /** Freshness limits enforced by the Rust verifier. */
40
+ export type SessionProofPolicy = {
41
+ maximumAgeMs: number;
42
+ maximumFutureSkewMs: number;
43
+ };
44
+ /** Parse and validate one signature envelope through Rust. */
45
+ export declare function parseSessionProof(value: unknown): SessionProof;
46
+ /** Hash a browser proof-bearing request using its protocol-owned payload rules. */
47
+ export declare function sessionProofRequestDigest(request: Record<string, unknown>): Promise<string>;
48
+ /** Return the protocol-owned signing digest without implementing its framing in JS. */
49
+ export declare function sessionProofSigningDigest(input: SessionProofInput): Promise<string>;
50
+ /** Sign the Rust-produced digest, then verify the declared key and signature in Rust. */
51
+ export declare function signSessionProof(input: SessionProofInput, privateKey: CryptoKey, signerPublicKey: string): Promise<SessionProof>;
52
+ /** Verify signature, signer binding, input shape, and freshness through Rust. */
53
+ export declare function verifySessionProof(input: SessionProofInput, proof: SessionProof, signerPublicKey: string, nowMs: number, policy?: SessionProofPolicy): Promise<void>;
@@ -0,0 +1,43 @@
1
+ import { initializeProtocolWasm, initializeProtocolWasmSync, } from "./protocol_wasm.js";
2
+ import * as protocol from "./protocol_wasm/trellis_protocol_wasm.js";
3
+ import { base64urlDecode, base64urlEncode, toArrayBuffer } from "./utils.js";
4
+ /** Strict signature envelope shared by auth, bootstrap, and context refresh. */
5
+ export const SESSION_PROOF_FORMAT_V1 = "trellis.session-proof.v1";
6
+ /** Parse and validate one signature envelope through Rust. */
7
+ export function parseSessionProof(value) {
8
+ initializeProtocolWasmSync();
9
+ return JSON.parse(protocol.parse_session_proof(JSON.stringify(value)));
10
+ }
11
+ /** Hash a browser proof-bearing request using its protocol-owned payload rules. */
12
+ export async function sessionProofRequestDigest(request) {
13
+ await initializeProtocolWasm();
14
+ return protocol.session_proof_request_digest(JSON.stringify(request));
15
+ }
16
+ /** Return the protocol-owned signing digest without implementing its framing in JS. */
17
+ export async function sessionProofSigningDigest(input) {
18
+ await initializeProtocolWasm();
19
+ return protocol.session_proof_signing_digest(JSON.stringify(input));
20
+ }
21
+ /** Sign the Rust-produced digest, then verify the declared key and signature in Rust. */
22
+ export async function signSessionProof(input, privateKey, signerPublicKey) {
23
+ const digest = base64urlDecode(await sessionProofSigningDigest(input));
24
+ const signature = await crypto.subtle.sign({ name: "Ed25519" }, privateKey, toArrayBuffer(digest));
25
+ const proof = {
26
+ format: SESSION_PROOF_FORMAT_V1,
27
+ signature: base64urlEncode(new Uint8Array(signature)),
28
+ };
29
+ await verifySessionProof(input, proof, signerPublicKey, Number(input.purpose === "serviceBootstrap" ||
30
+ input.purpose === "deviceBootstrap" ||
31
+ input.purpose === "deviceEnrollment"
32
+ ? input.unsignedRequest.iat
33
+ : input.unsignedRequest.issuedAt), { maximumAgeMs: 0, maximumFutureSkewMs: 0 });
34
+ return proof;
35
+ }
36
+ /** Verify signature, signer binding, input shape, and freshness through Rust. */
37
+ export async function verifySessionProof(input, proof, signerPublicKey, nowMs, policy = {
38
+ maximumAgeMs: 30_000,
39
+ maximumFutureSkewMs: 30_000,
40
+ }) {
41
+ await initializeProtocolWasm();
42
+ protocol.verify_session_proof(JSON.stringify(input), JSON.stringify(proof), signerPublicKey, nowMs, policy.maximumAgeMs, policy.maximumFutureSkewMs);
43
+ }
package/auth/time.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export declare function estimateMidpointClockOffsetMs(args: {
2
+ requestStartedAtMs: number;
3
+ responseReceivedAtMs: number;
4
+ serverNowSeconds: number;
5
+ }): number;
6
+ export declare function correctedIatSeconds(nowMs?: number, clockOffsetMs?: number): number;
package/auth/time.js ADDED
@@ -0,0 +1,7 @@
1
+ export function estimateMidpointClockOffsetMs(args) {
2
+ const midpointMs = (args.requestStartedAtMs + args.responseReceivedAtMs) / 2;
3
+ return args.serverNowSeconds * 1_000 - midpointMs;
4
+ }
5
+ export function correctedIatSeconds(nowMs = Date.now(), clockOffsetMs = 0) {
6
+ return Math.floor((nowMs + clockOffsetMs) / 1_000);
7
+ }
@@ -0,0 +1 @@
1
+ export declare function trellisIdFromOriginId(origin: string, id: string): Promise<string>;
@@ -0,0 +1,5 @@
1
+ import { base64urlEncode, sha256, utf8 } from "./utils.js";
2
+ export async function trellisIdFromOriginId(origin, id) {
3
+ const digest = await sha256(utf8(`${origin}:${id}`));
4
+ return base64urlEncode(digest).slice(0, 22);
5
+ }
@@ -0,0 +1,10 @@
1
+ export type JsonValue = null | boolean | number | string | JsonValue[] | {
2
+ [key: string]: JsonValue;
3
+ };
4
+ export declare function utf8(s: string): Uint8Array;
5
+ export declare function canonicalizeJson(value: JsonValue): string;
6
+ export declare function toArrayBuffer(data: Uint8Array): ArrayBuffer;
7
+ export declare function base64urlEncode(data: Uint8Array): string;
8
+ export declare function base64urlDecode(s: string): Uint8Array;
9
+ export declare function sha256(data: Uint8Array): Promise<Uint8Array>;
10
+ export declare function canonicalizeJsonValue(value: unknown): string;
package/auth/utils.js ADDED
@@ -0,0 +1,69 @@
1
+ export function utf8(s) {
2
+ return new TextEncoder().encode(s);
3
+ }
4
+ export function canonicalizeJson(value) {
5
+ if (value === null)
6
+ return "null";
7
+ if (typeof value === "boolean")
8
+ return value ? "true" : "false";
9
+ if (typeof value === "number")
10
+ return JSON.stringify(value);
11
+ if (typeof value === "string")
12
+ return JSON.stringify(value);
13
+ if (Array.isArray(value)) {
14
+ return `[${value.map(canonicalizeJson).join(",")}]`;
15
+ }
16
+ const keys = Object.keys(value).sort();
17
+ return `{${keys.map((key) => `${JSON.stringify(key)}:${canonicalizeJson(value[key])}`).join(",")}}`;
18
+ }
19
+ export function toArrayBuffer(data) {
20
+ const buf = data.buffer;
21
+ if (buf instanceof ArrayBuffer) {
22
+ return buf.slice(data.byteOffset, data.byteOffset + data.byteLength);
23
+ }
24
+ const copy = new Uint8Array(data.byteLength);
25
+ copy.set(data);
26
+ return copy.buffer;
27
+ }
28
+ export function base64urlEncode(data) {
29
+ const b64 = btoa(String.fromCharCode(...data));
30
+ return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
31
+ }
32
+ export function base64urlDecode(s) {
33
+ const normalized = s.replace(/-/g, "+").replace(/_/g, "/");
34
+ const padLen = (4 - (normalized.length % 4)) % 4;
35
+ const padded = normalized + "=".repeat(padLen);
36
+ const bin = atob(padded);
37
+ const out = new Uint8Array(bin.length);
38
+ for (let i = 0; i < bin.length; i++)
39
+ out[i] = bin.charCodeAt(i);
40
+ return out;
41
+ }
42
+ export async function sha256(data) {
43
+ const digest = await crypto.subtle.digest("SHA-256", toArrayBuffer(data));
44
+ return new Uint8Array(digest);
45
+ }
46
+ function canonicalizeUnknownJsonValue(value) {
47
+ if (value === null)
48
+ return "null";
49
+ if (typeof value === "boolean")
50
+ return value ? "true" : "false";
51
+ if (typeof value === "number") {
52
+ if (!Number.isFinite(value))
53
+ throw new Error("JSON numbers must be finite");
54
+ return JSON.stringify(value);
55
+ }
56
+ if (typeof value === "string")
57
+ return JSON.stringify(value);
58
+ if (Array.isArray(value)) {
59
+ return `[${value.map(canonicalizeUnknownJsonValue).join(",")}]`;
60
+ }
61
+ if (typeof value === "object") {
62
+ const keys = Object.keys(value).sort();
63
+ return `{${keys.map((key) => `${JSON.stringify(key)}:${canonicalizeUnknownJsonValue(value[key])}`).join(",")}}`;
64
+ }
65
+ throw new Error("Value is not JSON-serializable");
66
+ }
67
+ export function canonicalizeJsonValue(value) {
68
+ return canonicalizeUnknownJsonValue(value);
69
+ }
package/auth.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./auth/mod.ts";
package/auth.js ADDED
@@ -0,0 +1 @@
1
+ export * from "./auth/mod.js";