@noodleseed/one 0.161.2 → 0.163.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 (315) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +3 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/billing-catalog-ops.d.ts +4 -0
  5. package/dist/commands/billing-catalog-ops.d.ts.map +1 -0
  6. package/dist/commands/billing-catalog-ops.js +58 -0
  7. package/dist/commands/billing-catalog-ops.js.map +1 -0
  8. package/dist/commands/billing-ops.d.ts.map +1 -1
  9. package/dist/commands/billing-ops.js +3 -0
  10. package/dist/commands/billing-ops.js.map +1 -1
  11. package/dist/commands/catalog.d.ts.map +1 -1
  12. package/dist/commands/catalog.js +3 -0
  13. package/dist/commands/catalog.js.map +1 -1
  14. package/dist/commands/config-values.d.ts.map +1 -1
  15. package/dist/commands/config-values.js +16 -0
  16. package/dist/commands/config-values.js.map +1 -1
  17. package/dist/commands/installation-variables.d.ts +26 -0
  18. package/dist/commands/installation-variables.d.ts.map +1 -0
  19. package/dist/commands/installation-variables.js +171 -0
  20. package/dist/commands/installation-variables.js.map +1 -0
  21. package/dist/commands/solutions-activity.d.ts +5 -0
  22. package/dist/commands/solutions-activity.d.ts.map +1 -0
  23. package/dist/commands/solutions-activity.js +116 -0
  24. package/dist/commands/solutions-activity.js.map +1 -0
  25. package/dist/commands/solutions-connections.d.ts +7 -0
  26. package/dist/commands/solutions-connections.d.ts.map +1 -0
  27. package/dist/commands/solutions-connections.js +88 -0
  28. package/dist/commands/solutions-connections.js.map +1 -0
  29. package/dist/commands/solutions-installation-options.d.ts +5 -0
  30. package/dist/commands/solutions-installation-options.d.ts.map +1 -0
  31. package/dist/commands/solutions-installation-options.js +52 -0
  32. package/dist/commands/solutions-installation-options.js.map +1 -0
  33. package/dist/commands/solutions-onboarding.d.ts +5 -0
  34. package/dist/commands/solutions-onboarding.d.ts.map +1 -0
  35. package/dist/commands/solutions-onboarding.js +113 -0
  36. package/dist/commands/solutions-onboarding.js.map +1 -0
  37. package/dist/commands/solutions-ops.d.ts +7 -0
  38. package/dist/commands/solutions-ops.d.ts.map +1 -0
  39. package/dist/commands/solutions-ops.js +544 -0
  40. package/dist/commands/solutions-ops.js.map +1 -0
  41. package/dist/index.d.ts +1 -1
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +1 -1
  44. package/dist/index.js.map +1 -1
  45. package/node_modules/@noodle-borg/admission-limits/dist/counter-store.d.ts +21 -2
  46. package/node_modules/@noodle-borg/admission-limits/dist/counter-store.js +10 -1
  47. package/node_modules/@noodle-borg/admission-limits/dist/in-memory-counter-store.d.ts +5 -1
  48. package/node_modules/@noodle-borg/admission-limits/dist/in-memory-counter-store.js +31 -2
  49. package/node_modules/@noodle-borg/admission-limits/dist/portable.d.ts +3 -0
  50. package/node_modules/@noodle-borg/admission-limits/dist/portable.js +3 -0
  51. package/node_modules/@noodle-borg/admission-limits/dist/public-admission-assertion.d.ts +28 -0
  52. package/node_modules/@noodle-borg/admission-limits/dist/public-admission-assertion.js +124 -0
  53. package/node_modules/@noodle-borg/admission-limits/dist/public-record-admission.d.ts +54 -0
  54. package/node_modules/@noodle-borg/admission-limits/dist/public-record-admission.js +74 -0
  55. package/node_modules/@noodle-borg/admission-limits/dist/request-attribution.d.ts +11 -0
  56. package/node_modules/@noodle-borg/admission-limits/dist/request-attribution.js +19 -0
  57. package/node_modules/@noodle-borg/agent-kit/dist/curated/command-groups.js +4 -0
  58. package/node_modules/@noodle-borg/agent-kit/dist/curated/error-fixes.js +4 -1
  59. package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js +5 -5
  60. package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js +6 -0
  61. package/node_modules/@noodle-borg/agent-kit/dist/skill-authoring-refs.js +21 -2
  62. package/node_modules/@noodle-borg/agent-kit/dist/skill-content.js +1 -1
  63. package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
  64. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-configuration.d.ts +9 -1
  65. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-configuration.js +33 -2
  66. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-execution-bound.d.ts +3 -0
  67. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-execution-bound.js +29 -0
  68. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-interaction-state.d.ts +5 -3
  69. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-interaction-state.js +21 -10
  70. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-store.d.ts +1 -1
  71. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-store.js +3 -3
  72. package/node_modules/@noodle-borg/assistant-gateway/dist/portable.d.ts +1 -0
  73. package/node_modules/@noodle-borg/assistant-gateway/dist/portable.js +1 -0
  74. package/node_modules/@noodle-borg/assistant-gateway/dist/session-target.js +5 -4
  75. package/node_modules/@noodle-borg/authoring/dist/config.d.ts +20 -0
  76. package/node_modules/@noodle-borg/authoring/dist/config.js +29 -2
  77. package/node_modules/@noodle-borg/authoring/dist/connectors.d.ts +6 -1
  78. package/node_modules/@noodle-borg/authoring/dist/connectors.js +5 -0
  79. package/node_modules/@noodle-borg/authoring/dist/index.d.ts +2 -1
  80. package/node_modules/@noodle-borg/authoring/dist/index.js +1 -0
  81. package/node_modules/@noodle-borg/authoring/dist/json-schema.d.ts +1 -1
  82. package/node_modules/@noodle-borg/authoring/dist/json-schema.js +15 -2
  83. package/node_modules/@noodle-borg/authoring/dist/load-authored.js +1 -1
  84. package/node_modules/@noodle-borg/authoring/dist/managed-collection.d.ts +40 -0
  85. package/node_modules/@noodle-borg/authoring/dist/managed-collection.js +39 -0
  86. package/node_modules/@noodle-borg/authoring/dist/platform.d.ts +3 -0
  87. package/node_modules/@noodle-borg/authoring/dist/platform.js +4 -0
  88. package/node_modules/@noodle-borg/authoring/dist/server-presentation.js +43 -0
  89. package/node_modules/@noodle-borg/authoring/dist/server.d.ts +6 -1
  90. package/node_modules/@noodle-borg/authoring/dist/server.js +5 -43
  91. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-billing.js +18 -0
  92. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-config.js +31 -4
  93. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solutions.js +778 -0
  94. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-types.js +7 -0
  95. package/node_modules/@noodle-borg/cli-catalog/dist/index.js +20 -0
  96. package/node_modules/@noodle-borg/compiler/dist/artifact/assemble.js +5 -1
  97. package/node_modules/@noodle-borg/compiler/dist/artifact/catalog-emission.js +3 -1
  98. package/node_modules/@noodle-borg/compiler/dist/artifact/config.js +3 -0
  99. package/node_modules/@noodle-borg/compiler/dist/artifact/types.d.ts +26 -0
  100. package/node_modules/@noodle-borg/compiler/dist/artifact/version.d.ts +9 -1
  101. package/node_modules/@noodle-borg/compiler/dist/artifact/version.js +9 -1
  102. package/node_modules/@noodle-borg/compiler/dist/business-variables.d.ts +27 -0
  103. package/node_modules/@noodle-borg/compiler/dist/business-variables.js +230 -0
  104. package/node_modules/@noodle-borg/compiler/dist/compile.js +9 -0
  105. package/node_modules/@noodle-borg/compiler/dist/errors.d.ts +1 -1
  106. package/node_modules/@noodle-borg/compiler/dist/index.d.ts +5 -1
  107. package/node_modules/@noodle-borg/compiler/dist/index.js +4 -0
  108. package/node_modules/@noodle-borg/compiler/dist/managed-collection-controls.d.ts +52 -0
  109. package/node_modules/@noodle-borg/compiler/dist/managed-collection-controls.js +92 -0
  110. package/node_modules/@noodle-borg/compiler/dist/managed-collections.d.ts +50 -0
  111. package/node_modules/@noodle-borg/compiler/dist/managed-collections.js +373 -0
  112. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts +114 -36
  113. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js +5 -0
  114. package/node_modules/@noodle-borg/compiler/dist/native-record-operations.d.ts +7 -0
  115. package/node_modules/@noodle-borg/compiler/dist/native-record-operations.js +59 -0
  116. package/node_modules/@noodle-borg/connector-defs/dist/compile-http.js +83 -8
  117. package/node_modules/@noodle-borg/connector-defs/dist/schema.d.ts +31 -1
  118. package/node_modules/@noodle-borg/connector-defs/dist/schema.js +16 -0
  119. package/node_modules/@noodle-borg/connector-http/dist/http-connector.d.ts +12 -3
  120. package/node_modules/@noodle-borg/connector-http/dist/http-connector.js +41 -2
  121. package/node_modules/@noodle-borg/connector-http/dist/http-response.js +3 -2
  122. package/node_modules/@noodle-borg/connector-http/dist/mcp/config.js +1 -1
  123. package/node_modules/@noodle-borg/connector-http/dist/url-resolution.js +1 -1
  124. package/node_modules/@noodle-borg/control-plane/dist/contracts.d.ts +2 -1
  125. package/node_modules/@noodle-borg/control-plane/dist/in-memory-organization-store.d.ts +3 -0
  126. package/node_modules/@noodle-borg/control-plane/dist/in-memory-organization-store.js +11 -0
  127. package/node_modules/@noodle-borg/control-plane/dist/organization-agreements.d.ts +45 -0
  128. package/node_modules/@noodle-borg/control-plane/dist/organization-agreements.js +74 -0
  129. package/node_modules/@noodle-borg/control-plane/dist/portable.d.ts +1 -0
  130. package/node_modules/@noodle-borg/control-plane/dist/portable.js +1 -0
  131. package/node_modules/@noodle-borg/module/dist/contract.d.ts +20 -0
  132. package/node_modules/@noodle-borg/module/dist/platform-human-identity.d.ts +2 -0
  133. package/node_modules/@noodle-borg/protocol/dist/request-deps.js +1 -0
  134. package/node_modules/@noodle-borg/protocol/dist/request-state.d.ts +1 -0
  135. package/node_modules/@noodle-borg/protocol/dist/request-state.js +11 -2
  136. package/node_modules/@noodle-borg/protocol/dist/sdk-server.d.ts +2 -0
  137. package/node_modules/@noodle-borg/protocol/dist/v2/input-required.js +2 -1
  138. package/node_modules/@noodle-borg/protocol/dist/v2/server.js +2 -1
  139. package/node_modules/@noodle-borg/runtime/dist/ambient-context.js +6 -1
  140. package/node_modules/@noodle-borg/runtime/dist/broker/types.d.ts +2 -0
  141. package/node_modules/@noodle-borg/runtime/dist/business-variables.d.ts +15 -0
  142. package/node_modules/@noodle-borg/runtime/dist/business-variables.js +75 -0
  143. package/node_modules/@noodle-borg/runtime/dist/confirmation-continuation.js +2 -1
  144. package/node_modules/@noodle-borg/runtime/dist/confirmation.js +23 -3
  145. package/node_modules/@noodle-borg/runtime/dist/connector/types.d.ts +17 -1
  146. package/node_modules/@noodle-borg/runtime/dist/connector-snapshot.js +6 -0
  147. package/node_modules/@noodle-borg/runtime/dist/execute.d.ts +18 -3
  148. package/node_modules/@noodle-borg/runtime/dist/execute.js +13 -3
  149. package/node_modules/@noodle-borg/runtime/dist/index.d.ts +2 -0
  150. package/node_modules/@noodle-borg/runtime/dist/index.js +1 -0
  151. package/node_modules/@noodle-borg/runtime/dist/interactive.js +11 -0
  152. package/node_modules/@noodle-borg/runtime/dist/managed-origins.d.ts +3 -1
  153. package/node_modules/@noodle-borg/runtime/dist/managed-origins.js +32 -7
  154. package/node_modules/@noodle-borg/runtime/dist/operation-credential.js +6 -0
  155. package/node_modules/@noodle-borg/runtime/dist/operation-evidence.d.ts +30 -0
  156. package/node_modules/@noodle-borg/runtime/dist/operation-evidence.js +68 -0
  157. package/node_modules/@noodle-borg/runtime/dist/operation-execution.d.ts +2 -2
  158. package/node_modules/@noodle-borg/runtime/dist/operation-execution.js +142 -71
  159. package/node_modules/@noodle-borg/runtime/dist/result.d.ts +6 -4
  160. package/node_modules/@noodle-borg/runtime/dist/tool-dispatch.d.ts +7 -0
  161. package/node_modules/@noodle-borg/runtime/dist/tool-dispatch.js +48 -4
  162. package/node_modules/@noodle-borg/service/dist/admission.js +2 -1
  163. package/node_modules/@noodle-borg/service/dist/application-activity.js +236 -0
  164. package/node_modules/@noodle-borg/service/dist/application-business-notice.js +28 -0
  165. package/node_modules/@noodle-borg/service/dist/application-runtime-target.js +141 -0
  166. package/node_modules/@noodle-borg/service/dist/application-settings-targets.js +72 -0
  167. package/node_modules/@noodle-borg/service/dist/application-settings.js +210 -0
  168. package/node_modules/@noodle-borg/service/dist/business-api-admission.js +121 -0
  169. package/node_modules/@noodle-borg/service/dist/business-information/activity-pagination.js +73 -0
  170. package/node_modules/@noodle-borg/service/dist/business-information/business-notice.d.ts +24 -0
  171. package/node_modules/@noodle-borg/service/dist/business-information/business-notice.js +18 -0
  172. package/node_modules/@noodle-borg/service/dist/business-information/collection-controls.js +51 -0
  173. package/node_modules/@noodle-borg/service/dist/business-information/contracts.d.ts +439 -0
  174. package/node_modules/@noodle-borg/service/dist/business-information/contracts.js +5 -0
  175. package/node_modules/@noodle-borg/service/dist/business-information/definition-resolver.js +94 -0
  176. package/node_modules/@noodle-borg/service/dist/business-information/in-memory-installation-lifecycle.js +136 -0
  177. package/node_modules/@noodle-borg/service/dist/business-information/in-memory-invitations.js +160 -0
  178. package/node_modules/@noodle-borg/service/dist/business-information/in-memory-locks.js +23 -0
  179. package/node_modules/@noodle-borg/service/dist/business-information/in-memory-store.js +557 -0
  180. package/node_modules/@noodle-borg/service/dist/business-information/installation-capacity.js +10 -0
  181. package/node_modules/@noodle-borg/service/dist/business-information/invitations.js +68 -0
  182. package/node_modules/@noodle-borg/service/dist/business-information/legacy-request-migration.js +60 -0
  183. package/node_modules/@noodle-borg/service/dist/business-information/managed-releases.js +245 -0
  184. package/node_modules/@noodle-borg/service/dist/business-information/managed-solution-blueprints.js +51 -0
  185. package/node_modules/@noodle-borg/service/dist/business-information/managed-solution-executable.js +76 -0
  186. package/node_modules/@noodle-borg/service/dist/business-information/model.js +393 -0
  187. package/node_modules/@noodle-borg/service/dist/business-information/native-query.js +162 -0
  188. package/node_modules/@noodle-borg/service/dist/business-information/native-storage-budget.js +60 -0
  189. package/node_modules/@noodle-borg/service/dist/business-information/pagination.js +78 -0
  190. package/node_modules/@noodle-borg/service/dist/business-information/portable.js +15 -0
  191. package/node_modules/@noodle-borg/service/dist/business-information/principal-authority.d.ts +11 -0
  192. package/node_modules/@noodle-borg/service/dist/business-information/principal-authority.js +42 -0
  193. package/node_modules/@noodle-borg/service/dist/business-information/profiles.js +252 -0
  194. package/node_modules/@noodle-borg/service/dist/business-information/reader-floor.js +26 -0
  195. package/node_modules/@noodle-borg/service/dist/business-information/source-credential-fence.js +79 -0
  196. package/node_modules/@noodle-borg/service/dist/business-information/source-custody-budget.js +30 -0
  197. package/node_modules/@noodle-borg/service/dist/business-information/source-custody-memory.js +122 -0
  198. package/node_modules/@noodle-borg/service/dist/business-information/source-executor.js +191 -0
  199. package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-contracts.js +2 -0
  200. package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-coordinator.js +136 -0
  201. package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-failures.js +32 -0
  202. package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-memory-state.js +154 -0
  203. package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-memory-store.js +568 -0
  204. package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-memory-types.js +26 -0
  205. package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-memory-values.js +59 -0
  206. package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-pagination.js +54 -0
  207. package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-validation.js +163 -0
  208. package/node_modules/@noodle-borg/service/dist/business-information/source-refresh-retention.js +29 -0
  209. package/node_modules/@noodle-borg/service/dist/business-information/validation.js +200 -0
  210. package/node_modules/@noodle-borg/service/dist/business-information-runtime.js +80 -0
  211. package/node_modules/@noodle-borg/service/dist/business-onboarding.js +73 -0
  212. package/node_modules/@noodle-borg/service/dist/connections/types.js +8 -0
  213. package/node_modules/@noodle-borg/service/dist/credential-binding-index.js +38 -33
  214. package/node_modules/@noodle-borg/service/dist/deployment-execution.js +275 -0
  215. package/node_modules/@noodle-borg/service/dist/external-credential-binding-broker.js +19 -1
  216. package/node_modules/@noodle-borg/service/dist/external-credential-exchange.d.ts +16 -1
  217. package/node_modules/@noodle-borg/service/dist/modules/host.js +4 -1
  218. package/node_modules/@noodle-borg/service/dist/native-record-connector.d.ts +20 -0
  219. package/node_modules/@noodle-borg/service/dist/native-record-connector.js +206 -0
  220. package/node_modules/@noodle-borg/service/dist/oauth/store.d.ts +5 -2
  221. package/node_modules/@noodle-borg/service/dist/operation-evidence.js +89 -0
  222. package/node_modules/@noodle-borg/service/dist/recovery-quarantine.js +49 -0
  223. package/node_modules/@noodle-borg/service/dist/registry-compile.js +60 -11
  224. package/node_modules/@noodle-borg/service/dist/registry-deploy-transaction.js +18 -0
  225. package/node_modules/@noodle-borg/service/dist/registry-rollback.js +2 -1
  226. package/node_modules/@noodle-borg/service/dist/registry-state.d.ts +1 -1
  227. package/node_modules/@noodle-borg/service/dist/registry-state.js +6 -3
  228. package/node_modules/@noodle-borg/service/dist/registry-targets.js +49 -0
  229. package/node_modules/@noodle-borg/service/dist/registry-types.d.ts +2 -0
  230. package/node_modules/@noodle-borg/service/dist/registry.d.ts +15 -3
  231. package/node_modules/@noodle-borg/service/dist/registry.js +177 -137
  232. package/node_modules/@noodle-borg/service/dist/routes/assistant-appearance.js +3 -2
  233. package/node_modules/@noodle-borg/service/dist/routes/assistant-clients.js +2 -1
  234. package/node_modules/@noodle-borg/service/dist/routes/assistant-doctor.js +2 -1
  235. package/node_modules/@noodle-borg/service/dist/routes/assistant-embeds.js +8 -3
  236. package/node_modules/@noodle-borg/service/dist/routes/assistant-interaction-replay.js +1 -1
  237. package/node_modules/@noodle-borg/service/dist/routes/assistant-interactions.js +48 -36
  238. package/node_modules/@noodle-borg/service/dist/routes/assistant-public-configuration.js +3 -2
  239. package/node_modules/@noodle-borg/service/dist/routes/assistant-public-session.js +10 -10
  240. package/node_modules/@noodle-borg/service/dist/routes/assistant-session-target.js +32 -3
  241. package/node_modules/@noodle-borg/service/dist/routes/assistant-suggestions.js +1 -1
  242. package/node_modules/@noodle-borg/service/dist/routes/assistant-transcript.js +1 -1
  243. package/node_modules/@noodle-borg/service/dist/routes/assistant.js +10 -10
  244. package/node_modules/@noodle-borg/service/dist/routes/business-information-activity.js +83 -0
  245. package/node_modules/@noodle-borg/service/dist/routes/business-information-admission.js +26 -0
  246. package/node_modules/@noodle-borg/service/dist/routes/business-information-channels.js +153 -0
  247. package/node_modules/@noodle-borg/service/dist/routes/business-information-connections.js +107 -0
  248. package/node_modules/@noodle-borg/service/dist/routes/business-information-dispatch.js +131 -0
  249. package/node_modules/@noodle-borg/service/dist/routes/business-information-external.js +79 -0
  250. package/node_modules/@noodle-borg/service/dist/routes/business-information-installation.js +24 -0
  251. package/node_modules/@noodle-borg/service/dist/routes/business-information-notice.js +69 -0
  252. package/node_modules/@noodle-borg/service/dist/routes/business-information-onboarding.js +58 -0
  253. package/node_modules/@noodle-borg/service/dist/routes/business-information-paths.js +168 -0
  254. package/node_modules/@noodle-borg/service/dist/routes/business-information-public.js +151 -0
  255. package/node_modules/@noodle-borg/service/dist/routes/business-information-reader-floor.js +15 -0
  256. package/node_modules/@noodle-borg/service/dist/routes/business-information-record-create.js +29 -0
  257. package/node_modules/@noodle-borg/service/dist/routes/business-information-record-reads.js +36 -0
  258. package/node_modules/@noodle-borg/service/dist/routes/business-information-request.js +64 -0
  259. package/node_modules/@noodle-borg/service/dist/routes/business-information-settings.js +64 -0
  260. package/node_modules/@noodle-borg/service/dist/routes/business-information-source.js +249 -0
  261. package/node_modules/@noodle-borg/service/dist/routes/business-information-staff.js +258 -0
  262. package/node_modules/@noodle-borg/service/dist/routes/business-information-wire.js +317 -0
  263. package/node_modules/@noodle-borg/service/dist/routes/business-information.js +592 -0
  264. package/node_modules/@noodle-borg/service/dist/routes/config-values-dispatch.js +1 -1
  265. package/node_modules/@noodle-borg/service/dist/routes/config-values.js +26 -4
  266. package/node_modules/@noodle-borg/service/dist/routes/control-plane.js +19 -233
  267. package/node_modules/@noodle-borg/service/dist/routes/deployment-activation-response.js +13 -4
  268. package/node_modules/@noodle-borg/service/dist/service-resource-cleanup.js +6 -0
  269. package/node_modules/@noodle-borg/service/dist/service.js +77 -6
  270. package/node_modules/@noodle-borg/service/dist/solution-installation-activation.js +149 -0
  271. package/node_modules/@noodle-borg/service/dist/source-configuration-authority.js +94 -0
  272. package/node_modules/@noodle-borg/service/dist/state-catalog.js +6 -5
  273. package/node_modules/@noodle-borg/service/dist/store/config-values.d.ts +42 -17
  274. package/node_modules/@noodle-borg/service/dist/store/config-values.js +123 -24
  275. package/node_modules/@noodle-borg/service/dist/store/in-memory.d.ts +1 -0
  276. package/node_modules/@noodle-borg/service/dist/store/in-memory.js +3 -0
  277. package/node_modules/@noodle-borg/service/dist/store/json-file.d.ts +1 -0
  278. package/node_modules/@noodle-borg/service/dist/store/json-file.js +3 -0
  279. package/node_modules/@noodle-borg/service/dist/store.d.ts +3 -1
  280. package/node_modules/@noodle-borg/service/package.json +2 -2
  281. package/node_modules/@noodle-borg/transport-http/dist/serve-request.js +9 -0
  282. package/node_modules/@noodle-borg/transport-http/package.json +1 -0
  283. package/node_modules/@noodle-borg/wire-contracts/dist/application-activity.d.ts +143 -0
  284. package/node_modules/@noodle-borg/wire-contracts/dist/application-activity.js +90 -0
  285. package/node_modules/@noodle-borg/wire-contracts/dist/application-channels.d.ts +130 -0
  286. package/node_modules/@noodle-borg/wire-contracts/dist/application-channels.js +77 -0
  287. package/node_modules/@noodle-borg/wire-contracts/dist/application-connections.d.ts +105 -0
  288. package/node_modules/@noodle-borg/wire-contracts/dist/application-connections.js +67 -0
  289. package/node_modules/@noodle-borg/wire-contracts/dist/application-onboarding.d.ts +27 -0
  290. package/node_modules/@noodle-borg/wire-contracts/dist/application-onboarding.js +28 -0
  291. package/node_modules/@noodle-borg/wire-contracts/dist/application-settings.d.ts +112 -0
  292. package/node_modules/@noodle-borg/wire-contracts/dist/application-settings.js +88 -0
  293. package/node_modules/@noodle-borg/wire-contracts/dist/assistant.d.ts +1 -1
  294. package/node_modules/@noodle-borg/wire-contracts/dist/billing-catalog.d.ts +62 -0
  295. package/node_modules/@noodle-borg/wire-contracts/dist/billing-catalog.js +57 -0
  296. package/node_modules/@noodle-borg/wire-contracts/dist/billing-enforcement.d.ts +12 -12
  297. package/node_modules/@noodle-borg/wire-contracts/dist/billing-metering.d.ts +4 -4
  298. package/node_modules/@noodle-borg/wire-contracts/dist/billing-org-transfer.d.ts +3 -3
  299. package/node_modules/@noodle-borg/wire-contracts/dist/business-information-query.d.ts +25 -0
  300. package/node_modules/@noodle-borg/wire-contracts/dist/business-information-query.js +37 -0
  301. package/node_modules/@noodle-borg/wire-contracts/dist/business-information.d.ts +2241 -0
  302. package/node_modules/@noodle-borg/wire-contracts/dist/business-information.js +580 -0
  303. package/node_modules/@noodle-borg/wire-contracts/dist/control-plane.d.ts +2 -2
  304. package/node_modules/@noodle-borg/wire-contracts/dist/distribution.d.ts +5 -5
  305. package/node_modules/@noodle-borg/wire-contracts/dist/index.d.ts +12 -3
  306. package/node_modules/@noodle-borg/wire-contracts/dist/index.js +9 -0
  307. package/node_modules/@noodle-borg/wire-contracts/dist/knowledge.d.ts +6 -6
  308. package/node_modules/@noodle-borg/wire-contracts/dist/managed-assistant-sponsorship.d.ts +15 -15
  309. package/node_modules/@noodle-borg/wire-contracts/dist/platform-account-reset.d.ts +5 -0
  310. package/node_modules/@noodle-borg/wire-contracts/dist/platform-account-reset.js +1 -0
  311. package/node_modules/@noodle-borg/wire-contracts/dist/platform-auth.d.ts +66 -66
  312. package/node_modules/@noodle-borg/wire-contracts/dist/solution-onboarding.d.ts +143 -0
  313. package/node_modules/@noodle-borg/wire-contracts/dist/solution-onboarding.js +94 -0
  314. package/node_modules/@noodleseed/assistant/README.md +5 -0
  315. package/package.json +2 -2
@@ -0,0 +1,557 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { memoryActivityPage } from './activity-pagination.js';
3
+ import { collectionControlEnabled } from './collection-controls.js';
4
+ import { InMemoryInstallationLifecycle, } from './in-memory-installation-lifecycle.js';
5
+ import { InMemoryBusinessInvitations } from './in-memory-invitations.js';
6
+ import { BusinessMemoryLocks } from './in-memory-locks.js';
7
+ import { InstallationCapacityError, MAX_RETAINED_INSTALLATIONS_PER_ORG, } from './installation-capacity.js';
8
+ import { migrateLegacyRequestRecord } from './legacy-request-migration.js';
9
+ import { activityFromRecord, applyRequestOperation, cloneGrant, cloneRecord, deletedRecord, effectiveInstallation, idempotencyDigest, initialRecord, installationFingerprint, managedInstallationIntentMatches, normalizeInstallationInput, permissionsForBusinessRole, requestFingerprint, validateCollectionEnabled, validateExpectedRevision, validateStoredRecord, } from './model.js';
10
+ import { matchesNativeQueryMetadata, planNativeQuery, runNativeQuery } from './native-query.js';
11
+ import { commitNativeMemoryRecord, NativeStorageBudget } from './native-storage-budget.js';
12
+ import { afterCursor, compareRecords, decodeCursor, grantKey, installationIdKey, page, recordKey, scopeKey, } from './pagination.js';
13
+ import { BusinessPrincipalAuthority, } from './principal-authority.js';
14
+ import { boundedExportPageSize, boundedPageSize, validateEmail, validateScalar, validateScope, } from './validation.js';
15
+ /** Process-local development/test adapter. Hosted services must use the PostgreSQL adapter. */
16
+ export class InMemoryBusinessInformationStore {
17
+ #installations = new Map();
18
+ #installationIds = new Map();
19
+ #publicIds = new Map();
20
+ #installationFingerprints = new Map();
21
+ #grants = new Map();
22
+ #invitations;
23
+ #lifecycle;
24
+ #principals = new BusinessPrincipalAuthority();
25
+ #custody = new NativeStorageBudget();
26
+ #records = new Map();
27
+ #activities = new Map();
28
+ #idempotency = new Map();
29
+ #locks = new BusinessMemoryLocks();
30
+ #now;
31
+ #id;
32
+ #publicId;
33
+ #managedDefinition;
34
+ constructor(options = {}) {
35
+ this.#now = options.now ?? (() => new Date());
36
+ this.#id = options.id ?? randomUUID;
37
+ this.#publicId = options.publicId ?? (() => `sol_${randomUUID().replaceAll('-', '')}`);
38
+ this.#managedDefinition = options.managedDefinition;
39
+ this.#lifecycle = new InMemoryInstallationLifecycle({
40
+ installations: this.#installations,
41
+ getGrant: (scope, subject) => this.#grants.get(grantKey(scope, subject)),
42
+ withLock: (key, operation) => this.#locks.run(key, operation),
43
+ now: this.#now,
44
+ managedDefinition: this.#managedDefinition,
45
+ });
46
+ this.#invitations = new InMemoryBusinessInvitations({
47
+ now: this.#now,
48
+ getInstallation: (scope) => this.getInstallation(scope),
49
+ getGrant: (scope, subject) => this.getGrant(scope, subject),
50
+ putGrant: (grant) => this.#grants.set(grantKey(grant.scope, grant.subject), grant),
51
+ withGrantLock: (scope, operation) => this.#locks.run(`grants:${scopeKey(scope)}`, operation),
52
+ liveAdministratorCount: (scope) => this.#liveAdministratorCount(scope),
53
+ });
54
+ }
55
+ configurePrincipalAuthority(provider) {
56
+ this.#principals.configure(provider);
57
+ }
58
+ async listEligibleAssignees(scope) {
59
+ return this.#principals.eligible(await this.listGrants(scope));
60
+ }
61
+ getBusinessNotice(scope) {
62
+ return this.#lifecycle.getBusinessNotice(scope);
63
+ }
64
+ setBusinessNotice(input) {
65
+ return this.#lifecycle.setBusinessNotice(input);
66
+ }
67
+ async createInstallation(input) {
68
+ const normalized = normalizeInstallationInput(input);
69
+ const key = scopeKey(normalized.scope);
70
+ return this.#locks.run(`installations:${normalized.scope.org}`, async () => {
71
+ const existingKey = this.#installationIds.get(installationIdKey(normalized.scope.org, normalized.scope.installationId));
72
+ const existing = existingKey === undefined ? undefined : this.#installations.get(existingKey);
73
+ if (existing !== undefined) {
74
+ return {
75
+ disposition: existingKey === key &&
76
+ (this.#installationFingerprints.get(key) === installationFingerprint(normalized) ||
77
+ managedInstallationIntentMatches(existing, normalized))
78
+ ? 'replayed'
79
+ : 'conflict',
80
+ installation: effectiveInstallation(existing, this.#managedDefinition),
81
+ };
82
+ }
83
+ if ([...this.#installations.values()].filter((entry) => entry.scope.org === normalized.scope.org).length >= MAX_RETAINED_INSTALLATIONS_PER_ORG)
84
+ throw new InstallationCapacityError();
85
+ const now = this.#now().toISOString();
86
+ const installation = {
87
+ scope: { ...normalized.scope },
88
+ publicId: this.#uniquePublicId(),
89
+ profileKey: normalized.profileKey,
90
+ profileVersion: normalized.profileVersion,
91
+ managedCollections: [...normalized.managedCollections],
92
+ definition: structuredClone(normalized.definition),
93
+ retentionDays: normalized.retentionDays,
94
+ intakeActive: true,
95
+ applicationGeneration: 'pending',
96
+ revision: 1,
97
+ createdAt: now,
98
+ createdBySubject: normalized.actorSubject,
99
+ updatedAt: now,
100
+ updatedBySubject: normalized.actorSubject,
101
+ };
102
+ this.#installations.set(key, installation);
103
+ this.#installationIds.set(installationIdKey(normalized.scope.org, normalized.scope.installationId), key);
104
+ this.#publicIds.set(installation.publicId, key);
105
+ this.#installationFingerprints.set(key, installationFingerprint(normalized));
106
+ const administrator = {
107
+ scope: { ...normalized.scope },
108
+ subject: normalized.actorSubject,
109
+ ...(normalized.actorEmail === undefined ? {} : { email: normalized.actorEmail }),
110
+ role: 'administrator',
111
+ revision: 1,
112
+ createdAt: now,
113
+ createdBySubject: normalized.actorSubject,
114
+ updatedAt: now,
115
+ updatedBySubject: normalized.actorSubject,
116
+ };
117
+ this.#grants.set(grantKey(normalized.scope, normalized.actorSubject), administrator);
118
+ return {
119
+ disposition: 'created',
120
+ installation: effectiveInstallation(installation, this.#managedDefinition),
121
+ };
122
+ });
123
+ }
124
+ getInstallation(scope) {
125
+ return this.#lifecycle.getInstallation(scope);
126
+ }
127
+ getInstallationById(org, installationId) {
128
+ const key = this.#installationIds.get(installationIdKey(validateScalar('organization', org, 63), validateScalar('installation', installationId, 63)));
129
+ const found = key === undefined ? undefined : this.#installations.get(key);
130
+ return Promise.resolve(found === undefined ? undefined : effectiveInstallation(found, this.#managedDefinition));
131
+ }
132
+ resolveInstallationByPublicId(publicId) {
133
+ const key = this.#publicIds.get(validateScalar('public installation id', publicId, 128));
134
+ const found = key === undefined ? undefined : this.#installations.get(key);
135
+ return Promise.resolve(found === undefined ? undefined : effectiveInstallation(found, this.#managedDefinition));
136
+ }
137
+ listInstallations(org) {
138
+ return this.#lifecycle.listInstallations(org);
139
+ }
140
+ listInstallationsForSubject(subject) {
141
+ const normalized = validateScalar('identity subject', subject, 256);
142
+ return Promise.resolve([...this.#grants.values()]
143
+ .filter((grant) => grant.subject === normalized && grant.revokedAt === undefined)
144
+ .map((grant) => {
145
+ const installation = this.#installations.get(scopeKey(grant.scope));
146
+ if (installation === undefined)
147
+ throw new Error('business grant installation is missing');
148
+ return {
149
+ installation: effectiveInstallation(installation, this.#managedDefinition),
150
+ grant: cloneGrant(grant),
151
+ };
152
+ })
153
+ .sort((left, right) => left.installation.createdAt.localeCompare(right.installation.createdAt)));
154
+ }
155
+ configureApplicationLifecycle(resolve) {
156
+ this.#lifecycle.configureApplicationLifecycle(resolve);
157
+ }
158
+ bindApplication(scope, generation) {
159
+ return this.#lifecycle.bindApplication(scope, generation);
160
+ }
161
+ pauseApplication(org, app, at, retired = false) {
162
+ return this.#lifecycle.pauseApplication(org, app, at, retired);
163
+ }
164
+ setIntakeState(input) {
165
+ return this.#lifecycle.setIntakeState(input);
166
+ }
167
+ getGrant(scope, subject) {
168
+ const found = this.#grants.get(grantKey(validateScope(scope), subject));
169
+ return Promise.resolve(found === undefined ? undefined : cloneGrant(found));
170
+ }
171
+ listGrants(scope) {
172
+ const prefix = `${scopeKey(validateScope(scope))}\0`;
173
+ return Promise.resolve([...this.#grants.entries()]
174
+ .filter(([key]) => key.startsWith(prefix))
175
+ .map(([, grant]) => cloneGrant(grant))
176
+ .sort((left, right) => left.subject.localeCompare(right.subject)));
177
+ }
178
+ async setGrant(input) {
179
+ validateExpectedRevision(input.expectedRevision);
180
+ const subject = validateScalar('grant subject', input.subject, 256);
181
+ const actor = validateScalar('actor subject', input.actorSubject, 256);
182
+ permissionsForBusinessRole(input.role);
183
+ const scope = validateScope(input.scope);
184
+ const key = grantKey(scope, subject);
185
+ return this.#locks.run(`grants:${scopeKey(scope)}`, async () => {
186
+ if (!(await this.getInstallation(input.scope)))
187
+ return { ok: false, reason: 'not_found', currentRevision: 0 };
188
+ const current = this.#grants.get(key);
189
+ const currentRevision = current?.revision ?? 0;
190
+ if (currentRevision !== input.expectedRevision) {
191
+ return { ok: false, reason: 'conflict', currentRevision };
192
+ }
193
+ if (current?.role === 'administrator' &&
194
+ current.revokedAt === undefined &&
195
+ input.role !== 'administrator' &&
196
+ this.#liveAdministratorCount(scope) === 1) {
197
+ return { ok: false, reason: 'last_administrator', currentRevision };
198
+ }
199
+ const now = this.#now().toISOString();
200
+ const grant = {
201
+ scope: { ...input.scope },
202
+ subject,
203
+ email: validateEmail(input.email),
204
+ role: input.role,
205
+ revision: currentRevision + 1,
206
+ createdAt: current?.createdAt ?? now,
207
+ createdBySubject: current?.createdBySubject ?? actor,
208
+ updatedAt: now,
209
+ updatedBySubject: actor,
210
+ };
211
+ this.#grants.set(key, grant);
212
+ return { ok: true, grant: cloneGrant(grant) };
213
+ });
214
+ }
215
+ async revokeGrant(input) {
216
+ validateExpectedRevision(input.expectedRevision);
217
+ const scope = validateScope(input.scope);
218
+ const key = grantKey(scope, input.subject);
219
+ return this.#locks.run(`grants:${scopeKey(scope)}`, async () => {
220
+ const current = this.#grants.get(key);
221
+ if (current === undefined)
222
+ return { ok: false, reason: 'not_found', currentRevision: 0 };
223
+ if (current.revision !== input.expectedRevision) {
224
+ return { ok: false, reason: 'conflict', currentRevision: current.revision };
225
+ }
226
+ if (current.role === 'administrator' &&
227
+ current.revokedAt === undefined &&
228
+ this.#liveAdministratorCount(scope) === 1) {
229
+ return {
230
+ ok: false,
231
+ reason: 'last_administrator',
232
+ currentRevision: current.revision,
233
+ };
234
+ }
235
+ const now = this.#now().toISOString();
236
+ const grant = {
237
+ ...current,
238
+ revision: current.revision + 1,
239
+ updatedAt: now,
240
+ updatedBySubject: validateScalar('actor subject', input.actorSubject, 256),
241
+ revokedAt: now,
242
+ };
243
+ this.#grants.set(key, grant);
244
+ return { ok: true, grant: cloneGrant(grant) };
245
+ });
246
+ }
247
+ async createInvitation(input) {
248
+ return this.#invitations.create(input);
249
+ }
250
+ listInvitations(scope) {
251
+ return this.#invitations.list(scope);
252
+ }
253
+ async revokeInvitation(input) {
254
+ return this.#invitations.revoke(input);
255
+ }
256
+ async claimInvitation(input) {
257
+ return this.#invitations.claim(input);
258
+ }
259
+ async createRequest(input) {
260
+ const idempotencyKey = idempotencyDigest(input.idempotencyKey);
261
+ const key = `${scopeKey(input.scope)}\0${input.collectionKey}\0${idempotencyKey}`;
262
+ return this.#locks.run(`request-create:${key}`, async () => {
263
+ return this.#locks.run(`intake:${scopeKey(input.scope)}`, async () => {
264
+ const installation = await this.#requiredInstallation(input.scope);
265
+ validateCollectionEnabled(installation, input.collectionKey);
266
+ const candidate = initialRecord({
267
+ installation,
268
+ collectionKey: input.collectionKey,
269
+ id: this.#id(),
270
+ payload: input.payload,
271
+ ...(input.publicInput === undefined ? {} : { publicInput: input.publicInput }),
272
+ origin: input.origin,
273
+ actorSubject: input.actorSubject,
274
+ now: this.#now(),
275
+ });
276
+ const fingerprint = requestFingerprint({
277
+ collectionKey: candidate.collectionKey,
278
+ payload: input.payload,
279
+ origin: candidate.origin,
280
+ actorSubject: candidate.createdBySubject,
281
+ });
282
+ const replay = this.#idempotency.get(key);
283
+ if (replay !== undefined) {
284
+ const existing = this.#expireRecordIfNeeded(replay.recordKey, this.#now());
285
+ if (existing === undefined)
286
+ throw new Error('idempotency record points to a missing request');
287
+ validateStoredRecord(installation, existing);
288
+ return {
289
+ disposition: replay.fingerprint === fingerprint ? 'replayed' : 'conflict',
290
+ record: cloneRecord(existing),
291
+ };
292
+ }
293
+ if (!(await this.#lifecycle.applicationAllows(installation)) ||
294
+ ((input.origin.kind === 'embedded' || input.publicInput === true) &&
295
+ !installation.intakeActive)) {
296
+ return { disposition: 'paused' };
297
+ }
298
+ const currentKey = recordKey(input.scope, candidate.collectionKey, candidate.id);
299
+ this.#commitRecord(currentKey, candidate, 'created');
300
+ this.#idempotency.set(key, { fingerprint, recordKey: currentKey });
301
+ return { disposition: 'created', record: cloneRecord(candidate) };
302
+ });
303
+ });
304
+ }
305
+ async probeRequest(input) {
306
+ const installation = await this.#requiredInstallation(input.scope);
307
+ const candidate = initialRecord({
308
+ installation,
309
+ collectionKey: input.collectionKey,
310
+ id: this.#id(),
311
+ payload: input.payload,
312
+ ...(input.publicInput === undefined ? {} : { publicInput: input.publicInput }),
313
+ origin: input.origin,
314
+ actorSubject: input.actorSubject,
315
+ now: this.#now(),
316
+ });
317
+ const digest = idempotencyDigest(input.idempotencyKey);
318
+ const key = `${scopeKey(input.scope)}\0${input.collectionKey}\0${digest}`;
319
+ const replay = this.#idempotency.get(key);
320
+ if (replay === undefined)
321
+ return { disposition: 'missing' };
322
+ const existing = this.#expireRecordIfNeeded(replay.recordKey, this.#now());
323
+ if (existing === undefined)
324
+ throw new Error('idempotency record points to a missing request');
325
+ validateStoredRecord(installation, existing);
326
+ const fingerprint = requestFingerprint({
327
+ collectionKey: candidate.collectionKey,
328
+ payload: input.payload,
329
+ origin: candidate.origin,
330
+ actorSubject: candidate.createdBySubject,
331
+ });
332
+ return {
333
+ disposition: replay.fingerprint === fingerprint ? 'replayed' : 'conflict',
334
+ record: cloneRecord(existing),
335
+ };
336
+ }
337
+ #liveAdministratorCount(scope) {
338
+ const prefix = `${scopeKey(scope)}\0`;
339
+ return [...this.#grants.entries()].filter(([key, grant]) => key.startsWith(prefix) && grant.role === 'administrator' && grant.revokedAt === undefined).length;
340
+ }
341
+ async getRequest(scope, collectionKey, id, options = {}) {
342
+ const installation = await this.#requiredInstallation(scope);
343
+ const collection = validateCollectionEnabled(installation, collectionKey);
344
+ const key = recordKey(scope, collection.key, validateScalar('record id', id, 128));
345
+ const record = this.#expireRecordIfNeeded(key, this.#now());
346
+ if (record === undefined || (record.deletedAt !== undefined && options.includeDeleted !== true))
347
+ return undefined;
348
+ validateStoredRecord(installation, record);
349
+ return cloneRecord(record);
350
+ }
351
+ async listAcceptedSchemaInventory() {
352
+ const inventory = new Map();
353
+ for (const record of this.#records.values()) {
354
+ const identity = {
355
+ profileKey: record.profileKey,
356
+ profileVersion: record.profileVersion,
357
+ collectionKey: record.collectionKey,
358
+ schemaVersion: record.schemaVersion,
359
+ schemaDigest: record.schemaDigest,
360
+ };
361
+ inventory.set(JSON.stringify(identity), identity);
362
+ if (record.originalSchema !== undefined) {
363
+ const original = { ...identity, ...record.originalSchema };
364
+ inventory.set(JSON.stringify(original), original);
365
+ }
366
+ }
367
+ return [...inventory.entries()]
368
+ .sort(([left], [right]) => left.localeCompare(right))
369
+ .map(([, identity]) => ({ ...identity }));
370
+ }
371
+ async listRequests(input) {
372
+ const installation = await this.#requiredInstallation(input.scope);
373
+ const collection = validateCollectionEnabled(installation, input.collectionKey);
374
+ const now = this.#now();
375
+ const plan = await planNativeQuery(input, collection, now, (id) => this.getRequest(input.scope, collection.key, id, { includeDeleted: true }));
376
+ const records = this.#matchingRecords(input.scope, collection.key).filter((record) => matchesNativeQueryMetadata(record, plan, now));
377
+ const result = await runNativeQuery(plan, records);
378
+ for (const record of result.records)
379
+ validateStoredRecord(installation, record);
380
+ return result;
381
+ }
382
+ async mutateRequest(input) {
383
+ validateExpectedRevision(input.expectedRevision);
384
+ const installation = await this.#requiredInstallation(input.scope);
385
+ const collection = validateCollectionEnabled(installation, input.collectionKey);
386
+ const key = recordKey(input.scope, collection.key, validateScalar('record id', input.id, 128));
387
+ const mutate = () => this.#locks.run(`request:${key}`, async () => {
388
+ const current = this.#expireRecordIfNeeded(key, this.#now());
389
+ if (current === undefined || current.deletedAt !== undefined) {
390
+ return { ok: false, reason: 'not_found', currentRevision: 0 };
391
+ }
392
+ if (current.revision !== input.expectedRevision) {
393
+ return { ok: false, reason: 'conflict', currentRevision: current.revision };
394
+ }
395
+ if (input.operation.kind === 'assign' &&
396
+ !collectionControlEnabled(collection, 'assignment')) {
397
+ return { ok: false, reason: 'invalid_transition', currentRevision: current.revision };
398
+ }
399
+ if (input.operation.kind === 'assign' && input.operation.assigneeSubject !== undefined) {
400
+ const assignee = this.#grants.get(grantKey(input.scope, input.operation.assigneeSubject));
401
+ if (assignee === undefined ||
402
+ assignee.revokedAt !== undefined ||
403
+ assignee.role === 'viewer' ||
404
+ !(await this.#principals.allows(assignee.subject))) {
405
+ return { ok: false, reason: 'invalid_assignee', currentRevision: current.revision };
406
+ }
407
+ }
408
+ const historicalCollection = validateStoredRecord(installation, current);
409
+ const applied = applyRequestOperation(current, {
410
+ ...historicalCollection,
411
+ ...(collection.management === undefined ? {} : { management: collection.management }),
412
+ ...(collection.editableFields === undefined
413
+ ? {}
414
+ : { editableFields: collection.editableFields }),
415
+ }, input.operation, input.actorSubject, this.#now(), this.#id);
416
+ if (applied === undefined) {
417
+ return { ok: false, reason: 'invalid_transition', currentRevision: current.revision };
418
+ }
419
+ this.#commitRecord(key, applied.record, applied.activityKind);
420
+ return { ok: true, record: cloneRecord(applied.record) };
421
+ });
422
+ return input.operation.kind === 'assign'
423
+ ? this.#locks.run(`grants:${scopeKey(input.scope)}`, mutate)
424
+ : mutate();
425
+ }
426
+ async migrateLegacyRequest(input) {
427
+ validateExpectedRevision(input.expectedRevision);
428
+ const installation = await this.#requiredInstallation(input.scope);
429
+ validateCollectionEnabled(installation, input.collectionKey);
430
+ const key = recordKey(input.scope, input.collectionKey, validateScalar('record id', input.id, 128));
431
+ return this.#locks.run(`request:${key}`, async () => {
432
+ const current = this.#expireRecordIfNeeded(key, this.#now());
433
+ if (current === undefined || current.deletedAt !== undefined)
434
+ return { ok: false, reason: 'not_found', currentRevision: current?.revision ?? 0 };
435
+ if (current.revision !== input.expectedRevision)
436
+ return { ok: false, reason: 'conflict', currentRevision: current.revision };
437
+ const previous = validateStoredRecord(installation, current);
438
+ const migrated = migrateLegacyRequestRecord(current, previous, installation, input.actorSubject, this.#now());
439
+ if (migrated === undefined)
440
+ return { ok: false, reason: 'invalid_transition', currentRevision: current.revision };
441
+ if (migrated !== current) {
442
+ this.#commitRecord(key, migrated, 'schema_migrated');
443
+ }
444
+ return { ok: true, record: cloneRecord(migrated) };
445
+ });
446
+ }
447
+ async deleteRequest(input) {
448
+ validateExpectedRevision(input.expectedRevision);
449
+ const installation = await this.#requiredInstallation(input.scope);
450
+ const collection = validateCollectionEnabled(installation, input.collectionKey);
451
+ const key = recordKey(input.scope, collection.key, validateScalar('record id', input.id, 128));
452
+ return this.#locks.run(`request:${key}`, () => Promise.resolve(this.#eraseRecord(key, input.expectedRevision, input.actorSubject, 'customer_request')));
453
+ }
454
+ async listActivity(scope, collectionKey, id, input) {
455
+ const installation = await this.#requiredInstallation(scope);
456
+ const collection = validateCollectionEnabled(installation, collectionKey);
457
+ const key = recordKey(validateScope(scope), collection.key, validateScalar('record id', id, 128));
458
+ const record = this.#expireRecordIfNeeded(key, this.#now());
459
+ if (record !== undefined)
460
+ validateStoredRecord(installation, record);
461
+ return memoryActivityPage(scope, collection.key, id, this.#activities.get(key) ?? [], input);
462
+ }
463
+ async exportRequests(input) {
464
+ const installation = await this.#requiredInstallation(input.scope);
465
+ const collection = validateCollectionEnabled(installation, input.collectionKey);
466
+ const limit = boundedExportPageSize(input.limit);
467
+ const cursor = input.cursor === undefined
468
+ ? undefined
469
+ : decodeCursor(input.cursor, {
470
+ kind: 'export',
471
+ scope: input.scope,
472
+ collectionKey: collection.key,
473
+ });
474
+ const snapshotAt = cursor?.snapshotAt ?? this.#now().toISOString();
475
+ if (snapshotAt === undefined)
476
+ throw new Error('export cursor is missing its snapshot');
477
+ const records = this.#matchingRecords(input.scope, collection.key)
478
+ .filter((record) => record.createdAt <= snapshotAt)
479
+ .filter((record) => input.includeDeleted === true || record.deletedAt === undefined)
480
+ .filter((record) => cursor === undefined || afterCursor(record, cursor));
481
+ for (const record of records)
482
+ validateStoredRecord(installation, record);
483
+ return {
484
+ ...page(records, limit, 'export', input.scope, collection.key, snapshotAt),
485
+ snapshotAt,
486
+ };
487
+ }
488
+ async purgeExpired(input) {
489
+ const limit = boundedPageSize(input.limit);
490
+ const scope = input.scope === undefined ? undefined : scopeKey(validateScope(input.scope));
491
+ const now = this.#now();
492
+ const candidates = [...this.#records.entries()]
493
+ .filter(([key, record]) => (scope === undefined || key.startsWith(`${scope}\0`)) &&
494
+ record.deletedAt === undefined &&
495
+ record.retentionExpiresAt <= now.toISOString())
496
+ .slice(0, limit);
497
+ let purged = 0;
498
+ for (const [key, record] of candidates) {
499
+ const result = await this.#locks.run(`request:${key}`, () => Promise.resolve(this.#eraseRecord(key, record.revision, 'system:retention', 'retention_expired')));
500
+ if (result.ok)
501
+ purged += 1;
502
+ }
503
+ return purged;
504
+ }
505
+ #matchingRecords(scope, collectionKey) {
506
+ const prefix = `${scopeKey(scope)}\0${collectionKey}\0`;
507
+ const now = this.#now().toISOString();
508
+ return [...this.#records.entries()]
509
+ .filter(([key, record]) => key.startsWith(prefix) &&
510
+ (record.deletedAt !== undefined || record.retentionExpiresAt > now))
511
+ .map(([, record]) => record)
512
+ .sort(compareRecords);
513
+ }
514
+ #expireRecordIfNeeded(key, now) {
515
+ const current = this.#records.get(key);
516
+ if (current === undefined ||
517
+ current.deletedAt !== undefined ||
518
+ current.retentionExpiresAt > now.toISOString()) {
519
+ return current;
520
+ }
521
+ const erased = deletedRecord(current, 'system:retention', now, 'retention_expired');
522
+ this.#commitRecord(key, erased, 'retention_expired');
523
+ return erased;
524
+ }
525
+ #eraseRecord(key, expectedRevision, actorSubject, reason) {
526
+ const current = reason === 'retention_expired'
527
+ ? this.#records.get(key)
528
+ : this.#expireRecordIfNeeded(key, this.#now());
529
+ if (current === undefined || current.deletedAt !== undefined) {
530
+ return { ok: false, reason: 'not_found', currentRevision: current?.revision ?? 0 };
531
+ }
532
+ if (current.revision !== expectedRevision) {
533
+ return { ok: false, reason: 'conflict', currentRevision: current.revision };
534
+ }
535
+ const erased = deletedRecord(current, actorSubject, this.#now(), reason);
536
+ this.#commitRecord(key, erased, reason === 'customer_request' ? 'deleted' : 'retention_expired');
537
+ return { ok: true, record: cloneRecord(erased) };
538
+ }
539
+ #commitRecord(key, record, kind) {
540
+ commitNativeMemoryRecord(this.#records, this.#activities, this.#custody, key, record, activityFromRecord(record, kind));
541
+ }
542
+ async #requiredInstallation(scope) {
543
+ const installation = await this.getInstallation(scope);
544
+ if (installation === undefined)
545
+ throw new Error('solution installation was not found');
546
+ return installation;
547
+ }
548
+ #uniquePublicId() {
549
+ for (let attempt = 0; attempt < 8; attempt += 1) {
550
+ const candidate = validateScalar('public installation id', this.#publicId(), 128);
551
+ if (!this.#publicIds.has(candidate))
552
+ return candidate;
553
+ }
554
+ throw new Error('could not allocate a unique public installation id');
555
+ }
556
+ }
557
+ //# sourceMappingURL=in-memory-store.js.map
@@ -0,0 +1,10 @@
1
+ /** Technical retained-metadata guard, independent of app or commercial entitlements. */
2
+ export const MAX_RETAINED_INSTALLATIONS_PER_ORG = 1_000;
3
+ export class InstallationCapacityError extends Error {
4
+ code = 'installation_capacity_exceeded';
5
+ constructor() {
6
+ super('This organization has reached its retained installation limit. Reuse an existing application and environment; existing installations remain accessible.');
7
+ this.name = 'InstallationCapacityError';
8
+ }
9
+ }
10
+ //# sourceMappingURL=installation-capacity.js.map
@@ -0,0 +1,68 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { validateExpectedRevision } from './model.js';
3
+ import { validateEmail, validateScalar, validateScope } from './validation.js';
4
+ export function normalizeInvitationInput(input) {
5
+ const expiresAt = input.expiresAt;
6
+ if (!Number.isFinite(expiresAt.getTime()))
7
+ throw new Error('invitation expiry is invalid');
8
+ const tokenDigest = validateDigest('invitation token digest', input.tokenDigest);
9
+ const idempotencyDigest = createHash('sha256')
10
+ .update(validateScalar('invitation idempotency key', input.idempotencyKey, 128))
11
+ .digest('hex');
12
+ const normalized = {
13
+ scope: validateScope(input.scope),
14
+ invitationId: validateScalar('invitation id', input.invitationId, 128),
15
+ email: validateEmail(input.email),
16
+ role: input.role,
17
+ tokenDigest,
18
+ idempotencyDigest,
19
+ expiresAt,
20
+ actorSubject: validateScalar('actor subject', input.actorSubject, 256),
21
+ };
22
+ return {
23
+ ...normalized,
24
+ createFingerprint: createHash('sha256')
25
+ .update(JSON.stringify({
26
+ scope: normalized.scope,
27
+ email: normalized.email,
28
+ role: normalized.role,
29
+ tokenDigest: normalized.tokenDigest,
30
+ }))
31
+ .digest('hex'),
32
+ };
33
+ }
34
+ export function validateInvitationMutation(input) {
35
+ validateExpectedRevision(input.expectedRevision);
36
+ return {
37
+ scope: validateScope(input.scope),
38
+ invitationId: validateScalar('invitation id', input.invitationId, 128),
39
+ expectedRevision: input.expectedRevision,
40
+ actorSubject: validateScalar('actor subject', input.actorSubject, 256),
41
+ };
42
+ }
43
+ export function validateInvitationClaim(input) {
44
+ return {
45
+ tokenDigest: validateDigest('invitation token digest', input.tokenDigest),
46
+ subject: validateScalar('identity subject', input.subject, 256),
47
+ email: validateEmail(input.email),
48
+ };
49
+ }
50
+ export function invitationStatus(invitation, now) {
51
+ if (invitation.acceptedAt !== undefined)
52
+ return 'accepted';
53
+ if (invitation.revokedAt !== undefined)
54
+ return 'revoked';
55
+ if (Date.parse(invitation.expiresAt) <= now.getTime())
56
+ return 'expired';
57
+ return 'pending';
58
+ }
59
+ export function cloneInvitation(invitation) {
60
+ return { ...invitation, scope: { ...invitation.scope } };
61
+ }
62
+ function validateDigest(name, value) {
63
+ const digest = validateScalar(name, value, 64);
64
+ if (!/^[a-f0-9]{64}$/.test(digest))
65
+ throw new Error(`${name} is invalid`);
66
+ return digest;
67
+ }
68
+ //# sourceMappingURL=invitations.js.map