@dual-os/sdk 0.0.0-stage → 0.8.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/LICENSE +4 -0
  2. package/README.md +19 -2
  3. package/dist/Action.d.ts +201 -0
  4. package/dist/Action.d.ts.map +1 -0
  5. package/dist/Action.js +172 -0
  6. package/dist/Action.js.map +1 -0
  7. package/dist/AgentChannel.d.ts +1717 -0
  8. package/dist/AgentChannel.d.ts.map +1 -0
  9. package/dist/AgentChannel.js +708 -0
  10. package/dist/AgentChannel.js.map +1 -0
  11. package/dist/AgentChannelConformance.d.ts +1543 -0
  12. package/dist/AgentChannelConformance.d.ts.map +1 -0
  13. package/dist/AgentChannelConformance.js +163 -0
  14. package/dist/AgentChannelConformance.js.map +1 -0
  15. package/dist/AgentChannelRuntime.d.ts +78 -0
  16. package/dist/AgentChannelRuntime.d.ts.map +1 -0
  17. package/dist/AgentChannelRuntime.js +270 -0
  18. package/dist/AgentChannelRuntime.js.map +1 -0
  19. package/dist/AiProvider.d.ts +132 -0
  20. package/dist/AiProvider.d.ts.map +1 -0
  21. package/dist/AiProvider.js +100 -0
  22. package/dist/AiProvider.js.map +1 -0
  23. package/dist/AuthMethod.d.ts +381 -0
  24. package/dist/AuthMethod.d.ts.map +1 -0
  25. package/dist/AuthMethod.js +225 -0
  26. package/dist/AuthMethod.js.map +1 -0
  27. package/dist/AuthMethodBinding.d.ts +77 -0
  28. package/dist/AuthMethodBinding.d.ts.map +1 -0
  29. package/dist/AuthMethodBinding.js +31 -0
  30. package/dist/AuthMethodBinding.js.map +1 -0
  31. package/dist/AuthMethodExecution.d.ts +223 -0
  32. package/dist/AuthMethodExecution.d.ts.map +1 -0
  33. package/dist/AuthMethodExecution.js +277 -0
  34. package/dist/AuthMethodExecution.js.map +1 -0
  35. package/dist/ConnectionResolver.d.ts +219 -0
  36. package/dist/ConnectionResolver.d.ts.map +1 -0
  37. package/dist/ConnectionResolver.js +153 -0
  38. package/dist/ConnectionResolver.js.map +1 -0
  39. package/dist/DefinitionError.d.ts +67 -0
  40. package/dist/DefinitionError.d.ts.map +1 -0
  41. package/dist/DefinitionError.js +82 -0
  42. package/dist/DefinitionError.js.map +1 -0
  43. package/dist/DualRegistry.d.ts +71 -0
  44. package/dist/DualRegistry.d.ts.map +1 -0
  45. package/dist/DualRegistry.js +96 -0
  46. package/dist/DualRegistry.js.map +1 -0
  47. package/dist/DualRuntime.d.ts +279 -0
  48. package/dist/DualRuntime.d.ts.map +1 -0
  49. package/dist/DualRuntime.js +311 -0
  50. package/dist/DualRuntime.js.map +1 -0
  51. package/dist/Files.d.ts +80 -0
  52. package/dist/Files.d.ts.map +1 -0
  53. package/dist/Files.js +66 -0
  54. package/dist/Files.js.map +1 -0
  55. package/dist/Group.d.ts +106 -0
  56. package/dist/Group.d.ts.map +1 -0
  57. package/dist/Group.js +86 -0
  58. package/dist/Group.js.map +1 -0
  59. package/dist/Http.d.ts +342 -0
  60. package/dist/Http.d.ts.map +1 -0
  61. package/dist/Http.js +677 -0
  62. package/dist/Http.js.map +1 -0
  63. package/dist/Mcp.d.ts +109 -0
  64. package/dist/Mcp.d.ts.map +1 -0
  65. package/dist/Mcp.js +176 -0
  66. package/dist/Mcp.js.map +1 -0
  67. package/dist/OAuth2TokenRefresher.d.ts +18 -0
  68. package/dist/OAuth2TokenRefresher.d.ts.map +1 -0
  69. package/dist/OAuth2TokenRefresher.js +19 -0
  70. package/dist/OAuth2TokenRefresher.js.map +1 -0
  71. package/dist/OAuthFlow.d.ts +71 -0
  72. package/dist/OAuthFlow.d.ts.map +1 -0
  73. package/dist/OAuthFlow.js +488 -0
  74. package/dist/OAuthFlow.js.map +1 -0
  75. package/dist/Plugin.d.ts +383 -0
  76. package/dist/Plugin.d.ts.map +1 -0
  77. package/dist/Plugin.js +249 -0
  78. package/dist/Plugin.js.map +1 -0
  79. package/dist/PluginRuntime.d.ts +3186 -0
  80. package/dist/PluginRuntime.d.ts.map +1 -0
  81. package/dist/PluginRuntime.js +331 -0
  82. package/dist/PluginRuntime.js.map +1 -0
  83. package/dist/Runner.d.ts +1 -0
  84. package/dist/Runner.js +124 -0
  85. package/dist/Runner.js.map +1 -0
  86. package/dist/ToolFile.d.ts +23 -0
  87. package/dist/ToolFile.d.ts.map +1 -0
  88. package/dist/ToolFile.js +33 -0
  89. package/dist/ToolFile.js.map +1 -0
  90. package/dist/Trigger.d.ts +358 -0
  91. package/dist/Trigger.d.ts.map +1 -0
  92. package/dist/Trigger.js +287 -0
  93. package/dist/Trigger.js.map +1 -0
  94. package/dist/_virtual/_rolldown/runtime.js +13 -0
  95. package/dist/index.d.ts +24 -0
  96. package/dist/index.js +24 -0
  97. package/dist/internal/auth-context.d.ts +23 -0
  98. package/dist/internal/auth-context.d.ts.map +1 -0
  99. package/dist/internal/auth-context.js +1 -0
  100. package/dist/internal/auth-execution.d.ts +27 -0
  101. package/dist/internal/auth-execution.d.ts.map +1 -0
  102. package/dist/internal/auth-execution.js +66 -0
  103. package/dist/internal/auth-execution.js.map +1 -0
  104. package/dist/internal/auth-runtime.d.ts +5 -0
  105. package/dist/internal/auth-runtime.d.ts.map +1 -0
  106. package/dist/internal/auth-runtime.js +16 -0
  107. package/dist/internal/auth-runtime.js.map +1 -0
  108. package/dist/internal/capabilities.d.ts +24 -0
  109. package/dist/internal/capabilities.d.ts.map +1 -0
  110. package/dist/internal/capabilities.js +22 -0
  111. package/dist/internal/capabilities.js.map +1 -0
  112. package/dist/internal/children.d.ts +34 -0
  113. package/dist/internal/children.d.ts.map +1 -0
  114. package/dist/internal/children.js +53 -0
  115. package/dist/internal/children.js.map +1 -0
  116. package/dist/internal/collection-utils.d.ts +4 -0
  117. package/dist/internal/collection-utils.d.ts.map +1 -0
  118. package/dist/internal/collection-utils.js +6 -0
  119. package/dist/internal/collection-utils.js.map +1 -0
  120. package/dist/internal/dual/actions.d.ts +33 -0
  121. package/dist/internal/dual/actions.d.ts.map +1 -0
  122. package/dist/internal/dual/actions.js +26 -0
  123. package/dist/internal/dual/actions.js.map +1 -0
  124. package/dist/internal/dual/invoke.d.ts +63 -0
  125. package/dist/internal/dual/invoke.d.ts.map +1 -0
  126. package/dist/internal/dual/invoke.js +75 -0
  127. package/dist/internal/dual/invoke.js.map +1 -0
  128. package/dist/internal/dual/registry.d.ts +125 -0
  129. package/dist/internal/dual/registry.d.ts.map +1 -0
  130. package/dist/internal/dual/registry.js +172 -0
  131. package/dist/internal/dual/registry.js.map +1 -0
  132. package/dist/internal/dual/triggers.d.ts +29 -0
  133. package/dist/internal/dual/triggers.d.ts.map +1 -0
  134. package/dist/internal/dual/triggers.js +26 -0
  135. package/dist/internal/dual/triggers.js.map +1 -0
  136. package/dist/internal/handler-context.d.ts +9 -0
  137. package/dist/internal/handler-context.d.ts.map +1 -0
  138. package/dist/internal/handler-context.js +31 -0
  139. package/dist/internal/handler-context.js.map +1 -0
  140. package/dist/internal/identifier.d.ts +6 -0
  141. package/dist/internal/identifier.d.ts.map +1 -0
  142. package/dist/internal/identifier.js +28 -0
  143. package/dist/internal/identifier.js.map +1 -0
  144. package/dist/internal/plugin-handlers.d.ts +38 -0
  145. package/dist/internal/plugin-handlers.d.ts.map +1 -0
  146. package/dist/internal/plugin-handlers.js +52 -0
  147. package/dist/internal/plugin-handlers.js.map +1 -0
  148. package/dist/internal/proto.d.ts +7 -0
  149. package/dist/internal/proto.d.ts.map +1 -0
  150. package/dist/internal/proto.js +10 -0
  151. package/dist/internal/proto.js.map +1 -0
  152. package/dist/internal/schema-runtime.d.ts +6 -0
  153. package/dist/internal/schema-runtime.d.ts.map +1 -0
  154. package/dist/internal/schema-runtime.js +10 -0
  155. package/dist/internal/schema-runtime.js.map +1 -0
  156. package/dist/internal/trigger-runtime-shared.d.ts +41 -0
  157. package/dist/internal/trigger-runtime-shared.d.ts.map +1 -0
  158. package/dist/internal/trigger-runtime-shared.js +132 -0
  159. package/dist/internal/trigger-runtime-shared.js.map +1 -0
  160. package/dist/internal/trigger-runtime.d.ts +12 -0
  161. package/dist/internal/trigger-runtime.d.ts.map +1 -0
  162. package/dist/internal/trigger-runtime.js +95 -0
  163. package/dist/internal/trigger-runtime.js.map +1 -0
  164. package/dist/internal/types.d.ts +7 -0
  165. package/dist/internal/types.d.ts.map +1 -0
  166. package/dist/internal/types.js +1 -0
  167. package/dist/remote-runtime.d.ts +585 -0
  168. package/dist/remote-runtime.d.ts.map +1 -0
  169. package/dist/remote-runtime.js +367 -0
  170. package/dist/remote-runtime.js.map +1 -0
  171. package/package.json +55 -4
  172. package/src/Action.ts +370 -0
  173. package/src/AgentChannel.ts +860 -0
  174. package/src/AgentChannelConformance.ts +124 -0
  175. package/src/AgentChannelRuntime.ts +616 -0
  176. package/src/AiProvider.ts +255 -0
  177. package/src/AuthMethod.ts +954 -0
  178. package/src/AuthMethodBinding.ts +112 -0
  179. package/src/AuthMethodExecution.ts +542 -0
  180. package/src/ConnectionResolver.ts +265 -0
  181. package/src/DefinitionError.ts +115 -0
  182. package/src/DualRegistry.ts +152 -0
  183. package/src/DualRuntime.ts +1081 -0
  184. package/src/Files.ts +89 -0
  185. package/src/Group.ts +292 -0
  186. package/src/Http.ts +1205 -0
  187. package/src/Mcp.ts +299 -0
  188. package/src/OAuth2TokenRefresher.ts +22 -0
  189. package/src/OAuthFlow.ts +874 -0
  190. package/src/Plugin.ts +912 -0
  191. package/src/PluginRuntime.ts +414 -0
  192. package/src/Runner.ts +248 -0
  193. package/src/ToolFile.ts +28 -0
  194. package/src/Trigger.ts +722 -0
  195. package/src/index.ts +158 -0
  196. package/src/internal/auth-context.ts +27 -0
  197. package/src/internal/auth-execution.ts +241 -0
  198. package/src/internal/auth-runtime.ts +20 -0
  199. package/src/internal/capabilities.ts +55 -0
  200. package/src/internal/children.ts +126 -0
  201. package/src/internal/collection-utils.ts +8 -0
  202. package/src/internal/dual/actions.ts +116 -0
  203. package/src/internal/dual/invoke.ts +307 -0
  204. package/src/internal/dual/registry.ts +340 -0
  205. package/src/internal/dual/triggers.ts +128 -0
  206. package/src/internal/handler-context.ts +57 -0
  207. package/src/internal/identifier.ts +27 -0
  208. package/src/internal/plugin-handlers.ts +146 -0
  209. package/src/internal/proto.ts +8 -0
  210. package/src/internal/schema-runtime.ts +15 -0
  211. package/src/internal/trigger-runtime-shared.ts +449 -0
  212. package/src/internal/trigger-runtime.ts +223 -0
  213. package/src/internal/types.ts +12 -0
  214. package/src/remote-runtime.ts +469 -0
@@ -0,0 +1,488 @@
1
+ import { __exportAll } from "./_virtual/_rolldown/runtime.js";
2
+ import { Service as Service$1 } from "./OAuth2TokenRefresher.js";
3
+ import { OAuth2ProviderTokenResponse } from "./AuthMethod.js";
4
+ import "./OAuthFlow.js";
5
+ import { Array, Clock, ConfigProvider, Context, Effect, HashSet, Layer, Predicate, Random, Record, Redacted, Schema, String, pipe } from "effect";
6
+ import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/http";
7
+ import { Base64, Base64Url } from "effect/encoding";
8
+ //#region src/OAuthFlow.ts
9
+ /**
10
+ * OAuth protocol runner used by ConnectionStore.
11
+ *
12
+ * OAuthFlow owns provider-facing protocol mechanics: resolving OAuth client
13
+ * configuration, optional discovery, authorization URL construction, token
14
+ * exchange, token refresh, and token response normalization. It does not persist
15
+ * OAuth sessions or create Connections; ConnectionStore owns those product
16
+ * lifecycle records and calls this service for the protocol steps.
17
+ */
18
+ var OAuthFlow_exports = /* @__PURE__ */ __exportAll({
19
+ OAuthConnectionValidationFailed: () => OAuthConnectionValidationFailed,
20
+ OAuthFlow: () => OAuthFlow_exports,
21
+ OAuthGrantRejected: () => OAuthGrantRejected,
22
+ OAuthProviderRejected: () => OAuthProviderRejected,
23
+ Service: () => Service,
24
+ layer: () => layer,
25
+ oauth2TokenRefresherLayer: () => oauth2TokenRefresherLayer,
26
+ testing: () => testing
27
+ });
28
+ var OAuthConnectionValidationFailed = class extends Schema.TaggedError()("OAuthConnectionValidationFailed", {
29
+ cause: Schema.optionalKey(Schema.Redacted(Schema.Defect())),
30
+ message: Schema.String
31
+ }) {};
32
+ var OAuthProviderRejected = class extends Schema.TaggedError()("OAuthProviderRejected", {
33
+ error: Schema.String,
34
+ errorDescription: Schema.optional(Schema.String)
35
+ }) {};
36
+ var OAuthGrantRejected = class extends Schema.TaggedError()("OAuthGrantRejected", {
37
+ errorSubtype: Schema.optionalKey(Schema.String),
38
+ message: Schema.String
39
+ }) {};
40
+ const DefaultFlowTtlMs = 6e5;
41
+ Schema.Struct({
42
+ authorizationUrl: Schema.String,
43
+ expectedIssuer: Schema.optional(Schema.String),
44
+ tokenUrl: Schema.String
45
+ });
46
+ const ClientAuthentication = Schema.Union([
47
+ Schema.Literal("basic"),
48
+ Schema.Literal("post"),
49
+ Schema.Literal("none")
50
+ ]);
51
+ const ReservedTokenHeaders = HashSet.fromIterable([
52
+ "accept",
53
+ "accept-charset",
54
+ "accept-encoding",
55
+ "access-control-request-headers",
56
+ "access-control-request-method",
57
+ "authorization",
58
+ "connection",
59
+ "content-encoding",
60
+ "content-length",
61
+ "content-type",
62
+ "cookie",
63
+ "cookie2",
64
+ "date",
65
+ "dnt",
66
+ "expect",
67
+ "host",
68
+ "keep-alive",
69
+ "origin",
70
+ "permissions-policy",
71
+ "referer",
72
+ "set-cookie",
73
+ "te",
74
+ "trailer",
75
+ "transfer-encoding",
76
+ "upgrade",
77
+ "user-agent",
78
+ "via"
79
+ ]);
80
+ const TokenHeaders = Schema.Record(Schema.String, Schema.String.check(Schema.isPattern(/^[\t\x20-\x7e\x80-\xff]*$/u))).check(Schema.makeFilter((headers) => {
81
+ const names = Array.map(Record.keys(headers), String.toLowerCase);
82
+ return HashSet.size(HashSet.fromIterable(names)) === names.length && Array.every(names, (name) => /^[!#$%&'*+.^_`|~0-9a-z-]+$/u.test(name) && !HashSet.has(ReservedTokenHeaders, name) && !String.startsWith("proxy-")(name) && !String.startsWith("sec-")(name));
83
+ }, { message: "Invalid provider token headers" }));
84
+ Schema.Struct({
85
+ authorizationParams: Schema.Record(Schema.String, Schema.String),
86
+ authorizationUrl: Schema.String,
87
+ clientAuthentication: ClientAuthentication,
88
+ clientId: Schema.String,
89
+ clientSecret: Schema.optional(Schema.String),
90
+ expectedIssuer: Schema.optional(Schema.String),
91
+ pkce: Schema.Boolean,
92
+ scopes: Schema.Array(Schema.String),
93
+ tokenHeaders: TokenHeaders,
94
+ tokenParams: Schema.Record(Schema.String, Schema.String),
95
+ tokenRequestEncoding: Schema.Literals(["form", "json"]),
96
+ tokenUrl: Schema.String
97
+ });
98
+ const ProviderDiscoveryDocument = Schema.Struct({
99
+ authorization_endpoint: Schema.String,
100
+ issuer: Schema.optional(Schema.String),
101
+ token_endpoint: Schema.String
102
+ });
103
+ const decodeDiscoveryDocument = Schema.decodeUnknownSync(ProviderDiscoveryDocument);
104
+ const encodeJsonTokenParams = Schema.encodeSync(Schema.fromJsonString(Schema.Record(Schema.String, Schema.String)));
105
+ const decodeProviderTokenError = Schema.decodeSync(Schema.fromJsonString(Schema.Struct({ error: Schema.Literals([
106
+ "invalid_request",
107
+ "invalid_client",
108
+ "invalid_grant",
109
+ "unauthorized_client",
110
+ "unsupported_grant_type",
111
+ "invalid_scope",
112
+ "server_error",
113
+ "temporarily_unavailable"
114
+ ]) })));
115
+ const decodeProviderTokenErrorSubtype = Schema.decodeSync(Schema.fromJsonString(Schema.Struct({ error_subtype: Schema.Literals(["invalid_rapt", "rapt_required"]) })));
116
+ const randomBase64Url = (bytes) => {
117
+ const data = new Uint8Array(bytes);
118
+ crypto.getRandomValues(data);
119
+ return Base64Url.encode(data);
120
+ };
121
+ const sha256Base64Url = (value) => Effect.promise(() => crypto.subtle.digest("SHA-256", new TextEncoder().encode(value))).pipe(Effect.map((digest) => Base64Url.encode(new Uint8Array(digest))));
122
+ const requiredString = (value, message) => typeof value === "string" && value.trim() !== "" ? Effect.succeed(value) : Effect.fail(new OAuthConnectionValidationFailed({ message }));
123
+ const fetchDiscovery = Effect.fn("OAuthFlow.fetchDiscovery")(function* (discoveryUrl, client) {
124
+ const rawDocument = yield* pipe(HttpClient.filterStatusOk(client).get(discoveryUrl, { headers: { Accept: "application/json" } }), Effect.flatMap((response) => response.json), Effect.mapError((cause) => OAuthConnectionValidationFailed.make({
125
+ cause: Redacted.make(cause),
126
+ message: "failed to load oauth discovery document"
127
+ })));
128
+ const document = yield* Effect.try({
129
+ catch: () => new OAuthConnectionValidationFailed({ message: "invalid oauth discovery document" }),
130
+ try: () => decodeDiscoveryDocument(rawDocument)
131
+ });
132
+ const authorizationUrl = yield* requiredString(document.authorization_endpoint, "oauth discovery document missing authorization_endpoint");
133
+ const tokenUrl = yield* requiredString(document.token_endpoint, "oauth discovery document missing token_endpoint");
134
+ const expectedIssuer = typeof document.issuer === "string" && document.issuer.trim() !== "" ? document.issuer : void 0;
135
+ return {
136
+ authorizationUrl,
137
+ tokenUrl,
138
+ ...expectedIssuer === void 0 ? {} : { expectedIssuer }
139
+ };
140
+ });
141
+ const resolveEndpoint = (value, setup) => value === void 0 ? void 0 : typeof value === "function" ? value({ setup }) : value;
142
+ const resolveParams = (value, setup) => typeof value === "function" ? value({ setup }) : value ?? {};
143
+ function invalidTokenHeaders() {
144
+ return OAuthConnectionValidationFailed.make({ message: "invalid oauth token headers" });
145
+ }
146
+ const resolveTokenHeaders = Effect.fnUntraced(function* (input) {
147
+ const raw = yield* Effect.try({
148
+ catch: invalidTokenHeaders,
149
+ try: () => {
150
+ if (Predicate.isFunction(input.value)) return input.value({ setup: input.setup });
151
+ if (input.value === void 0) return {};
152
+ return input.value;
153
+ }
154
+ });
155
+ return yield* pipe(Schema.decodeEffect(TokenHeaders)(raw), Effect.mapError(invalidTokenHeaders));
156
+ });
157
+ const resolveClientValue = Effect.fn("OAuthFlow.resolveClientValue")(function* (input) {
158
+ if (input.value === void 0) return;
159
+ if (typeof input.value === "string") return yield* requiredString(input.value, `${input.field} is empty`);
160
+ return yield* input.value.parse(input.configProvider).pipe(Effect.mapError((cause) => new OAuthConnectionValidationFailed({ message: `failed to resolve ${input.field}: ${cause.message}` })));
161
+ });
162
+ const resolveOAuthConfig = Effect.fn("OAuthFlow.resolveOAuthConfig")(function* (input) {
163
+ const oauth = input.method.oauth2;
164
+ if (oauth === void 0) return yield* new OAuthConnectionValidationFailed({ message: "auth method is not oauth2" });
165
+ const tokenHeaders = yield* resolveTokenHeaders({
166
+ setup: input.setup,
167
+ value: oauth.tokenHeaders
168
+ });
169
+ const client = typeof oauth.client === "function" ? oauth.client({ setup: input.setup }) : oauth.client;
170
+ const clientId = yield* resolveClientValue({
171
+ configProvider: input.configProvider,
172
+ field: "clientId",
173
+ value: client.clientId
174
+ });
175
+ const clientSecret = yield* resolveClientValue({
176
+ configProvider: input.configProvider,
177
+ field: "clientSecret",
178
+ value: client.clientSecret
179
+ });
180
+ if (clientId === void 0) return yield* new OAuthConnectionValidationFailed({ message: "missing oauth client id" });
181
+ const authorizationUrl = resolveEndpoint(oauth.authorizationUrl, input.setup);
182
+ const tokenUrl = resolveEndpoint(oauth.tokenUrl, input.setup);
183
+ const discoveryUrl = resolveEndpoint(oauth.discoveryUrl, input.setup);
184
+ return {
185
+ ...authorizationUrl !== void 0 && tokenUrl !== void 0 ? {
186
+ authorizationUrl,
187
+ tokenUrl
188
+ } : discoveryUrl === void 0 ? yield* new OAuthConnectionValidationFailed({ message: "oauth method requires explicit endpoints or discoveryUrl" }) : yield* fetchDiscovery(discoveryUrl, input.client),
189
+ authorizationParams: resolveParams(oauth.authorizationParams, input.setup),
190
+ clientAuthentication: client.authentication ?? "basic",
191
+ clientId,
192
+ clientSecret,
193
+ pkce: oauth.pkce ?? true,
194
+ scopes: oauth.scopes,
195
+ tokenHeaders,
196
+ tokenParams: resolveParams(oauth.tokenParams, input.setup),
197
+ tokenRequestEncoding: oauth.tokenRequestEncoding ?? "form"
198
+ };
199
+ });
200
+ const buildAuthorizationUrl = (input) => {
201
+ const url = new URL(input.config.authorizationUrl);
202
+ url.searchParams.set("response_type", "code");
203
+ url.searchParams.set("client_id", input.config.clientId);
204
+ url.searchParams.set("redirect_uri", input.redirectUri);
205
+ url.searchParams.set("state", input.state);
206
+ if (input.config.scopes.length > 0) url.searchParams.set("scope", input.config.scopes.join(" "));
207
+ if (input.pkceChallenge !== void 0) {
208
+ url.searchParams.set("code_challenge", input.pkceChallenge);
209
+ url.searchParams.set("code_challenge_method", "S256");
210
+ }
211
+ for (const [key, value] of Object.entries(input.config.authorizationParams)) url.searchParams.set(key, value);
212
+ return url.toString();
213
+ };
214
+ const httpStatusClass = (status) => {
215
+ if (status >= 500) return "5xx";
216
+ if (status >= 400) return "4xx";
217
+ return "unexpected";
218
+ };
219
+ const oauthProtocolErrorCode = (body) => {
220
+ try {
221
+ return decodeProviderTokenError(body).error;
222
+ } catch {
223
+ return;
224
+ }
225
+ };
226
+ const oauthProtocolErrorSubtype = (body) => {
227
+ try {
228
+ return decodeProviderTokenErrorSubtype(body).error_subtype;
229
+ } catch {
230
+ return;
231
+ }
232
+ };
233
+ const tokenRequestHeaders = (config) => {
234
+ const headers = {
235
+ ...config.tokenHeaders,
236
+ Accept: "application/json",
237
+ "Content-Type": config.tokenRequestEncoding === "json" ? "application/json" : "application/x-www-form-urlencoded"
238
+ };
239
+ if (config.clientAuthentication === "basic") {
240
+ if (config.clientSecret === void 0) return Effect.fail(new OAuthConnectionValidationFailed({ message: "missing client secret for basic token auth" }));
241
+ headers["Authorization"] = `Basic ${Base64.encode(`${config.clientId}:${config.clientSecret}`)}`;
242
+ }
243
+ return Effect.succeed(headers);
244
+ };
245
+ const postTokenRequest = Effect.fn("OAuthFlow.postTokenRequest")(function* (input) {
246
+ if (input.config.clientAuthentication === "post") {
247
+ input.params.set("client_id", input.config.clientId);
248
+ if (input.config.clientSecret !== void 0) input.params.set("client_secret", input.config.clientSecret);
249
+ } else if (input.config.clientAuthentication === "none") input.params.set("client_id", input.config.clientId);
250
+ for (const [key, value] of Object.entries(input.config.tokenParams)) input.params.set(key, value);
251
+ const headers = yield* tokenRequestHeaders(input.config);
252
+ const request = HttpClientRequest.post(input.config.tokenUrl, { headers }).pipe(HttpClientRequest.bodyText(input.config.tokenRequestEncoding === "json" ? encodeJsonTokenParams(Record.fromEntries(input.params)) : input.params.toString(), headers["Content-Type"]));
253
+ const response = yield* pipe(input.client.execute(request), Effect.provideService(FetchHttpClient.RequestInit, Record.isEmptyRecord(input.config.tokenHeaders) ? {} : { redirect: "error" }), Effect.mapError((cause) => OAuthConnectionValidationFailed.make({
254
+ cause: Redacted.make(cause),
255
+ message: `${input.failurePrefix} (network)`
256
+ })));
257
+ if (response.status < 200 || response.status >= 300) {
258
+ const body = yield* pipe(response.text, Effect.mapError((cause) => OAuthConnectionValidationFailed.make({
259
+ cause: Redacted.make(cause),
260
+ message: `${input.failurePrefix} (unreadable response)`
261
+ })));
262
+ const statusClass = httpStatusClass(response.status);
263
+ const protocolError = oauthProtocolErrorCode(body);
264
+ const errorSubtype = oauthProtocolErrorSubtype(body);
265
+ const reason = Array.join(Array.filter([protocolError, errorSubtype], Predicate.isNotUndefined), ", ");
266
+ const message = `${input.failurePrefix} (${Array.join(Array.filter([statusClass, reason], String.isNonEmpty), ": ")})`;
267
+ if (protocolError === "invalid_grant") return yield* OAuthGrantRejected.make({
268
+ message,
269
+ ...errorSubtype === void 0 ? {} : { errorSubtype }
270
+ });
271
+ return yield* OAuthConnectionValidationFailed.make({ message });
272
+ }
273
+ return yield* pipe(response.json, Effect.mapError((cause) => OAuthConnectionValidationFailed.make({
274
+ cause: Redacted.make(cause),
275
+ message: `${input.failurePrefix} (network)`
276
+ })), Effect.flatMap((raw) => pipe(Schema.decodeUnknownEffect(Schema.Record(Schema.String, Schema.Unknown))(raw), Effect.mapError(() => OAuthConnectionValidationFailed.make({ message: "invalid oauth token response" })))));
277
+ });
278
+ const numberFromToken = (value) => {
279
+ if (typeof value === "number" && Number.isFinite(value)) return value;
280
+ if (typeof value === "string" && value.trim() !== "") {
281
+ const parsed = Number(value);
282
+ return Number.isFinite(parsed) ? parsed : void 0;
283
+ }
284
+ };
285
+ const normalizeTokenResponse = Effect.fn("OAuthFlow.normalizeTokenResponse")(function* (input) {
286
+ const response = yield* pipe(Schema.decodeUnknownEffect(input.method.oauth2?.tokenResponse ?? OAuth2ProviderTokenResponse)(input.raw), Effect.mapError(() => OAuthConnectionValidationFailed.make({ message: "invalid oauth token response" })));
287
+ const accessToken = yield* requiredString(response.access_token, "oauth token response missing access_token");
288
+ if (response.refresh_token?.trim() === "") return yield* OAuthConnectionValidationFailed.make({ message: "invalid oauth token response" });
289
+ const refreshToken = response.refresh_token ?? input.previousRefreshToken;
290
+ const expiresIn = numberFromToken(response.expires_in);
291
+ if (response.expires_in !== void 0 && (expiresIn === void 0 || expiresIn < 0)) return yield* OAuthConnectionValidationFailed.make({ message: "invalid oauth token response" });
292
+ const now = yield* Clock.currentTimeMillis;
293
+ const absoluteExpiry = response.expires_at === void 0 ? void 0 : Date.parse(response.expires_at);
294
+ if (absoluteExpiry !== void 0 && !Number.isFinite(absoluteExpiry)) return yield* OAuthConnectionValidationFailed.make({ message: "invalid oauth token response" });
295
+ return {
296
+ accessToken,
297
+ ...refreshToken === void 0 ? {} : { refreshToken },
298
+ ...response.token_type === void 0 ? {} : { tokenType: response.token_type },
299
+ ...expiresIn === void 0 ? {} : {
300
+ expiresAt: now + expiresIn * 1e3,
301
+ expiresIn
302
+ },
303
+ ...absoluteExpiry === void 0 ? {} : { expiresAt: absoluteExpiry },
304
+ ...response.scope === void 0 ? {} : { scope: response.scope },
305
+ raw: input.raw
306
+ };
307
+ });
308
+ var Service = class extends Context.Service()("@dual-os/sdk/OAuthFlow") {};
309
+ /** Deterministic OAuthFlow test layer that avoids external provider traffic. */
310
+ const testing = (options = {}) => Layer.succeed(Service, Service.of({
311
+ complete: Effect.fn("OAuthFlow.testing.complete")(function* (input) {
312
+ if (input.query["state"] !== input.continuation.state) return yield* new OAuthConnectionValidationFailed({ message: "oauth state mismatch" });
313
+ if (input.query["error"] !== void 0) return yield* new OAuthProviderRejected({
314
+ error: input.query["error"],
315
+ errorDescription: input.query["error_description"]
316
+ });
317
+ if (input.query["code"] === void 0 || input.query["code"].trim() === "") return yield* new OAuthConnectionValidationFailed({ message: "missing oauth authorization code" });
318
+ const tokens = {
319
+ accessToken: options.accessToken ?? `test_access_${input.query["code"]}`,
320
+ expiresIn: options.expiresIn ?? 3600,
321
+ raw: {
322
+ code: input.query["code"],
323
+ grantType: "authorization_code",
324
+ testing: true
325
+ },
326
+ refreshToken: options.refreshToken ?? `test_refresh_${input.query["code"]}`,
327
+ tokenType: options.tokenType ?? "Bearer"
328
+ };
329
+ return {
330
+ material: tokens,
331
+ tokens
332
+ };
333
+ }),
334
+ refresh: Effect.fn("OAuthFlow.testing.refresh")(function* (input) {
335
+ const tokens = {
336
+ accessToken: options.refreshedAccessToken ?? `test_refreshed_${input.refreshToken}`,
337
+ expiresIn: options.expiresIn ?? 3600,
338
+ raw: {
339
+ grantType: "refresh_token",
340
+ testing: true
341
+ },
342
+ refreshToken: input.refreshToken,
343
+ tokenType: options.tokenType ?? "Bearer"
344
+ };
345
+ yield* Effect.void;
346
+ return {
347
+ material: tokens,
348
+ tokens
349
+ };
350
+ }),
351
+ start: Effect.fn("OAuthFlow.testing.start")(function* (input) {
352
+ const oauth = input.method.oauth2;
353
+ if (oauth === void 0) return yield* new OAuthConnectionValidationFailed({ message: "auth method is not oauth2" });
354
+ const client = typeof oauth.client === "function" ? oauth.client({ setup: input.setup }) : oauth.client;
355
+ const state = `test_state_${yield* Random.nextInt}`;
356
+ const pkceVerifier = oauth.pkce === false ? null : `test_pkce_${yield* Random.nextInt}`;
357
+ const authorizationUrl = new URL(resolveEndpoint(oauth.authorizationUrl, input.setup) ?? "https://oauth.testing.local/authorize");
358
+ authorizationUrl.searchParams.set("response_type", "code");
359
+ authorizationUrl.searchParams.set("client_id", globalThis.String(client.clientId));
360
+ authorizationUrl.searchParams.set("redirect_uri", input.redirectUri);
361
+ authorizationUrl.searchParams.set("state", state);
362
+ if (oauth.scopes.length > 0) authorizationUrl.searchParams.set("scope", oauth.scopes.join(" "));
363
+ if (pkceVerifier !== null) {
364
+ authorizationUrl.searchParams.set("code_challenge", "testing-code-challenge");
365
+ authorizationUrl.searchParams.set("code_challenge_method", "S256");
366
+ }
367
+ for (const [key, value] of Object.entries(resolveParams(oauth.authorizationParams, input.setup))) authorizationUrl.searchParams.set(key, value);
368
+ return {
369
+ authorizationUrl: authorizationUrl.toString(),
370
+ continuation: {
371
+ expiresAt: new Date((yield* Clock.currentTimeMillis) + (input.ttlMs ?? DefaultFlowTtlMs)),
372
+ pkceVerifier,
373
+ redirectUri: input.redirectUri,
374
+ state
375
+ }
376
+ };
377
+ })
378
+ }));
379
+ /** Live protocol layer that reads OAuth client config from Effect ConfigProvider. */
380
+ const layer = Layer.effect(Service, Effect.gen(function* () {
381
+ const configProvider = yield* ConfigProvider.ConfigProvider;
382
+ const client = yield* HttpClient.HttpClient;
383
+ const start = Effect.fn("OAuthFlow.start")(function* (input) {
384
+ const config = yield* resolveOAuthConfig({
385
+ client,
386
+ configProvider,
387
+ method: input.method,
388
+ setup: input.setup
389
+ });
390
+ const expiresAt = new Date((yield* Clock.currentTimeMillis) + (input.ttlMs ?? DefaultFlowTtlMs));
391
+ const state = randomBase64Url(32);
392
+ const pkceVerifier = config.pkce ? randomBase64Url(32) : void 0;
393
+ const pkceChallenge = pkceVerifier === void 0 ? void 0 : yield* sha256Base64Url(pkceVerifier);
394
+ return {
395
+ authorizationUrl: buildAuthorizationUrl({
396
+ config,
397
+ pkceChallenge,
398
+ redirectUri: input.redirectUri,
399
+ state
400
+ }),
401
+ continuation: {
402
+ expiresAt,
403
+ pkceVerifier: pkceVerifier ?? null,
404
+ redirectUri: input.redirectUri,
405
+ state
406
+ }
407
+ };
408
+ });
409
+ const complete = Effect.fn("OAuthFlow.complete")(function* (input) {
410
+ if (input.query["state"] !== input.continuation.state) return yield* new OAuthConnectionValidationFailed({ message: "oauth state mismatch" });
411
+ if (input.query["error"] !== void 0) return yield* new OAuthProviderRejected({
412
+ error: input.query["error"],
413
+ errorDescription: input.query["error_description"]
414
+ });
415
+ const code = input.query["code"];
416
+ if (code === void 0 || code.trim() === "") return yield* new OAuthConnectionValidationFailed({ message: "missing oauth authorization code" });
417
+ const config = yield* resolveOAuthConfig({
418
+ client,
419
+ configProvider,
420
+ method: input.method,
421
+ setup: input.setup
422
+ });
423
+ if (config.expectedIssuer !== void 0 && input.query["iss"] !== void 0 && input.query["iss"] !== config.expectedIssuer) return yield* new OAuthConnectionValidationFailed({ message: "oauth issuer mismatch" });
424
+ const tokenParams = new URLSearchParams({
425
+ code,
426
+ grant_type: "authorization_code",
427
+ redirect_uri: input.continuation.redirectUri
428
+ });
429
+ if (input.continuation.pkceVerifier !== null) tokenParams.set("code_verifier", input.continuation.pkceVerifier);
430
+ const rawTokens = yield* pipe(postTokenRequest({
431
+ client,
432
+ config,
433
+ failurePrefix: "oauth token exchange failed",
434
+ params: tokenParams
435
+ }), Effect.catchTag("OAuthGrantRejected", (error) => Effect.fail(OAuthConnectionValidationFailed.make({ message: error.message }))));
436
+ const tokens = yield* normalizeTokenResponse({
437
+ method: input.method,
438
+ raw: rawTokens
439
+ });
440
+ return {
441
+ material: tokens,
442
+ tokens
443
+ };
444
+ });
445
+ const refresh = Effect.fn("OAuthFlow.refresh")(function* (input) {
446
+ const config = yield* resolveOAuthConfig({
447
+ client,
448
+ configProvider,
449
+ method: input.method,
450
+ setup: input.setup
451
+ });
452
+ const rawTokens = yield* postTokenRequest({
453
+ client,
454
+ config,
455
+ failurePrefix: "oauth token refresh failed",
456
+ params: new URLSearchParams({
457
+ grant_type: "refresh_token",
458
+ refresh_token: input.refreshToken
459
+ })
460
+ });
461
+ const tokens = yield* normalizeTokenResponse({
462
+ method: input.method,
463
+ previousRefreshToken: input.refreshToken,
464
+ raw: rawTokens
465
+ });
466
+ return {
467
+ material: tokens,
468
+ tokens
469
+ };
470
+ });
471
+ return Service.of({
472
+ complete,
473
+ refresh,
474
+ start
475
+ });
476
+ })).pipe(Layer.provide(FetchHttpClient.layer));
477
+ const oauth2TokenRefresherLayer = Layer.effect(Service$1, Effect.gen(function* () {
478
+ const flow = yield* Service;
479
+ return Service$1.of({ refresh: (input) => flow.refresh({
480
+ method: input.method,
481
+ refreshToken: input.refreshToken,
482
+ setup: input.setup
483
+ }).pipe(Effect.map((refreshed) => refreshed.tokens)) });
484
+ }));
485
+ //#endregion
486
+ export { OAuthConnectionValidationFailed, OAuthFlow_exports as OAuthFlow, OAuthFlow_exports, OAuthGrantRejected, OAuthProviderRejected, Service, layer, oauth2TokenRefresherLayer, testing };
487
+
488
+ //# sourceMappingURL=OAuthFlow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OAuthFlow.js","names":["AuthMethod.OAuth2ProviderTokenResponse","OAuth2TokenRefresher.Service"],"sources":["../src/OAuthFlow.ts"],"sourcesContent":["import type { Config } from \"effect\";\nimport {\n Array,\n Clock,\n ConfigProvider,\n Context,\n Effect,\n HashSet,\n Layer,\n Predicate,\n Random,\n Redacted,\n Record,\n Schema,\n String,\n pipe,\n} from \"effect\";\n\n/**\n * OAuth protocol runner used by ConnectionStore.\n *\n * OAuthFlow owns provider-facing protocol mechanics: resolving OAuth client\n * configuration, optional discovery, authorization URL construction, token\n * exchange, token refresh, and token response normalization. It does not persist\n * OAuth sessions or create Connections; ConnectionStore owns those product\n * lifecycle records and calls this service for the protocol steps.\n */\nimport { Base64, Base64Url } from \"effect/encoding\";\nimport { FetchHttpClient, HttpClient, HttpClientRequest } from \"effect/http\";\n\nimport * as AuthMethod from \"./AuthMethod.ts\";\nimport * as OAuth2TokenRefresher from \"./OAuth2TokenRefresher.ts\";\n\nexport class OAuthConnectionValidationFailed extends Schema.TaggedError<OAuthConnectionValidationFailed>()(\n \"OAuthConnectionValidationFailed\",\n { cause: Schema.optionalKey(Schema.Redacted(Schema.Defect())), message: Schema.String },\n) {}\nexport class OAuthProviderRejected extends Schema.TaggedError<OAuthProviderRejected>()(\n \"OAuthProviderRejected\",\n { error: Schema.String, errorDescription: Schema.optional(Schema.String) },\n) {}\nexport class OAuthGrantRejected extends Schema.TaggedError<OAuthGrantRejected>()(\n \"OAuthGrantRejected\",\n { errorSubtype: Schema.optionalKey(Schema.String), message: Schema.String },\n) {}\n\nconst DefaultFlowTtlMs = 10 * 60 * 1000;\n\nconst OAuthEndpoints = Schema.Struct({\n authorizationUrl: Schema.String,\n expectedIssuer: Schema.optional(Schema.String),\n tokenUrl: Schema.String,\n});\ntype OAuthEndpoints = typeof OAuthEndpoints.Type;\n\nconst ClientAuthentication = Schema.Union([\n Schema.Literal(\"basic\"),\n Schema.Literal(\"post\"),\n Schema.Literal(\"none\"),\n]);\n\nconst ReservedTokenHeaders = HashSet.fromIterable([\n \"accept\",\n \"accept-charset\",\n \"accept-encoding\",\n \"access-control-request-headers\",\n \"access-control-request-method\",\n \"authorization\",\n \"connection\",\n \"content-encoding\",\n \"content-length\",\n \"content-type\",\n \"cookie\",\n \"cookie2\",\n \"date\",\n \"dnt\",\n \"expect\",\n \"host\",\n \"keep-alive\",\n \"origin\",\n \"permissions-policy\",\n \"referer\",\n \"set-cookie\",\n \"te\",\n \"trailer\",\n \"transfer-encoding\",\n \"upgrade\",\n \"user-agent\",\n \"via\",\n]);\n\ntype TokenHeaders = typeof TokenHeaders.Type;\nconst TokenHeaders = Schema.Record(\n Schema.String,\n Schema.String.check(Schema.isPattern(/^[\\t\\x20-\\x7e\\x80-\\xff]*$/u)),\n).check(\n Schema.makeFilter(\n headers => {\n const names = Array.map(Record.keys(headers), String.toLowerCase);\n return (\n HashSet.size(HashSet.fromIterable(names)) === names.length &&\n Array.every(\n names,\n name =>\n /^[!#$%&'*+.^_`|~0-9a-z-]+$/u.test(name) &&\n !HashSet.has(ReservedTokenHeaders, name) &&\n !String.startsWith(\"proxy-\")(name) &&\n !String.startsWith(\"sec-\")(name),\n )\n );\n },\n { message: \"Invalid provider token headers\" },\n ),\n);\n\nconst ResolvedOAuth2Config = Schema.Struct({\n authorizationParams: Schema.Record(Schema.String, Schema.String),\n authorizationUrl: Schema.String,\n clientAuthentication: ClientAuthentication,\n clientId: Schema.String,\n clientSecret: Schema.optional(Schema.String),\n expectedIssuer: Schema.optional(Schema.String),\n pkce: Schema.Boolean,\n scopes: Schema.Array(Schema.String),\n tokenHeaders: TokenHeaders,\n tokenParams: Schema.Record(Schema.String, Schema.String),\n tokenRequestEncoding: Schema.Literals([\"form\", \"json\"]),\n tokenUrl: Schema.String,\n});\ntype ResolvedOAuth2Config = typeof ResolvedOAuth2Config.Type;\n\nconst ProviderDiscoveryDocument = Schema.Struct({\n authorization_endpoint: Schema.String,\n issuer: Schema.optional(Schema.String),\n token_endpoint: Schema.String,\n});\n\nconst decodeDiscoveryDocument = Schema.decodeUnknownSync(ProviderDiscoveryDocument);\nconst encodeJsonTokenParams = Schema.encodeSync(\n Schema.fromJsonString(Schema.Record(Schema.String, Schema.String)),\n);\nconst decodeProviderTokenError = Schema.decodeSync(\n Schema.fromJsonString(\n Schema.Struct({\n error: Schema.Literals([\n \"invalid_request\",\n \"invalid_client\",\n \"invalid_grant\",\n \"unauthorized_client\",\n \"unsupported_grant_type\",\n \"invalid_scope\",\n \"server_error\",\n \"temporarily_unavailable\",\n ]),\n }),\n ),\n);\n// Only Google's documented reauthentication subtypes pass, so an echoed secret never reaches an error.\nconst decodeProviderTokenErrorSubtype = Schema.decodeSync(\n Schema.fromJsonString(\n Schema.Struct({ error_subtype: Schema.Literals([\"invalid_rapt\", \"rapt_required\"]) }),\n ),\n);\n\nconst randomBase64Url = (bytes: number): string => {\n const data = new Uint8Array(bytes);\n crypto.getRandomValues(data);\n return Base64Url.encode(data);\n};\n\nconst sha256Base64Url = (value: string): Effect.Effect<string> =>\n Effect.promise(() => crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(value))).pipe(\n Effect.map(digest => Base64Url.encode(new Uint8Array(digest))),\n );\n\nconst requiredString = (\n value: unknown,\n message: string,\n): Effect.Effect<string, OAuthConnectionValidationFailed> =>\n typeof value === \"string\" && value.trim() !== \"\"\n ? Effect.succeed(value)\n : Effect.fail(new OAuthConnectionValidationFailed({ message }));\n\nconst fetchDiscovery = Effect.fn(\"OAuthFlow.fetchDiscovery\")(function* (\n discoveryUrl: string,\n client: HttpClient.HttpClient,\n): Effect.fn.Return<OAuthEndpoints, OAuthConnectionValidationFailed> {\n const rawDocument = yield* pipe(\n HttpClient.filterStatusOk(client).get(discoveryUrl, {\n headers: { Accept: \"application/json\" },\n }),\n Effect.flatMap(response => response.json),\n Effect.mapError(cause =>\n OAuthConnectionValidationFailed.make({\n cause: Redacted.make(cause),\n message: \"failed to load oauth discovery document\",\n }),\n ),\n );\n\n const document = yield* Effect.try({\n catch: () =>\n new OAuthConnectionValidationFailed({ message: \"invalid oauth discovery document\" }),\n try: () => decodeDiscoveryDocument(rawDocument),\n });\n\n const authorizationUrl = yield* requiredString(\n document.authorization_endpoint,\n \"oauth discovery document missing authorization_endpoint\",\n );\n const tokenUrl = yield* requiredString(\n document.token_endpoint,\n \"oauth discovery document missing token_endpoint\",\n );\n const expectedIssuer =\n typeof document.issuer === \"string\" && document.issuer.trim() !== \"\"\n ? document.issuer\n : undefined;\n\n return {\n authorizationUrl,\n tokenUrl,\n ...(expectedIssuer === undefined ? {} : { expectedIssuer }),\n };\n});\n\nconst resolveEndpoint = (\n value: AuthMethod.OAuth2Endpoint<unknown> | undefined,\n setup: unknown,\n): string | undefined =>\n value === undefined ? undefined : typeof value === \"function\" ? value({ setup }) : value;\n\nconst resolveParams = (\n value: AuthMethod.OAuth2Params<unknown> | undefined,\n setup: unknown,\n): Readonly<Record<string, string>> =>\n typeof value === \"function\" ? value({ setup }) : (value ?? {});\n\nfunction invalidTokenHeaders() {\n return OAuthConnectionValidationFailed.make({ message: \"invalid oauth token headers\" });\n}\n\nconst resolveTokenHeaders = Effect.fnUntraced(function* (input: {\n value: AuthMethod.OAuth2Headers<unknown> | undefined;\n setup: unknown;\n}): Effect.fn.Return<TokenHeaders, OAuthConnectionValidationFailed> {\n const raw = yield* Effect.try({\n catch: invalidTokenHeaders,\n try: () => {\n if (Predicate.isFunction(input.value)) {\n return input.value({ setup: input.setup });\n }\n if (input.value === undefined) {\n return {};\n }\n return input.value;\n },\n });\n return yield* pipe(Schema.decodeEffect(TokenHeaders)(raw), Effect.mapError(invalidTokenHeaders));\n});\n\nconst resolveClientValue = Effect.fn(\"OAuthFlow.resolveClientValue\")(function* (input: {\n readonly value: string | Config.Config<string> | undefined;\n readonly field: string;\n readonly configProvider: ConfigProvider.ConfigProvider;\n}): Effect.fn.Return<string | undefined, OAuthConnectionValidationFailed> {\n if (input.value === undefined) {\n return undefined;\n }\n if (typeof input.value === \"string\") {\n return yield* requiredString(input.value, `${input.field} is empty`);\n }\n\n return yield* input.value\n .parse(input.configProvider)\n .pipe(\n Effect.mapError(\n cause =>\n new OAuthConnectionValidationFailed({\n message: `failed to resolve ${input.field}: ${cause.message}`,\n }),\n ),\n );\n});\n\nconst resolveOAuthConfig = Effect.fn(\"OAuthFlow.resolveOAuthConfig\")(function* (input: {\n readonly method: AuthMethod.Any;\n readonly setup: unknown;\n readonly configProvider: ConfigProvider.ConfigProvider;\n readonly client: HttpClient.HttpClient;\n}): Effect.fn.Return<ResolvedOAuth2Config, OAuthConnectionValidationFailed> {\n const oauth = input.method.oauth2;\n if (oauth === undefined) {\n return yield* new OAuthConnectionValidationFailed({ message: \"auth method is not oauth2\" });\n }\n\n const tokenHeaders = yield* resolveTokenHeaders({\n setup: input.setup,\n value: oauth.tokenHeaders,\n });\n\n const client =\n typeof oauth.client === \"function\" ? oauth.client({ setup: input.setup }) : oauth.client;\n const clientId = yield* resolveClientValue({\n configProvider: input.configProvider,\n field: \"clientId\",\n value: client.clientId,\n });\n const clientSecret = yield* resolveClientValue({\n configProvider: input.configProvider,\n field: \"clientSecret\",\n value: client.clientSecret,\n });\n if (clientId === undefined) {\n return yield* new OAuthConnectionValidationFailed({ message: \"missing oauth client id\" });\n }\n\n const authorizationUrl = resolveEndpoint(oauth.authorizationUrl, input.setup);\n const tokenUrl = resolveEndpoint(oauth.tokenUrl, input.setup);\n const discoveryUrl = resolveEndpoint(oauth.discoveryUrl, input.setup);\n\n const endpoints =\n authorizationUrl !== undefined && tokenUrl !== undefined\n ? { authorizationUrl, tokenUrl }\n : discoveryUrl === undefined\n ? yield* new OAuthConnectionValidationFailed({\n message: \"oauth method requires explicit endpoints or discoveryUrl\",\n })\n : yield* fetchDiscovery(discoveryUrl, input.client);\n\n return {\n ...endpoints,\n authorizationParams: resolveParams(oauth.authorizationParams, input.setup),\n clientAuthentication: client.authentication ?? \"basic\",\n clientId,\n clientSecret,\n pkce: oauth.pkce ?? true,\n scopes: oauth.scopes,\n tokenHeaders,\n tokenParams: resolveParams(oauth.tokenParams, input.setup),\n tokenRequestEncoding: oauth.tokenRequestEncoding ?? \"form\",\n };\n});\n\nconst buildAuthorizationUrl = (input: {\n readonly config: ResolvedOAuth2Config;\n readonly redirectUri: string;\n readonly state: string;\n readonly pkceChallenge: string | undefined;\n}): string => {\n const url = new URL(input.config.authorizationUrl);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"client_id\", input.config.clientId);\n url.searchParams.set(\"redirect_uri\", input.redirectUri);\n url.searchParams.set(\"state\", input.state);\n if (input.config.scopes.length > 0) {\n url.searchParams.set(\"scope\", input.config.scopes.join(\" \"));\n }\n if (input.pkceChallenge !== undefined) {\n url.searchParams.set(\"code_challenge\", input.pkceChallenge);\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n }\n for (const [key, value] of Object.entries(input.config.authorizationParams)) {\n url.searchParams.set(key, value);\n }\n return url.toString();\n};\n\nconst httpStatusClass = (status: number): string => {\n if (status >= 500) {\n return \"5xx\";\n }\n if (status >= 400) {\n return \"4xx\";\n }\n return \"unexpected\";\n};\n\nconst oauthProtocolErrorCode = (body: string): string | undefined => {\n try {\n return decodeProviderTokenError(body).error;\n } catch {\n return undefined;\n }\n};\n\nconst oauthProtocolErrorSubtype = (body: string): string | undefined => {\n try {\n return decodeProviderTokenErrorSubtype(body).error_subtype;\n } catch {\n return undefined;\n }\n};\n\nconst tokenRequestHeaders = (\n config: ResolvedOAuth2Config,\n): Effect.Effect<Record<string, string>, OAuthConnectionValidationFailed> => {\n const headers: Record<string, string> = {\n ...config.tokenHeaders,\n Accept: \"application/json\",\n \"Content-Type\":\n config.tokenRequestEncoding === \"json\"\n ? \"application/json\"\n : \"application/x-www-form-urlencoded\",\n };\n if (config.clientAuthentication === \"basic\") {\n if (config.clientSecret === undefined) {\n return Effect.fail(\n new OAuthConnectionValidationFailed({\n message: \"missing client secret for basic token auth\",\n }),\n );\n }\n headers[\"Authorization\"] =\n `Basic ${Base64.encode(`${config.clientId}:${config.clientSecret}`)}`;\n }\n return Effect.succeed(headers);\n};\n\nconst postTokenRequest = Effect.fn(\"OAuthFlow.postTokenRequest\")(function* (input: {\n readonly config: ResolvedOAuth2Config;\n readonly params: URLSearchParams;\n readonly failurePrefix: string;\n readonly client: HttpClient.HttpClient;\n}): Effect.fn.Return<\n Record<string, unknown>,\n OAuthConnectionValidationFailed | OAuthGrantRejected\n> {\n if (input.config.clientAuthentication === \"post\") {\n input.params.set(\"client_id\", input.config.clientId);\n if (input.config.clientSecret !== undefined) {\n input.params.set(\"client_secret\", input.config.clientSecret);\n }\n } else if (input.config.clientAuthentication === \"none\") {\n input.params.set(\"client_id\", input.config.clientId);\n }\n\n for (const [key, value] of Object.entries(input.config.tokenParams)) {\n input.params.set(key, value);\n }\n\n const headers = yield* tokenRequestHeaders(input.config);\n const request = HttpClientRequest.post(input.config.tokenUrl, { headers }).pipe(\n HttpClientRequest.bodyText(\n input.config.tokenRequestEncoding === \"json\"\n ? encodeJsonTokenParams(Record.fromEntries(input.params))\n : input.params.toString(),\n headers[\"Content-Type\"],\n ),\n );\n const response = yield* pipe(\n input.client.execute(request),\n Effect.provideService(\n FetchHttpClient.RequestInit,\n Record.isEmptyRecord(input.config.tokenHeaders) ? {} : { redirect: \"error\" },\n ),\n Effect.mapError(cause =>\n OAuthConnectionValidationFailed.make({\n cause: Redacted.make(cause),\n message: `${input.failurePrefix} (network)`,\n }),\n ),\n );\n if (response.status < 200 || response.status >= 300) {\n const body = yield* pipe(\n response.text,\n Effect.mapError(cause =>\n OAuthConnectionValidationFailed.make({\n cause: Redacted.make(cause),\n message: `${input.failurePrefix} (unreadable response)`,\n }),\n ),\n );\n const statusClass = httpStatusClass(response.status);\n const protocolError = oauthProtocolErrorCode(body);\n const errorSubtype = oauthProtocolErrorSubtype(body);\n const reason = Array.join(\n Array.filter([protocolError, errorSubtype], Predicate.isNotUndefined),\n \", \",\n );\n const message = `${input.failurePrefix} (${Array.join(Array.filter([statusClass, reason], String.isNonEmpty), \": \")})`;\n if (protocolError === \"invalid_grant\") {\n return yield* OAuthGrantRejected.make({\n message,\n ...(errorSubtype === undefined ? {} : { errorSubtype }),\n });\n }\n return yield* OAuthConnectionValidationFailed.make({ message });\n }\n return yield* pipe(\n response.json,\n Effect.mapError(cause =>\n OAuthConnectionValidationFailed.make({\n cause: Redacted.make(cause),\n message: `${input.failurePrefix} (network)`,\n }),\n ),\n Effect.flatMap(raw =>\n pipe(\n Schema.decodeUnknownEffect(Schema.Record(Schema.String, Schema.Unknown))(raw),\n Effect.mapError(() =>\n OAuthConnectionValidationFailed.make({ message: \"invalid oauth token response\" }),\n ),\n ),\n ),\n );\n});\n\nconst numberFromToken = (value: unknown): number | undefined => {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return value;\n }\n if (typeof value === \"string\" && value.trim() !== \"\") {\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n }\n return undefined;\n};\n\nconst normalizeTokenResponse = Effect.fn(\"OAuthFlow.normalizeTokenResponse\")(function* (input: {\n readonly raw: Record<string, unknown>;\n readonly method: AuthMethod.Any;\n readonly previousRefreshToken?: string | undefined;\n}): Effect.fn.Return<AuthMethod.OAuth2TokenResponse, OAuthConnectionValidationFailed> {\n const response = yield* pipe(\n Schema.decodeUnknownEffect(\n input.method.oauth2?.tokenResponse ?? AuthMethod.OAuth2ProviderTokenResponse,\n )(input.raw),\n Effect.mapError(() =>\n OAuthConnectionValidationFailed.make({ message: \"invalid oauth token response\" }),\n ),\n );\n const accessToken = yield* requiredString(\n response.access_token,\n \"oauth token response missing access_token\",\n );\n if (response.refresh_token?.trim() === \"\") {\n return yield* OAuthConnectionValidationFailed.make({ message: \"invalid oauth token response\" });\n }\n const refreshToken = response.refresh_token ?? input.previousRefreshToken;\n const expiresIn = numberFromToken(response.expires_in);\n if (response.expires_in !== undefined && (expiresIn === undefined || expiresIn < 0)) {\n return yield* OAuthConnectionValidationFailed.make({ message: \"invalid oauth token response\" });\n }\n const now = yield* Clock.currentTimeMillis;\n const absoluteExpiry =\n response.expires_at === undefined ? undefined : Date.parse(response.expires_at);\n if (absoluteExpiry !== undefined && !Number.isFinite(absoluteExpiry)) {\n return yield* OAuthConnectionValidationFailed.make({ message: \"invalid oauth token response\" });\n }\n\n return {\n accessToken,\n ...(refreshToken === undefined ? {} : { refreshToken }),\n ...(response.token_type === undefined ? {} : { tokenType: response.token_type }),\n ...(expiresIn === undefined ? {} : { expiresAt: now + expiresIn * 1000, expiresIn }),\n ...(absoluteExpiry === undefined ? {} : { expiresAt: absoluteExpiry }),\n ...(response.scope === undefined ? {} : { scope: response.scope }),\n raw: input.raw,\n };\n});\n\nexport type OAuthFlowError = OAuthConnectionValidationFailed | OAuthProviderRejected;\n\nexport interface OAuthFlowContinuation {\n readonly state: string;\n readonly redirectUri: string;\n readonly pkceVerifier: string | null;\n readonly expiresAt: Date;\n}\n\nexport interface OAuthFlowStarted {\n readonly authorizationUrl: string;\n readonly continuation: OAuthFlowContinuation;\n}\n\nexport interface OAuthFlowCompleted<Material> {\n readonly tokens: AuthMethod.OAuth2TokenResponse;\n readonly material: Material;\n}\n\nexport class Service extends Context.Service<\n Service,\n {\n readonly start: <Method extends AuthMethod.Any>(input: {\n readonly method: Method;\n readonly setup: AuthMethod.Setup<Method>;\n readonly redirectUri: string;\n readonly ttlMs?: number;\n }) => Effect.Effect<OAuthFlowStarted, OAuthFlowError>;\n readonly complete: <Method extends AuthMethod.Any>(input: {\n readonly method: Method;\n readonly setup: AuthMethod.Setup<Method>;\n readonly continuation: OAuthFlowContinuation;\n readonly query: Readonly<Record<string, string | undefined>>;\n }) => Effect.Effect<OAuthFlowCompleted<AuthMethod.OAuth2TokenResponse>, OAuthFlowError>;\n readonly refresh: <Method extends AuthMethod.Any>(input: {\n readonly method: Method;\n readonly setup: AuthMethod.Setup<Method>;\n readonly refreshToken: string;\n }) => Effect.Effect<\n OAuthFlowCompleted<AuthMethod.OAuth2TokenResponse>,\n OAuthFlowError | OAuthGrantRejected\n >;\n }\n>()(\"@dual-os/sdk/OAuthFlow\") {}\n\n/** Deterministic OAuthFlow test layer that avoids external provider traffic. */\nexport const testing = (\n options: {\n readonly accessToken?: string;\n readonly refreshToken?: string;\n readonly refreshedAccessToken?: string;\n readonly tokenType?: string;\n readonly expiresIn?: number;\n } = {},\n) =>\n Layer.succeed(\n Service,\n Service.of({\n complete: Effect.fn(\"OAuthFlow.testing.complete\")(function* <\n Method extends AuthMethod.Any,\n >(input: {\n readonly method: Method;\n readonly setup: AuthMethod.Setup<Method>;\n readonly continuation: OAuthFlowContinuation;\n readonly query: Readonly<Record<string, string | undefined>>;\n }) {\n if (input.query[\"state\"] !== input.continuation.state) {\n return yield* new OAuthConnectionValidationFailed({ message: \"oauth state mismatch\" });\n }\n if (input.query[\"error\"] !== undefined) {\n return yield* new OAuthProviderRejected({\n error: input.query[\"error\"],\n errorDescription: input.query[\"error_description\"],\n });\n }\n if (input.query[\"code\"] === undefined || input.query[\"code\"].trim() === \"\") {\n return yield* new OAuthConnectionValidationFailed({\n message: \"missing oauth authorization code\",\n });\n }\n\n const tokens: AuthMethod.OAuth2TokenResponse = {\n accessToken: options.accessToken ?? `test_access_${input.query[\"code\"]}`,\n expiresIn: options.expiresIn ?? 3600,\n raw: { code: input.query[\"code\"], grantType: \"authorization_code\", testing: true },\n refreshToken: options.refreshToken ?? `test_refresh_${input.query[\"code\"]}`,\n tokenType: options.tokenType ?? \"Bearer\",\n };\n return { material: tokens, tokens };\n }),\n refresh: Effect.fn(\"OAuthFlow.testing.refresh\")(function* <\n Method extends AuthMethod.Any,\n >(input: {\n readonly method: Method;\n readonly setup: AuthMethod.Setup<Method>;\n readonly refreshToken: string;\n }) {\n const tokens: AuthMethod.OAuth2TokenResponse = {\n accessToken: options.refreshedAccessToken ?? `test_refreshed_${input.refreshToken}`,\n expiresIn: options.expiresIn ?? 3600,\n raw: { grantType: \"refresh_token\", testing: true },\n refreshToken: input.refreshToken,\n tokenType: options.tokenType ?? \"Bearer\",\n };\n yield* Effect.void;\n return { material: tokens, tokens };\n }),\n start: Effect.fn(\"OAuthFlow.testing.start\")(function* <Method extends AuthMethod.Any>(input: {\n readonly method: Method;\n readonly setup: AuthMethod.Setup<Method>;\n readonly redirectUri: string;\n readonly ttlMs?: number;\n }) {\n const oauth = input.method.oauth2;\n if (oauth === undefined) {\n return yield* new OAuthConnectionValidationFailed({\n message: \"auth method is not oauth2\",\n });\n }\n const client =\n typeof oauth.client === \"function\" ? oauth.client({ setup: input.setup }) : oauth.client;\n const state = `test_state_${yield* Random.nextInt}`;\n const pkceVerifier = oauth.pkce === false ? null : `test_pkce_${yield* Random.nextInt}`;\n const authorizationUrl = new URL(\n resolveEndpoint(oauth.authorizationUrl, input.setup) ??\n \"https://oauth.testing.local/authorize\",\n );\n authorizationUrl.searchParams.set(\"response_type\", \"code\");\n authorizationUrl.searchParams.set(\"client_id\", globalThis.String(client.clientId));\n authorizationUrl.searchParams.set(\"redirect_uri\", input.redirectUri);\n authorizationUrl.searchParams.set(\"state\", state);\n if (oauth.scopes.length > 0) {\n authorizationUrl.searchParams.set(\"scope\", oauth.scopes.join(\" \"));\n }\n if (pkceVerifier !== null) {\n authorizationUrl.searchParams.set(\"code_challenge\", \"testing-code-challenge\");\n authorizationUrl.searchParams.set(\"code_challenge_method\", \"S256\");\n }\n for (const [key, value] of Object.entries(\n resolveParams(oauth.authorizationParams, input.setup),\n )) {\n authorizationUrl.searchParams.set(key, value);\n }\n\n return {\n authorizationUrl: authorizationUrl.toString(),\n continuation: {\n expiresAt: new Date(\n (yield* Clock.currentTimeMillis) + (input.ttlMs ?? DefaultFlowTtlMs),\n ),\n pkceVerifier,\n redirectUri: input.redirectUri,\n state,\n },\n };\n }),\n }),\n );\n\n/** Live protocol layer that reads OAuth client config from Effect ConfigProvider. */\nexport const layer = Layer.effect(\n Service,\n Effect.gen(function* () {\n const configProvider = yield* ConfigProvider.ConfigProvider;\n const client = yield* HttpClient.HttpClient;\n\n const start = Effect.fn(\"OAuthFlow.start\")(function* <Method extends AuthMethod.Any>(input: {\n readonly method: Method;\n readonly setup: AuthMethod.Setup<Method>;\n readonly redirectUri: string;\n readonly ttlMs?: number;\n }) {\n const config = yield* resolveOAuthConfig({\n client,\n configProvider,\n method: input.method,\n setup: input.setup,\n });\n const expiresAt = new Date(\n (yield* Clock.currentTimeMillis) + (input.ttlMs ?? DefaultFlowTtlMs),\n );\n const state = randomBase64Url(32);\n const pkceVerifier = config.pkce ? randomBase64Url(32) : undefined;\n const pkceChallenge =\n pkceVerifier === undefined ? undefined : yield* sha256Base64Url(pkceVerifier);\n\n return {\n authorizationUrl: buildAuthorizationUrl({\n config,\n pkceChallenge,\n redirectUri: input.redirectUri,\n state,\n }),\n continuation: {\n expiresAt,\n pkceVerifier: pkceVerifier ?? null,\n redirectUri: input.redirectUri,\n state,\n },\n };\n });\n\n const complete = Effect.fn(\"OAuthFlow.complete\")(function* <\n Method extends AuthMethod.Any,\n >(input: {\n readonly method: Method;\n readonly setup: AuthMethod.Setup<Method>;\n readonly continuation: OAuthFlowContinuation;\n readonly query: Readonly<Record<string, string | undefined>>;\n }) {\n if (input.query[\"state\"] !== input.continuation.state) {\n return yield* new OAuthConnectionValidationFailed({ message: \"oauth state mismatch\" });\n }\n if (input.query[\"error\"] !== undefined) {\n return yield* new OAuthProviderRejected({\n error: input.query[\"error\"],\n errorDescription: input.query[\"error_description\"],\n });\n }\n const code = input.query[\"code\"];\n if (code === undefined || code.trim() === \"\") {\n return yield* new OAuthConnectionValidationFailed({\n message: \"missing oauth authorization code\",\n });\n }\n\n const config = yield* resolveOAuthConfig({\n client,\n configProvider,\n method: input.method,\n setup: input.setup,\n });\n if (\n config.expectedIssuer !== undefined &&\n input.query[\"iss\"] !== undefined &&\n input.query[\"iss\"] !== config.expectedIssuer\n ) {\n return yield* new OAuthConnectionValidationFailed({ message: \"oauth issuer mismatch\" });\n }\n\n const tokenParams = new URLSearchParams({\n code,\n grant_type: \"authorization_code\",\n redirect_uri: input.continuation.redirectUri,\n });\n if (input.continuation.pkceVerifier !== null) {\n tokenParams.set(\"code_verifier\", input.continuation.pkceVerifier);\n }\n\n const rawTokens = yield* pipe(\n postTokenRequest({\n client,\n config,\n failurePrefix: \"oauth token exchange failed\",\n params: tokenParams,\n }),\n Effect.catchTag(\"OAuthGrantRejected\", error =>\n Effect.fail(OAuthConnectionValidationFailed.make({ message: error.message })),\n ),\n );\n const tokens = yield* normalizeTokenResponse({ method: input.method, raw: rawTokens });\n return { material: tokens, tokens };\n });\n\n const refresh = Effect.fn(\"OAuthFlow.refresh\")(function* <\n Method extends AuthMethod.Any,\n >(input: {\n readonly method: Method;\n readonly setup: AuthMethod.Setup<Method>;\n readonly refreshToken: string;\n }) {\n const config = yield* resolveOAuthConfig({\n client,\n configProvider,\n method: input.method,\n setup: input.setup,\n });\n const rawTokens = yield* postTokenRequest({\n client,\n config,\n failurePrefix: \"oauth token refresh failed\",\n params: new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: input.refreshToken,\n }),\n });\n const tokens = yield* normalizeTokenResponse({\n method: input.method,\n previousRefreshToken: input.refreshToken,\n raw: rawTokens,\n });\n return { material: tokens, tokens };\n });\n\n return Service.of({ complete, refresh, start });\n }),\n).pipe(Layer.provide(FetchHttpClient.layer));\n\nexport const oauth2TokenRefresherLayer = Layer.effect(\n OAuth2TokenRefresher.Service,\n Effect.gen(function* () {\n const flow = yield* Service;\n return OAuth2TokenRefresher.Service.of({\n refresh: input =>\n flow\n .refresh({ method: input.method, refreshToken: input.refreshToken, setup: input.setup })\n .pipe(Effect.map(refreshed => refreshed.tokens)),\n });\n }),\n);\n\nexport * as OAuthFlow from \"./OAuthFlow.ts\";\n"],"mappings":"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"}