@apifuse/provider-sdk 2.2.0-beta.5 → 2.2.0-beta.50

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 (365) hide show
  1. package/AUTHORING.md +537 -33
  2. package/CHANGELOG.md +201 -1
  3. package/README.md +83 -22
  4. package/SUBMISSION.md +2 -2
  5. package/bin/apifuse-check.ts +165 -11
  6. package/bin/apifuse-dev.ts +57 -13
  7. package/bin/apifuse-migrate-operation-declaration.ts +55 -0
  8. package/bin/apifuse-migrate-shape.ts +202 -0
  9. package/bin/apifuse-pack-check.ts +22 -2
  10. package/bin/apifuse-pack-smoke.ts +57 -2
  11. package/bin/apifuse-pack-types.ts +357 -38
  12. package/bin/apifuse-perf.ts +14 -13
  13. package/bin/apifuse-record.ts +709 -72
  14. package/bin/apifuse-submit-check.ts +2344 -324
  15. package/bin/apifuse-sync-assets.ts +117 -0
  16. package/bin/submit-check-delimited-text.ts +50 -0
  17. package/dist/auth-turn/index.d.ts +3 -3
  18. package/dist/auth-turn/index.js +1 -1
  19. package/dist/auth.d.ts +14 -0
  20. package/dist/auth.js +67 -0
  21. package/dist/ceremonies/index.d.ts +16 -0
  22. package/dist/ceremonies/index.js +141 -36
  23. package/dist/cli/commands.d.ts +1 -1
  24. package/dist/cli/commands.js +27 -0
  25. package/dist/cli/create.d.ts +4 -1
  26. package/dist/cli/create.js +42 -37
  27. package/dist/cli/migrate-operation-declaration.d.ts +59 -0
  28. package/dist/cli/migrate-operation-declaration.js +1178 -0
  29. package/dist/cli/migrate-operation-shape.d.ts +44 -0
  30. package/dist/cli/migrate-operation-shape.js +113 -0
  31. package/dist/cli/migrate-provider-shape.d.ts +52 -0
  32. package/dist/cli/migrate-provider-shape.js +578 -0
  33. package/dist/cli/prompt-assets.d.ts +80 -0
  34. package/dist/cli/prompt-assets.js +743 -0
  35. package/dist/cli/templates/provider/AGENTS.md.tpl +17 -8
  36. package/dist/cli/templates/provider/Dockerfile.tpl +1 -1
  37. package/dist/cli/templates/provider/README.md.tpl +5 -5
  38. package/dist/cli/templates/provider/index.ts.tpl +6 -3
  39. package/dist/cli/templates/provider/operations/ping.ts.tpl +4 -1
  40. package/dist/cli/templates/provider/provider.json.tpl +6 -0
  41. package/dist/config/loader.d.ts +179 -16
  42. package/dist/config/loader.js +435 -127
  43. package/dist/contract-serialization.js +4 -8
  44. package/dist/contract-types.d.ts +12 -5
  45. package/dist/contract.js +24 -10
  46. package/dist/declaration-validation.d.ts +33 -0
  47. package/dist/declaration-validation.js +266 -0
  48. package/dist/define.d.ts +66 -29
  49. package/dist/define.js +778 -69
  50. package/dist/dev.d.ts +3 -0
  51. package/dist/dev.js +1 -1
  52. package/dist/engine.d.ts +78 -0
  53. package/dist/engine.js +133 -0
  54. package/dist/error-observability.d.ts +7 -0
  55. package/dist/error-observability.js +61 -0
  56. package/dist/error-resolution.d.ts +4 -0
  57. package/dist/error-resolution.js +122 -0
  58. package/dist/errors.d.ts +33 -0
  59. package/dist/errors.js +40 -0
  60. package/dist/fixture-sanitization.d.ts +28 -0
  61. package/dist/fixture-sanitization.js +227 -0
  62. package/dist/health-scenario.d.ts +1842 -0
  63. package/dist/health-scenario.js +624 -0
  64. package/dist/index.d.ts +21 -10
  65. package/dist/index.js +12 -7
  66. package/dist/lint.d.ts +23 -11
  67. package/dist/lint.js +572 -69
  68. package/dist/native-address.d.ts +43 -0
  69. package/dist/native-address.js +281 -0
  70. package/dist/native-egress-policy.d.ts +31 -0
  71. package/dist/native-egress-policy.js +288 -0
  72. package/dist/observability.d.ts +5 -2
  73. package/dist/observability.js +48 -1
  74. package/dist/provider.d.ts +10 -2
  75. package/dist/provider.js +4 -1
  76. package/dist/runtime/auth-flow.d.ts +5 -1
  77. package/dist/runtime/auth-flow.js +6 -0
  78. package/dist/runtime/browser.d.ts +1 -0
  79. package/dist/runtime/browser.js +492 -49
  80. package/dist/runtime/cache.d.ts +1 -0
  81. package/dist/runtime/cache.js +169 -15
  82. package/dist/runtime/choice-wordlist.d.ts +9 -0
  83. package/dist/runtime/choice-wordlist.js +138 -0
  84. package/dist/runtime/choice.d.ts +13 -1
  85. package/dist/runtime/choice.js +490 -102
  86. package/dist/runtime/chrome149-header-order.d.ts +58 -0
  87. package/dist/runtime/chrome149-header-order.js +289 -0
  88. package/dist/runtime/env.js +12 -0
  89. package/dist/runtime/executor.d.ts +3 -2
  90. package/dist/runtime/executor.js +26 -25
  91. package/dist/runtime/http.d.ts +1 -0
  92. package/dist/runtime/http.js +515 -53
  93. package/dist/runtime/insights.js +2 -2
  94. package/dist/runtime/instrumentation.d.ts +2 -2
  95. package/dist/runtime/instrumentation.js +366 -8
  96. package/dist/runtime/native-network-errors.d.ts +33 -0
  97. package/dist/runtime/native-network-errors.js +69 -0
  98. package/dist/runtime/native-network.d.ts +96 -0
  99. package/dist/runtime/native-network.js +1232 -0
  100. package/dist/runtime/ocr.d.ts +29 -0
  101. package/dist/runtime/ocr.js +440 -0
  102. package/dist/runtime/otlp.d.ts +71 -2
  103. package/dist/runtime/otlp.js +397 -16
  104. package/dist/runtime/proxy-errors.js +6 -2
  105. package/dist/runtime/proxy-nodemaven.d.ts +56 -0
  106. package/dist/runtime/proxy-nodemaven.js +146 -0
  107. package/dist/runtime/proxy-telemetry.d.ts +80 -1
  108. package/dist/runtime/proxy-telemetry.js +154 -47
  109. package/dist/runtime/redirects.d.ts +29 -0
  110. package/dist/runtime/redirects.js +36 -0
  111. package/dist/runtime/redis.d.ts +1 -1
  112. package/dist/runtime/redis.js +4 -2
  113. package/dist/runtime/request-options.d.ts +68 -1
  114. package/dist/runtime/request-options.js +548 -0
  115. package/dist/runtime/resolver-config.d.ts +6 -0
  116. package/dist/runtime/resolver-config.js +6 -0
  117. package/dist/runtime/resolver-public.d.ts +1 -0
  118. package/dist/runtime/resolver-public.js +1 -0
  119. package/dist/runtime/resolver-shared.d.ts +14 -0
  120. package/dist/runtime/resolver-shared.js +12 -0
  121. package/dist/runtime/resolver-vendors/bindings.d.ts +48 -0
  122. package/dist/runtime/resolver-vendors/bindings.js +40 -0
  123. package/dist/runtime/resolver-vendors/browser.d.ts +22 -0
  124. package/dist/runtime/resolver-vendors/browser.js +377 -0
  125. package/dist/runtime/resolver-vendors/capsolver.d.ts +22 -0
  126. package/dist/runtime/resolver-vendors/capsolver.js +531 -0
  127. package/dist/runtime/resolver-vendors/hosts.d.ts +2 -0
  128. package/dist/runtime/resolver-vendors/hosts.js +33 -0
  129. package/dist/runtime/resolver-vendors/twocaptcha.d.ts +24 -0
  130. package/dist/runtime/resolver-vendors/twocaptcha.js +408 -0
  131. package/dist/runtime/resolver-vendors/types.d.ts +94 -0
  132. package/dist/runtime/resolver-vendors/types.js +96 -0
  133. package/dist/runtime/resolver.d.ts +72 -0
  134. package/dist/runtime/resolver.js +771 -0
  135. package/dist/runtime/secrets.d.ts +27 -0
  136. package/dist/runtime/secrets.js +51 -0
  137. package/dist/runtime/state.d.ts +3 -0
  138. package/dist/runtime/state.js +277 -71
  139. package/dist/runtime/stealth-cookies.d.ts +20 -0
  140. package/dist/runtime/stealth-cookies.js +111 -0
  141. package/dist/runtime/stealth.d.ts +41 -5
  142. package/dist/runtime/stealth.js +997 -291
  143. package/dist/runtime/stt.js +1 -12
  144. package/dist/runtime/timeout.d.ts +5 -0
  145. package/dist/runtime/timeout.js +12 -0
  146. package/dist/runtime/trace-config.d.ts +12 -0
  147. package/dist/runtime/trace-config.js +62 -0
  148. package/dist/runtime/trace.d.ts +5 -0
  149. package/dist/runtime/trace.js +43 -10
  150. package/dist/serve.d.ts +1 -1
  151. package/dist/serve.js +1 -1
  152. package/dist/server/error-observability.d.ts +1 -0
  153. package/dist/server/error-observability.js +1 -0
  154. package/dist/server/index.d.ts +5 -2
  155. package/dist/server/index.js +2 -2
  156. package/dist/server/self-test-input-tokens.d.ts +2 -1
  157. package/dist/server/self-test-input-tokens.js +18 -14
  158. package/dist/server/self-test.d.ts +14 -3
  159. package/dist/server/self-test.js +129 -58
  160. package/dist/server/serve-implementation.d.ts +230 -0
  161. package/dist/server/serve-implementation.js +2265 -0
  162. package/dist/server/serve.d.ts +1 -70
  163. package/dist/server/serve.js +1 -1131
  164. package/dist/server/trace-output.d.ts +6 -0
  165. package/dist/server/trace-output.js +79 -0
  166. package/dist/server/types.d.ts +30 -5
  167. package/dist/server/types.js +13 -1
  168. package/dist/stateful/errors.d.ts +19 -0
  169. package/dist/stateful/errors.js +24 -0
  170. package/dist/stateful/http-provider-event-emitter.d.ts +40 -0
  171. package/dist/stateful/http-provider-event-emitter.js +237 -0
  172. package/dist/stateful/http-session-owner-registry.d.ts +44 -0
  173. package/dist/stateful/http-session-owner-registry.js +210 -0
  174. package/dist/stateful/index.d.ts +18 -0
  175. package/dist/stateful/index.js +18 -0
  176. package/dist/stateful/provider-event-delivery-failures.d.ts +32 -0
  177. package/dist/stateful/provider-event-delivery-failures.js +43 -0
  178. package/dist/stateful/provider-event-pipeline-metrics.d.ts +46 -0
  179. package/dist/stateful/provider-event-pipeline-metrics.js +48 -0
  180. package/dist/stateful/provider-event-pipeline.d.ts +50 -0
  181. package/dist/stateful/provider-event-pipeline.js +1 -0
  182. package/dist/stateful/provider-events.d.ts +101 -0
  183. package/dist/stateful/provider-events.js +289 -0
  184. package/dist/stateful/session-key.d.ts +15 -0
  185. package/dist/stateful/session-key.js +86 -0
  186. package/dist/stateful/stateful-provider-adapter-context.d.ts +5 -0
  187. package/dist/stateful/stateful-provider-adapter-context.js +42 -0
  188. package/dist/stateful/stateful-provider-adapter-metrics.d.ts +15 -0
  189. package/dist/stateful/stateful-provider-adapter-metrics.js +21 -0
  190. package/dist/stateful/stateful-provider-adapter.d.ts +98 -0
  191. package/dist/stateful/stateful-provider-adapter.js +287 -0
  192. package/dist/stateful/stateful-provider-observability.d.ts +62 -0
  193. package/dist/stateful/stateful-provider-observability.js +161 -0
  194. package/dist/stateful/stateful-provider-owner-forwarder.d.ts +41 -0
  195. package/dist/stateful/stateful-provider-owner-forwarder.js +215 -0
  196. package/dist/stateful/stateful-provider-runtime-context.d.ts +32 -0
  197. package/dist/stateful/stateful-provider-runtime-context.js +60 -0
  198. package/dist/stateful/stateful-provider-runtime-executor.d.ts +34 -0
  199. package/dist/stateful/stateful-provider-runtime-executor.js +52 -0
  200. package/dist/stateful/stateful-provider-session-routing.d.ts +67 -0
  201. package/dist/stateful/stateful-provider-session-routing.js +345 -0
  202. package/dist/stateful/stateful-provider-session-runtime.d.ts +98 -0
  203. package/dist/stateful/stateful-provider-session-runtime.js +245 -0
  204. package/dist/stateful-signing.d.ts +18 -0
  205. package/dist/stateful-signing.js +27 -0
  206. package/dist/stealth/profiles.d.ts +9 -4
  207. package/dist/stealth/profiles.js +160 -211
  208. package/dist/stream-evidence.d.ts +74 -0
  209. package/dist/stream-evidence.js +785 -0
  210. package/dist/stream.js +7 -1
  211. package/dist/testing/index.d.ts +2 -1
  212. package/dist/testing/index.js +2 -1
  213. package/dist/testing/run.d.ts +32 -2
  214. package/dist/testing/run.js +489 -21
  215. package/dist/trace-sanitization.d.ts +5 -0
  216. package/dist/trace-sanitization.js +45 -0
  217. package/dist/types.d.ts +673 -131
  218. package/dist/types.js +1 -0
  219. package/package.json +45 -5
  220. package/src/auth-turn/index.ts +1 -1
  221. package/src/auth.ts +118 -0
  222. package/src/ceremonies/index.ts +189 -46
  223. package/src/cli/__tests__/fixtures/migrate-operation-declaration/approval-override.ts.txt +6 -0
  224. package/src/cli/__tests__/fixtures/migrate-operation-declaration/codemod-syntax.ts.txt +3 -0
  225. package/src/cli/__tests__/fixtures/migrate-operation-declaration/connection-precedence.ts.txt +10 -0
  226. package/src/cli/__tests__/fixtures/migrate-operation-declaration/docs-conflict.ts.txt +8 -0
  227. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-map.ts.txt +5 -0
  228. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-operation.ts.txt +16 -0
  229. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-map.ts.txt +3 -0
  230. package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoist-all.ts.txt +31 -0
  231. package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoisted-const.ts.txt +11 -0
  232. package/src/cli/__tests__/fixtures/migrate-operation-declaration/imported-spread.ts.txt +11 -0
  233. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-map.ts.txt +11 -0
  234. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-cast-tail.ts.txt +21 -0
  235. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-ekitan.ts.txt +11 -0
  236. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-override.ts.txt +14 -0
  237. package/src/cli/__tests__/fixtures/migrate-operation-declaration/missing-english-locale.ts.txt +7 -0
  238. package/src/cli/__tests__/fixtures/migrate-operation-declaration/no-safety.ts.txt +6 -0
  239. package/src/cli/__tests__/fixtures/migrate-operation-declaration/non-literal.ts.txt +7 -0
  240. package/src/cli/__tests__/fixtures/migrate-operation-declaration/redundant-approval.ts.txt +6 -0
  241. package/src/cli/__tests__/fixtures/migrate-operation-declaration/safety-conflict.ts.txt +7 -0
  242. package/src/cli/__tests__/fixtures/migrate-operation-declaration/stream.ts.txt +7 -0
  243. package/src/cli/__tests__/fixtures/migrate-operation-declaration/tool-router-spread.ts.txt +15 -0
  244. package/src/cli/__tests__/fixtures/migrate-operation-declaration/unparseable.ts.txt +4 -0
  245. package/src/cli/__tests__/fixtures/migrate-operation-declaration/verbatim-template.ts.txt +12 -0
  246. package/src/cli/commands.ts +33 -0
  247. package/src/cli/create.ts +50 -37
  248. package/src/cli/migrate-operation-declaration.ts +1654 -0
  249. package/src/cli/migrate-operation-shape.ts +184 -0
  250. package/src/cli/migrate-provider-shape.ts +772 -0
  251. package/src/cli/prompt-assets.ts +865 -0
  252. package/src/cli/templates/provider/AGENTS.md.tpl +17 -8
  253. package/src/cli/templates/provider/Dockerfile.tpl +1 -1
  254. package/src/cli/templates/provider/README.md.tpl +5 -5
  255. package/src/cli/templates/provider/index.ts.tpl +6 -3
  256. package/src/cli/templates/provider/operations/ping.ts.tpl +4 -1
  257. package/src/cli/templates/provider/provider.json.tpl +6 -0
  258. package/src/config/loader.ts +690 -163
  259. package/src/contract-serialization.ts +5 -7
  260. package/src/contract-types.ts +12 -5
  261. package/src/contract.ts +24 -10
  262. package/src/declaration-validation.ts +330 -0
  263. package/src/define.ts +1048 -131
  264. package/src/dev.ts +4 -1
  265. package/src/engine.ts +279 -0
  266. package/src/error-observability.ts +64 -0
  267. package/src/error-resolution.ts +127 -0
  268. package/src/errors.ts +68 -0
  269. package/src/fixture-sanitization.ts +264 -0
  270. package/src/health-scenario.ts +875 -0
  271. package/src/index.ts +220 -13
  272. package/src/lint.ts +698 -90
  273. package/src/native-address.ts +340 -0
  274. package/src/native-egress-policy.ts +358 -0
  275. package/src/observability.ts +51 -1
  276. package/src/provider.ts +161 -3
  277. package/src/runtime/auth-flow.ts +12 -0
  278. package/src/runtime/browser.ts +661 -63
  279. package/src/runtime/cache.ts +189 -14
  280. package/src/runtime/choice-wordlist.ts +145 -0
  281. package/src/runtime/choice.ts +631 -120
  282. package/src/runtime/chrome149-header-order.ts +330 -0
  283. package/src/runtime/env.ts +13 -0
  284. package/src/runtime/executor.ts +43 -31
  285. package/src/runtime/http.ts +641 -61
  286. package/src/runtime/insights.ts +2 -2
  287. package/src/runtime/instrumentation.ts +520 -15
  288. package/src/runtime/native-network-errors.ts +99 -0
  289. package/src/runtime/native-network.ts +1605 -0
  290. package/src/runtime/ocr.ts +523 -0
  291. package/src/runtime/otlp.ts +467 -21
  292. package/src/runtime/proxy-errors.ts +12 -4
  293. package/src/runtime/proxy-nodemaven.ts +221 -0
  294. package/src/runtime/proxy-telemetry.ts +244 -75
  295. package/src/runtime/redirects.ts +66 -0
  296. package/src/runtime/redis.ts +7 -2
  297. package/src/runtime/request-options.ts +680 -1
  298. package/src/runtime/resolver-config.ts +6 -0
  299. package/src/runtime/resolver-public.ts +23 -0
  300. package/src/runtime/resolver-shared.ts +33 -0
  301. package/src/runtime/resolver-vendors/bindings.ts +56 -0
  302. package/src/runtime/resolver-vendors/browser.ts +533 -0
  303. package/src/runtime/resolver-vendors/capsolver.ts +707 -0
  304. package/src/runtime/resolver-vendors/hosts.ts +38 -0
  305. package/src/runtime/resolver-vendors/twocaptcha.ts +540 -0
  306. package/src/runtime/resolver-vendors/types.ts +212 -0
  307. package/src/runtime/resolver.ts +1157 -0
  308. package/src/runtime/secrets.ts +64 -0
  309. package/src/runtime/state.ts +394 -77
  310. package/src/runtime/stealth-cookies.ts +132 -0
  311. package/src/runtime/stealth.ts +1280 -336
  312. package/src/runtime/stt.ts +1 -19
  313. package/src/runtime/timeout.ts +18 -0
  314. package/src/runtime/trace-config.ts +78 -0
  315. package/src/runtime/trace.ts +57 -17
  316. package/src/serve.ts +6 -1
  317. package/src/server/error-observability.ts +1 -0
  318. package/src/server/index.ts +34 -2
  319. package/src/server/self-test-input-tokens.ts +29 -14
  320. package/src/server/self-test.ts +191 -68
  321. package/src/server/serve-implementation.ts +3378 -0
  322. package/src/server/serve.ts +1 -1632
  323. package/src/server/trace-output.ts +129 -0
  324. package/src/server/types.ts +13 -1
  325. package/src/stateful/README.md +146 -0
  326. package/src/stateful/errors.ts +35 -0
  327. package/src/stateful/http-provider-event-emitter.ts +314 -0
  328. package/src/stateful/http-session-owner-registry.ts +306 -0
  329. package/src/stateful/index.ts +18 -0
  330. package/src/stateful/provider-event-delivery-failures.ts +80 -0
  331. package/src/stateful/provider-event-pipeline-metrics.ts +95 -0
  332. package/src/stateful/provider-event-pipeline.ts +61 -0
  333. package/src/stateful/provider-events.ts +462 -0
  334. package/src/stateful/session-key.ts +111 -0
  335. package/src/stateful/stateful-provider-adapter-context.ts +59 -0
  336. package/src/stateful/stateful-provider-adapter-metrics.ts +48 -0
  337. package/src/stateful/stateful-provider-adapter.ts +562 -0
  338. package/src/stateful/stateful-provider-observability.ts +261 -0
  339. package/src/stateful/stateful-provider-owner-forwarder.ts +287 -0
  340. package/src/stateful/stateful-provider-runtime-context.ts +92 -0
  341. package/src/stateful/stateful-provider-runtime-executor.ts +96 -0
  342. package/src/stateful/stateful-provider-session-routing.ts +546 -0
  343. package/src/stateful/stateful-provider-session-runtime.ts +403 -0
  344. package/src/stateful-signing.ts +46 -0
  345. package/src/stealth/profiles.ts +202 -231
  346. package/src/stream-evidence.ts +988 -0
  347. package/src/stream.ts +8 -1
  348. package/src/testing/index.ts +10 -1
  349. package/src/testing/run.ts +658 -15
  350. package/src/trace-sanitization.ts +63 -0
  351. package/src/types.ts +788 -174
  352. package/dist/cli/templates/provider/CLAUDE.md.tpl +0 -1
  353. package/src/cli/templates/provider/CLAUDE.md.tpl +0 -1
  354. /package/dist/cli/templates/provider/{skills → .agents/skills}/fixtures-and-recording/SKILL.md.tpl +0 -0
  355. /package/dist/cli/templates/provider/{skills → .agents/skills}/health-checks-and-fail-closed/SKILL.md.tpl +0 -0
  356. /package/dist/cli/templates/provider/{skills → .agents/skills}/normalization-standards/SKILL.md.tpl +0 -0
  357. /package/dist/cli/templates/provider/{skills → .agents/skills}/pagination-and-counts/SKILL.md.tpl +0 -0
  358. /package/dist/cli/templates/provider/{skills → .agents/skills}/upstream-contract-verification/SKILL.md.tpl +0 -0
  359. /package/dist/cli/templates/provider/{skills → .agents/skills}/upstream-notes/README.md.tpl +0 -0
  360. /package/src/cli/templates/provider/{skills → .agents/skills}/fixtures-and-recording/SKILL.md.tpl +0 -0
  361. /package/src/cli/templates/provider/{skills → .agents/skills}/health-checks-and-fail-closed/SKILL.md.tpl +0 -0
  362. /package/src/cli/templates/provider/{skills → .agents/skills}/normalization-standards/SKILL.md.tpl +0 -0
  363. /package/src/cli/templates/provider/{skills → .agents/skills}/pagination-and-counts/SKILL.md.tpl +0 -0
  364. /package/src/cli/templates/provider/{skills → .agents/skills}/upstream-contract-verification/SKILL.md.tpl +0 -0
  365. /package/src/cli/templates/provider/{skills → .agents/skills}/upstream-notes/README.md.tpl +0 -0
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import {
4
+ formatPromptAssetIssues,
5
+ installedSdkVersion,
6
+ syncPromptAssets,
7
+ verifyPromptAssets,
8
+ } from "../src/cli/prompt-assets.js";
9
+ import { resolveProviderRoot } from "./apifuse-check.js";
10
+
11
+ const HELP_TEXT = `Usage: apifuse sync-assets [path] [--check]
12
+ Example: apifuse sync-assets .
13
+ Default: apifuse sync-assets .
14
+
15
+ Regenerates the SDK-managed agent prompt assets for the installed SDK version:
16
+ AGENTS.md, .agents/skills/**, the CLAUDE.md/.claude/.codex symlinks, and the
17
+ .apifuse/prompt-assets.json manifest. Legacy top-level skills/ layouts are
18
+ migrated. Idempotent.
19
+
20
+ Options:
21
+ --check Verify only; exit 1 with a diff list when assets are stale/missing/modified
22
+ --help, -h Show this help`;
23
+
24
+ export async function main() {
25
+ const args = normalizeArgs(process.argv.slice(2));
26
+
27
+ if (args.includes("--help") || args.includes("-h")) {
28
+ console.log(HELP_TEXT);
29
+ return;
30
+ }
31
+
32
+ let checkOnly = false;
33
+ let inputPath: string | undefined;
34
+ for (const arg of args) {
35
+ if (arg === "--check") {
36
+ checkOnly = true;
37
+ continue;
38
+ }
39
+ if (arg.startsWith("-")) {
40
+ throw new Error(`Unknown option: ${arg}`);
41
+ }
42
+ if (inputPath !== undefined) {
43
+ throw new Error(`Unexpected argument: ${arg}`);
44
+ }
45
+ inputPath = arg;
46
+ }
47
+
48
+ const providerRoot = resolveProviderRoot(inputPath ?? ".");
49
+
50
+ if (checkOnly) {
51
+ const verification = verifyPromptAssets(providerRoot);
52
+ if (verification.ok) {
53
+ console.log(
54
+ `Prompt assets are in sync with the installed SDK (${installedSdkVersion()}): ${providerRoot}`,
55
+ );
56
+ return;
57
+ }
58
+ console.error(`Prompt assets are out of sync in ${providerRoot}:`);
59
+ for (const issue of formatPromptAssetIssues(verification)) {
60
+ console.error(` - ${issue}`);
61
+ }
62
+ console.error("\nRun `bun run sync-assets` (or `bunx apifuse sync-assets .`) to regenerate.");
63
+ process.exit(1);
64
+ }
65
+
66
+ const result = syncPromptAssets(providerRoot);
67
+
68
+ // Honesty gate: writes alone never imply success. sync-assets intentionally
69
+ // PRESERVES (does not delete) unauthorized skills and symlinks under
70
+ // .agents/skills, so it can return changed:false while verify still fails.
71
+ // Re-verify AFTER writing and let the true post-sync state drive the exit
72
+ // code — never claim success while the freshness gate would reject the tree.
73
+ const verification = verifyPromptAssets(providerRoot);
74
+
75
+ if (result.changed) {
76
+ for (const removed of result.removed) {
77
+ console.log(`removed ${removed}`);
78
+ }
79
+ for (const wrote of result.wroteFiles) {
80
+ console.log(`wrote ${wrote}`);
81
+ }
82
+ for (const link of result.createdSymlinks) {
83
+ console.log(`symlink ${link}`);
84
+ }
85
+ console.log(`manifest ${result.manifestPath} (sdkVersion ${installedSdkVersion()})`);
86
+ }
87
+
88
+ if (!verification.ok) {
89
+ console.error(`\nPrompt assets are still out of sync in ${providerRoot}:`);
90
+ for (const issue of formatPromptAssetIssues(verification)) {
91
+ console.error(` - ${issue}`);
92
+ }
93
+ console.error(
94
+ "\nsync-assets never deletes unrecognized content: resolve these by hand — remove any unauthorized skill directory or symlink under .agents/skills/, migrate a real .claude/.codex directory into .agents/ — then re-run `apifuse sync-assets .`.",
95
+ );
96
+ process.exit(1);
97
+ }
98
+
99
+ if (!result.changed) {
100
+ console.log(
101
+ `Prompt assets already in sync with the installed SDK (${installedSdkVersion()}): ${providerRoot}`,
102
+ );
103
+ return;
104
+ }
105
+ console.log(`\nPrompt assets synced: ${providerRoot}`);
106
+ }
107
+
108
+ function normalizeArgs(argv: string[]): string[] {
109
+ return argv[0] === "sync-assets" ? argv.slice(1) : argv;
110
+ }
111
+
112
+ if (import.meta.main) {
113
+ await main().catch((error: unknown) => {
114
+ console.error(error instanceof Error ? error.message : String(error));
115
+ process.exit(1);
116
+ });
117
+ }
@@ -0,0 +1,50 @@
1
+ const MIN_RECORDED_DELIMITED_TEXT_LENGTH = 200;
2
+ const MIN_RECORDED_DELIMITED_TEXT_LINES = 3;
3
+ const MAX_SAMPLED_DELIMITED_TEXT_LINES = 10;
4
+ const DELIMITER_CANDIDATES = [",", "\t", ";"] as const;
5
+
6
+ // Recognizes a recorded operation value that is a substantive tabular text
7
+ // payload. The length floor and repeated, quote-aware field structure keep
8
+ // short strings and prose from being treated as fixture provenance.
9
+ export function hasSubstantiveDelimitedTextStructure(value: string): boolean {
10
+ if (value.length < MIN_RECORDED_DELIMITED_TEXT_LENGTH) {
11
+ return false;
12
+ }
13
+
14
+ const lines = value
15
+ .replace(/^\uFEFF/, "")
16
+ .split(/\r\n?|\n/)
17
+ .filter((line) => line.trim().length > 0);
18
+ if (lines.length < MIN_RECORDED_DELIMITED_TEXT_LINES) {
19
+ return false;
20
+ }
21
+
22
+ const sampledLines = lines.slice(0, MAX_SAMPLED_DELIMITED_TEXT_LINES);
23
+ return DELIMITER_CANDIDATES.some((delimiter) => {
24
+ const fieldCounts = sampledLines.map((line) => countDelimitedFields(line, delimiter));
25
+ const expectedFieldCount = fieldCounts[0];
26
+ return (
27
+ expectedFieldCount !== undefined &&
28
+ expectedFieldCount >= 2 &&
29
+ fieldCounts.every((fieldCount) => fieldCount === expectedFieldCount)
30
+ );
31
+ });
32
+ }
33
+
34
+ function countDelimitedFields(line: string, delimiter: string): number | undefined {
35
+ let fieldCount = 1;
36
+ let insideQuotes = false;
37
+ for (let index = 0; index < line.length; index += 1) {
38
+ const character = line[index];
39
+ if (character === '"') {
40
+ if (insideQuotes && line[index + 1] === '"') {
41
+ index += 1;
42
+ } else {
43
+ insideQuotes = !insideQuotes;
44
+ }
45
+ } else if (!insideQuotes && character === delimiter) {
46
+ fieldCount += 1;
47
+ }
48
+ }
49
+ return insideQuotes ? undefined : fieldCount;
50
+ }
@@ -20,7 +20,7 @@ export declare const AUTH_TURN_SCHEMA_ARTIFACT_PATH = "dist/auth-turn/auth-turn.
20
20
  *
21
21
  * This is the exact codification of the runtime validation the SDK applies to
22
22
  * ceremony outputs (see `validateCeremonyOutput` in `src/ceremonies`), which
23
- * compiles this same document. `kind` is an OPEN string on the wire: the known
23
+ * evaluates this same document. `kind` is an OPEN string on the wire: the known
24
24
  * kinds in {@link TURN_KINDS} are tooling metadata, never a wire constraint.
25
25
  *
26
26
  * The committed artifact at `src/auth-turn/auth-turn.v1.schema.json` (shipped
@@ -87,7 +87,7 @@ export declare const AUTH_TURN_SCHEMA: {
87
87
  };
88
88
  readonly $defs: {
89
89
  readonly completeTurnData: {
90
- readonly title: 'Terminal payload for kind "complete"';
90
+ readonly title: "Terminal payload for kind \"complete\"";
91
91
  readonly description: "data payload of a complete turn. The gateway extracts data.credential for persistence; complete turns are never echoed to browsers.";
92
92
  readonly type: "object";
93
93
  readonly additionalProperties: true;
@@ -104,7 +104,7 @@ export declare const AUTH_TURN_SCHEMA: {
104
104
  };
105
105
  };
106
106
  readonly abortTurnData: {
107
- readonly title: 'Terminal payload for kind "abort"';
107
+ readonly title: "Terminal payload for kind \"abort\"";
108
108
  readonly description: "data payload of an abort turn. code, when present, is the machine-readable abort reason.";
109
109
  readonly type: "object";
110
110
  readonly additionalProperties: true;
@@ -18,7 +18,7 @@ export const AUTH_TURN_SCHEMA_ARTIFACT_PATH = "dist/auth-turn/auth-turn.v1.schem
18
18
  *
19
19
  * This is the exact codification of the runtime validation the SDK applies to
20
20
  * ceremony outputs (see `validateCeremonyOutput` in `src/ceremonies`), which
21
- * compiles this same document. `kind` is an OPEN string on the wire: the known
21
+ * evaluates this same document. `kind` is an OPEN string on the wire: the known
22
22
  * kinds in {@link TURN_KINDS} are tooling metadata, never a wire constraint.
23
23
  *
24
24
  * The committed artifact at `src/auth-turn/auth-turn.v1.schema.json` (shipped
package/dist/auth.d.ts CHANGED
@@ -66,6 +66,20 @@ export interface DefineCredentialsAuthOptions<TFields extends CredentialsAuthFie
66
66
  /** Extra auth-flow context keys used by custom login/challenge code. */
67
67
  contextKeys?: readonly string[];
68
68
  login(ctx: FlowContext, input: CredentialsAuthInput<TFields>): CredentialsAuthLoginResult<TCredentialKeys, keyof TChallenges & string> | Promise<CredentialsAuthLoginResult<TCredentialKeys, keyof TChallenges & string>>;
69
+ /**
70
+ * Optional re-mint of an expired session from the stored credential, wired
71
+ * to `auth.flow.refresh`.
72
+ *
73
+ * Credential-auth upstreams routinely invalidate a session well before the
74
+ * `expiresAt` the provider advertised, which leaves every operation failing
75
+ * with a reauth error until a human repeats the whole interactive login.
76
+ * Implement this to re-establish the session from what is already stored on
77
+ * the connection; the result is resolved exactly like `login`, so it may
78
+ * also raise a challenge when the upstream demands one. Omit it when the
79
+ * upstream has no non-interactive path and re-authentication genuinely
80
+ * requires the user.
81
+ */
82
+ refresh?(ctx: FlowContext, input: Partial<CredentialsAuthInput<TFields>>): CredentialsAuthLoginResult<TCredentialKeys, keyof TChallenges & string> | Promise<CredentialsAuthLoginResult<TCredentialKeys, keyof TChallenges & string>>;
69
83
  }
70
84
  export interface DefinedCredentialsAuth {
71
85
  auth: AuthConfig;
package/dist/auth.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { AuthError, ProviderError } from "./errors.js";
2
+ import { declarationInvalidError, DECLARATION_RULE_IDS, } from "./declaration-validation.js";
2
3
  const CREDENTIALS_AUTH_CHALLENGE_CONTEXT_KEY = "__credentialsAuthChallenge";
3
4
  const DEFAULT_COMPLETE_TURN_ID = "auth.complete";
4
5
  const DEFAULT_ABORT_TURN_ID = "auth.abort";
@@ -198,6 +199,23 @@ function normalizeInput(fields, input) {
198
199
  }
199
200
  return result;
200
201
  }
202
+ /**
203
+ * Refresh variant of {@link normalizeInput}. `login` coerces every declared
204
+ * field to a string because the interactive turn has already enforced that they
205
+ * are present; refresh runs with no user present, so an absent field is omitted
206
+ * rather than turned into an empty string. That keeps "the user did not supply
207
+ * this" distinguishable from "the user supplied an empty value".
208
+ */
209
+ function normalizePartialInput(fields, input) {
210
+ const result = {};
211
+ for (const name of Object.keys(fields)) {
212
+ const value = input?.[name];
213
+ if (typeof value === "string") {
214
+ result[name] = value;
215
+ }
216
+ }
217
+ return result;
218
+ }
201
219
  function assertCredentialKeys(credentialKeys, credential) {
202
220
  const missing = credentialKeys.filter((key) => {
203
221
  const value = credential[key];
@@ -379,6 +397,7 @@ export function defineCredentialsAuth(options) {
379
397
  const retryTurnId = options.retryTurnId ?? "credentials.retry";
380
398
  const completeTurnId = options.completeTurnId ?? "credentials.complete";
381
399
  const challenges = (options.challenges ?? {});
400
+ validateCredentialsAuthChallenges(challenges);
382
401
  return {
383
402
  auth: {
384
403
  mode: "credentials",
@@ -411,6 +430,27 @@ export function defineCredentialsAuth(options) {
411
430
  }
412
431
  return await pollPendingChallenge(ctx, options.credentialKeys, challenges, pending, completeTurnId);
413
432
  },
433
+ // Only advertise refresh when the provider implements it: the
434
+ // protocol treats the hook's presence as "this connection can be
435
+ // re-established without the user", and exposing a stub that
436
+ // cannot actually re-mint would turn a recoverable expiry into a
437
+ // silent failure.
438
+ ...(options.refresh
439
+ ? {
440
+ refresh: async (ctx, rawInput) => {
441
+ // A pending challenge belongs to the interactive flow that
442
+ // raised it; finish it there rather than restarting.
443
+ const pending = getPendingChallenge(ctx);
444
+ if (pending) {
445
+ return await continuePendingChallenge(ctx, options.credentialKeys, challenges, pending, rawInput, completeTurnId);
446
+ }
447
+ // Refresh runs without user input, so fields are optional
448
+ // here — unlike `continue`, missing ones are not a retry.
449
+ const result = await options.refresh(ctx, normalizePartialInput(options.fields, rawInput));
450
+ return await resolveAuthResult(ctx, options.credentialKeys, challenges, result, completeTurnId);
451
+ },
452
+ }
453
+ : {}),
414
454
  },
415
455
  },
416
456
  credential: {
@@ -425,3 +465,30 @@ export function defineCredentialsAuth(options) {
425
465
  },
426
466
  };
427
467
  }
468
+ function validateCredentialsAuthChallenges(challenges) {
469
+ const violations = [];
470
+ for (const [challengeId, challenge] of Object.entries(challenges)) {
471
+ const fieldCount = challenge.fields && typeof challenge.fields === "object"
472
+ ? Object.keys(challenge.fields).length
473
+ : 0;
474
+ const fieldsDeclared = challenge.fields !== undefined && challenge.fields !== null;
475
+ const hasFields = fieldCount > 0;
476
+ const hasVerify = typeof challenge.verify === "function";
477
+ const hasPoll = typeof challenge.poll === "function";
478
+ const isInteractive = hasFields && hasVerify && !hasPoll;
479
+ const isPolling = !fieldsDeclared && !hasVerify && hasPoll;
480
+ const isHybrid = hasFields && hasVerify && hasPoll;
481
+ const emptyFieldsDeclared = fieldsDeclared && !hasFields;
482
+ if (!emptyFieldsDeclared && (isInteractive || isPolling || isHybrid))
483
+ continue;
484
+ const path = `challenges.${challengeId}`;
485
+ violations.push({
486
+ ruleId: DECLARATION_RULE_IDS.challengeShape,
487
+ path,
488
+ message: "challenge must be interactive, polling, or an explicit hybrid.",
489
+ fix: `Give ${path} non-empty fields plus verify, poll alone, or all three for a hybrid.`,
490
+ });
491
+ }
492
+ if (violations.length > 0)
493
+ throw declarationInvalidError(violations);
494
+ }
@@ -1,6 +1,16 @@
1
+ import type { AuthStartNoInputGuard } from "../define.js";
1
2
  import type { AuthFlowDefinition, AuthTurn } from "../types.js";
2
3
  type JsonObject = Record<string, unknown>;
4
+ export declare const OAUTH2_PROXIED_AUTH_PROXY_ORIGIN_ENV_KEY = "APIFUSE__AUTH_PROXY__URL";
5
+ export declare const OAUTH2_PROXIED_PKCE_VERIFIER_KEY = "__oauth2_proxied_pkce_verifier";
3
6
  export declare function validateCeremonyOutput(turn: unknown): AuthTurn;
7
+ /**
8
+ * Defines an auth flow while preserving its concrete type for downstream checks.
9
+ * The compile-time guard validates the inferred literal; annotating or widening
10
+ * a flow to `AuthFlowDefinition` before passing it defeats the check. Full
11
+ * enforcement requires branding, which is deferred to a future major.
12
+ */
13
+ export declare function defineAuthFlow<const TFlow extends AuthFlowDefinition>(flow: TFlow & AuthStartNoInputGuard<TFlow>): TFlow;
4
14
  export declare function createOAuth2Ceremony(options: {
5
15
  authorizeUrl: string;
6
16
  tokenUrl: string;
@@ -9,6 +19,12 @@ export declare function createOAuth2Ceremony(options: {
9
19
  scopes: string[];
10
20
  usePKCE?: boolean;
11
21
  }): AuthFlowDefinition;
22
+ /**
23
+ * Builds the start handler for a custom-scheme OAuth provider. The shared
24
+ * auth-proxy owns state minting and callback capture, while the provider owns
25
+ * token exchange and any following authentication turns.
26
+ */
27
+ export declare function createOAuth2ProxiedStart(options: import("../types.js").ProxiedOAuthConfig): import("../types.js").AuthFlowStartHandler;
12
28
  export declare function createDeviceFlowCeremony(options: {
13
29
  deviceCodeUrl: string;
14
30
  tokenUrl: string;
@@ -1,14 +1,17 @@
1
1
  import { createHash, randomBytes, randomUUID } from "node:crypto";
2
- import Ajv2020 from "ajv/dist/2020.js";
3
2
  import { AUTH_TURN_SCHEMA } from "../auth-turn/index.js";
4
3
  import { FlowExpiredError, ProviderSecretError, TurnValidationError, ValidationError, } from "../errors.js";
5
- const ajv = new Ajv2020({ allErrors: true, strict: true, strictSchema: true });
6
- // Runtime ceremony-output validation derives from the exported versioned
7
- // contract: it compiles the exact AUTH_TURN_SCHEMA document shipped at
8
- // dist/auth-turn/auth-turn.v1.schema.json, so the two cannot drift.
9
- const validateAuthTurn = ajv.compile(AUTH_TURN_SCHEMA);
10
4
  const OAUTH2_STATE_KEY = "__oauth2_state";
11
5
  const OAUTH2_PKCE_VERIFIER_KEY = "__oauth2_pkce_verifier";
6
+ export const OAUTH2_PROXIED_AUTH_PROXY_ORIGIN_ENV_KEY = "APIFUSE__AUTH_PROXY__URL";
7
+ export const OAUTH2_PROXIED_PKCE_VERIFIER_KEY = "__oauth2_proxied_pkce_verifier";
8
+ const OAUTH2_PROXIED_RESERVED_AUTHORIZE_PARAMS = new Set([
9
+ "client_id",
10
+ "response_type",
11
+ "state",
12
+ "code_challenge",
13
+ "code_challenge_method",
14
+ ]);
12
15
  const DEVICE_FLOW_KEY = "__device_flow";
13
16
  const MAGIC_LINK_KEY = "__magic_link";
14
17
  const COMBINED_STAGE_KEY = "__combined_stage";
@@ -17,6 +20,50 @@ const FORM_FIELD_ORDER_EXTENSION = "x-apifuse-field-order";
17
20
  function isRecord(value) {
18
21
  return !!value && typeof value === "object" && !Array.isArray(value);
19
22
  }
23
+ function validateSchemaNode(value, schema, path, errors) {
24
+ if (schema.type === "object") {
25
+ if (!isRecord(value)) {
26
+ errors.push(`${path} must be object`);
27
+ return;
28
+ }
29
+ const properties = schema.properties ?? {};
30
+ for (const required of schema.required ?? []) {
31
+ if (!Object.hasOwn(value, required) || value[required] === undefined) {
32
+ errors.push(`${path} must have required property '${required}'`);
33
+ }
34
+ }
35
+ if (schema.additionalProperties === false) {
36
+ for (const key of Object.keys(value)) {
37
+ if (!Object.hasOwn(properties, key)) {
38
+ errors.push(`${path} must NOT have additional property '${key}'`);
39
+ }
40
+ }
41
+ }
42
+ for (const [key, childSchema] of Object.entries(properties)) {
43
+ if (Object.hasOwn(value, key) && value[key] !== undefined) {
44
+ validateSchemaNode(value[key], childSchema, `${path}/${key}`, errors);
45
+ }
46
+ }
47
+ return;
48
+ }
49
+ if (schema.type === "string") {
50
+ if (typeof value !== "string") {
51
+ errors.push(`${path} must be string`);
52
+ }
53
+ else if (schema.minLength !== undefined && value.length < schema.minLength) {
54
+ errors.push(`${path} must NOT have fewer than ${schema.minLength} characters`);
55
+ }
56
+ return;
57
+ }
58
+ if (schema.type === "number") {
59
+ if (typeof value !== "number" || !Number.isFinite(value)) {
60
+ errors.push(`${path} must be number`);
61
+ }
62
+ else if (schema.minimum !== undefined && value < schema.minimum) {
63
+ errors.push(`${path} must be >= ${schema.minimum}`);
64
+ }
65
+ }
66
+ }
20
67
  function ensureRecord(value) {
21
68
  return isRecord(value) ? value : {};
22
69
  }
@@ -105,16 +152,28 @@ function withDeclaredFormFieldOrder(expectedInput) {
105
152
  };
106
153
  }
107
154
  export function validateCeremonyOutput(turn) {
108
- if (!validateAuthTurn(turn)) {
109
- const detail = validateAuthTurn.errors
110
- ?.map((error) => `${error.instancePath || "$"} ${error.message ?? "invalid"}`)
111
- .join("; ");
112
- throw new TurnValidationError(detail || "Invalid AuthTurn output");
155
+ // Evaluate the exact exported versioned schema without eagerly initializing
156
+ // a general-purpose JSON Schema compiler in every provider process. Contract
157
+ // parity tests compare this focused evaluator with AJV over all fixtures and
158
+ // edge probes, so the runtime and shipped document remain locked together.
159
+ const errors = [];
160
+ validateSchemaNode(turn, AUTH_TURN_SCHEMA, "", errors);
161
+ if (errors.length > 0) {
162
+ throw new TurnValidationError(errors.join("; "));
113
163
  }
114
164
  return turn;
115
165
  }
166
+ /**
167
+ * Defines an auth flow while preserving its concrete type for downstream checks.
168
+ * The compile-time guard validates the inferred literal; annotating or widening
169
+ * a flow to `AuthFlowDefinition` before passing it defeats the check. Full
170
+ * enforcement requires branding, which is deferred to a future major.
171
+ */
172
+ export function defineAuthFlow(flow) {
173
+ return flow;
174
+ }
116
175
  export function createOAuth2Ceremony(options) {
117
- return {
176
+ return defineAuthFlow({
118
177
  start: (ctx) => runCeremonyHandler(async () => {
119
178
  const clientId = getRequiredEnv(ctx, options.clientIdEnvKey);
120
179
  getRequiredEnv(ctx, options.clientSecretEnvKey);
@@ -171,10 +230,58 @@ export function createOAuth2Ceremony(options) {
171
230
  });
172
231
  }, "OAuth token exchange failed", ctx, input),
173
232
  abort: async () => validateCeremonyOutput(createTurn("abort", { hint: "OAuth flow aborted." })),
174
- };
233
+ });
234
+ }
235
+ /**
236
+ * Builds the start handler for a custom-scheme OAuth provider. The shared
237
+ * auth-proxy owns state minting and callback capture, while the provider owns
238
+ * token exchange and any following authentication turns.
239
+ */
240
+ export function createOAuth2ProxiedStart(options) {
241
+ const pkce = options.pkce ?? "S256";
242
+ return (ctx) => runCeremonyHandler(async () => {
243
+ for (const key of Object.keys(options.authorizeParams ?? {})) {
244
+ if (OAUTH2_PROXIED_RESERVED_AUTHORIZE_PARAMS.has(key.toLowerCase())) {
245
+ throw new ValidationError(`OAuth2 proxied authorizeParams cannot override reserved parameter "${key}".`);
246
+ }
247
+ }
248
+ const proxyOrigin = ctx.env.get(OAUTH2_PROXIED_AUTH_PROXY_ORIGIN_ENV_KEY);
249
+ if (!proxyOrigin) {
250
+ throw new ProviderSecretError(`Missing required platform environment: ${OAUTH2_PROXIED_AUTH_PROXY_ORIGIN_ENV_KEY}`);
251
+ }
252
+ const clientId = getRequiredEnv(ctx, options.clientIdEnvKey);
253
+ if (!ctx.flowId) {
254
+ throw new ValidationError("OAuth2 proxied start requires the gateway flow id.");
255
+ }
256
+ const authorizePath = new URL(options.authorizeUrl).pathname;
257
+ const url = new URL(`/p/${encodeURIComponent(ctx.providerId)}/f/${encodeURIComponent(ctx.flowId)}${authorizePath}`, proxyOrigin);
258
+ url.searchParams.set("client_id", clientId);
259
+ url.searchParams.set("response_type", "code");
260
+ if (pkce === "S256") {
261
+ const verifier = createCodeVerifier();
262
+ ctx.context.set(OAUTH2_PROXIED_PKCE_VERIFIER_KEY, verifier);
263
+ url.searchParams.set("code_challenge", createCodeChallenge(verifier));
264
+ url.searchParams.set("code_challenge_method", "S256");
265
+ }
266
+ for (const [key, value] of Object.entries(options.authorizeParams ?? {})) {
267
+ url.searchParams.set(key, value);
268
+ }
269
+ return createTurn("redirect", {
270
+ data: { url: url.toString() },
271
+ hint: "Open the provider authorization page to continue.",
272
+ expectedInput: {
273
+ type: "object",
274
+ required: ["code", "state"],
275
+ properties: {
276
+ code: { type: "string" },
277
+ state: { type: "string" },
278
+ },
279
+ },
280
+ });
281
+ }, "OAuth2 proxied start failed", ctx);
175
282
  }
176
283
  export function createDeviceFlowCeremony(options) {
177
- return {
284
+ return defineAuthFlow({
178
285
  start: (ctx) => runCeremonyHandler(async () => {
179
286
  const response = await ctx.http.post(options.deviceCodeUrl, {
180
287
  client_id: getRequiredEnv(ctx, options.clientIdEnvKey),
@@ -232,10 +339,10 @@ export function createDeviceFlowCeremony(options) {
232
339
  });
233
340
  }, "Device flow polling failed", ctx),
234
341
  abort: async () => validateCeremonyOutput(createTurn("abort", { hint: "Device flow aborted." })),
235
- };
342
+ });
236
343
  }
237
344
  export function createWebAuthnCeremony(options) {
238
- return {
345
+ return defineAuthFlow({
239
346
  start: (ctx) => runCeremonyHandler(async () => {
240
347
  const challenge = toBase64Url(randomBytes(32));
241
348
  ctx.context.set("__webauthn_challenge", challenge);
@@ -277,21 +384,23 @@ export function createWebAuthnCeremony(options) {
277
384
  });
278
385
  }, "WebAuthn verification failed", ctx, input),
279
386
  abort: async () => validateCeremonyOutput(createTurn("abort", { hint: "WebAuthn ceremony aborted." })),
280
- };
387
+ });
281
388
  }
282
389
  export function createMagicLinkCeremony(options) {
283
390
  const emailField = options.emailField ?? "email";
284
- return {
285
- start: (ctx, input = {}) => runCeremonyHandler(async () => {
391
+ const buildEmailForm = () => buildJsonSchemaForm({
392
+ type: "object",
393
+ required: [emailField],
394
+ properties: {
395
+ [emailField]: { type: "string", format: "email" },
396
+ },
397
+ }, "Provide the email address to receive a magic link.");
398
+ return defineAuthFlow({
399
+ start: (ctx) => runCeremonyHandler(async () => buildEmailForm(), "Magic link start failed", ctx),
400
+ continue: (ctx, input = {}) => runCeremonyHandler(async () => {
286
401
  const email = getString(input, emailField);
287
402
  if (!email) {
288
- return buildJsonSchemaForm({
289
- type: "object",
290
- required: [emailField],
291
- properties: {
292
- [emailField]: { type: "string", format: "email" },
293
- },
294
- }, "Provide the email address to receive a magic link.");
403
+ return buildEmailForm();
295
404
  }
296
405
  await ctx.http.post(options.sendUrl, { email });
297
406
  ctx.context.set(MAGIC_LINK_KEY, {
@@ -303,11 +412,7 @@ export function createMagicLinkCeremony(options) {
303
412
  hint: "Check your email for the magic link, then poll for completion.",
304
413
  timing: { suggestedPollIntervalMs: 5_000, maxWaitMs: 300_000 },
305
414
  });
306
- }, "Magic link start failed", ctx, input),
307
- continue: async () => validateCeremonyOutput(createTurn("poll", {
308
- hint: "Continue polling for magic link completion.",
309
- timing: { suggestedPollIntervalMs: 5_000, maxWaitMs: 300_000 },
310
- })),
415
+ }, "Magic link continuation failed", ctx, input),
311
416
  poll: (ctx) => runCeremonyHandler(async () => {
312
417
  const state = getNestedRecord(ctx, MAGIC_LINK_KEY);
313
418
  const email = getString(state, "email");
@@ -333,10 +438,10 @@ export function createMagicLinkCeremony(options) {
333
438
  });
334
439
  }, "Magic link polling failed", ctx),
335
440
  abort: async () => validateCeremonyOutput(createTurn("abort", { hint: "Magic link flow aborted." })),
336
- };
441
+ });
337
442
  }
338
443
  export function createFormCeremony(options) {
339
- return {
444
+ return defineAuthFlow({
340
445
  start: async () => validateCeremonyOutput(buildJsonSchemaForm(options.schema, options.hint ?? "Provide the required input to continue.")),
341
446
  continue: (ctx, input = {}) => runCeremonyHandler(async () => {
342
447
  const { prevalidate } = await import("../runtime/prevalidate.js");
@@ -354,7 +459,7 @@ export function createFormCeremony(options) {
354
459
  });
355
460
  }, "Form submission failed", ctx, input),
356
461
  abort: async () => validateCeremonyOutput(createTurn("abort", { hint: "Form ceremony aborted." })),
357
- };
462
+ });
358
463
  }
359
464
  export function combineCeremonies(...ceremonies) {
360
465
  function getStage(ctx) {
@@ -406,7 +511,7 @@ export function combineCeremonies(...ceremonies) {
406
511
  }
407
512
  export function createSwitchCeremony(options) {
408
513
  const choiceKeys = Object.keys(options.choices);
409
- return {
514
+ return defineAuthFlow({
410
515
  start: async () => validateCeremonyOutput(createTurn("multi_choice", {
411
516
  data: { choices: choiceKeys },
412
517
  hint: options.prompt ?? "Choose an authentication method.",
@@ -452,5 +557,5 @@ export function createSwitchCeremony(options) {
452
557
  }
453
558
  return createTurn("abort", { hint: "Switch ceremony aborted." });
454
559
  }, "Switch ceremony abort failed", ctx),
455
- };
560
+ });
456
561
  }
@@ -1,4 +1,4 @@
1
- export type ApifuseCommandName = "create" | "dev" | "check" | "submit-check" | "bounty-check" | "record" | "test" | "perf";
1
+ export type ApifuseCommandName = "create" | "dev" | "check" | "sync-assets" | "migrate-shape" | "migrate-operation-declaration" | "submit-check" | "bounty-check" | "record" | "test" | "perf";
2
2
  export type ApifuseCommandManifest = {
3
3
  name: ApifuseCommandName;
4
4
  summary: string;
@@ -23,6 +23,30 @@ export const COMMAND_MANIFEST = {
23
23
  examples: ["apifuse check .", "apifuse check providers/korea-air-quality"],
24
24
  modulePath: "./apifuse-check",
25
25
  },
26
+ "sync-assets": {
27
+ name: "sync-assets",
28
+ summary: "Regenerate SDK-managed agent prompt assets (AGENTS.md, .agents/skills, symlinks, manifest) for the installed SDK version.",
29
+ usage: "apifuse sync-assets [path] [--check]",
30
+ examples: ["apifuse sync-assets .", "apifuse sync-assets . --check"],
31
+ modulePath: "./apifuse-sync-assets",
32
+ },
33
+ "migrate-shape": {
34
+ name: "migrate-shape",
35
+ summary: "Migrate a provider to the phase-separated SDK: two-phase defineProvider in index.ts and curried defineOperation across sources.",
36
+ usage: "apifuse migrate-shape [path] [--check] [--json]",
37
+ examples: ["apifuse migrate-shape .", "apifuse migrate-shape . --check"],
38
+ modulePath: "./apifuse-migrate-shape",
39
+ },
40
+ "migrate-operation-declaration": {
41
+ name: "migrate-operation-declaration",
42
+ summary: "Migrate legacy nested operation declarations to the ADR-0009 flat shape, refusing ambiguous safety or metadata.",
43
+ usage: "apifuse migrate-operation-declaration [path] [--check] [--json]",
44
+ examples: [
45
+ "apifuse migrate-operation-declaration .",
46
+ "apifuse migrate-operation-declaration . --check --json",
47
+ ],
48
+ modulePath: "./apifuse-migrate-operation-declaration",
49
+ },
26
50
  "submit-check": {
27
51
  name: "submit-check",
28
52
  summary: "Score provider bounty submission readiness and emit checklist evidence.",
@@ -73,6 +97,9 @@ export const COMMAND_ORDER = [
73
97
  "create",
74
98
  "dev",
75
99
  "check",
100
+ "sync-assets",
101
+ "migrate-shape",
102
+ "migrate-operation-declaration",
76
103
  "submit-check",
77
104
  "record",
78
105
  "test",