@voxgig/sdkgen 4.10.0 → 4.11.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 (304) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/package.json +1 -1
  3. package/project/.sdk/model/feature/secrets.aon +330 -0
  4. package/project/.sdk/model/target/c.aon +15 -2
  5. package/project/.sdk/model/target/cpp.aon +18 -0
  6. package/project/.sdk/model/target/lua.aon +17 -0
  7. package/project/.sdk/model/target/ocaml.aon +48 -5
  8. package/project/.sdk/model/target/zig.aon +30 -4
  9. package/project/.sdk/src/cmp/c/Config_c.ts +338 -1
  10. package/project/.sdk/src/cmp/c/Main_c.ts +57 -2
  11. package/project/.sdk/src/cmp/c/Package_c.ts +12 -2
  12. package/project/.sdk/src/cmp/cpp/Config_cpp.ts +324 -2
  13. package/project/.sdk/src/cmp/cpp/Gitignore_cpp.ts +2 -0
  14. package/project/.sdk/src/cmp/cpp/Main_cpp.ts +62 -4
  15. package/project/.sdk/src/cmp/cpp/Package_cpp.ts +10 -0
  16. package/project/.sdk/src/cmp/lua/Config_lua.ts +88 -0
  17. package/project/.sdk/src/cmp/lua/Gitignore_lua.ts +4 -0
  18. package/project/.sdk/src/cmp/lua/Main_lua.ts +93 -3
  19. package/project/.sdk/src/cmp/lua/Package_lua.ts +60 -0
  20. package/project/.sdk/src/cmp/lua/fragment/Main.fragment.lua +10 -0
  21. package/project/.sdk/src/cmp/ocaml/Config_ocaml.ts +183 -5
  22. package/project/.sdk/src/cmp/ocaml/Main_ocaml.ts +160 -3
  23. package/project/.sdk/src/cmp/ocaml/Package_ocaml.ts +25 -1
  24. package/project/.sdk/src/cmp/zig/Config_zig.ts +130 -9
  25. package/project/.sdk/src/cmp/zig/Main_zig.ts +208 -4
  26. package/project/.sdk/{tm/zig/build.zig → src/cmp/zig/fragment/Build.fragment.zig} +7 -0
  27. package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +25 -0
  28. package/project/.sdk/{tm/zig/root.zig → src/cmp/zig/fragment/Root.fragment.zig} +9 -0
  29. package/project/.sdk/tm/c/Makefile +58 -9
  30. package/project/.sdk/tm/c/core/sdk.h +10 -0
  31. package/project/.sdk/tm/c/feature/secrets/plugin/capability.c +133 -0
  32. package/project/.sdk/tm/c/feature/secrets/plugin/capability.h +39 -0
  33. package/project/.sdk/tm/c/feature/secrets/plugin/catalog.c +83 -0
  34. package/project/.sdk/tm/c/feature/secrets/plugin/catalog.h +48 -0
  35. package/project/.sdk/tm/c/feature/secrets/plugin/config.c +413 -0
  36. package/project/.sdk/tm/c/feature/secrets/plugin/config.h +24 -0
  37. package/project/.sdk/tm/c/feature/secrets/plugin/depend.c +264 -0
  38. package/project/.sdk/tm/c/feature/secrets/plugin/depend.h +29 -0
  39. package/project/.sdk/tm/c/feature/secrets/plugin/env.c +220 -0
  40. package/project/.sdk/tm/c/feature/secrets/plugin/env.h +19 -0
  41. package/project/.sdk/tm/c/feature/secrets/plugin/export.c +97 -0
  42. package/project/.sdk/tm/c/feature/secrets/plugin/export.h +19 -0
  43. package/project/.sdk/tm/c/feature/secrets/plugin/graph.c +237 -0
  44. package/project/.sdk/tm/c/feature/secrets/plugin/graph.h +17 -0
  45. package/project/.sdk/tm/c/feature/secrets/plugin/host.c +1494 -0
  46. package/project/.sdk/tm/c/feature/secrets/plugin/host.h +135 -0
  47. package/project/.sdk/tm/c/feature/secrets/plugin/order.c +288 -0
  48. package/project/.sdk/tm/c/feature/secrets/plugin/order.h +18 -0
  49. package/project/.sdk/tm/c/feature/secrets/plugin/point.c +141 -0
  50. package/project/.sdk/tm/c/feature/secrets/plugin/point.h +80 -0
  51. package/project/.sdk/tm/c/feature/secrets/plugin/ref.c +170 -0
  52. package/project/.sdk/tm/c/feature/secrets/plugin/ref.h +52 -0
  53. package/project/.sdk/tm/c/feature/secrets/plugin/resolve.c +98 -0
  54. package/project/.sdk/tm/c/feature/secrets/plugin/resolve.h +18 -0
  55. package/project/.sdk/tm/c/feature/secrets/plugin/types.c +150 -0
  56. package/project/.sdk/tm/c/feature/secrets/plugin/types.h +104 -0
  57. package/project/.sdk/tm/c/feature/secrets/plugin/value.c +649 -0
  58. package/project/.sdk/tm/c/feature/secrets/plugin/value.h +135 -0
  59. package/project/.sdk/tm/c/feature/secrets/plugin/version.c +151 -0
  60. package/project/.sdk/tm/c/feature/secrets/plugin/version.h +34 -0
  61. package/project/.sdk/tm/c/feature/secrets/plugins/aws.c +281 -0
  62. package/project/.sdk/tm/c/feature/secrets/plugins/azuresecrets.c +207 -0
  63. package/project/.sdk/tm/c/feature/secrets/plugins/boru.c +164 -0
  64. package/project/.sdk/tm/c/feature/secrets/plugins/clock.c +75 -0
  65. package/project/.sdk/tm/c/feature/secrets/plugins/doppler.c +141 -0
  66. package/project/.sdk/tm/c/feature/secrets/plugins/encode.c +144 -0
  67. package/project/.sdk/tm/c/feature/secrets/plugins/gcpsecrets.c +177 -0
  68. package/project/.sdk/tm/c/feature/secrets/plugins/hashicorp.c +239 -0
  69. package/project/.sdk/tm/c/feature/secrets/plugins/httpjson.c +599 -0
  70. package/project/.sdk/tm/c/feature/secrets/plugins/infisical.c +165 -0
  71. package/project/.sdk/tm/c/feature/secrets/plugins/onepassword.c +194 -0
  72. package/project/.sdk/tm/c/feature/secrets/plugins/proc.c +233 -0
  73. package/project/.sdk/tm/c/feature/secrets/plugins/secretspec.c +125 -0
  74. package/project/.sdk/tm/c/feature/secrets/plugins/sekretoplugins.h +125 -0
  75. package/project/.sdk/tm/c/feature/secrets/plugins/sha256.c +270 -0
  76. package/project/.sdk/tm/c/feature/secrets/plugins/sigv4.c +382 -0
  77. package/project/.sdk/tm/c/feature/secrets/plugins/support.h +153 -0
  78. package/project/.sdk/tm/c/feature/secrets/plugins/tls.c +420 -0
  79. package/project/.sdk/tm/c/feature/secrets/sekreto/internal.h +86 -0
  80. package/project/.sdk/tm/c/feature/secrets/sekreto/json.c +721 -0
  81. package/project/.sdk/tm/c/feature/secrets/sekreto/providers.c +813 -0
  82. package/project/.sdk/tm/c/feature/secrets/sekreto/sekreto.c +944 -0
  83. package/project/.sdk/tm/c/feature/secrets/sekreto/sekreto.h +490 -0
  84. package/project/.sdk/tm/c/feature/secrets/sekreto/util.c +442 -0
  85. package/project/.sdk/tm/c/feature/secrets.c +797 -0
  86. package/project/.sdk/tm/c/feature/secrets.h +46 -0
  87. package/project/.sdk/tm/c/src/feature/secrets/.gitkeep +0 -0
  88. package/project/.sdk/tm/c/tests/feature/secrets/secrets_test.c +802 -0
  89. package/project/.sdk/tm/clojure/feature/secrets/sdk/feature/secrets.clj +38 -11
  90. package/project/.sdk/tm/clojure/test/sdk/test/feature/secrets.clj +40 -6
  91. package/project/.sdk/tm/cpp/Makefile +48 -4
  92. package/project/.sdk/tm/cpp/feature/secrets/plugin/capability.cpp +121 -0
  93. package/project/.sdk/tm/cpp/feature/secrets/plugin/capability.hpp +41 -0
  94. package/project/.sdk/tm/cpp/feature/secrets/plugin/catalog.cpp +60 -0
  95. package/project/.sdk/tm/cpp/feature/secrets/plugin/catalog.hpp +66 -0
  96. package/project/.sdk/tm/cpp/feature/secrets/plugin/config.cpp +376 -0
  97. package/project/.sdk/tm/cpp/feature/secrets/plugin/config.hpp +29 -0
  98. package/project/.sdk/tm/cpp/feature/secrets/plugin/depend.cpp +230 -0
  99. package/project/.sdk/tm/cpp/feature/secrets/plugin/depend.hpp +31 -0
  100. package/project/.sdk/tm/cpp/feature/secrets/plugin/env.cpp +205 -0
  101. package/project/.sdk/tm/cpp/feature/secrets/plugin/env.hpp +25 -0
  102. package/project/.sdk/tm/cpp/feature/secrets/plugin/export.cpp +84 -0
  103. package/project/.sdk/tm/cpp/feature/secrets/plugin/export.hpp +24 -0
  104. package/project/.sdk/tm/cpp/feature/secrets/plugin/graph.cpp +222 -0
  105. package/project/.sdk/tm/cpp/feature/secrets/plugin/graph.hpp +21 -0
  106. package/project/.sdk/tm/cpp/feature/secrets/plugin/host.cpp +1200 -0
  107. package/project/.sdk/tm/cpp/feature/secrets/plugin/host.hpp +250 -0
  108. package/project/.sdk/tm/cpp/feature/secrets/plugin/order.cpp +250 -0
  109. package/project/.sdk/tm/cpp/feature/secrets/plugin/order.hpp +22 -0
  110. package/project/.sdk/tm/cpp/feature/secrets/plugin/point.cpp +110 -0
  111. package/project/.sdk/tm/cpp/feature/secrets/plugin/point.hpp +79 -0
  112. package/project/.sdk/tm/cpp/feature/secrets/plugin/ref.cpp +136 -0
  113. package/project/.sdk/tm/cpp/feature/secrets/plugin/ref.hpp +60 -0
  114. package/project/.sdk/tm/cpp/feature/secrets/plugin/resolve.cpp +82 -0
  115. package/project/.sdk/tm/cpp/feature/secrets/plugin/resolve.hpp +25 -0
  116. package/project/.sdk/tm/cpp/feature/secrets/plugin/types.cpp +90 -0
  117. package/project/.sdk/tm/cpp/feature/secrets/plugin/types.hpp +65 -0
  118. package/project/.sdk/tm/cpp/feature/secrets/plugin/value.cpp +491 -0
  119. package/project/.sdk/tm/cpp/feature/secrets/plugin/value.hpp +120 -0
  120. package/project/.sdk/tm/cpp/feature/secrets/plugin/version.cpp +143 -0
  121. package/project/.sdk/tm/cpp/feature/secrets/plugin/version.hpp +36 -0
  122. package/project/.sdk/tm/cpp/feature/secrets/plugins/Aws.cpp +248 -0
  123. package/project/.sdk/tm/cpp/feature/secrets/plugins/Aws.hpp +30 -0
  124. package/project/.sdk/tm/cpp/feature/secrets/plugins/Azuresecrets.cpp +149 -0
  125. package/project/.sdk/tm/cpp/feature/secrets/plugins/Azuresecrets.hpp +23 -0
  126. package/project/.sdk/tm/cpp/feature/secrets/plugins/Boru.cpp +117 -0
  127. package/project/.sdk/tm/cpp/feature/secrets/plugins/Boru.hpp +27 -0
  128. package/project/.sdk/tm/cpp/feature/secrets/plugins/Crypto.cpp +180 -0
  129. package/project/.sdk/tm/cpp/feature/secrets/plugins/Crypto.hpp +52 -0
  130. package/project/.sdk/tm/cpp/feature/secrets/plugins/Doppler.cpp +87 -0
  131. package/project/.sdk/tm/cpp/feature/secrets/plugins/Doppler.hpp +23 -0
  132. package/project/.sdk/tm/cpp/feature/secrets/plugins/Gcpsecrets.cpp +121 -0
  133. package/project/.sdk/tm/cpp/feature/secrets/plugins/Gcpsecrets.hpp +23 -0
  134. package/project/.sdk/tm/cpp/feature/secrets/plugins/Hashicorp.cpp +153 -0
  135. package/project/.sdk/tm/cpp/feature/secrets/plugins/Hashicorp.hpp +23 -0
  136. package/project/.sdk/tm/cpp/feature/secrets/plugins/Httpjson.cpp +666 -0
  137. package/project/.sdk/tm/cpp/feature/secrets/plugins/Httpjson.hpp +160 -0
  138. package/project/.sdk/tm/cpp/feature/secrets/plugins/Infisical.cpp +123 -0
  139. package/project/.sdk/tm/cpp/feature/secrets/plugins/Infisical.hpp +23 -0
  140. package/project/.sdk/tm/cpp/feature/secrets/plugins/Onepassword.cpp +125 -0
  141. package/project/.sdk/tm/cpp/feature/secrets/plugins/Onepassword.hpp +23 -0
  142. package/project/.sdk/tm/cpp/feature/secrets/plugins/Proc.cpp +223 -0
  143. package/project/.sdk/tm/cpp/feature/secrets/plugins/Proc.hpp +47 -0
  144. package/project/.sdk/tm/cpp/feature/secrets/plugins/Secretspec.cpp +104 -0
  145. package/project/.sdk/tm/cpp/feature/secrets/plugins/Secretspec.hpp +27 -0
  146. package/project/.sdk/tm/cpp/feature/secrets/plugins/Sigv4.cpp +242 -0
  147. package/project/.sdk/tm/cpp/feature/secrets/plugins/Sigv4.hpp +58 -0
  148. package/project/.sdk/tm/cpp/feature/secrets/plugins/Tls.cpp +260 -0
  149. package/project/.sdk/tm/cpp/feature/secrets/plugins/Tls.hpp +47 -0
  150. package/project/.sdk/tm/cpp/feature/secrets/sekreto/Json.cpp +476 -0
  151. package/project/.sdk/tm/cpp/feature/secrets/sekreto/Json.hpp +89 -0
  152. package/project/.sdk/tm/cpp/feature/secrets/sekreto/Provider.cpp +312 -0
  153. package/project/.sdk/tm/cpp/feature/secrets/sekreto/Provider.hpp +263 -0
  154. package/project/.sdk/tm/cpp/feature/secrets/sekreto/Providers.cpp +354 -0
  155. package/project/.sdk/tm/cpp/feature/secrets/sekreto/Providers.hpp +111 -0
  156. package/project/.sdk/tm/cpp/feature/secrets/sekreto/Sekreto.cpp +613 -0
  157. package/project/.sdk/tm/cpp/feature/secrets/sekreto/Sekreto.hpp +227 -0
  158. package/project/.sdk/tm/cpp/feature/secrets.hpp +745 -0
  159. package/project/.sdk/tm/cpp/src/feature/secrets/.gitkeep +0 -0
  160. package/project/.sdk/tm/cpp/test/feature/secrets/secrets_test.cpp +808 -0
  161. package/project/.sdk/tm/csharp/feature/SecretsFeature.cs +34 -8
  162. package/project/.sdk/tm/csharp/test/feature/secrets/SecretsFeatureTest.cs +85 -0
  163. package/project/.sdk/tm/elixir/lib/projectname/feature/secrets.ex +17 -2
  164. package/project/.sdk/tm/elixir/test/feature/secrets/secrets_test.exs +41 -0
  165. package/project/.sdk/tm/go/feature/secrets_feature.go +32 -10
  166. package/project/.sdk/tm/go/test/feature/secrets/secrets_feature_test.go +116 -0
  167. package/project/.sdk/tm/java/feature/SecretsFeature.java +33 -8
  168. package/project/.sdk/tm/java/test/feature/secrets/SecretsFeatureTest.java +64 -0
  169. package/project/.sdk/tm/js/src/feature/secrets/SecretsFeature.js +34 -11
  170. package/project/.sdk/tm/js/test/feature/secrets/Secrets.test.js +73 -0
  171. package/project/.sdk/tm/kotlin/feature/SecretsFeature.kt +32 -7
  172. package/project/.sdk/tm/kotlin/test/feature/secrets/SecretsTest.kt +69 -0
  173. package/project/.sdk/tm/lua/Makefile +15 -4
  174. package/project/.sdk/tm/lua/feature/secrets/native/sekretonet.c +806 -0
  175. package/project/.sdk/tm/lua/feature/secrets/plugin/capability.lua +135 -0
  176. package/project/.sdk/tm/lua/feature/secrets/plugin/catalog.lua +63 -0
  177. package/project/.sdk/tm/lua/feature/secrets/plugin/config.lua +361 -0
  178. package/project/.sdk/tm/lua/feature/secrets/plugin/depend.lua +232 -0
  179. package/project/.sdk/tm/lua/feature/secrets/plugin/env.lua +168 -0
  180. package/project/.sdk/tm/lua/feature/secrets/plugin/export.lua +66 -0
  181. package/project/.sdk/tm/lua/feature/secrets/plugin/graph.lua +194 -0
  182. package/project/.sdk/tm/lua/feature/secrets/plugin/host.lua +1190 -0
  183. package/project/.sdk/tm/lua/feature/secrets/plugin/json.lua +169 -0
  184. package/project/.sdk/tm/lua/feature/secrets/plugin/order.lua +207 -0
  185. package/project/.sdk/tm/lua/feature/secrets/plugin/point.lua +106 -0
  186. package/project/.sdk/tm/lua/feature/secrets/plugin/ref.lua +115 -0
  187. package/project/.sdk/tm/lua/feature/secrets/plugin/resolve.lua +78 -0
  188. package/project/.sdk/tm/lua/feature/secrets/plugin/types.lua +275 -0
  189. package/project/.sdk/tm/lua/feature/secrets/plugin/version.lua +131 -0
  190. package/project/.sdk/tm/lua/feature/secrets/plugin.lua +76 -0
  191. package/project/.sdk/tm/lua/feature/secrets/sekreto/addr.lua +124 -0
  192. package/project/.sdk/tm/lua/feature/secrets/sekreto/err.lua +47 -0
  193. package/project/.sdk/tm/lua/feature/secrets/sekreto/name.lua +315 -0
  194. package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/aws.lua +228 -0
  195. package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/azuresecrets.lua +137 -0
  196. package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/boru.lua +124 -0
  197. package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/crypto.lua +212 -0
  198. package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/doppler.lua +89 -0
  199. package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/gcpsecrets.lua +129 -0
  200. package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/hashicorp.lua +154 -0
  201. package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/httpjson.lua +248 -0
  202. package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/infisical.lua +113 -0
  203. package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/json.lua +449 -0
  204. package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/net.lua +198 -0
  205. package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/onepassword.lua +126 -0
  206. package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/secretspec.lua +93 -0
  207. package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/sigv4.lua +269 -0
  208. package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/support.lua +146 -0
  209. package/project/.sdk/tm/lua/feature/secrets/sekreto/providers.lua +346 -0
  210. package/project/.sdk/tm/lua/feature/secrets/sekreto.lua +479 -0
  211. package/project/.sdk/tm/lua/feature/secrets_feature.lua +690 -0
  212. package/project/.sdk/tm/lua/src/feature/secrets/.gitkeep +0 -0
  213. package/project/.sdk/tm/lua/test/extend_test.lua +105 -0
  214. package/project/.sdk/tm/lua/test/feature/secrets/secrets_feature_test.lua +862 -0
  215. package/project/.sdk/tm/ocaml/Makefile +52 -8
  216. package/project/.sdk/tm/ocaml/feature/secrets/plugin/capability.ml +106 -0
  217. package/project/.sdk/tm/ocaml/feature/secrets/plugin/catalog.ml +43 -0
  218. package/project/.sdk/tm/ocaml/feature/secrets/plugin/config.ml +349 -0
  219. package/project/.sdk/tm/ocaml/feature/secrets/plugin/defs.ml +143 -0
  220. package/project/.sdk/tm/ocaml/feature/secrets/plugin/depend.ml +217 -0
  221. package/project/.sdk/tm/ocaml/feature/secrets/plugin/env.ml +197 -0
  222. package/project/.sdk/tm/ocaml/feature/secrets/plugin/export.ml +89 -0
  223. package/project/.sdk/tm/ocaml/feature/secrets/plugin/graph.ml +227 -0
  224. package/project/.sdk/tm/ocaml/feature/secrets/plugin/host.ml +1112 -0
  225. package/project/.sdk/tm/ocaml/feature/secrets/plugin/order.ml +202 -0
  226. package/project/.sdk/tm/ocaml/feature/secrets/plugin/point.ml +138 -0
  227. package/project/.sdk/tm/ocaml/feature/secrets/plugin/ref.ml +126 -0
  228. package/project/.sdk/tm/ocaml/feature/secrets/plugin/resolve.ml +62 -0
  229. package/project/.sdk/tm/ocaml/feature/secrets/plugin/types.ml +97 -0
  230. package/project/.sdk/tm/ocaml/feature/secrets/plugin/value.ml +387 -0
  231. package/project/.sdk/tm/ocaml/feature/secrets/plugin/version.ml +139 -0
  232. package/project/.sdk/tm/ocaml/feature/secrets/plugins/aws.ml +171 -0
  233. package/project/.sdk/tm/ocaml/feature/secrets/plugins/azuresecrets.ml +116 -0
  234. package/project/.sdk/tm/ocaml/feature/secrets/plugins/boru.ml +95 -0
  235. package/project/.sdk/tm/ocaml/feature/secrets/plugins/crypto.ml +149 -0
  236. package/project/.sdk/tm/ocaml/feature/secrets/plugins/doppler.ml +61 -0
  237. package/project/.sdk/tm/ocaml/feature/secrets/plugins/gcpsecrets.ml +93 -0
  238. package/project/.sdk/tm/ocaml/feature/secrets/plugins/hashicorp.ml +120 -0
  239. package/project/.sdk/tm/ocaml/feature/secrets/plugins/http.ml +421 -0
  240. package/project/.sdk/tm/ocaml/feature/secrets/plugins/httpjson.ml +66 -0
  241. package/project/.sdk/tm/ocaml/feature/secrets/plugins/infisical.ml +85 -0
  242. package/project/.sdk/tm/ocaml/feature/secrets/plugins/onepassword.ml +112 -0
  243. package/project/.sdk/tm/ocaml/feature/secrets/plugins/runcmd.ml +97 -0
  244. package/project/.sdk/tm/ocaml/feature/secrets/plugins/secretspec.ml +68 -0
  245. package/project/.sdk/tm/ocaml/feature/secrets/plugins/sigv4.ml +259 -0
  246. package/project/.sdk/tm/ocaml/feature/secrets/plugins/tls.ml +44 -0
  247. package/project/.sdk/tm/ocaml/feature/secrets/plugins/tls_stubs.c +358 -0
  248. package/project/.sdk/tm/ocaml/feature/secrets/sekreto/json.ml +376 -0
  249. package/project/.sdk/tm/ocaml/feature/secrets/sekreto/provider.ml +647 -0
  250. package/project/.sdk/tm/ocaml/feature/secrets/sekreto/secret.ml +299 -0
  251. package/project/.sdk/tm/ocaml/feature/secrets/sekreto/sekreto.ml +347 -0
  252. package/project/.sdk/tm/ocaml/feature/secrets_feature.ml +453 -0
  253. package/project/.sdk/tm/ocaml/src/feature/secrets/.gitkeep +0 -0
  254. package/project/.sdk/tm/ocaml/test/feature/secrets/t_secrets.ml +670 -0
  255. package/project/.sdk/tm/perl/feature/secrets_feature.pm +33 -12
  256. package/project/.sdk/tm/perl/t/feature/secrets/secrets.t +47 -0
  257. package/project/.sdk/tm/php/feature/SecretsFeature.php +30 -6
  258. package/project/.sdk/tm/php/test/feature/secrets/SecretsTest.php +98 -0
  259. package/project/.sdk/tm/py/pkg/feature/secrets_feature.py +28 -6
  260. package/project/.sdk/tm/py/test/feature/secrets/test_secrets.py +114 -0
  261. package/project/.sdk/tm/rb/feature/secrets_feature.rb +28 -6
  262. package/project/.sdk/tm/rb/test/feature/secrets/secrets_feature_test.rb +93 -0
  263. package/project/.sdk/tm/rust/feature/secrets.rs +33 -10
  264. package/project/.sdk/tm/rust/tests/feature/secrets/main.rs +96 -0
  265. package/project/.sdk/tm/scala/feature/SecretsFeature.scala +29 -7
  266. package/project/.sdk/tm/scala/sdktest/feature/secrets/SecretsTestMain.scala +71 -0
  267. package/project/.sdk/tm/ts/src/feature/secrets/SecretsFeature.ts +35 -12
  268. package/project/.sdk/tm/ts/test/feature/secrets/Secrets.test.ts +73 -0
  269. package/project/.sdk/tm/zig/feature/secrets/plugin/capability.zig +137 -0
  270. package/project/.sdk/tm/zig/feature/secrets/plugin/catalog.zig +90 -0
  271. package/project/.sdk/tm/zig/feature/secrets/plugin/config.zig +346 -0
  272. package/project/.sdk/tm/zig/feature/secrets/plugin/depend.zig +244 -0
  273. package/project/.sdk/tm/zig/feature/secrets/plugin/env.zig +201 -0
  274. package/project/.sdk/tm/zig/feature/secrets/plugin/export.zig +83 -0
  275. package/project/.sdk/tm/zig/feature/secrets/plugin/graph.zig +212 -0
  276. package/project/.sdk/tm/zig/feature/secrets/plugin/host.zig +1224 -0
  277. package/project/.sdk/tm/zig/feature/secrets/plugin/inst.zig +126 -0
  278. package/project/.sdk/tm/zig/feature/secrets/plugin/order.zig +228 -0
  279. package/project/.sdk/tm/zig/feature/secrets/plugin/plugin.zig +34 -0
  280. package/project/.sdk/tm/zig/feature/secrets/plugin/point.zig +166 -0
  281. package/project/.sdk/tm/zig/feature/secrets/plugin/ref.zig +147 -0
  282. package/project/.sdk/tm/zig/feature/secrets/plugin/resolve.zig +74 -0
  283. package/project/.sdk/tm/zig/feature/secrets/plugin/types.zig +140 -0
  284. package/project/.sdk/tm/zig/feature/secrets/plugin/value.zig +662 -0
  285. package/project/.sdk/tm/zig/feature/secrets/plugin/version.zig +139 -0
  286. package/project/.sdk/tm/zig/feature/secrets/plugins/aws.zig +294 -0
  287. package/project/.sdk/tm/zig/feature/secrets/plugins/azuresecrets.zig +222 -0
  288. package/project/.sdk/tm/zig/feature/secrets/plugins/boru.zig +188 -0
  289. package/project/.sdk/tm/zig/feature/secrets/plugins/doppler.zig +135 -0
  290. package/project/.sdk/tm/zig/feature/secrets/plugins/gcpsecrets.zig +170 -0
  291. package/project/.sdk/tm/zig/feature/secrets/plugins/hashicorp.zig +242 -0
  292. package/project/.sdk/tm/zig/feature/secrets/plugins/httpjson.zig +535 -0
  293. package/project/.sdk/tm/zig/feature/secrets/plugins/infisical.zig +167 -0
  294. package/project/.sdk/tm/zig/feature/secrets/plugins/onepassword.zig +202 -0
  295. package/project/.sdk/tm/zig/feature/secrets/plugins/secretspec.zig +160 -0
  296. package/project/.sdk/tm/zig/feature/secrets/plugins/sigv4.zig +336 -0
  297. package/project/.sdk/tm/zig/feature/secrets/sekreto/addr.zig +148 -0
  298. package/project/.sdk/tm/zig/feature/secrets/sekreto/builtins.zig +259 -0
  299. package/project/.sdk/tm/zig/feature/secrets/sekreto/provider.zig +440 -0
  300. package/project/.sdk/tm/zig/feature/secrets/sekreto/sekreto.zig +944 -0
  301. package/project/.sdk/tm/zig/feature/secrets.zig +854 -0
  302. package/project/.sdk/tm/zig/src/feature/secrets/.gitkeep +0 -0
  303. package/project/.sdk/tm/zig/test/feature/secrets/secrets_test.zig +891 -0
  304. package/project/sdkgen-package.json +1 -1
@@ -0,0 +1,1190 @@
1
+ -- VENDORED: @voxgig/plugin sdk-20260908-1556-0 (lua/src/plugin/host.lua)
2
+ -- Source: https://github.com/voxgig/plugin @ 48392f5e2b6d1434ee9b1a4a9a11f4480aaeb46a [tag: sdk-20260908-1556-0]
3
+ -- License: MIT (c) voxgig - see repository LICENSE. Do not edit: resync from upstream.
4
+ -- The host: the lifecycle state machine (section 5), extension points
5
+ -- (section 6), and resource capture (section 8).
6
+ --
7
+ -- TWO RULES SHAPE EVERY METHOD BELOW.
8
+ --
9
+ -- Transitions are SEQUENTIAL (section 5.2). One at a time, in call order,
10
+ -- never interleaved; a transition triggered from inside a lifecycle
11
+ -- callback is `plugin_reentrant`. A hard rule, because it is the only way
12
+ -- the semantics can be identical in Go, in Lua and in single-threaded
13
+ -- JavaScript.
14
+ --
15
+ -- Reconciliation is EAGER (section 18's portability budget). A transition
16
+ -- settles by running the state machine to a fixed point, not by suspending
17
+ -- on a promise.
18
+ --
19
+ -- A LUA TABLE HAS NO ORDER. Every walk of the registry here sorts its keys
20
+ -- first: `T.keys` is not tidiness, it is the difference between a
21
+ -- deterministic teardown and one that changes between runs.
22
+
23
+ local T = require 'feature.secrets.plugin.types'
24
+ local R = require 'feature.secrets.plugin.ref'
25
+ local Cat = require 'feature.secrets.plugin.catalog'
26
+ local Ord = require 'feature.secrets.plugin.order'
27
+ local Pt = require 'feature.secrets.plugin.point'
28
+ local Ex = require 'feature.secrets.plugin.export'
29
+ local Cap = require 'feature.secrets.plugin.capability'
30
+ local Cfg = require 'feature.secrets.plugin.config'
31
+ local Dep = require 'feature.secrets.plugin.depend'
32
+
33
+ local M = {}
34
+
35
+ -- ------------------------------------------------------------------
36
+ -- Inst - what a definition's callbacks see
37
+ -- ------------------------------------------------------------------
38
+ --
39
+ -- Deliberately not the internal record: a plugin that could reach `status`
40
+ -- could also write it.
41
+
42
+ local Inst = {}
43
+ Inst.__index = Inst
44
+ M.Inst = Inst
45
+
46
+ function Inst.new(host, entry)
47
+ local parsed = R.parse_ref(entry.ref)
48
+ return setmetatable({
49
+ host = host,
50
+ entry = entry,
51
+ ref = entry.ref,
52
+ name = parsed.name,
53
+ tag = parsed.tag,
54
+ }, Inst)
55
+ end
56
+
57
+ -- The resolved options and the instance's own state, both LIVE: a lua
58
+ -- table is a reference, so a callback that keeps one sees what `apply` and
59
+ -- `options` write into it.
60
+ function Inst:options()
61
+ return self.entry.options
62
+ end
63
+
64
+ function Inst:state()
65
+ return self.entry.state
66
+ end
67
+
68
+ -- Foreign resources the host did not hand out are registered explicitly
69
+ -- (section 8.3); host calls are recorded automatically.
70
+ --
71
+ -- SYMMETRIC WITH `acquire`, and it has to be: `open` counts the resources
72
+ -- CURRENTLY HELD, so an entry that is registered and then unwound must
73
+ -- leave the count where it found it.
74
+ function Inst:release(fn)
75
+ -- Section 8.3: "`inst.release` outside `activate` is
76
+ -- `plugin_release_scope`". A flag saying merely that a transition is
77
+ -- running is true in `define` too, and a scope entry registered there is
78
+ -- never unwound.
79
+ if 'activate' ~= self.host.phase then
80
+ T.fail('plugin_release_scope', 'release called outside activate', nil)
81
+ end
82
+ local host = self.host
83
+ local done = false
84
+ table.insert(self.entry.scope, function()
85
+ if done then return end
86
+ done = true
87
+ host.open = host.open - 1
88
+ fn()
89
+ end)
90
+ host.open = host.open + 1
91
+ end
92
+
93
+ -- The synthetic counter the driver owns, so "what is open" is data rather
94
+ -- than an assertion each port words differently.
95
+ --
96
+ -- Returns its own release, so a plugin can hand one back early. The scope
97
+ -- still holds the entry and unwinding it twice is a no-op - releasing
98
+ -- early must not make teardown wrong.
99
+ function Inst:acquire()
100
+ -- Section 8.1: resources are "acquired during `activate` - the scope's
101
+ -- actual job". Same reason as `release` above.
102
+ if 'activate' ~= self.host.phase then
103
+ T.fail('plugin_release_scope', 'acquire called outside activate', nil)
104
+ end
105
+ local host = self.host
106
+ local done = false
107
+ local rel = function()
108
+ if done then return end
109
+ done = true
110
+ host.open = host.open - 1
111
+ end
112
+ table.insert(self.entry.scope, rel)
113
+ host.open = host.open + 1
114
+ return rel
115
+ end
116
+
117
+ -- Bind into a host point. Declared in `define`; the host inserts it only
118
+ -- after `activate` returns successfully (section 8.1), which is why a
119
+ -- failing activate leaves no live binding behind.
120
+ function Inst:bind(point, fn, band)
121
+ -- Section 12 has carried `plugin_bind_scope` - "binding declared outside
122
+ -- `define`" - since before anything raised it. Section 8.1 puts binding
123
+ -- DECLARATION in `define` and INSERTION at a successful activate, and
124
+ -- the guard was the half nobody wrote.
125
+ if 'define' ~= self.host.phase then
126
+ T.fail('plugin_bind_scope', 'bind called outside define: ' .. point,
127
+ T.map { ref = self.ref, point = point })
128
+ end
129
+ if not T.has(self.host.points, point) then
130
+ T.fail('plugin_point_unknown', 'no such point: ' .. point,
131
+ T.map { point = point })
132
+ end
133
+ table.insert(self.entry.bindings, {
134
+ ref = self.ref,
135
+ point = point,
136
+ fn = fn,
137
+ band = 'integer' == math.type(band) and band or 0,
138
+ })
139
+ end
140
+
141
+ -- Published for other plugins and for the application (section 11).
142
+ function Inst:export(key, value)
143
+ self.entry.exports[key] = value
144
+ self.entry.exportkeys[key] = true
145
+ end
146
+
147
+ -- What this instance can do for others (section 11.1).
148
+ function Inst:provides(prov)
149
+ table.insert(self.entry.provides, prov)
150
+ end
151
+
152
+ -- Where this binding landed (section 6.6) - the plugin-side counterpart to
153
+ -- a host pin. THE HOST DOES NOT POLICE THIS; it just makes the fact
154
+ -- available.
155
+ function Inst:position(point)
156
+ return self.host:positionof(self.ref, point)
157
+ end
158
+
159
+ -- AN INSTANCE MAY ITSELF BE A HOST (section 6.5), and THE OUTER ONE OWNS
160
+ -- THE INNER ONE'S LIFETIME. Registering the teardown in the instance scope
161
+ -- is what makes that true rather than aspirational.
162
+ function Inst:nest(nestopts)
163
+ if not self.host.transition then
164
+ T.fail('plugin_release_scope', 'nest called outside a lifecycle callback',
165
+ nil)
166
+ end
167
+ local inner = M.make_host(nestopts)
168
+ table.insert(self.entry.scope, function() inner:close() end)
169
+ self.entry.inner = inner
170
+ return inner
171
+ end
172
+
173
+ -- ------------------------------------------------------------------
174
+ -- Host
175
+ -- ------------------------------------------------------------------
176
+
177
+ local Host = {}
178
+ Host.__index = Host
179
+ M.Host = Host
180
+
181
+ function M.make_host(options)
182
+ options = options or T.map {}
183
+ return setmetatable({
184
+ opts = options,
185
+ dependency = T.getv(options, 'dependency') or 'restart',
186
+ reserved = T.getv(options, 'reserved') or T.list {},
187
+ points = T.getv(options, 'points') or T.map {},
188
+ catalog = T.getv(options, 'catalog') or Cat.make_catalog {},
189
+ inst = {},
190
+ order_of = {}, -- refs, kept sorted, so every walk is stable
191
+ log = {},
192
+ -- Section 14: the lifecycle event record. `seq` distinguishes ONE
193
+ -- INCARNATION of stripe$test from the next, which is the whole reason
194
+ -- it is not `pos` (section 4 rule 4).
195
+ events = {},
196
+ seqn = 0,
197
+ open = 0,
198
+ transition = false,
199
+ -- WHICH callback is running, not merely that one is. Section 8.1 puts
200
+ -- resource capture in `activate` and 8.3 says `release` outside
201
+ -- `activate` is `plugin_release_scope` - and a bare flag cannot tell
202
+ -- `activate` from `define`, so it admitted an acquire in `define`
203
+ -- whose scope `unload` would never unwind.
204
+ phase = nil,
205
+ coordinated = false,
206
+ }, Host)
207
+ end
208
+
209
+ -- The registry's refs, sorted. Lua tables have no order, so this is the
210
+ -- one walk every method uses.
211
+ function Host:refs()
212
+ local out = {}
213
+ for k in pairs(self.inst) do out[#out + 1] = k end
214
+ table.sort(out)
215
+ return out
216
+ end
217
+
218
+ function Host:define(definition)
219
+ self.catalog:add(definition)
220
+ end
221
+
222
+ -- --- observation ------------------------------------------------
223
+
224
+ -- Introspection NEVER advances the state (section 5.2). A status page must
225
+ -- not be a way to accidentally import twenty packages.
226
+ function Host:list()
227
+ local out = T.map {}
228
+ for _, ref in ipairs(self:refs()) do
229
+ out[ref] = self.inst[ref].status
230
+ end
231
+ return out
232
+ end
233
+
234
+ -- The instance record, or nil when nothing is registered under that ref.
235
+ -- THE REF IS VALIDATED, not merely canonicalized: looking an instance up
236
+ -- by `"bad name"` is `plugin_bad_name`, not a quiet miss.
237
+ function Host:instance(ref)
238
+ return self.inst[R.canon_ref(ref)]
239
+ end
240
+
241
+ function Host:trace()
242
+ local out = {}
243
+ for i, e in ipairs(self.events) do out[i] = e end
244
+ return T.list(out)
245
+ end
246
+
247
+ function Host:observable(result)
248
+ local log = {}
249
+ for i, l in ipairs(self.log) do log[i] = l end
250
+ return T.map {
251
+ status = self:list(),
252
+ open = self.open,
253
+ log = T.list(log),
254
+ result = nil == result and T.NULL or result,
255
+ }
256
+ end
257
+
258
+ -- --- the state machine ------------------------------------------
259
+
260
+ function Host:guard()
261
+ if not self.transition then return end
262
+ T.fail('plugin_reentrant',
263
+ 'transition attempted from inside a lifecycle callback', nil)
264
+ end
265
+
266
+ function Host:need(ref)
267
+ local r = R.canon_ref(ref)
268
+ local entry = self.inst[r]
269
+ if nil == entry then
270
+ T.fail('plugin_not_loaded', 'no such instance: ' .. r, T.map { ref = r })
271
+ end
272
+ return entry
273
+ end
274
+
275
+ function Host:checkreserved(ref)
276
+ if 0 == T.len(self.reserved) then return end
277
+ local name = R.refname(ref)
278
+ for i = 1, T.len(self.reserved) do
279
+ if self.reserved[i] == name then
280
+ T.fail('plugin_ref_reserved', 'ref is reserved by the host: ' .. ref,
281
+ T.map { ref = ref })
282
+ end
283
+ end
284
+ end
285
+
286
+ function Host:run(entry, callback, at)
287
+ local fn = entry.def[callback]
288
+ table.insert(self.log, entry.ref .. ':' .. at)
289
+ table.insert(self.events, T.map {
290
+ ref = entry.ref, event = at, seq = entry.seq, status = entry.status,
291
+ })
292
+ if 'function' ~= type(fn) then return end
293
+
294
+ self.transition = true
295
+ self.phase = at
296
+ local ok, err = pcall(fn, Inst.new(self, entry))
297
+ self.transition = false
298
+ self.phase = nil
299
+ if ok then return end
300
+
301
+ -- Section 12: `plugin_define_failed` and its three siblings are "a
302
+ -- callback raised; wraps the cause". AN ERROR THAT ALREADY CARRIES A
303
+ -- CODE KEEPS IT - the code is the error's identity, and a plugin raising
304
+ -- `store_unreachable` must not have it rewritten. Only a code-less error
305
+ -- is wrapped.
306
+ if '' ~= T.codeof(err) then error(err, 0) end
307
+
308
+ T.fail('plugin_' .. at .. '_failed',
309
+ entry.ref .. ' raised in ' .. at .. ': ' .. T.message(err),
310
+ T.map { ref = entry.ref, cause = T.message(err) })
311
+ end
312
+
313
+ -- AUTO-TAGGING IS EXPLICIT (section 4 rule 3). `declare('stripe', {tag =
314
+ -- '?'})` assigns the LOWEST UNUSED POSITIVE INTEGER tag and returns the
315
+ -- assigned pair. Without `'?'`, a collision is an error.
316
+ function Host:autotag(name)
317
+ local n = 1
318
+ while true do
319
+ local cand = R.format_ref(name, tostring(n))
320
+ if nil == self.inst[cand] then return cand end
321
+ n = n + 1
322
+ end
323
+ end
324
+
325
+ function Host:count()
326
+ local n = 0
327
+ for _ in pairs(self.inst) do n = n + 1 end
328
+ return n
329
+ end
330
+
331
+ function Host:declare(ref, spec)
332
+ spec = spec or T.map {}
333
+ if '?' == T.getv(spec, 'tag') then
334
+ ref = self:autotag(R.refname(R.canon_ref(ref)))
335
+ end
336
+ local r = R.canon_ref(ref)
337
+ if not T.truthy(T.getv(spec, 'hostowned')) then
338
+ self:checkreserved(r)
339
+ end
340
+ local defname = T.getv(spec, 'definition') or R.refname(r)
341
+ local definition = self.catalog:get(defname)
342
+ if nil == definition then
343
+ T.fail('plugin_unknown_definition', 'not in catalog: ' .. defname,
344
+ T.map { name = defname })
345
+ end
346
+
347
+ local existing = self.inst[r]
348
+ if nil ~= existing then
349
+ -- Section 4 rule 1: a pair addresses at most one instance.
350
+ -- Re-declaring the SAME definition is the idempotent case; a different
351
+ -- one is a duplicate, not a silent overwrite (seneca) and not an
352
+ -- impossibility (sdkgen).
353
+ if existing.def.name ~= definition.name then
354
+ T.fail('plugin_ref_duplicate', 'instance already declared: ' .. r,
355
+ T.map { ref = r })
356
+ end
357
+ return existing
358
+ end
359
+
360
+ local pos = T.getv(spec, 'pos')
361
+ local entry = {
362
+ ref = r,
363
+ def = definition,
364
+ status = 'declared',
365
+ pos = nil == pos and self:count() or pos,
366
+ seq = self.seqn,
367
+ options = T.getv(spec, 'options') or T.map {},
368
+ state = T.map {},
369
+ order = T.getv(spec, 'order'),
370
+ unmet = {},
371
+ scope = {},
372
+ -- Section 11.4's ALWAYS-RELUCTANT rebinding made concrete: the
373
+ -- provider ref this instance's activation actually chose, per
374
+ -- requirement name. Re-ranking on every question silently re-points a
375
+ -- live consumer at any better newcomer, and then losing the provider
376
+ -- it was really using does not restart it.
377
+ selected = {},
378
+ bindings = {},
379
+ exports = T.map {},
380
+ exportkeys = {},
381
+ provides = {},
382
+ inner = nil,
383
+ barred = false,
384
+ }
385
+ self.seqn = self.seqn + 1
386
+ self.inst[r] = entry
387
+ return entry
388
+ end
389
+
390
+ -- Section 9.1: a host that reserves a name MUST still be able to declare
391
+ -- the instance it reserved - "The host declares those instances itself,
392
+ -- after the user merge, and always wins."
393
+ --
394
+ -- THE BOUNDARY IS BY METHOD, NOT BY CALLER, and that is a real limit: no
395
+ -- language here can tell the embedding host from a plugin holding the same
396
+ -- host object. What reservation protects is CONFIGURATION - documents,
397
+ -- overlays, `VOXGIG_PLUGIN_*`, construction options and ordinary
398
+ -- declare/load/options - and all of that still checks.
399
+ function Host:hostdeclare(ref, spec)
400
+ self:guard()
401
+ local owned = T.map {}
402
+ for k, v in pairs(spec or T.map {}) do owned[k] = v end
403
+ owned.hostowned = true
404
+ return self:declare(ref, owned)
405
+ end
406
+
407
+ function Host:load(ref, spec)
408
+ self:guard()
409
+ spec = spec or T.map {}
410
+ local entry = self:declare(ref, spec)
411
+ if 'declared' ~= entry.status then return entry end -- idempotent
412
+
413
+ -- PRESENCE, NOT TRUTH: an empty options map must CLEAR what the instance
414
+ -- was declared with.
415
+ if T.has(spec, 'options') and T.NULL ~= spec.options then
416
+ entry.options = spec.options
417
+ end
418
+ local ok, err = pcall(function() self:run(entry, 'define', 'define') end)
419
+ if not ok then
420
+ entry.status = 'failed'
421
+ error(err, 0)
422
+ end
423
+ entry.status = 'loaded'
424
+
425
+ -- AT LOAD, and before anything runs: a cycle through restart-causing
426
+ -- requirements does not settle, and the only safe time to report a
427
+ -- non-terminating reconcile is before it starts (section 11.3).
428
+ -- `provides` is populated by `define`, which has just run, so this is
429
+ -- the first moment the graph is complete.
430
+ ok, err = pcall(function() Dep.checkcycle(self:graphnodes()) end)
431
+ if not ok then
432
+ entry.status = 'failed'
433
+ error(err, 0)
434
+ end
435
+ return entry
436
+ end
437
+
438
+ -- The requirement graph as plain data, for the pure detector.
439
+ function Host:graphnodes()
440
+ local out = {}
441
+ for _, ref in ipairs(self:refs()) do
442
+ local entry = self.inst[ref]
443
+ local provides = {}
444
+ for _, p in ipairs(entry.provides) do
445
+ provides[#provides + 1] = T.getv(p, 'name')
446
+ end
447
+ out[#out + 1] = {
448
+ ref = ref,
449
+ provides = provides,
450
+ requires = Dep.requirements(entry.options),
451
+ }
452
+ end
453
+ return out
454
+ end
455
+
456
+ function Host:activate(ref)
457
+ self:guard()
458
+ local entry = self:need(ref)
459
+ if 'live' == entry.status then return entry end -- no-op, success
460
+
461
+ if 'failed' == entry.status then
462
+ T.fail('plugin_bad_state', 'instance has failed: ' .. entry.ref,
463
+ T.map { ref = entry.ref })
464
+ end
465
+ -- Section 9.6: `active: false` bars the instance from running, and the
466
+ -- bar is on the INSTANCE rather than on the apply that set it. `ready`
467
+ -- reaches this through `activate`, so one guard covers both verbs the
468
+ -- design names.
469
+ if entry.barred then
470
+ T.fail('plugin_inactive',
471
+ 'instance is barred by active: false: ' .. entry.ref,
472
+ T.map { ref = entry.ref })
473
+ end
474
+ if 'declared' == entry.status then
475
+ self:load(entry.ref)
476
+ end
477
+
478
+ -- A declared requirement that is not live means `pending`: activation is
479
+ -- a STANDING REQUEST, not a one-shot event.
480
+ local unmet = self:unmetof(entry)
481
+ if 0 < #unmet then
482
+ entry.unmet = unmet
483
+ entry.status = 'pending'
484
+ return entry
485
+ end
486
+
487
+ local ok, err = pcall(function() self:run(entry, 'activate', 'activate') end)
488
+ if not ok then
489
+ -- Unwind whatever the partial activation captured, in reverse.
490
+ self:unwind(entry)
491
+ entry.status = 'failed'
492
+ error(err, 0)
493
+ end
494
+ -- Section 11.4: THE SELECTION IS MADE HERE, once, and remembered. Every
495
+ -- later question - the cascade, `hold`, `unmet` - reads it back rather
496
+ -- than re-ranking, which is what "always-reluctant" means.
497
+ for _, req in ipairs(Dep.requirements(entry.options)) do
498
+ self:chosen(entry, req, true)
499
+ end
500
+ entry.status = 'live'
501
+ self:reconcile()
502
+ return entry
503
+ end
504
+
505
+ function Host:deactivate(ref)
506
+ self:guard()
507
+ local entry = self:need(ref)
508
+ if 'loaded' == entry.status or 'declared' == entry.status then
509
+ return entry
510
+ end
511
+
512
+ -- Section 5.2: `unload` is THE ONLY TRANSITION OUT OF `failed`.
513
+ if 'failed' == entry.status then
514
+ T.fail('plugin_bad_state', 'instance has failed: ' .. entry.ref,
515
+ T.map { ref = entry.ref })
516
+ end
517
+
518
+ if 'pending' == entry.status then
519
+ -- DEACTIVATING A PENDING INSTANCE RUNS NO CALLBACK (section 5.2). It
520
+ -- never reached activate, so it holds no scope and no live bindings;
521
+ -- running the definition's deactivate there would be teardown without
522
+ -- matching setup, which plugins are not written to survive and which
523
+ -- could fail an instance that had done nothing wrong. It cannot fail.
524
+ entry.status = 'loaded'
525
+ entry.unmet = {}
526
+ return entry
527
+ end
528
+
529
+ self:held(entry.ref)
530
+ self:cascade(entry.ref, {})
531
+
532
+ local ok, err = pcall(function()
533
+ self:run(entry, 'deactivate', 'deactivate')
534
+ end)
535
+ if not ok then
536
+ self:unwind(entry)
537
+ entry.status = 'failed'
538
+ error(err, 0)
539
+ end
540
+ self:releasecheck(entry, self:unwind(entry))
541
+ entry.status = 'loaded'
542
+ self:reconcile()
543
+ return entry
544
+ end
545
+
546
+ function Host:unload(ref)
547
+ self:guard()
548
+ local entry = self:need(ref)
549
+ if 'live' == entry.status or 'pending' == entry.status then
550
+ if 'live' == entry.status then
551
+ self:held(entry.ref)
552
+ self:cascade(entry.ref, {})
553
+ local ok, err = pcall(function()
554
+ self:run(entry, 'deactivate', 'deactivate')
555
+ end)
556
+ if not ok then
557
+ -- Section 5.2: ANY failure during a transition lands the instance
558
+ -- in `failed`, with the scope STILL FULLY UNWOUND - and the
559
+ -- instance STAYS REGISTERED, because `failed` is a state an
560
+ -- operator has to be able to see.
561
+ self:unwind(entry)
562
+ entry.status = 'failed'
563
+ error(err, 0)
564
+ end
565
+ self:releasecheck(entry, self:unwind(entry))
566
+ end
567
+ entry.status = 'loaded'
568
+ end
569
+ if 'loaded' == entry.status or 'failed' == entry.status then
570
+ local ok, err = pcall(function() self:run(entry, 'close', 'close') end)
571
+ self.inst[entry.ref] = nil
572
+ if not ok then error(err, 0) end
573
+ return
574
+ end
575
+ self.inst[entry.ref] = nil
576
+ end
577
+
578
+ -- Runs the whole forward path in one call (section 5.1).
579
+ function Host:ready(ref)
580
+ self:guard()
581
+ local r = R.canon_ref(ref)
582
+ if nil == self.inst[r] then self:declare(r) end
583
+ if 'declared' == self.inst[r].status then self:load(r) end
584
+ return self:activate(r)
585
+ end
586
+
587
+ -- Bindings go live only when activation succeeds (section 8.1), so the
588
+ -- teardown is the exact inverse: reverse order, always. Returns the errors
589
+ -- the scope raised. Section 8.3: "A failing release does not stop the
590
+ -- rest. Every entry runs, in reverse order, whatever any of them does; the
591
+ -- errors are collected and raised as one `plugin_release_failed`."
592
+ --
593
+ -- A selection belongs to ONE activation (section 11.4). Leaving `live` by
594
+ -- any door drops it, so the next activation ranks afresh - keeping it
595
+ -- would make a consumer prefer a provider it never actually ran against.
596
+ function Host:unwind(entry)
597
+ entry.selected = {}
598
+ local scope = entry.scope
599
+ entry.scope = {}
600
+ local errors = {}
601
+ for i = #scope, 1, -1 do
602
+ local ok, err = pcall(scope[i])
603
+ if not ok then errors[#errors + 1] = err end
604
+ end
605
+ return errors
606
+ end
607
+
608
+ -- Section 8.3: "A failed release ends the instance in `failed`, exactly as
609
+ -- a failed callback does (5.2) - a release that raised may have leaked,
610
+ -- and an instance that may be holding resources it cannot account for must
611
+ -- not be reactivated."
612
+ function Host:releasecheck(entry, errors)
613
+ if 0 == #errors then return end
614
+ entry.status = 'failed'
615
+ local causes = {}
616
+ for _, e in ipairs(errors) do causes[#causes + 1] = T.message(e) end
617
+ T.fail('plugin_release_failed',
618
+ 'release failed for ' .. entry.ref .. ': '
619
+ .. table.concat(causes, '; '),
620
+ T.map { ref = entry.ref, cause = T.list(causes) })
621
+ end
622
+
623
+ -- A REQUIREMENT IS ON A CAPABILITY, not on a ref (section 11.1). A bare
624
+ -- string is shorthand for `{name}`. A ref satisfies too, because a host
625
+ -- that genuinely needs a specific instance should not have to invent a
626
+ -- capability for it.
627
+ function Host:unmetof(entry)
628
+ local out = {}
629
+ for _, req in ipairs(Dep.requirements(entry.options)) do
630
+ if Dep.gatesactivation(req) and 0 == #self:providersof(req) then
631
+ out[#out + 1] = T.getv(req, 'name')
632
+ end
633
+ end
634
+ return out
635
+ end
636
+
637
+ -- Section 11.4's always-reluctant selection, and the ONE place a provider
638
+ -- is picked for a live instance. If this instance already selected a
639
+ -- provider for `req` and that provider is STILL a candidate, it keeps it -
640
+ -- a better-ranked newcomer does not take it.
641
+ --
642
+ -- `remember` is false for the questions asked ABOUT an instance rather
643
+ -- than BY it: introspection must not create a binding.
644
+ function Host:chosen(entry, req, remember)
645
+ local cands = self:providersof(req)
646
+ if 0 == #cands then return nil end
647
+
648
+ local name = T.getv(req, 'name')
649
+ local held = entry.selected[name]
650
+ if nil ~= held then
651
+ for i = 1, #cands do
652
+ if T.getv(cands[i], 'ref') == held then return held end
653
+ end
654
+ end
655
+
656
+ local best = T.getv(cands[1], 'ref')
657
+ if remember then entry.selected[name] = best end
658
+ return best
659
+ end
660
+
661
+ function Host:boundproviders(entry)
662
+ local out = {}
663
+ local seen = {}
664
+ for _, req in ipairs(Dep.requirements(entry.options)) do
665
+ if Dep.restartsonloss(req) then
666
+ local ref = self:chosen(entry, req, false)
667
+ if nil ~= ref and not seen[ref] then
668
+ seen[ref] = true
669
+ out[#out + 1] = ref
670
+ end
671
+ end
672
+ end
673
+ return out
674
+ end
675
+
676
+ -- Live instances whose selected provider is `ref` and which would be
677
+ -- restarted by losing it.
678
+ function Host:consumersof(ref)
679
+ local out = {}
680
+ for _, r in ipairs(self:refs()) do
681
+ local c = self.inst[r]
682
+ if r ~= ref and 'live' == c.status then
683
+ for _, p in ipairs(self:boundproviders(c)) do
684
+ if p == ref then
685
+ out[#out + 1] = r
686
+ break
687
+ end
688
+ end
689
+ end
690
+ end
691
+ return out
692
+ end
693
+
694
+ -- Section 11.3's `hold` asks a DIFFERENT question from the cascade, and
695
+ -- reading it off `consumersof` answered the cascade's.
696
+ --
697
+ -- The cascade wants the edges that RESTART - mandatory-static and
698
+ -- optional-static - because a restart is what it performs. `hold` says
699
+ -- "deactivating a REQUIRED instance is `plugin_dependency_held`", and
700
+ -- required is cardinality: `gatesactivation`, not `restartsonloss`. The
701
+ -- two sets differ in both directions and each difference was a real bug.
702
+ function Host:holdersof(ref)
703
+ local out = {}
704
+ for _, r in ipairs(self:refs()) do
705
+ local c = self.inst[r]
706
+ if r ~= ref and 'live' == c.status then
707
+ for _, req in ipairs(Dep.requirements(c.options)) do
708
+ if Dep.gatesactivation(req) and ref == self:chosen(c, req, false) then
709
+ out[#out + 1] = r
710
+ break
711
+ end
712
+ end
713
+ end
714
+ end
715
+ return out
716
+ end
717
+
718
+ function Host:providersof(req)
719
+ local name = T.getv(req, 'name')
720
+ local want = R.canon(name)
721
+ local cands = {}
722
+ for _, ref in ipairs(self:refs()) do
723
+ local target = self.inst[ref]
724
+ if 'live' == target.status then
725
+ -- A ref satisfies directly.
726
+ if ref == want then
727
+ cands[#cands + 1] = T.map {
728
+ ref = ref, pos = target.pos, provides = T.map { name = name },
729
+ }
730
+ else
731
+ for _, prov in ipairs(target.provides) do
732
+ if T.same(T.getv(prov, 'name'), name) then
733
+ cands[#cands + 1] = T.map {
734
+ ref = ref, pos = target.pos, provides = prov,
735
+ }
736
+ end
737
+ end
738
+ end
739
+ end
740
+ end
741
+ return Cap.resolve_capability(req, T.list(cands))
742
+ end
743
+
744
+ -- CONSUMERS GO DOWN FIRST, NOT AFTERWARDS (section 11.3).
745
+ --
746
+ -- The cascade is part of the provider's own deactivation and runs BEFORE
747
+ -- the provider's `deactivate` callback and scope unwind, so a consumer's
748
+ -- teardown can still call the thing it depends on - flushing a buffer to
749
+ -- the store it is about to lose is exactly what a `deactivate` callback is
750
+ -- for, and a cascade that fired after the provider was already gone would
751
+ -- make that impossible.
752
+ function Host:cascade(provider, seen)
753
+ if seen[provider] then return end
754
+ seen[provider] = true
755
+
756
+ for _, r in ipairs(self:consumersof(provider)) do
757
+ local consumer = self.inst[r]
758
+ if nil ~= consumer and 'live' == consumer.status then
759
+ self:cascade(r, seen) -- deepest-first
760
+ local ok = pcall(function()
761
+ self:run(consumer, 'deactivate', 'deactivate')
762
+ end)
763
+ local errors = self:unwind(consumer)
764
+ if not ok or 0 < #errors then
765
+ -- Section 5.2: ANY failure during a transition lands the instance
766
+ -- in `failed`. Marking it `pending` handed it straight back to
767
+ -- `reconcile`, which would activate it again the moment the
768
+ -- provider returned.
769
+ consumer.status = 'failed'
770
+ else
771
+ consumer.status = 'pending'
772
+ consumer.unmet = self:unmetof(consumer)
773
+ end
774
+ end
775
+ end
776
+ end
777
+
778
+ -- The hold check is A GUARD ON AD-HOC DEACTIVATION, NOT ON COORDINATED
779
+ -- TEARDOWN. In a bulk operation that is removing the holders too -
780
+ -- `close`, or an `apply` plan whose own steps deactivate them - it is
781
+ -- suspended for exactly those holders, and the teardown still runs
782
+ -- consumers before providers.
783
+ function Host:held(ref)
784
+ if 'hold' ~= self.dependency then return end
785
+ if self.coordinated then return end
786
+
787
+ local holders = self:holdersof(ref)
788
+ if 0 == #holders then return end
789
+
790
+ T.fail('plugin_dependency_held',
791
+ 'instance is required by live consumers: ' .. ref,
792
+ T.map { ref = ref, holders = T.list(holders) })
793
+ end
794
+
795
+ -- EAGER reconciliation: run to a fixed point rather than scheduling.
796
+ --
797
+ -- Two directions, and both are the reason `pending` exists. Activation is
798
+ -- a STANDING REQUEST, not a one-shot event.
799
+ function Host:reconcile()
800
+ local moved = true
801
+ local rounds = 0
802
+ while moved do
803
+ moved = false
804
+ rounds = rounds + 1
805
+ if 1000 < rounds then break end
806
+
807
+ -- Losses first, so a cascade settles in one pass rather than
808
+ -- alternating with re-activations.
809
+ for _, r in ipairs(self:refs()) do
810
+ local entry = self.inst[r]
811
+ if nil ~= entry and 'live' == entry.status then
812
+ local lost = {}
813
+ for _, q in ipairs(Dep.requirements(entry.options)) do
814
+ if Dep.gatesactivation(q) and 0 == #self:providersof(q) then
815
+ lost[#lost + 1] = q
816
+ end
817
+ end
818
+ if 0 < #lost then
819
+ -- POLICY IS PER REQUIREMENT, not per instance (section 11.3). A
820
+ -- `dynamic` requirement whose provider is gone leaves the
821
+ -- consumer LIVE and notified.
822
+ local restarts = false
823
+ for _, q in ipairs(lost) do
824
+ if Dep.restartsonloss(q) then restarts = true break end
825
+ end
826
+ if restarts then
827
+ local ok = pcall(function()
828
+ self:run(entry, 'deactivate', 'deactivate')
829
+ end)
830
+ local errors = self:unwind(entry)
831
+ if not ok or 0 < #errors then
832
+ entry.status = 'failed'
833
+ else
834
+ entry.status = 'pending'
835
+ entry.unmet = self:unmetof(entry)
836
+ end
837
+ moved = true
838
+ end
839
+ end
840
+ end
841
+ end
842
+
843
+ for _, r in ipairs(self:refs()) do
844
+ local entry = self.inst[r]
845
+ if nil ~= entry and 'pending' == entry.status
846
+ and 0 == #self:unmetof(entry) then
847
+ local ok = pcall(function()
848
+ self:run(entry, 'activate', 'activate')
849
+ end)
850
+ if ok then
851
+ entry.status = 'live'
852
+ entry.unmet = {}
853
+ else
854
+ self:unwind(entry)
855
+ entry.status = 'failed'
856
+ end
857
+ moved = true
858
+ end
859
+ end
860
+ end
861
+ end
862
+
863
+ -- --- ordering ---------------------------------------------------
864
+
865
+ function Host:order(point)
866
+ -- Sorted by declaration SEQUENCE, which is what makes the section 7
867
+ -- sort's fall-through deterministic in a language whose maps have no
868
+ -- insertion order. Section 7 breaks ties by `pos`; two instances CAN
869
+ -- share one - `declare` defaults `pos` to the registry size, so an
870
+ -- unload followed by a fresh declare reuses a surviving instance's - and
871
+ -- past that this was falling through to table order. `seq` is that
872
+ -- order, made explicit.
873
+ local live = {}
874
+ for _, ref in ipairs(self:refs()) do
875
+ local entry = self.inst[ref]
876
+ if 'live' == entry.status then live[#live + 1] = entry end
877
+ end
878
+ live = T.stable_sort(live, function(a, b) return a.seq < b.seq end)
879
+
880
+ local bindings = {}
881
+ for _, entry in ipairs(live) do
882
+ bindings[#bindings + 1] = {
883
+ ref = entry.ref, pos = entry.pos, order = entry.order,
884
+ }
885
+ end
886
+ local pin
887
+ if nil ~= point then
888
+ pin = T.getv(T.getv(self.points, point) or T.map {}, 'pin')
889
+ end
890
+ return Ord.resolve_order(bindings, pin)
891
+ end
892
+
893
+ -- --- points -----------------------------------------------------
894
+
895
+ -- Live bindings on a point, in resolved order. Recomputed on any change to
896
+ -- the live set (section 7) rather than cached at startup - the bug a host
897
+ -- discovers only when something deactivates in production.
898
+ function Host:bound(point)
899
+ local out = {}
900
+ for _, ref in ipairs(self:order(point)) do
901
+ local entry = self.inst[ref]
902
+ -- The band is the INSTANCE's ordering block (section 7), stamped by
903
+ -- the host. A plugin passing its own would be ranking itself above the
904
+ -- order its document declared.
905
+ local block = T.ismap(entry.order) and entry.order or T.map {}
906
+ local band = T.getv(block, 'band')
907
+ band = 'integer' == math.type(band) and band or 0
908
+ for _, b in ipairs(entry.bindings) do
909
+ if b.point == point then
910
+ out[#out + 1] = { ref = b.ref, point = b.point, fn = b.fn, band = band }
911
+ end
912
+ end
913
+ end
914
+ return out
915
+ end
916
+
917
+ function Host:pointspec(point, want)
918
+ if not T.has(self.points, point) then
919
+ T.fail('plugin_point_unknown', 'no such point: ' .. tostring(point),
920
+ T.map { point = point })
921
+ end
922
+ local spec = self.points[point]
923
+ local kind = T.getv(spec, 'kind')
924
+ if 'hook' == want then
925
+ -- A point with no declared kind is a hook, which is what makes `{}`
926
+ -- the minimal point declaration.
927
+ if nil ~= kind and 'hook' ~= kind then
928
+ T.fail('plugin_point_kind', 'point is not a hook: ' .. point,
929
+ T.map { point = point, kind = kind })
930
+ end
931
+ return spec
932
+ end
933
+ if kind ~= want then
934
+ T.fail('plugin_point_kind', 'point is not a ' .. want .. ': ' .. point,
935
+ T.map { point = point, kind = kind })
936
+ end
937
+ return spec
938
+ end
939
+
940
+ function Host:emit(point, arg)
941
+ local spec = self:pointspec(point, 'hook')
942
+ return Pt.point_emit(self:bound(point), T.getv(spec, 'mode') or 'emit', arg)
943
+ end
944
+
945
+ function Host:call(point, ...)
946
+ local spec = self:pointspec(point, 'chain')
947
+ local base = T.getv(spec, 'base')
948
+ if 'function' ~= type(base) then
949
+ base = function(v) return v end
950
+ end
951
+ return Pt.compose(self:bound(point), base)(...)
952
+ end
953
+
954
+ function Host:provider(point, ...)
955
+ local spec = self:pointspec(point, 'provider')
956
+ local pick = Pt.point_provider(self:bound(point), spec)
957
+ if nil == pick.winner then return T.getv(spec, 'default') end
958
+ return pick.winner.fn(nil, ...)
959
+ end
960
+
961
+ -- The losers are VISIBLE rather than silently ignored (section 6.3).
962
+ function Host:shadowed(point)
963
+ if not T.has(self.points, point) then return T.list {} end
964
+ return Pt.point_provider(self:bound(point), self.points[point]).shadowed
965
+ end
966
+
967
+ function Host:exports(spec)
968
+ local all = {}
969
+ for _, ref in ipairs(self:refs()) do
970
+ local entry = self.inst[ref]
971
+ -- Exports of a `loaded` (not live) instance are VISIBLE (11).
972
+ if 'declared' ~= entry.status and 'failed' ~= entry.status then
973
+ local keys = {}
974
+ for k in pairs(entry.exportkeys) do keys[#keys + 1] = k end
975
+ table.sort(keys)
976
+ for _, k in ipairs(keys) do
977
+ all[#all + 1] = { ref = ref, key = k, value = entry.exports[k] }
978
+ end
979
+ end
980
+ end
981
+ return Ex.resolve_export(spec, all)
982
+ end
983
+
984
+ -- The live providers of a capability, best-first (section 11.1).
985
+ function Host:capability(name)
986
+ local cands = {}
987
+ for _, ref in ipairs(self:refs()) do
988
+ local entry = self.inst[ref]
989
+ if 'live' == entry.status then
990
+ for _, prov in ipairs(entry.provides) do
991
+ if T.getv(prov, 'name') == name then
992
+ cands[#cands + 1] = T.map {
993
+ ref = ref, pos = entry.pos, provides = prov,
994
+ }
995
+ end
996
+ end
997
+ end
998
+ end
999
+ local ranked = Cap.resolve_capability(T.map { name = name }, T.list(cands))
1000
+ local out = {}
1001
+ for i = 1, #ranked do out[#out + 1] = T.getv(ranked[i], 'ref') end
1002
+ return T.list(out)
1003
+ end
1004
+
1005
+ -- --- documents --------------------------------------------------
1006
+
1007
+ function Host:shapeof(ref)
1008
+ local definition = self.catalog:get(R.refname(ref))
1009
+ if nil == definition then return nil end
1010
+ return definition.shape
1011
+ end
1012
+
1013
+ -- Section 9.6: "load what is missing, UNLOAD WHAT IS GONE, patch what
1014
+ -- changed, and move activation state to match", with the stated ordering -
1015
+ -- "deactivations and unloads first (reverse load order), then loads, then
1016
+ -- activations in load order".
1017
+ --
1018
+ -- FOUR PHASES, NOT ONE INTERLEAVED LOOP. An earlier draft walked the
1019
+ -- document once, which never looked at instances the new document had
1020
+ -- DROPPED - so an integration removed from a config reload stayed live
1021
+ -- with its bindings and resources.
1022
+ function Host:apply(doc, profile)
1023
+ self:guard()
1024
+ if nil == profile then profile = T.getv(self.opts, 'profile') end
1025
+
1026
+ local norm = Cfg.normalize_config(T.map {
1027
+ doc = doc,
1028
+ profile = profile,
1029
+ keys = T.getv(self.opts, 'keys'),
1030
+ reserved = self.reserved,
1031
+ })
1032
+
1033
+ local want = {}
1034
+ for i = 1, T.len(norm.order) do want[#want + 1] = norm.order[i] end
1035
+
1036
+ local defaults = T.getv(self.opts, 'defaults') or T.map {}
1037
+ local optionsof = {}
1038
+ for _, ref in ipairs(want) do
1039
+ optionsof[ref] = Cfg.resolve_options(T.map {
1040
+ ref = ref,
1041
+ doc = doc,
1042
+ profile = profile,
1043
+ shape = self:shapeof(ref),
1044
+ hostdefaults = T.getv(defaults, R.refname(ref)),
1045
+ })
1046
+ end
1047
+
1048
+ -- Should this ref be LIVE after the apply? False for a ref the document
1049
+ -- declares lazy or inactive AND for one it does not name at all - which
1050
+ -- is what makes "unload what is gone" and "unload what was toggled off"
1051
+ -- one rule rather than two.
1052
+ local function wantlive(ref)
1053
+ local ent = T.getv(norm.instance, ref)
1054
+ return nil ~= ent and T.truthy(T.getv(ent, 'active'))
1055
+ and 'eager' == T.getv(ent, 'start')
1056
+ end
1057
+
1058
+ -- --- phase 1: deactivations and unloads, REVERSE load order ----
1059
+ local drop = {}
1060
+ for _, ref in ipairs(self:refs()) do
1061
+ if 'declared' ~= self.inst[ref].status and not wantlive(ref) then
1062
+ drop[#drop + 1] = ref
1063
+ end
1064
+ end
1065
+ -- Highest `pos` first, ref-descending for a tie, so a consumer declared
1066
+ -- after its provider goes down first.
1067
+ local inst = self.inst
1068
+ table.sort(drop, function(a, b)
1069
+ if inst[a].pos ~= inst[b].pos then return inst[a].pos > inst[b].pos end
1070
+ return a > b
1071
+ end)
1072
+ for _, ref in ipairs(drop) do self:unload(ref) end
1073
+
1074
+ -- --- phase 2: declare and patch EVERYTHING, in load order ------
1075
+ for _, ref in ipairs(want) do
1076
+ local ent = T.getv(norm.instance, ref)
1077
+ -- NO OPTIONS HERE, and the omission is the fix rather than an
1078
+ -- oversight. `declare` ADOPTS the options table it is handed as the
1079
+ -- instance's own, so passing the resolved table made target and
1080
+ -- source THE SAME TABLE in the refill below - which cleared its own
1081
+ -- source and left a first-time instance with no options at all.
1082
+ -- `declare` makes its own empty table and the refill fills it, so
1083
+ -- both paths are now one path.
1084
+ self:declare(ref, T.map {
1085
+ order = T.getv(ent, 'order'),
1086
+ pos = T.getv(ent, 'pos'),
1087
+ })
1088
+ -- The bar is REASSERTED ON EVERY APPLY, in both directions - a
1089
+ -- document that turns the instance back on clears it, which is the
1090
+ -- whole point of a config switch.
1091
+ self.inst[ref].barred = not T.truthy(T.getv(ent, 'active'))
1092
+ -- REFILL rather than REBIND. A definition's callbacks close over the
1093
+ -- options table they were handed at `define`.
1094
+ local target = self.inst[ref].options
1095
+ for k in pairs(target) do target[k] = nil end
1096
+ for k, v in pairs(optionsof[ref]) do target[k] = v end
1097
+ self.inst[ref].order = T.getv(ent, 'order')
1098
+ self.inst[ref].pos = T.getv(ent, 'pos')
1099
+ end
1100
+
1101
+ -- --- phase 3: loads, in load order -----------------------------
1102
+ -- ONLY THE EAGER, ACTIVE ONES: "a document of twenty lazy instances is
1103
+ -- twenty map entries and no executed code" (9.6).
1104
+ for _, ref in ipairs(want) do
1105
+ if wantlive(ref) then self:load(ref) end
1106
+ end
1107
+
1108
+ -- --- phase 4: activations, in load order -----------------------
1109
+ for _, ref in ipairs(want) do
1110
+ if wantlive(ref) then self:activate(ref) end
1111
+ end
1112
+ end
1113
+
1114
+ function Host:options(ref, patch)
1115
+ self:guard()
1116
+ local entry = self:need(ref)
1117
+ local previous = T.map {}
1118
+ for k, v in pairs(entry.options) do previous[k] = v end
1119
+
1120
+ local merged = T.map {}
1121
+ for k, v in pairs(previous) do merged[k] = v end
1122
+ for _, k in ipairs(T.keys(patch)) do merged[k] = patch[k] end
1123
+
1124
+ local resolved = Cfg.resolve_options(T.map {
1125
+ ref = entry.ref,
1126
+ shape = self:shapeof(entry.ref),
1127
+ doc = T.map {},
1128
+ patch = merged,
1129
+ })
1130
+ local target = entry.options
1131
+ for k in pairs(target) do target[k] = nil end
1132
+ for k, v in pairs(resolved) do target[k] = v end
1133
+
1134
+ if 'live' ~= entry.status then return end
1135
+
1136
+ local reconfigure = entry.def.reconfigure
1137
+ if 'function' == type(reconfigure) then
1138
+ self.transition = true
1139
+ local ok, err = pcall(reconfigure, Inst.new(self, entry), entry.options,
1140
+ previous)
1141
+ self.transition = false
1142
+ if not ok then error(err, 0) end
1143
+ else
1144
+ -- Always correct and sometimes expensive; `reconfigure` exists to make
1145
+ -- the common case cheap (section 9.4).
1146
+ self:deactivate(entry.ref)
1147
+ self:activate(entry.ref)
1148
+ end
1149
+ end
1150
+
1151
+ function Host:close()
1152
+ -- A bulk teardown removing the holders too, so `hold` is suspended for
1153
+ -- exactly those holders (section 11.3) - while the consumers-first
1154
+ -- cascade still runs, which is the half that matters.
1155
+ self.coordinated = true
1156
+ local refs = self:refs()
1157
+ local ok, err = pcall(function()
1158
+ for i = #refs, 1, -1 do
1159
+ if nil ~= self.inst[refs[i]] then self:unload(refs[i]) end
1160
+ end
1161
+ end)
1162
+ self.coordinated = false
1163
+ if not ok then error(err, 0) end
1164
+ end
1165
+
1166
+ -- The same record section 6.6 gives a plugin about itself, reachable from
1167
+ -- outside for the corpus.
1168
+ function Host:positionof(ref, point)
1169
+ local entry = self.inst[R.canon(ref)]
1170
+ if nil == entry then
1171
+ T.fail('plugin_not_loaded', 'no such instance: ' .. tostring(ref),
1172
+ T.map { ref = ref })
1173
+ end
1174
+ local ranked = self:order(point)
1175
+ local index = -1
1176
+ for i = 1, #ranked do
1177
+ if ranked[i] == entry.ref then index = i - 1 break end
1178
+ end
1179
+ return T.map {
1180
+ index = index,
1181
+ count = #ranked,
1182
+ -- Section 6.2 composes b1(b2(b3(base))) with the FIRST binding
1183
+ -- OUTERMOST, so these are not index 0 and index count-1 the other way
1184
+ -- round.
1185
+ outermost = 0 == index,
1186
+ innermost = index == #ranked - 1,
1187
+ }
1188
+ end
1189
+
1190
+ return M