@noodleseed/one 0.162.0 → 0.164.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 (326) hide show
  1. package/dist/banner.d.ts +6 -0
  2. package/dist/banner.d.ts.map +1 -0
  3. package/dist/banner.js +29 -0
  4. package/dist/banner.js.map +1 -0
  5. package/dist/commands/billing-catalog-ops.d.ts +4 -0
  6. package/dist/commands/billing-catalog-ops.d.ts.map +1 -0
  7. package/dist/commands/billing-catalog-ops.js +58 -0
  8. package/dist/commands/billing-catalog-ops.js.map +1 -0
  9. package/dist/commands/billing-ops.d.ts.map +1 -1
  10. package/dist/commands/billing-ops.js +3 -0
  11. package/dist/commands/billing-ops.js.map +1 -1
  12. package/dist/commands/catalog.d.ts.map +1 -1
  13. package/dist/commands/catalog.js +2 -0
  14. package/dist/commands/catalog.js.map +1 -1
  15. package/dist/commands/config-values.d.ts.map +1 -1
  16. package/dist/commands/config-values.js +16 -0
  17. package/dist/commands/config-values.js.map +1 -1
  18. package/dist/commands/installation-variables.d.ts +26 -0
  19. package/dist/commands/installation-variables.d.ts.map +1 -0
  20. package/dist/commands/installation-variables.js +171 -0
  21. package/dist/commands/installation-variables.js.map +1 -0
  22. package/dist/commands/project-setup.d.ts.map +1 -1
  23. package/dist/commands/project-setup.js +2 -0
  24. package/dist/commands/project-setup.js.map +1 -1
  25. package/dist/commands/solutions-activity.d.ts +5 -0
  26. package/dist/commands/solutions-activity.d.ts.map +1 -0
  27. package/dist/commands/solutions-activity.js +116 -0
  28. package/dist/commands/solutions-activity.js.map +1 -0
  29. package/dist/commands/solutions-connections.d.ts +7 -0
  30. package/dist/commands/solutions-connections.d.ts.map +1 -0
  31. package/dist/commands/solutions-connections.js +88 -0
  32. package/dist/commands/solutions-connections.js.map +1 -0
  33. package/dist/commands/solutions-installation-options.d.ts +5 -0
  34. package/dist/commands/solutions-installation-options.d.ts.map +1 -0
  35. package/dist/commands/solutions-installation-options.js +52 -0
  36. package/dist/commands/solutions-installation-options.js.map +1 -0
  37. package/dist/commands/solutions-onboarding.d.ts +5 -0
  38. package/dist/commands/solutions-onboarding.d.ts.map +1 -0
  39. package/dist/commands/solutions-onboarding.js +113 -0
  40. package/dist/commands/solutions-onboarding.js.map +1 -0
  41. package/dist/commands/solutions-ops.d.ts.map +1 -1
  42. package/dist/commands/solutions-ops.js +278 -17
  43. package/dist/commands/solutions-ops.js.map +1 -1
  44. package/dist/first-run.d.ts.map +1 -1
  45. package/dist/first-run.js +2 -0
  46. package/dist/first-run.js.map +1 -1
  47. package/dist/index.d.ts +1 -1
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +1 -1
  50. package/dist/index.js.map +1 -1
  51. package/node_modules/@noodle-borg/admission-limits/dist/counter-store.d.ts +21 -2
  52. package/node_modules/@noodle-borg/admission-limits/dist/counter-store.js +10 -1
  53. package/node_modules/@noodle-borg/admission-limits/dist/in-memory-counter-store.d.ts +5 -1
  54. package/node_modules/@noodle-borg/admission-limits/dist/in-memory-counter-store.js +31 -2
  55. package/node_modules/@noodle-borg/admission-limits/dist/portable.d.ts +3 -0
  56. package/node_modules/@noodle-borg/admission-limits/dist/portable.js +3 -0
  57. package/node_modules/@noodle-borg/admission-limits/dist/public-admission-assertion.d.ts +28 -0
  58. package/node_modules/@noodle-borg/admission-limits/dist/public-admission-assertion.js +124 -0
  59. package/node_modules/@noodle-borg/admission-limits/dist/public-record-admission.d.ts +54 -0
  60. package/node_modules/@noodle-borg/admission-limits/dist/public-record-admission.js +74 -0
  61. package/node_modules/@noodle-borg/admission-limits/dist/request-attribution.d.ts +11 -0
  62. package/node_modules/@noodle-borg/admission-limits/dist/request-attribution.js +19 -0
  63. package/node_modules/@noodle-borg/agent-kit/dist/curated/error-fixes.js +2 -0
  64. package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js +5 -5
  65. package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js +3 -0
  66. package/node_modules/@noodle-borg/agent-kit/dist/index.d.ts +1 -0
  67. package/node_modules/@noodle-borg/agent-kit/dist/index.js +1 -0
  68. package/node_modules/@noodle-borg/agent-kit/dist/plugin-bootstrap-skill.js +10 -0
  69. package/node_modules/@noodle-borg/agent-kit/dist/skill-authoring-refs.js +15 -3
  70. package/node_modules/@noodle-borg/agent-kit/dist/skill-content.js +1 -1
  71. package/node_modules/@noodle-borg/agent-kit/dist/welcome-wordmark.d.ts +3 -0
  72. package/node_modules/@noodle-borg/agent-kit/dist/welcome-wordmark.js +10 -0
  73. package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
  74. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-configuration.d.ts +9 -1
  75. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-configuration.js +33 -2
  76. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-execution-bound.d.ts +3 -0
  77. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-execution-bound.js +29 -0
  78. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-interaction-state.d.ts +5 -3
  79. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-interaction-state.js +21 -10
  80. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-store.d.ts +1 -1
  81. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-store.js +3 -3
  82. package/node_modules/@noodle-borg/assistant-gateway/dist/portable.d.ts +1 -0
  83. package/node_modules/@noodle-borg/assistant-gateway/dist/portable.js +1 -0
  84. package/node_modules/@noodle-borg/assistant-gateway/dist/session-target.js +5 -4
  85. package/node_modules/@noodle-borg/assistant-gateway/package.json +1 -1
  86. package/node_modules/@noodle-borg/authoring/dist/config.d.ts +20 -0
  87. package/node_modules/@noodle-borg/authoring/dist/config.js +29 -2
  88. package/node_modules/@noodle-borg/authoring/dist/connectors.d.ts +6 -1
  89. package/node_modules/@noodle-borg/authoring/dist/connectors.js +5 -0
  90. package/node_modules/@noodle-borg/authoring/dist/index.d.ts +2 -2
  91. package/node_modules/@noodle-borg/authoring/dist/json-schema.d.ts +1 -1
  92. package/node_modules/@noodle-borg/authoring/dist/json-schema.js +15 -2
  93. package/node_modules/@noodle-borg/authoring/dist/load-authored.js +1 -1
  94. package/node_modules/@noodle-borg/authoring/dist/managed-collection.d.ts +18 -4
  95. package/node_modules/@noodle-borg/authoring/dist/managed-collection.js +22 -3
  96. package/node_modules/@noodle-borg/authoring/dist/platform.d.ts +3 -0
  97. package/node_modules/@noodle-borg/authoring/dist/platform.js +4 -0
  98. package/node_modules/@noodle-borg/authoring/dist/server-presentation.js +43 -0
  99. package/node_modules/@noodle-borg/authoring/dist/server.d.ts +3 -1
  100. package/node_modules/@noodle-borg/authoring/dist/server.js +4 -44
  101. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-billing.js +18 -0
  102. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-config.js +31 -4
  103. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solutions.js +778 -0
  104. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-tenant-resources.js +0 -241
  105. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-types.js +7 -0
  106. package/node_modules/@noodle-borg/cli-catalog/dist/index.js +20 -0
  107. package/node_modules/@noodle-borg/compiler/dist/artifact/assemble.js +2 -1
  108. package/node_modules/@noodle-borg/compiler/dist/artifact/catalog-emission.js +3 -1
  109. package/node_modules/@noodle-borg/compiler/dist/artifact/config.js +3 -0
  110. package/node_modules/@noodle-borg/compiler/dist/artifact/types.d.ts +17 -1
  111. package/node_modules/@noodle-borg/compiler/dist/artifact/version.d.ts +6 -1
  112. package/node_modules/@noodle-borg/compiler/dist/artifact/version.js +6 -1
  113. package/node_modules/@noodle-borg/compiler/dist/business-variables.d.ts +27 -0
  114. package/node_modules/@noodle-borg/compiler/dist/business-variables.js +230 -0
  115. package/node_modules/@noodle-borg/compiler/dist/compile.js +7 -1
  116. package/node_modules/@noodle-borg/compiler/dist/errors.d.ts +1 -1
  117. package/node_modules/@noodle-borg/compiler/dist/index.d.ts +3 -0
  118. package/node_modules/@noodle-borg/compiler/dist/index.js +3 -0
  119. package/node_modules/@noodle-borg/compiler/dist/managed-collection-controls.d.ts +52 -0
  120. package/node_modules/@noodle-borg/compiler/dist/managed-collection-controls.js +92 -0
  121. package/node_modules/@noodle-borg/compiler/dist/managed-collections.d.ts +26 -1
  122. package/node_modules/@noodle-borg/compiler/dist/managed-collections.js +190 -1
  123. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts +100 -36
  124. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js +2 -0
  125. package/node_modules/@noodle-borg/compiler/dist/native-record-operations.d.ts +7 -0
  126. package/node_modules/@noodle-borg/compiler/dist/native-record-operations.js +59 -0
  127. package/node_modules/@noodle-borg/connector-defs/dist/compile-http.js +83 -8
  128. package/node_modules/@noodle-borg/connector-defs/dist/schema.d.ts +31 -1
  129. package/node_modules/@noodle-borg/connector-defs/dist/schema.js +16 -0
  130. package/node_modules/@noodle-borg/connector-http/dist/http-connector.d.ts +12 -3
  131. package/node_modules/@noodle-borg/connector-http/dist/http-connector.js +41 -2
  132. package/node_modules/@noodle-borg/connector-http/dist/http-response.js +3 -2
  133. package/node_modules/@noodle-borg/connector-http/dist/mcp/config.js +1 -1
  134. package/node_modules/@noodle-borg/connector-http/dist/url-resolution.js +1 -1
  135. package/node_modules/@noodle-borg/control-plane/dist/contracts.d.ts +4 -1
  136. package/node_modules/@noodle-borg/control-plane/dist/deploy-gates.js +1 -0
  137. package/node_modules/@noodle-borg/control-plane/dist/in-memory-organization-store.d.ts +3 -0
  138. package/node_modules/@noodle-borg/control-plane/dist/in-memory-organization-store.js +11 -0
  139. package/node_modules/@noodle-borg/control-plane/dist/organization-agreements.d.ts +45 -0
  140. package/node_modules/@noodle-borg/control-plane/dist/organization-agreements.js +74 -0
  141. package/node_modules/@noodle-borg/control-plane/dist/portable.d.ts +1 -0
  142. package/node_modules/@noodle-borg/control-plane/dist/portable.js +1 -0
  143. package/node_modules/@noodle-borg/module/dist/contract.d.ts +22 -0
  144. package/node_modules/@noodle-borg/module/dist/platform-human-identity.d.ts +2 -0
  145. package/node_modules/@noodle-borg/protocol/dist/request-deps.js +1 -0
  146. package/node_modules/@noodle-borg/protocol/dist/request-state.d.ts +1 -0
  147. package/node_modules/@noodle-borg/protocol/dist/request-state.js +11 -2
  148. package/node_modules/@noodle-borg/protocol/dist/sdk-server.d.ts +2 -0
  149. package/node_modules/@noodle-borg/protocol/dist/v2/input-required.js +2 -1
  150. package/node_modules/@noodle-borg/protocol/dist/v2/server.js +2 -1
  151. package/node_modules/@noodle-borg/runtime/dist/ambient-context.js +6 -1
  152. package/node_modules/@noodle-borg/runtime/dist/broker/types.d.ts +2 -0
  153. package/node_modules/@noodle-borg/runtime/dist/business-variables.d.ts +15 -0
  154. package/node_modules/@noodle-borg/runtime/dist/business-variables.js +75 -0
  155. package/node_modules/@noodle-borg/runtime/dist/confirmation-continuation.js +2 -1
  156. package/node_modules/@noodle-borg/runtime/dist/confirmation.js +23 -3
  157. package/node_modules/@noodle-borg/runtime/dist/connector/types.d.ts +17 -1
  158. package/node_modules/@noodle-borg/runtime/dist/connector-snapshot.js +6 -0
  159. package/node_modules/@noodle-borg/runtime/dist/execute.d.ts +18 -3
  160. package/node_modules/@noodle-borg/runtime/dist/execute.js +13 -3
  161. package/node_modules/@noodle-borg/runtime/dist/index.d.ts +2 -0
  162. package/node_modules/@noodle-borg/runtime/dist/index.js +1 -0
  163. package/node_modules/@noodle-borg/runtime/dist/interactive.js +11 -0
  164. package/node_modules/@noodle-borg/runtime/dist/managed-origins.d.ts +3 -1
  165. package/node_modules/@noodle-borg/runtime/dist/managed-origins.js +32 -7
  166. package/node_modules/@noodle-borg/runtime/dist/operation-credential.js +6 -0
  167. package/node_modules/@noodle-borg/runtime/dist/operation-evidence.d.ts +30 -0
  168. package/node_modules/@noodle-borg/runtime/dist/operation-evidence.js +68 -0
  169. package/node_modules/@noodle-borg/runtime/dist/operation-execution.d.ts +2 -2
  170. package/node_modules/@noodle-borg/runtime/dist/operation-execution.js +142 -71
  171. package/node_modules/@noodle-borg/runtime/dist/result.d.ts +6 -4
  172. package/node_modules/@noodle-borg/runtime/dist/tool-dispatch.d.ts +7 -0
  173. package/node_modules/@noodle-borg/runtime/dist/tool-dispatch.js +48 -4
  174. package/node_modules/@noodle-borg/service/dist/admission.js +2 -1
  175. package/node_modules/@noodle-borg/service/dist/application-activity.js +236 -0
  176. package/node_modules/@noodle-borg/service/dist/application-business-notice.js +28 -0
  177. package/node_modules/@noodle-borg/service/dist/application-runtime-target.js +141 -0
  178. package/node_modules/@noodle-borg/service/dist/application-settings-targets.js +72 -0
  179. package/node_modules/@noodle-borg/service/dist/application-settings.js +210 -0
  180. package/node_modules/@noodle-borg/service/dist/business-api-admission.js +121 -0
  181. package/node_modules/@noodle-borg/service/dist/business-information/activity-pagination.js +73 -0
  182. package/node_modules/@noodle-borg/service/dist/business-information/business-notice.d.ts +24 -0
  183. package/node_modules/@noodle-borg/service/dist/business-information/business-notice.js +18 -0
  184. package/node_modules/@noodle-borg/service/dist/business-information/collection-controls.js +51 -0
  185. package/node_modules/@noodle-borg/service/dist/business-information/contracts.d.ts +439 -0
  186. package/node_modules/@noodle-borg/service/dist/business-information/definition-resolver.js +94 -0
  187. package/node_modules/@noodle-borg/service/dist/business-information/in-memory-installation-lifecycle.js +136 -0
  188. package/node_modules/@noodle-borg/service/dist/business-information/in-memory-invitations.js +160 -0
  189. package/node_modules/@noodle-borg/service/dist/business-information/in-memory-locks.js +23 -0
  190. package/node_modules/@noodle-borg/service/dist/business-information/in-memory-store.js +287 -132
  191. package/node_modules/@noodle-borg/service/dist/business-information/installation-capacity.js +10 -0
  192. package/node_modules/@noodle-borg/service/dist/business-information/invitations.js +68 -0
  193. package/node_modules/@noodle-borg/service/dist/business-information/legacy-request-migration.js +60 -0
  194. package/node_modules/@noodle-borg/service/dist/business-information/managed-releases.js +245 -0
  195. package/node_modules/@noodle-borg/service/dist/business-information/managed-solution-blueprints.js +51 -0
  196. package/node_modules/@noodle-borg/service/dist/business-information/managed-solution-executable.js +76 -0
  197. package/node_modules/@noodle-borg/service/dist/business-information/model.js +124 -23
  198. package/node_modules/@noodle-borg/service/dist/business-information/native-query.js +162 -0
  199. package/node_modules/@noodle-borg/service/dist/business-information/native-storage-budget.js +60 -0
  200. package/node_modules/@noodle-borg/service/dist/business-information/pagination.js +28 -0
  201. package/node_modules/@noodle-borg/service/dist/business-information/portable.js +9 -0
  202. package/node_modules/@noodle-borg/service/dist/business-information/principal-authority.d.ts +11 -0
  203. package/node_modules/@noodle-borg/service/dist/business-information/principal-authority.js +42 -0
  204. package/node_modules/@noodle-borg/service/dist/business-information/profiles.js +137 -6
  205. package/node_modules/@noodle-borg/service/dist/business-information/reader-floor.js +26 -0
  206. package/node_modules/@noodle-borg/service/dist/business-information/source-credential-fence.js +79 -0
  207. package/node_modules/@noodle-borg/service/dist/business-information/source-custody-budget.js +30 -0
  208. package/node_modules/@noodle-borg/service/dist/business-information/source-custody-memory.js +122 -0
  209. package/node_modules/@noodle-borg/service/dist/business-information/source-executor.js +191 -0
  210. package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-contracts.js +2 -0
  211. package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-coordinator.js +136 -0
  212. package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-failures.js +32 -0
  213. package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-memory-state.js +154 -0
  214. package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-memory-store.js +568 -0
  215. package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-memory-types.js +26 -0
  216. package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-memory-values.js +59 -0
  217. package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-pagination.js +54 -0
  218. package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-validation.js +163 -0
  219. package/node_modules/@noodle-borg/service/dist/business-information/source-refresh-retention.js +29 -0
  220. package/node_modules/@noodle-borg/service/dist/business-information-runtime.js +80 -0
  221. package/node_modules/@noodle-borg/service/dist/business-onboarding.js +73 -0
  222. package/node_modules/@noodle-borg/service/dist/connections/types.js +8 -0
  223. package/node_modules/@noodle-borg/service/dist/credential-binding-index.js +38 -33
  224. package/node_modules/@noodle-borg/service/dist/deployment-execution.js +275 -0
  225. package/node_modules/@noodle-borg/service/dist/external-credential-binding-broker.js +19 -1
  226. package/node_modules/@noodle-borg/service/dist/external-credential-exchange.d.ts +16 -1
  227. package/node_modules/@noodle-borg/service/dist/modules/host.js +4 -1
  228. package/node_modules/@noodle-borg/service/dist/native-record-connector.d.ts +20 -0
  229. package/node_modules/@noodle-borg/service/dist/native-record-connector.js +206 -0
  230. package/node_modules/@noodle-borg/service/dist/oauth/store.d.ts +3 -0
  231. package/node_modules/@noodle-borg/service/dist/operation-evidence.js +89 -0
  232. package/node_modules/@noodle-borg/service/dist/recovery-quarantine.js +49 -0
  233. package/node_modules/@noodle-borg/service/dist/registry-compile.js +60 -11
  234. package/node_modules/@noodle-borg/service/dist/registry-deploy-transaction.js +18 -0
  235. package/node_modules/@noodle-borg/service/dist/registry-rollback.js +2 -1
  236. package/node_modules/@noodle-borg/service/dist/registry-state.d.ts +1 -1
  237. package/node_modules/@noodle-borg/service/dist/registry-state.js +6 -3
  238. package/node_modules/@noodle-borg/service/dist/registry-targets.js +49 -0
  239. package/node_modules/@noodle-borg/service/dist/registry-types.d.ts +2 -0
  240. package/node_modules/@noodle-borg/service/dist/registry.d.ts +15 -3
  241. package/node_modules/@noodle-borg/service/dist/registry.js +177 -137
  242. package/node_modules/@noodle-borg/service/dist/routes/assistant-appearance.js +3 -2
  243. package/node_modules/@noodle-borg/service/dist/routes/assistant-clients.js +2 -1
  244. package/node_modules/@noodle-borg/service/dist/routes/assistant-doctor.js +2 -1
  245. package/node_modules/@noodle-borg/service/dist/routes/assistant-embeds.js +8 -3
  246. package/node_modules/@noodle-borg/service/dist/routes/assistant-interaction-replay.js +1 -1
  247. package/node_modules/@noodle-borg/service/dist/routes/assistant-interactions.js +48 -36
  248. package/node_modules/@noodle-borg/service/dist/routes/assistant-public-configuration.js +3 -2
  249. package/node_modules/@noodle-borg/service/dist/routes/assistant-public-session.js +10 -10
  250. package/node_modules/@noodle-borg/service/dist/routes/assistant-session-target.js +32 -3
  251. package/node_modules/@noodle-borg/service/dist/routes/assistant-suggestions.js +1 -1
  252. package/node_modules/@noodle-borg/service/dist/routes/assistant-transcript.js +1 -1
  253. package/node_modules/@noodle-borg/service/dist/routes/assistant.js +10 -10
  254. package/node_modules/@noodle-borg/service/dist/routes/business-information-activity.js +83 -0
  255. package/node_modules/@noodle-borg/service/dist/routes/business-information-admission.js +26 -0
  256. package/node_modules/@noodle-borg/service/dist/routes/business-information-channels.js +153 -0
  257. package/node_modules/@noodle-borg/service/dist/routes/business-information-connections.js +107 -0
  258. package/node_modules/@noodle-borg/service/dist/routes/business-information-dispatch.js +87 -4
  259. package/node_modules/@noodle-borg/service/dist/routes/business-information-external.js +79 -0
  260. package/node_modules/@noodle-borg/service/dist/routes/business-information-installation.js +24 -0
  261. package/node_modules/@noodle-borg/service/dist/routes/business-information-notice.js +69 -0
  262. package/node_modules/@noodle-borg/service/dist/routes/business-information-onboarding.js +58 -0
  263. package/node_modules/@noodle-borg/service/dist/routes/business-information-paths.js +76 -0
  264. package/node_modules/@noodle-borg/service/dist/routes/business-information-public.js +151 -0
  265. package/node_modules/@noodle-borg/service/dist/routes/business-information-reader-floor.js +15 -0
  266. package/node_modules/@noodle-borg/service/dist/routes/business-information-record-create.js +29 -0
  267. package/node_modules/@noodle-borg/service/dist/routes/business-information-record-reads.js +36 -0
  268. package/node_modules/@noodle-borg/service/dist/routes/business-information-request.js +64 -0
  269. package/node_modules/@noodle-borg/service/dist/routes/business-information-settings.js +64 -0
  270. package/node_modules/@noodle-borg/service/dist/routes/business-information-source.js +249 -0
  271. package/node_modules/@noodle-borg/service/dist/routes/business-information-staff.js +258 -0
  272. package/node_modules/@noodle-borg/service/dist/routes/business-information-wire.js +226 -26
  273. package/node_modules/@noodle-borg/service/dist/routes/business-information.js +238 -197
  274. package/node_modules/@noodle-borg/service/dist/routes/config-values-dispatch.js +1 -1
  275. package/node_modules/@noodle-borg/service/dist/routes/config-values.js +26 -4
  276. package/node_modules/@noodle-borg/service/dist/routes/control-plane.js +33 -234
  277. package/node_modules/@noodle-borg/service/dist/routes/deployment-activation-response.js +13 -4
  278. package/node_modules/@noodle-borg/service/dist/service-resource-cleanup.js +4 -0
  279. package/node_modules/@noodle-borg/service/dist/service.js +57 -11
  280. package/node_modules/@noodle-borg/service/dist/solution-installation-activation.js +149 -0
  281. package/node_modules/@noodle-borg/service/dist/source-configuration-authority.js +94 -0
  282. package/node_modules/@noodle-borg/service/dist/state-catalog.js +6 -5
  283. package/node_modules/@noodle-borg/service/dist/store/config-values.d.ts +42 -17
  284. package/node_modules/@noodle-borg/service/dist/store/config-values.js +123 -24
  285. package/node_modules/@noodle-borg/service/dist/store/in-memory.d.ts +1 -0
  286. package/node_modules/@noodle-borg/service/dist/store/in-memory.js +3 -0
  287. package/node_modules/@noodle-borg/service/dist/store/json-file.d.ts +1 -0
  288. package/node_modules/@noodle-borg/service/dist/store/json-file.js +3 -0
  289. package/node_modules/@noodle-borg/service/dist/store.d.ts +3 -1
  290. package/node_modules/@noodle-borg/service/package.json +2 -2
  291. package/node_modules/@noodle-borg/transport-http/dist/serve-request.js +9 -0
  292. package/node_modules/@noodle-borg/transport-http/package.json +1 -0
  293. package/node_modules/@noodle-borg/wire-contracts/dist/application-activity.d.ts +143 -0
  294. package/node_modules/@noodle-borg/wire-contracts/dist/application-activity.js +90 -0
  295. package/node_modules/@noodle-borg/wire-contracts/dist/application-channels.d.ts +130 -0
  296. package/node_modules/@noodle-borg/wire-contracts/dist/application-channels.js +77 -0
  297. package/node_modules/@noodle-borg/wire-contracts/dist/application-connections.d.ts +105 -0
  298. package/node_modules/@noodle-borg/wire-contracts/dist/application-connections.js +67 -0
  299. package/node_modules/@noodle-borg/wire-contracts/dist/application-onboarding.d.ts +27 -0
  300. package/node_modules/@noodle-borg/wire-contracts/dist/application-onboarding.js +28 -0
  301. package/node_modules/@noodle-borg/wire-contracts/dist/application-settings.d.ts +112 -0
  302. package/node_modules/@noodle-borg/wire-contracts/dist/application-settings.js +88 -0
  303. package/node_modules/@noodle-borg/wire-contracts/dist/assistant.d.ts +1 -1
  304. package/node_modules/@noodle-borg/wire-contracts/dist/billing-catalog.d.ts +62 -0
  305. package/node_modules/@noodle-borg/wire-contracts/dist/billing-catalog.js +57 -0
  306. package/node_modules/@noodle-borg/wire-contracts/dist/billing-enforcement.d.ts +12 -12
  307. package/node_modules/@noodle-borg/wire-contracts/dist/billing-metering.d.ts +4 -4
  308. package/node_modules/@noodle-borg/wire-contracts/dist/billing-org-transfer.d.ts +3 -3
  309. package/node_modules/@noodle-borg/wire-contracts/dist/business-information-query.d.ts +25 -0
  310. package/node_modules/@noodle-borg/wire-contracts/dist/business-information-query.js +37 -0
  311. package/node_modules/@noodle-borg/wire-contracts/dist/business-information.d.ts +1816 -158
  312. package/node_modules/@noodle-borg/wire-contracts/dist/business-information.js +416 -41
  313. package/node_modules/@noodle-borg/wire-contracts/dist/control-plane.d.ts +2 -2
  314. package/node_modules/@noodle-borg/wire-contracts/dist/distribution.d.ts +5 -5
  315. package/node_modules/@noodle-borg/wire-contracts/dist/index.d.ts +8 -0
  316. package/node_modules/@noodle-borg/wire-contracts/dist/index.js +8 -0
  317. package/node_modules/@noodle-borg/wire-contracts/dist/knowledge.d.ts +3 -3
  318. package/node_modules/@noodle-borg/wire-contracts/dist/managed-assistant-sponsorship.d.ts +7 -7
  319. package/node_modules/@noodle-borg/wire-contracts/dist/platform-account-reset.d.ts +5 -0
  320. package/node_modules/@noodle-borg/wire-contracts/dist/platform-account-reset.js +1 -0
  321. package/node_modules/@noodle-borg/wire-contracts/dist/platform-auth.d.ts +66 -66
  322. package/node_modules/@noodle-borg/wire-contracts/dist/solution-onboarding.d.ts +143 -0
  323. package/node_modules/@noodle-borg/wire-contracts/dist/solution-onboarding.js +94 -0
  324. package/node_modules/@noodleseed/assistant/README.md +5 -0
  325. package/node_modules/@noodleseed/assistant/package.json +1 -1
  326. package/package.json +2 -2
@@ -0,0 +1,568 @@
1
+ import { createHmac } from 'node:crypto';
2
+ import { SourceMemoryCapacity } from './source-custody-memory.js';
3
+ import { sourceFailureHealth } from './source-ingestion-failures.js';
4
+ import { bindingFingerprint, bindingKey, completedBinding, due, dueOrder, externalRecordId, externalRecordKey, leaseFrom, normalizeSuppression, ownsLease, refreshIdempotencyDigest, refreshJobId, refreshReceipt, refreshRequestKey, suppressionKey, validatePage, withoutScanState, } from './source-ingestion-memory-state.js';
5
+ import { erasedMemoryExternal, restoreMap, } from './source-ingestion-memory-types.js';
6
+ import { boundedInteger, clone, jsonDigest, requiredCursor, requiredScanMode, sourceToken, } from './source-ingestion-memory-values.js';
7
+ import { decodeExternalRecordCursor, encodeExternalRecordCursor, externalRecordPageLimit, } from './source-ingestion-pagination.js';
8
+ import { normalizeSourceBindingCreate, sourceBindingCreateFrom, } from './source-ingestion-validation.js';
9
+ import { pruneMemoryRefreshReceipts, terminalRefresh } from './source-refresh-retention.js';
10
+ import { validateManagedPayload, validateScalar } from './validation.js';
11
+ /** Process-local reference implementation for generic source-ingestion conformance. */
12
+ export class InMemorySourceIngestionStore {
13
+ #bindings = new Map();
14
+ #records = new Map();
15
+ #suppressions = new Map();
16
+ #refreshRequests = new Map();
17
+ #identityKey;
18
+ #now;
19
+ #pending = Promise.resolve();
20
+ #capacity = new SourceMemoryCapacity();
21
+ constructor(options) {
22
+ if (Buffer.byteLength(options.identityKey, 'utf8') < 32) {
23
+ throw new Error('source identity key must contain at least 32 bytes');
24
+ }
25
+ this.#identityKey = options.identityKey;
26
+ this.#now = options.now ?? (() => new Date());
27
+ }
28
+ createBinding(input) {
29
+ return this.#exclusive(() => {
30
+ const normalized = normalizeSourceBindingCreate(input);
31
+ const key = bindingKey(normalized);
32
+ const existing = this.#bindings.get(key)?.record;
33
+ if (existing !== undefined) {
34
+ if (bindingFingerprint(sourceBindingCreateFrom(existing)) !== bindingFingerprint(normalized)) {
35
+ throw new Error('source binding already exists with different immutable configuration');
36
+ }
37
+ return clone(existing);
38
+ }
39
+ const timestamp = this.#now().toISOString();
40
+ const record = {
41
+ ...normalized,
42
+ state: 'active',
43
+ health: 'initializing',
44
+ completeness: 'incomplete',
45
+ revision: 1,
46
+ fence: 0,
47
+ scanGeneration: 0,
48
+ nextAttemptAt: timestamp,
49
+ createdAt: timestamp,
50
+ updatedAt: timestamp,
51
+ };
52
+ this.#bindings.set(key, { record });
53
+ return clone(record);
54
+ });
55
+ }
56
+ replaceBinding(input) {
57
+ return this.#exclusive(() => {
58
+ const normalized = normalizeSourceBindingCreate(input);
59
+ const key = bindingKey(normalized);
60
+ const current = this.#bindings.get(key)?.record;
61
+ if (current === undefined)
62
+ return { ok: false, reason: 'not_found', currentRevision: 0 };
63
+ if (current.revision !== input.expectedRevision) {
64
+ return { ok: false, reason: 'conflict', currentRevision: current.revision };
65
+ }
66
+ if (normalized.generation <= current.generation) {
67
+ return { ok: false, reason: 'invalid_state', currentRevision: current.revision };
68
+ }
69
+ const sameAccount = normalized.bindingReference === current.bindingReference &&
70
+ normalized.credentialIdentity?.account === current.credentialIdentity?.account;
71
+ const timestamp = input.now.toISOString();
72
+ const replacement = {
73
+ ...normalized,
74
+ state: 'active',
75
+ health: 'initializing',
76
+ completeness: 'incomplete',
77
+ revision: current.revision + 1,
78
+ fence: current.fence + 1,
79
+ scanGeneration: 0,
80
+ nextAttemptAt: timestamp,
81
+ createdAt: current.createdAt,
82
+ updatedAt: timestamp,
83
+ };
84
+ for (const recordKey of this.#records.keys()) {
85
+ if (recordKey.startsWith(`${key}\0record\0`))
86
+ this.#records.delete(recordKey);
87
+ }
88
+ const carried = [...this.#suppressions.entries()].filter(([suppressionKeyValue, item]) => suppressionKeyValue.startsWith(`${key}\0suppression\0`) &&
89
+ item.bindingGeneration === current.generation);
90
+ for (const suppressionKeyValue of this.#suppressions.keys()) {
91
+ if (suppressionKeyValue.startsWith(`${key}\0suppression\0`)) {
92
+ this.#suppressions.delete(suppressionKeyValue);
93
+ }
94
+ }
95
+ if (sameAccount) {
96
+ for (const [, item] of carried) {
97
+ const next = { ...item, bindingGeneration: normalized.generation };
98
+ this.#suppressions.set(suppressionKey(replacement, item.sourceIdentityDigest), next);
99
+ }
100
+ }
101
+ this.#setRefreshJobState(key, current.generation, 'superseded', Number.MAX_SAFE_INTEGER);
102
+ this.#bindings.set(key, { record: replacement });
103
+ return { ok: true, binding: clone(replacement) };
104
+ });
105
+ }
106
+ getBinding(input) {
107
+ const record = this.#bindings.get(bindingKey(input))?.record;
108
+ return Promise.resolve(record === undefined ? undefined : clone(record));
109
+ }
110
+ setBindingState(input) {
111
+ return this.#exclusive(() => {
112
+ const key = bindingKey(input);
113
+ const current = this.#bindings.get(key)?.record;
114
+ if (current === undefined) {
115
+ return { ok: false, reason: 'not_found', currentRevision: 0 };
116
+ }
117
+ if (current.revision !== input.expectedRevision) {
118
+ return { ok: false, reason: 'conflict', currentRevision: current.revision };
119
+ }
120
+ if (current.state === 'revoked' || current.state === input.state) {
121
+ return { ok: false, reason: 'invalid_state', currentRevision: current.revision };
122
+ }
123
+ const { leaseOwner: ignoredOwner, leaseExpiresAt: ignoredExpiry, ...rest } = current;
124
+ void ignoredOwner;
125
+ void ignoredExpiry;
126
+ const changed = {
127
+ ...rest,
128
+ state: input.state,
129
+ health: input.state === 'paused'
130
+ ? 'paused'
131
+ : current.lastSuccessfulSyncAt === undefined
132
+ ? 'initializing'
133
+ : 'stale',
134
+ ...(input.state === 'active' ? { nextAttemptAt: input.now.toISOString() } : {}),
135
+ revision: current.revision + 1,
136
+ updatedAt: input.now.toISOString(),
137
+ };
138
+ this.#bindings.set(key, { record: changed });
139
+ return { ok: true, binding: clone(changed) };
140
+ });
141
+ }
142
+ requestRefresh(input) {
143
+ return this.#exclusive(() => {
144
+ const key = bindingKey(input);
145
+ const current = this.#bindings.get(key);
146
+ if (current === undefined)
147
+ return { ok: false, reason: 'not_found', currentRevision: 0 };
148
+ const idempotencyDigest = refreshIdempotencyDigest(input.idempotencyKey);
149
+ const requestKey = refreshRequestKey(key, current.record.generation, idempotencyDigest);
150
+ const replay = this.#refreshRequests.get(requestKey);
151
+ if (replay !== undefined) {
152
+ return {
153
+ ok: true,
154
+ binding: clone(current.record),
155
+ receipt: refreshReceipt(replay, true),
156
+ };
157
+ }
158
+ if (current.record.revision !== input.expectedRevision) {
159
+ return { ok: false, reason: 'conflict', currentRevision: current.record.revision };
160
+ }
161
+ if (current.record.state !== 'active') {
162
+ return { ok: false, reason: 'invalid_state', currentRevision: current.record.revision };
163
+ }
164
+ const targetScanGeneration = current.record.scanGeneration + 1;
165
+ const pending = [...this.#refreshRequests.values()].find((item) => item.bindingKey === key &&
166
+ item.bindingGeneration === current.record.generation &&
167
+ item.targetScanGeneration === targetScanGeneration &&
168
+ !terminalRefresh(item.state));
169
+ const request = pending === undefined
170
+ ? {
171
+ bindingKey: key,
172
+ bindingGeneration: current.record.generation,
173
+ idempotencyDigest,
174
+ targetScanGeneration,
175
+ jobId: refreshJobId(key, current.record.generation, idempotencyDigest, targetScanGeneration),
176
+ requestedAt: input.now.toISOString(),
177
+ state: 'queued',
178
+ }
179
+ : { ...pending, idempotencyDigest };
180
+ const record = {
181
+ ...current.record,
182
+ nextAttemptAt: input.now.toISOString(),
183
+ revision: current.record.revision + 1,
184
+ updatedAt: input.now.toISOString(),
185
+ };
186
+ this.#bindings.set(key, {
187
+ ...current,
188
+ record,
189
+ });
190
+ this.#refreshRequests.set(requestKey, request);
191
+ return {
192
+ ok: true,
193
+ binding: clone(record),
194
+ receipt: refreshReceipt(request, pending !== undefined),
195
+ };
196
+ });
197
+ }
198
+ claimDue(input) {
199
+ return this.#exclusive(() => {
200
+ const workerId = validateScalar('source worker id', input.workerId, 128);
201
+ const leaseMs = boundedInteger('source lease', input.leaseMs, 1_000, 15 * 60_000);
202
+ const candidate = [...this.#bindings.entries()]
203
+ .filter(([, item]) => due(item.record, input.now))
204
+ .sort((left, right) => dueOrder(left[1].record, right[1].record))[0];
205
+ if (candidate === undefined)
206
+ return undefined;
207
+ const [key, current] = candidate;
208
+ const continuing = current.record.cursor !== undefined;
209
+ const mode = continuing
210
+ ? requiredScanMode(current.record.scanMode)
211
+ : current.record.checkpoint === undefined
212
+ ? 'snapshot'
213
+ : 'changes';
214
+ const scanGeneration = continuing
215
+ ? current.record.scanGeneration
216
+ : current.record.scanGeneration + 1;
217
+ const fence = current.record.fence + 1;
218
+ const expiresAt = new Date(input.now.getTime() + leaseMs).toISOString();
219
+ const record = {
220
+ ...current.record,
221
+ health: current.record.lastSuccessfulSyncAt === undefined ? 'initializing' : 'stale',
222
+ completeness: 'incomplete',
223
+ scanMode: mode,
224
+ scanGeneration,
225
+ fence,
226
+ leaseOwner: workerId,
227
+ leaseExpiresAt: expiresAt,
228
+ revision: current.record.revision + 1,
229
+ updatedAt: input.now.toISOString(),
230
+ };
231
+ this.#bindings.set(key, { record, leaseMs });
232
+ this.#setRefreshJobState(key, record.generation, 'running', record.scanGeneration);
233
+ return leaseFrom(record, workerId, leaseMs);
234
+ });
235
+ }
236
+ commitPage(input) {
237
+ return this.#exclusive(() => {
238
+ validatePage(input.page);
239
+ const key = bindingKey(input.lease.binding);
240
+ const mutable = this.#bindings.get(key);
241
+ if (!ownsLease(mutable?.record, input.lease, input.now)) {
242
+ return { ok: false, reason: 'stale_fence' };
243
+ }
244
+ if (mutable.record.cursor !== input.lease.cursor) {
245
+ return { ok: false, reason: 'stale_cursor' };
246
+ }
247
+ for (const source of input.page.records) {
248
+ this.#upsertExternal(mutable.record, input.lease.scanGeneration, source, input.now);
249
+ }
250
+ for (const sourceId of input.page.deletedIds) {
251
+ this.#deleteExternal(mutable.record, sourceId);
252
+ }
253
+ if (input.page.complete)
254
+ return this.#completePage(key, mutable, input);
255
+ const leaseMs = mutable.leaseMs ?? input.lease.leaseMs;
256
+ const expiresAt = new Date(input.now.getTime() + leaseMs).toISOString();
257
+ const record = {
258
+ ...mutable.record,
259
+ cursor: requiredCursor(input.page.nextCursor),
260
+ leaseExpiresAt: expiresAt,
261
+ revision: mutable.record.revision + 1,
262
+ updatedAt: input.now.toISOString(),
263
+ };
264
+ this.#bindings.set(key, { record, leaseMs });
265
+ return {
266
+ ok: true,
267
+ binding: clone(record),
268
+ lease: leaseFrom(record, input.lease.owner, leaseMs),
269
+ };
270
+ });
271
+ }
272
+ resetCheckpoint(input) {
273
+ return this.#exclusive(() => {
274
+ const key = bindingKey(input.lease.binding);
275
+ const current = this.#bindings.get(key);
276
+ if (!ownsLease(current?.record, input.lease, input.now))
277
+ return false;
278
+ const record = withoutScanState(current.record, {
279
+ health: current.record.lastSuccessfulSyncAt === undefined ? 'initializing' : 'stale',
280
+ completeness: 'incomplete',
281
+ errorCode: validateScalar('source error code', input.errorCode, 80),
282
+ nextAttemptAt: input.now.toISOString(),
283
+ revision: current.record.revision + 1,
284
+ updatedAt: input.now.toISOString(),
285
+ });
286
+ this.#bindings.set(key, { record });
287
+ this.#setRefreshJobState(key, record.generation, 'queued', record.scanGeneration);
288
+ return true;
289
+ });
290
+ }
291
+ failLease(input) {
292
+ return this.#exclusive(() => {
293
+ const key = bindingKey(input.lease.binding);
294
+ const current = this.#bindings.get(key);
295
+ if (!ownsLease(current?.record, input.lease, input.now, true))
296
+ return false;
297
+ const { leaseOwner: ignoredOwner, leaseExpiresAt: ignoredExpiry, ...rest } = current.record;
298
+ void ignoredOwner;
299
+ void ignoredExpiry;
300
+ const record = {
301
+ ...rest,
302
+ health: sourceFailureHealth(input.errorCode),
303
+ completeness: 'incomplete',
304
+ errorCode: validateScalar('source error code', input.errorCode, 80),
305
+ nextAttemptAt: input.retryAt.toISOString(),
306
+ revision: current.record.revision + 1,
307
+ updatedAt: input.now.toISOString(),
308
+ };
309
+ this.#bindings.set(key, { record });
310
+ this.#setRefreshJobState(key, record.generation, 'queued', record.scanGeneration);
311
+ return true;
312
+ });
313
+ }
314
+ listExternalRecords(input) {
315
+ const binding = this.#bindings.get(bindingKey(input))?.record;
316
+ if (binding === undefined ||
317
+ binding.health === 'reauth_required' ||
318
+ binding.state === 'revoked') {
319
+ return Promise.resolve({ records: [] });
320
+ }
321
+ const prefix = `${bindingKey(input)}\0record\0`;
322
+ const cursor = decodeExternalRecordCursor(input.cursor, input);
323
+ const limit = externalRecordPageLimit(input.limit);
324
+ const now = this.#now().toISOString();
325
+ const matched = [...this.#records.entries()]
326
+ .filter(([key, stored]) => key.startsWith(prefix) &&
327
+ stored.record.source.bindingGeneration === input.generation &&
328
+ stored.record.deletedAt === undefined &&
329
+ stored.record.retentionExpiresAt > now)
330
+ .map(([key, stored]) => ({ digest: key.slice(prefix.length), record: stored.record }))
331
+ .filter((item) => cursor === undefined || item.digest > cursor)
332
+ .sort((left, right) => left.digest.localeCompare(right.digest))
333
+ .slice(0, limit + 1);
334
+ const selected = matched.slice(0, limit);
335
+ const records = selected
336
+ .map((item) => clone(item.record))
337
+ .sort((left, right) => left.source.id.localeCompare(right.source.id));
338
+ const last = selected.at(-1);
339
+ return Promise.resolve({
340
+ records,
341
+ ...(matched.length > limit && last !== undefined
342
+ ? { nextCursor: encodeExternalRecordCursor(input, last.digest) }
343
+ : {}),
344
+ });
345
+ }
346
+ getExternalRecord(input) {
347
+ const binding = this.#bindings.get(bindingKey(input))?.record;
348
+ if (binding === undefined ||
349
+ binding.health === 'reauth_required' ||
350
+ binding.state === 'revoked') {
351
+ return Promise.resolve(undefined);
352
+ }
353
+ const prefix = `${bindingKey(input)}\0record\0`;
354
+ const recordId = validateScalar('external record id', input.recordId, 128);
355
+ const now = this.#now().toISOString();
356
+ const record = [...this.#records.entries()].find(([key, stored]) => key.startsWith(prefix) &&
357
+ stored.record.id === recordId &&
358
+ stored.record.source.bindingGeneration === input.generation &&
359
+ stored.record.deletedAt === undefined &&
360
+ stored.record.retentionExpiresAt > now)?.[1].record;
361
+ return Promise.resolve(record === undefined ? undefined : clone(record));
362
+ }
363
+ suppressExternalRecord(input) {
364
+ return this.#exclusive(() => {
365
+ const key = bindingKey(input);
366
+ const binding = this.#bindings.get(key)?.record;
367
+ if (binding === undefined)
368
+ throw new Error('source binding not found');
369
+ const digest = this.#sourceDigest(binding, input.sourceId);
370
+ const suppression = {
371
+ scope: clone(binding.scope),
372
+ collectionKey: binding.collectionKey,
373
+ id: binding.id,
374
+ bindingGeneration: binding.generation,
375
+ sourceIdentityDigest: digest,
376
+ reason: input.reason,
377
+ erasedAt: input.now.toISOString(),
378
+ };
379
+ this.#suppressions.set(suppressionKey(binding, digest), suppression);
380
+ this.#eraseStoredRecord(binding, digest);
381
+ });
382
+ }
383
+ listSuppressions(input) {
384
+ const prefix = `${bindingKey(input)}\0suppression\0`;
385
+ return Promise.resolve([...this.#suppressions.entries()]
386
+ .filter(([key]) => key.startsWith(prefix))
387
+ .map(([, item]) => clone(item)));
388
+ }
389
+ restoreSuppressions(input) {
390
+ return this.#exclusive(() => {
391
+ for (const raw of input) {
392
+ const binding = this.#bindings.get(bindingKey(raw))?.record;
393
+ if (binding === undefined || binding.generation !== raw.bindingGeneration) {
394
+ throw new Error('source suppression does not match an active binding generation');
395
+ }
396
+ const item = normalizeSuppression(raw);
397
+ this.#suppressions.set(suppressionKey(binding, item.sourceIdentityDigest), item);
398
+ this.#eraseStoredRecord(binding, item.sourceIdentityDigest);
399
+ }
400
+ });
401
+ }
402
+ purgeExpired(input) {
403
+ return this.#exclusive(() => {
404
+ const limit = boundedInteger('source retention limit', input.limit ?? 100, 1, 100);
405
+ const now = this.#now().toISOString();
406
+ const candidates = [...this.#records.entries()]
407
+ .filter(([, stored]) => stored.record.deletedAt === undefined && stored.record.retentionExpiresAt <= now)
408
+ .sort((left, right) => left[1].record.retentionExpiresAt.localeCompare(right[1].record.retentionExpiresAt))
409
+ .slice(0, limit);
410
+ for (const [key, stored] of candidates)
411
+ this.#records.set(key, erasedMemoryExternal(stored, this.#now()));
412
+ return (candidates.length +
413
+ pruneMemoryRefreshReceipts(this.#refreshRequests, this.#now(), limit - candidates.length));
414
+ });
415
+ }
416
+ #completePage(key, mutable, input) {
417
+ if (input.lease.mode === 'snapshot') {
418
+ const prefix = `${key}\0record\0`;
419
+ for (const [recordKey, stored] of this.#records) {
420
+ if (recordKey.startsWith(prefix) &&
421
+ stored.record.deletedAt === undefined &&
422
+ stored.lastSeenGeneration !== input.lease.scanGeneration) {
423
+ this.#records.set(recordKey, erasedMemoryExternal(stored, input.now));
424
+ }
425
+ }
426
+ }
427
+ const checkpoint = input.page.checkpoint ??
428
+ (input.lease.mode === 'changes' ? mutable.record.checkpoint : undefined);
429
+ const completeAt = input.now.toISOString();
430
+ this.#setRefreshJobState(key, mutable.record.generation, 'completed', mutable.record.scanGeneration);
431
+ const pending = [...this.#refreshRequests.values()].some((request) => request.bindingKey === key &&
432
+ request.bindingGeneration === mutable.record.generation &&
433
+ !terminalRefresh(request.state));
434
+ const record = {
435
+ ...completedBinding(mutable.record, completeAt, checkpoint),
436
+ ...(pending ? { health: 'stale', nextAttemptAt: completeAt } : {}),
437
+ };
438
+ this.#bindings.set(key, { record });
439
+ const prefix = `${key}\0record\0`;
440
+ for (const [recordKey, stored] of this.#records) {
441
+ if (recordKey.startsWith(prefix) && stored.record.deletedAt === undefined) {
442
+ this.#records.set(recordKey, {
443
+ ...stored,
444
+ record: { ...stored.record, lastSuccessfulSyncAt: completeAt },
445
+ });
446
+ }
447
+ }
448
+ return { ok: true, binding: clone(record) };
449
+ }
450
+ #upsertExternal(binding, scanGeneration, source, now) {
451
+ const sourceId = sourceToken('source record id', source.id);
452
+ const digest = this.#sourceDigest(binding, sourceId);
453
+ if (this.#suppressions.has(suppressionKey(binding, digest)))
454
+ return;
455
+ const key = externalRecordKey(binding, digest);
456
+ const current = this.#records.get(key);
457
+ const content = validateManagedPayload(source.record);
458
+ const contentDigest = jsonDigest(content);
459
+ const timestamp = now.toISOString();
460
+ if (current !== undefined &&
461
+ current.contentDigest === contentDigest &&
462
+ current.record.source.version === source.version &&
463
+ current.record.deletedAt === undefined) {
464
+ this.#records.set(key, {
465
+ ...current,
466
+ lastSeenGeneration: scanGeneration,
467
+ record: {
468
+ ...current.record,
469
+ observedAt: timestamp,
470
+ retentionExpiresAt: new Date(now.getTime() + binding.retentionDays * 86_400_000).toISOString(),
471
+ updatedAt: timestamp,
472
+ },
473
+ });
474
+ return;
475
+ }
476
+ const createdAt = current?.record.createdAt ?? timestamp;
477
+ const record = {
478
+ scope: clone(binding.scope),
479
+ collectionKey: binding.collectionKey,
480
+ id: externalRecordId(binding, digest),
481
+ authority: 'external',
482
+ schemaVersion: binding.schemaVersion,
483
+ schemaDigest: binding.schemaDigest,
484
+ source: {
485
+ bindingId: binding.id,
486
+ bindingGeneration: binding.generation,
487
+ id: sourceId,
488
+ ...(source.version === undefined
489
+ ? {}
490
+ : { version: sourceToken('source version', source.version) }),
491
+ },
492
+ record: content,
493
+ revision: (current?.record.revision ?? 0) + 1,
494
+ completeness: 'complete',
495
+ observedAt: timestamp,
496
+ ...(current?.record.lastSuccessfulSyncAt === undefined
497
+ ? {}
498
+ : { lastSuccessfulSyncAt: current.record.lastSuccessfulSyncAt }),
499
+ retentionExpiresAt: new Date(now.getTime() + binding.retentionDays * 86_400_000).toISOString(),
500
+ createdAt,
501
+ updatedAt: timestamp,
502
+ };
503
+ this.#records.set(key, { record, lastSeenGeneration: scanGeneration, contentDigest });
504
+ }
505
+ #deleteExternal(binding, sourceId) {
506
+ const digest = this.#sourceDigest(binding, sourceToken('deleted source id', sourceId));
507
+ this.#eraseStoredRecord(binding, digest);
508
+ }
509
+ #eraseStoredRecord(binding, digest) {
510
+ const key = externalRecordKey(binding, digest);
511
+ const current = this.#records.get(key);
512
+ if (current === undefined || current.record.deletedAt !== undefined)
513
+ return;
514
+ this.#records.set(key, erasedMemoryExternal(current, this.#now()));
515
+ }
516
+ #sourceDigest(binding, sourceId) {
517
+ return createHmac('sha256', this.#identityKey)
518
+ .update(`${bindingKey(binding)}\0${binding.bindingReference ?? binding.id}\0${sourceId}`)
519
+ .digest('hex');
520
+ }
521
+ #setRefreshJobState(key, generation, state, scanGeneration) {
522
+ for (const [requestKey, request] of this.#refreshRequests) {
523
+ if (request.bindingKey === key &&
524
+ request.bindingGeneration === generation &&
525
+ request.targetScanGeneration <= scanGeneration &&
526
+ !terminalRefresh(request.state)) {
527
+ this.#refreshRequests.set(requestKey, {
528
+ ...request,
529
+ state,
530
+ ...(terminalRefresh(state) ? { terminalAt: this.#now().toISOString() } : {}),
531
+ });
532
+ }
533
+ }
534
+ }
535
+ async #exclusive(operation) {
536
+ const previous = this.#pending;
537
+ let release = () => { };
538
+ this.#pending = new Promise((resolve) => {
539
+ release = resolve;
540
+ });
541
+ await previous;
542
+ const bindings = new Map(this.#bindings);
543
+ const records = new Map(this.#records);
544
+ const suppressions = new Map(this.#suppressions);
545
+ const refresh = new Map(this.#refreshRequests);
546
+ try {
547
+ const result = operation();
548
+ this.#capacity.admit({ bindings, records, suppressions, refresh }, {
549
+ bindings: this.#bindings,
550
+ records: this.#records,
551
+ suppressions: this.#suppressions,
552
+ refresh: this.#refreshRequests,
553
+ });
554
+ return result;
555
+ }
556
+ catch (error) {
557
+ restoreMap(this.#bindings, bindings);
558
+ restoreMap(this.#records, records);
559
+ restoreMap(this.#suppressions, suppressions);
560
+ restoreMap(this.#refreshRequests, refresh);
561
+ throw error;
562
+ }
563
+ finally {
564
+ release();
565
+ }
566
+ }
567
+ }
568
+ //# sourceMappingURL=source-ingestion-memory-store.js.map
@@ -0,0 +1,26 @@
1
+ export function erasedMemoryExternal(stored, now) {
2
+ const { record: ignoredPayload, source, ...metadata } = stored.record;
3
+ void ignoredPayload;
4
+ return {
5
+ ...stored,
6
+ record: {
7
+ ...metadata,
8
+ source: {
9
+ bindingId: source.bindingId,
10
+ bindingGeneration: source.bindingGeneration,
11
+ id: '',
12
+ },
13
+ revision: metadata.revision + 1,
14
+ deletedAt: now.toISOString(),
15
+ observedAt: now.toISOString(),
16
+ updatedAt: now.toISOString(),
17
+ completeness: 'complete',
18
+ },
19
+ };
20
+ }
21
+ export function restoreMap(target, saved) {
22
+ target.clear();
23
+ for (const [key, value] of saved)
24
+ target.set(key, value);
25
+ }
26
+ //# sourceMappingURL=source-ingestion-memory-types.js.map
@@ -0,0 +1,59 @@
1
+ import { createHash } from 'node:crypto';
2
+ export function jsonDigest(value) {
3
+ return createHash('sha256').update(stableJson(value)).digest('hex');
4
+ }
5
+ function stableJson(value) {
6
+ if (Array.isArray(value))
7
+ return `[${value.map(stableJson).join(',')}]`;
8
+ if (value !== null && typeof value === 'object') {
9
+ return `{${Object.entries(value)
10
+ .filter(([, entry]) => entry !== undefined)
11
+ .sort(([left], [right]) => left.localeCompare(right))
12
+ .map(([key, entry]) => `${JSON.stringify(key)}:${stableJson(entry)}`)
13
+ .join(',')}}`;
14
+ }
15
+ return JSON.stringify(value);
16
+ }
17
+ export function fixedDigest(label, value) {
18
+ if (!/^[a-f0-9]{64}$/.test(value))
19
+ throw new Error(`${label} must be a SHA-256 hex digest`);
20
+ return value;
21
+ }
22
+ export function sourceToken(label, value) {
23
+ const normalized = value.trim();
24
+ if (normalized.length === 0 || normalized.length > 4_096 || /[\0\r\n]/.test(normalized)) {
25
+ throw new Error(`${label} is invalid`);
26
+ }
27
+ return normalized;
28
+ }
29
+ export function requiredCursor(value) {
30
+ if (value === undefined)
31
+ throw new Error('source continuation is missing');
32
+ return sourceToken('source continuation', value);
33
+ }
34
+ export function requiredScanMode(value) {
35
+ if (value !== 'snapshot' && value !== 'changes')
36
+ throw new Error('source scan mode is missing');
37
+ return value;
38
+ }
39
+ export function boundedInteger(label, value, minimum, maximum) {
40
+ if (!Number.isSafeInteger(value) || value < minimum || value > maximum) {
41
+ throw new Error(`${label} is outside the supported range`);
42
+ }
43
+ return value;
44
+ }
45
+ export function suppressionReason(value) {
46
+ if (value !== 'customer_request' && value !== 'source_access_revoked') {
47
+ throw new Error('source suppression reason is invalid');
48
+ }
49
+ return value;
50
+ }
51
+ export function validInstant(label, value) {
52
+ if (!Number.isFinite(Date.parse(value)))
53
+ throw new Error(`${label} is invalid`);
54
+ return new Date(value).toISOString();
55
+ }
56
+ export function clone(value) {
57
+ return structuredClone(value);
58
+ }
59
+ //# sourceMappingURL=source-ingestion-memory-values.js.map