@noodleseed/one 0.162.0 → 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.
- package/dist/commands/billing-catalog-ops.d.ts +4 -0
- package/dist/commands/billing-catalog-ops.d.ts.map +1 -0
- package/dist/commands/billing-catalog-ops.js +58 -0
- package/dist/commands/billing-catalog-ops.js.map +1 -0
- package/dist/commands/billing-ops.d.ts.map +1 -1
- package/dist/commands/billing-ops.js +3 -0
- package/dist/commands/billing-ops.js.map +1 -1
- package/dist/commands/catalog.d.ts.map +1 -1
- package/dist/commands/catalog.js +2 -0
- package/dist/commands/catalog.js.map +1 -1
- package/dist/commands/config-values.d.ts.map +1 -1
- package/dist/commands/config-values.js +16 -0
- package/dist/commands/config-values.js.map +1 -1
- package/dist/commands/installation-variables.d.ts +26 -0
- package/dist/commands/installation-variables.d.ts.map +1 -0
- package/dist/commands/installation-variables.js +171 -0
- package/dist/commands/installation-variables.js.map +1 -0
- package/dist/commands/solutions-activity.d.ts +5 -0
- package/dist/commands/solutions-activity.d.ts.map +1 -0
- package/dist/commands/solutions-activity.js +116 -0
- package/dist/commands/solutions-activity.js.map +1 -0
- package/dist/commands/solutions-connections.d.ts +7 -0
- package/dist/commands/solutions-connections.d.ts.map +1 -0
- package/dist/commands/solutions-connections.js +88 -0
- package/dist/commands/solutions-connections.js.map +1 -0
- package/dist/commands/solutions-installation-options.d.ts +5 -0
- package/dist/commands/solutions-installation-options.d.ts.map +1 -0
- package/dist/commands/solutions-installation-options.js +52 -0
- package/dist/commands/solutions-installation-options.js.map +1 -0
- package/dist/commands/solutions-onboarding.d.ts +5 -0
- package/dist/commands/solutions-onboarding.d.ts.map +1 -0
- package/dist/commands/solutions-onboarding.js +113 -0
- package/dist/commands/solutions-onboarding.js.map +1 -0
- package/dist/commands/solutions-ops.d.ts.map +1 -1
- package/dist/commands/solutions-ops.js +278 -17
- package/dist/commands/solutions-ops.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/node_modules/@noodle-borg/admission-limits/dist/counter-store.d.ts +21 -2
- package/node_modules/@noodle-borg/admission-limits/dist/counter-store.js +10 -1
- package/node_modules/@noodle-borg/admission-limits/dist/in-memory-counter-store.d.ts +5 -1
- package/node_modules/@noodle-borg/admission-limits/dist/in-memory-counter-store.js +31 -2
- package/node_modules/@noodle-borg/admission-limits/dist/portable.d.ts +3 -0
- package/node_modules/@noodle-borg/admission-limits/dist/portable.js +3 -0
- package/node_modules/@noodle-borg/admission-limits/dist/public-admission-assertion.d.ts +28 -0
- package/node_modules/@noodle-borg/admission-limits/dist/public-admission-assertion.js +124 -0
- package/node_modules/@noodle-borg/admission-limits/dist/public-record-admission.d.ts +54 -0
- package/node_modules/@noodle-borg/admission-limits/dist/public-record-admission.js +74 -0
- package/node_modules/@noodle-borg/admission-limits/dist/request-attribution.d.ts +11 -0
- package/node_modules/@noodle-borg/admission-limits/dist/request-attribution.js +19 -0
- package/node_modules/@noodle-borg/agent-kit/dist/curated/error-fixes.js +2 -0
- package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js +5 -5
- package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js +3 -0
- package/node_modules/@noodle-borg/agent-kit/dist/skill-authoring-refs.js +15 -3
- package/node_modules/@noodle-borg/agent-kit/dist/skill-content.js +1 -1
- package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-configuration.d.ts +9 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-configuration.js +33 -2
- package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-execution-bound.d.ts +3 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-execution-bound.js +29 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-interaction-state.d.ts +5 -3
- package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-interaction-state.js +21 -10
- package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-store.d.ts +1 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-store.js +3 -3
- package/node_modules/@noodle-borg/assistant-gateway/dist/portable.d.ts +1 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/portable.js +1 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/session-target.js +5 -4
- package/node_modules/@noodle-borg/authoring/dist/config.d.ts +20 -0
- package/node_modules/@noodle-borg/authoring/dist/config.js +29 -2
- package/node_modules/@noodle-borg/authoring/dist/connectors.d.ts +6 -1
- package/node_modules/@noodle-borg/authoring/dist/connectors.js +5 -0
- package/node_modules/@noodle-borg/authoring/dist/index.d.ts +2 -2
- package/node_modules/@noodle-borg/authoring/dist/json-schema.d.ts +1 -1
- package/node_modules/@noodle-borg/authoring/dist/json-schema.js +15 -2
- package/node_modules/@noodle-borg/authoring/dist/load-authored.js +1 -1
- package/node_modules/@noodle-borg/authoring/dist/managed-collection.d.ts +18 -4
- package/node_modules/@noodle-borg/authoring/dist/managed-collection.js +22 -3
- package/node_modules/@noodle-borg/authoring/dist/platform.d.ts +3 -0
- package/node_modules/@noodle-borg/authoring/dist/platform.js +4 -0
- package/node_modules/@noodle-borg/authoring/dist/server-presentation.js +43 -0
- package/node_modules/@noodle-borg/authoring/dist/server.d.ts +3 -1
- package/node_modules/@noodle-borg/authoring/dist/server.js +4 -44
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-billing.js +18 -0
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-config.js +31 -4
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solutions.js +778 -0
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-tenant-resources.js +0 -241
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-types.js +7 -0
- package/node_modules/@noodle-borg/cli-catalog/dist/index.js +20 -0
- package/node_modules/@noodle-borg/compiler/dist/artifact/assemble.js +2 -1
- package/node_modules/@noodle-borg/compiler/dist/artifact/catalog-emission.js +3 -1
- package/node_modules/@noodle-borg/compiler/dist/artifact/config.js +3 -0
- package/node_modules/@noodle-borg/compiler/dist/artifact/types.d.ts +17 -1
- package/node_modules/@noodle-borg/compiler/dist/artifact/version.d.ts +6 -1
- package/node_modules/@noodle-borg/compiler/dist/artifact/version.js +6 -1
- package/node_modules/@noodle-borg/compiler/dist/business-variables.d.ts +27 -0
- package/node_modules/@noodle-borg/compiler/dist/business-variables.js +230 -0
- package/node_modules/@noodle-borg/compiler/dist/compile.js +7 -1
- package/node_modules/@noodle-borg/compiler/dist/errors.d.ts +1 -1
- package/node_modules/@noodle-borg/compiler/dist/index.d.ts +3 -0
- package/node_modules/@noodle-borg/compiler/dist/index.js +3 -0
- package/node_modules/@noodle-borg/compiler/dist/managed-collection-controls.d.ts +52 -0
- package/node_modules/@noodle-borg/compiler/dist/managed-collection-controls.js +92 -0
- package/node_modules/@noodle-borg/compiler/dist/managed-collections.d.ts +26 -1
- package/node_modules/@noodle-borg/compiler/dist/managed-collections.js +190 -1
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts +100 -36
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js +2 -0
- package/node_modules/@noodle-borg/compiler/dist/native-record-operations.d.ts +7 -0
- package/node_modules/@noodle-borg/compiler/dist/native-record-operations.js +59 -0
- package/node_modules/@noodle-borg/connector-defs/dist/compile-http.js +83 -8
- package/node_modules/@noodle-borg/connector-defs/dist/schema.d.ts +31 -1
- package/node_modules/@noodle-borg/connector-defs/dist/schema.js +16 -0
- package/node_modules/@noodle-borg/connector-http/dist/http-connector.d.ts +12 -3
- package/node_modules/@noodle-borg/connector-http/dist/http-connector.js +41 -2
- package/node_modules/@noodle-borg/connector-http/dist/http-response.js +3 -2
- package/node_modules/@noodle-borg/connector-http/dist/mcp/config.js +1 -1
- package/node_modules/@noodle-borg/connector-http/dist/url-resolution.js +1 -1
- package/node_modules/@noodle-borg/control-plane/dist/contracts.d.ts +2 -1
- package/node_modules/@noodle-borg/control-plane/dist/in-memory-organization-store.d.ts +3 -0
- package/node_modules/@noodle-borg/control-plane/dist/in-memory-organization-store.js +11 -0
- package/node_modules/@noodle-borg/control-plane/dist/organization-agreements.d.ts +45 -0
- package/node_modules/@noodle-borg/control-plane/dist/organization-agreements.js +74 -0
- package/node_modules/@noodle-borg/control-plane/dist/portable.d.ts +1 -0
- package/node_modules/@noodle-borg/control-plane/dist/portable.js +1 -0
- package/node_modules/@noodle-borg/module/dist/contract.d.ts +20 -0
- package/node_modules/@noodle-borg/module/dist/platform-human-identity.d.ts +2 -0
- package/node_modules/@noodle-borg/protocol/dist/request-deps.js +1 -0
- package/node_modules/@noodle-borg/protocol/dist/request-state.d.ts +1 -0
- package/node_modules/@noodle-borg/protocol/dist/request-state.js +11 -2
- package/node_modules/@noodle-borg/protocol/dist/sdk-server.d.ts +2 -0
- package/node_modules/@noodle-borg/protocol/dist/v2/input-required.js +2 -1
- package/node_modules/@noodle-borg/protocol/dist/v2/server.js +2 -1
- package/node_modules/@noodle-borg/runtime/dist/ambient-context.js +6 -1
- package/node_modules/@noodle-borg/runtime/dist/broker/types.d.ts +2 -0
- package/node_modules/@noodle-borg/runtime/dist/business-variables.d.ts +15 -0
- package/node_modules/@noodle-borg/runtime/dist/business-variables.js +75 -0
- package/node_modules/@noodle-borg/runtime/dist/confirmation-continuation.js +2 -1
- package/node_modules/@noodle-borg/runtime/dist/confirmation.js +23 -3
- package/node_modules/@noodle-borg/runtime/dist/connector/types.d.ts +17 -1
- package/node_modules/@noodle-borg/runtime/dist/connector-snapshot.js +6 -0
- package/node_modules/@noodle-borg/runtime/dist/execute.d.ts +18 -3
- package/node_modules/@noodle-borg/runtime/dist/execute.js +13 -3
- package/node_modules/@noodle-borg/runtime/dist/index.d.ts +2 -0
- package/node_modules/@noodle-borg/runtime/dist/index.js +1 -0
- package/node_modules/@noodle-borg/runtime/dist/interactive.js +11 -0
- package/node_modules/@noodle-borg/runtime/dist/managed-origins.d.ts +3 -1
- package/node_modules/@noodle-borg/runtime/dist/managed-origins.js +32 -7
- package/node_modules/@noodle-borg/runtime/dist/operation-credential.js +6 -0
- package/node_modules/@noodle-borg/runtime/dist/operation-evidence.d.ts +30 -0
- package/node_modules/@noodle-borg/runtime/dist/operation-evidence.js +68 -0
- package/node_modules/@noodle-borg/runtime/dist/operation-execution.d.ts +2 -2
- package/node_modules/@noodle-borg/runtime/dist/operation-execution.js +142 -71
- package/node_modules/@noodle-borg/runtime/dist/result.d.ts +6 -4
- package/node_modules/@noodle-borg/runtime/dist/tool-dispatch.d.ts +7 -0
- package/node_modules/@noodle-borg/runtime/dist/tool-dispatch.js +48 -4
- package/node_modules/@noodle-borg/service/dist/admission.js +2 -1
- package/node_modules/@noodle-borg/service/dist/application-activity.js +236 -0
- package/node_modules/@noodle-borg/service/dist/application-business-notice.js +28 -0
- package/node_modules/@noodle-borg/service/dist/application-runtime-target.js +141 -0
- package/node_modules/@noodle-borg/service/dist/application-settings-targets.js +72 -0
- package/node_modules/@noodle-borg/service/dist/application-settings.js +210 -0
- package/node_modules/@noodle-borg/service/dist/business-api-admission.js +121 -0
- package/node_modules/@noodle-borg/service/dist/business-information/activity-pagination.js +73 -0
- package/node_modules/@noodle-borg/service/dist/business-information/business-notice.d.ts +24 -0
- package/node_modules/@noodle-borg/service/dist/business-information/business-notice.js +18 -0
- package/node_modules/@noodle-borg/service/dist/business-information/collection-controls.js +51 -0
- package/node_modules/@noodle-borg/service/dist/business-information/contracts.d.ts +439 -0
- package/node_modules/@noodle-borg/service/dist/business-information/definition-resolver.js +94 -0
- package/node_modules/@noodle-borg/service/dist/business-information/in-memory-installation-lifecycle.js +136 -0
- package/node_modules/@noodle-borg/service/dist/business-information/in-memory-invitations.js +160 -0
- package/node_modules/@noodle-borg/service/dist/business-information/in-memory-locks.js +23 -0
- package/node_modules/@noodle-borg/service/dist/business-information/in-memory-store.js +287 -132
- package/node_modules/@noodle-borg/service/dist/business-information/installation-capacity.js +10 -0
- package/node_modules/@noodle-borg/service/dist/business-information/invitations.js +68 -0
- package/node_modules/@noodle-borg/service/dist/business-information/legacy-request-migration.js +60 -0
- package/node_modules/@noodle-borg/service/dist/business-information/managed-releases.js +245 -0
- package/node_modules/@noodle-borg/service/dist/business-information/managed-solution-blueprints.js +51 -0
- package/node_modules/@noodle-borg/service/dist/business-information/managed-solution-executable.js +76 -0
- package/node_modules/@noodle-borg/service/dist/business-information/model.js +124 -23
- package/node_modules/@noodle-borg/service/dist/business-information/native-query.js +162 -0
- package/node_modules/@noodle-borg/service/dist/business-information/native-storage-budget.js +60 -0
- package/node_modules/@noodle-borg/service/dist/business-information/pagination.js +28 -0
- package/node_modules/@noodle-borg/service/dist/business-information/portable.js +9 -0
- package/node_modules/@noodle-borg/service/dist/business-information/principal-authority.d.ts +11 -0
- package/node_modules/@noodle-borg/service/dist/business-information/principal-authority.js +42 -0
- package/node_modules/@noodle-borg/service/dist/business-information/profiles.js +137 -6
- package/node_modules/@noodle-borg/service/dist/business-information/reader-floor.js +26 -0
- package/node_modules/@noodle-borg/service/dist/business-information/source-credential-fence.js +79 -0
- package/node_modules/@noodle-borg/service/dist/business-information/source-custody-budget.js +30 -0
- package/node_modules/@noodle-borg/service/dist/business-information/source-custody-memory.js +122 -0
- package/node_modules/@noodle-borg/service/dist/business-information/source-executor.js +191 -0
- package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-contracts.js +2 -0
- package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-coordinator.js +136 -0
- package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-failures.js +32 -0
- package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-memory-state.js +154 -0
- package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-memory-store.js +568 -0
- package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-memory-types.js +26 -0
- package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-memory-values.js +59 -0
- package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-pagination.js +54 -0
- package/node_modules/@noodle-borg/service/dist/business-information/source-ingestion-validation.js +163 -0
- package/node_modules/@noodle-borg/service/dist/business-information/source-refresh-retention.js +29 -0
- package/node_modules/@noodle-borg/service/dist/business-information-runtime.js +80 -0
- package/node_modules/@noodle-borg/service/dist/business-onboarding.js +73 -0
- package/node_modules/@noodle-borg/service/dist/connections/types.js +8 -0
- package/node_modules/@noodle-borg/service/dist/credential-binding-index.js +38 -33
- package/node_modules/@noodle-borg/service/dist/deployment-execution.js +275 -0
- package/node_modules/@noodle-borg/service/dist/external-credential-binding-broker.js +19 -1
- package/node_modules/@noodle-borg/service/dist/external-credential-exchange.d.ts +16 -1
- package/node_modules/@noodle-borg/service/dist/modules/host.js +4 -1
- package/node_modules/@noodle-borg/service/dist/native-record-connector.d.ts +20 -0
- package/node_modules/@noodle-borg/service/dist/native-record-connector.js +206 -0
- package/node_modules/@noodle-borg/service/dist/oauth/store.d.ts +3 -0
- package/node_modules/@noodle-borg/service/dist/operation-evidence.js +89 -0
- package/node_modules/@noodle-borg/service/dist/recovery-quarantine.js +49 -0
- package/node_modules/@noodle-borg/service/dist/registry-compile.js +60 -11
- package/node_modules/@noodle-borg/service/dist/registry-deploy-transaction.js +18 -0
- package/node_modules/@noodle-borg/service/dist/registry-rollback.js +2 -1
- package/node_modules/@noodle-borg/service/dist/registry-state.d.ts +1 -1
- package/node_modules/@noodle-borg/service/dist/registry-state.js +6 -3
- package/node_modules/@noodle-borg/service/dist/registry-targets.js +49 -0
- package/node_modules/@noodle-borg/service/dist/registry-types.d.ts +2 -0
- package/node_modules/@noodle-borg/service/dist/registry.d.ts +15 -3
- package/node_modules/@noodle-borg/service/dist/registry.js +177 -137
- package/node_modules/@noodle-borg/service/dist/routes/assistant-appearance.js +3 -2
- package/node_modules/@noodle-borg/service/dist/routes/assistant-clients.js +2 -1
- package/node_modules/@noodle-borg/service/dist/routes/assistant-doctor.js +2 -1
- package/node_modules/@noodle-borg/service/dist/routes/assistant-embeds.js +8 -3
- package/node_modules/@noodle-borg/service/dist/routes/assistant-interaction-replay.js +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/assistant-interactions.js +48 -36
- package/node_modules/@noodle-borg/service/dist/routes/assistant-public-configuration.js +3 -2
- package/node_modules/@noodle-borg/service/dist/routes/assistant-public-session.js +10 -10
- package/node_modules/@noodle-borg/service/dist/routes/assistant-session-target.js +32 -3
- package/node_modules/@noodle-borg/service/dist/routes/assistant-suggestions.js +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/assistant-transcript.js +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/assistant.js +10 -10
- package/node_modules/@noodle-borg/service/dist/routes/business-information-activity.js +83 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-admission.js +26 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-channels.js +153 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-connections.js +107 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-dispatch.js +87 -4
- package/node_modules/@noodle-borg/service/dist/routes/business-information-external.js +79 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-installation.js +24 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-notice.js +69 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-onboarding.js +58 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-paths.js +76 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-public.js +151 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-reader-floor.js +15 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-record-create.js +29 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-record-reads.js +36 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-request.js +64 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-settings.js +64 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-source.js +249 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-staff.js +258 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-wire.js +226 -26
- package/node_modules/@noodle-borg/service/dist/routes/business-information.js +238 -197
- package/node_modules/@noodle-borg/service/dist/routes/config-values-dispatch.js +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/config-values.js +26 -4
- package/node_modules/@noodle-borg/service/dist/routes/control-plane.js +19 -233
- package/node_modules/@noodle-borg/service/dist/routes/deployment-activation-response.js +13 -4
- package/node_modules/@noodle-borg/service/dist/service-resource-cleanup.js +4 -0
- package/node_modules/@noodle-borg/service/dist/service.js +57 -11
- package/node_modules/@noodle-borg/service/dist/solution-installation-activation.js +149 -0
- package/node_modules/@noodle-borg/service/dist/source-configuration-authority.js +94 -0
- package/node_modules/@noodle-borg/service/dist/state-catalog.js +6 -5
- package/node_modules/@noodle-borg/service/dist/store/config-values.d.ts +42 -17
- package/node_modules/@noodle-borg/service/dist/store/config-values.js +123 -24
- package/node_modules/@noodle-borg/service/dist/store/in-memory.d.ts +1 -0
- package/node_modules/@noodle-borg/service/dist/store/in-memory.js +3 -0
- package/node_modules/@noodle-borg/service/dist/store/json-file.d.ts +1 -0
- package/node_modules/@noodle-borg/service/dist/store/json-file.js +3 -0
- package/node_modules/@noodle-borg/service/dist/store.d.ts +3 -1
- package/node_modules/@noodle-borg/service/package.json +2 -2
- package/node_modules/@noodle-borg/transport-http/dist/serve-request.js +9 -0
- package/node_modules/@noodle-borg/transport-http/package.json +1 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/application-activity.d.ts +143 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/application-activity.js +90 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/application-channels.d.ts +130 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/application-channels.js +77 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/application-connections.d.ts +105 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/application-connections.js +67 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/application-onboarding.d.ts +27 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/application-onboarding.js +28 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/application-settings.d.ts +112 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/application-settings.js +88 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/assistant.d.ts +1 -1
- package/node_modules/@noodle-borg/wire-contracts/dist/billing-catalog.d.ts +62 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/billing-catalog.js +57 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/billing-enforcement.d.ts +12 -12
- package/node_modules/@noodle-borg/wire-contracts/dist/billing-metering.d.ts +4 -4
- package/node_modules/@noodle-borg/wire-contracts/dist/billing-org-transfer.d.ts +3 -3
- package/node_modules/@noodle-borg/wire-contracts/dist/business-information-query.d.ts +25 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/business-information-query.js +37 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/business-information.d.ts +1816 -158
- package/node_modules/@noodle-borg/wire-contracts/dist/business-information.js +416 -41
- package/node_modules/@noodle-borg/wire-contracts/dist/control-plane.d.ts +2 -2
- package/node_modules/@noodle-borg/wire-contracts/dist/distribution.d.ts +5 -5
- package/node_modules/@noodle-borg/wire-contracts/dist/index.d.ts +8 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/index.js +8 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/knowledge.d.ts +3 -3
- package/node_modules/@noodle-borg/wire-contracts/dist/managed-assistant-sponsorship.d.ts +7 -7
- package/node_modules/@noodle-borg/wire-contracts/dist/platform-account-reset.d.ts +5 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/platform-account-reset.js +1 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/platform-auth.d.ts +66 -66
- package/node_modules/@noodle-borg/wire-contracts/dist/solution-onboarding.d.ts +143 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/solution-onboarding.js +94 -0
- package/node_modules/@noodleseed/assistant/README.md +5 -0
- package/package.json +2 -2
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { publicAdmissionRequestDigest } from '@noodle-borg/admission-limits/portable';
|
|
2
|
+
import { readJsonBody, sendJson } from '@noodle-borg/transport-http';
|
|
3
|
+
import { ManagedRecordCreateRequestSchema } from '@noodle-borg/wire-contracts';
|
|
4
|
+
import { creationPayload } from '../business-information/collection-controls.js';
|
|
5
|
+
import { idempotencyDigest, PayloadValidationError, requestFingerprint, validateManagedPayload, } from '../business-information/portable.js';
|
|
6
|
+
import { createNativeRecord, idempotencyConflict, invalid, methodNotAllowed, now, } from './business-information.js';
|
|
7
|
+
import { consumePublicIntakeQuota } from './business-information-admission.js';
|
|
8
|
+
import { requestIdempotencyKey } from './business-information-request.js';
|
|
9
|
+
import { collectionToPublicWire } from './business-information-wire.js';
|
|
10
|
+
const MAX_PUBLIC_INTAKE_BODY_BYTES = 32 * 1024;
|
|
11
|
+
/** Anonymous, quota-bound creation for an installation's explicitly enabled native collection. */
|
|
12
|
+
export async function handlePublicSolutionIntake(req, res, ref, deps) {
|
|
13
|
+
if (deps.publicIntakeEnabled === false) {
|
|
14
|
+
return sendJson(res, 503, {
|
|
15
|
+
error: 'public intake is temporarily disabled',
|
|
16
|
+
code: 'intake_disabled',
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
const installation = await deps.store.resolveInstallationByPublicId(ref.publicId);
|
|
20
|
+
if (installation === undefined)
|
|
21
|
+
return sendJson(res, 404, { error: 'solution not found' });
|
|
22
|
+
if (deps.businessOnboarding && !(await deps.businessOnboarding.ready(installation)))
|
|
23
|
+
return sendJson(res, 409, {
|
|
24
|
+
code: 'business_setup_required',
|
|
25
|
+
error: 'This business has not completed application setup.',
|
|
26
|
+
});
|
|
27
|
+
if (!installation.intakeActive && req.method === 'GET') {
|
|
28
|
+
return sendJson(res, 503, { error: 'public intake is paused', code: 'intake_paused' });
|
|
29
|
+
}
|
|
30
|
+
const publicCollection = installation.definition.collections.find((candidate) => installation.managedCollections.includes(candidate.key) &&
|
|
31
|
+
candidate.authority.authority === 'native');
|
|
32
|
+
if (req.method === 'GET' && ref.collection === undefined) {
|
|
33
|
+
const notice = await deps.store.getBusinessNotice(installation.scope);
|
|
34
|
+
if (publicCollection === undefined)
|
|
35
|
+
return sendJson(res, 404, { error: 'public intake unavailable' });
|
|
36
|
+
return sendJson(res, 200, {
|
|
37
|
+
ok: true,
|
|
38
|
+
data: {
|
|
39
|
+
publicId: installation.publicId,
|
|
40
|
+
...(notice ? { businessNotice: notice.notice } : {}),
|
|
41
|
+
title: installation.definition.title,
|
|
42
|
+
description: installation.definition.description.slice(0, 240),
|
|
43
|
+
collection: collectionToPublicWire(publicCollection),
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
if (req.method === 'POST' && ref.collection !== undefined) {
|
|
48
|
+
if (publicCollection === undefined || publicCollection.key !== ref.collection) {
|
|
49
|
+
return sendJson(res, 404, { error: 'public intake unavailable' });
|
|
50
|
+
}
|
|
51
|
+
const idempotencyKey = requestIdempotencyKey(req);
|
|
52
|
+
if (idempotencyKey === undefined) {
|
|
53
|
+
return sendJson(res, 400, { error: 'Idempotency-Key header is required (1-128 characters)' });
|
|
54
|
+
}
|
|
55
|
+
const body = await readJsonBody(req, Math.min(deps.maxBody, MAX_PUBLIC_INTAKE_BODY_BYTES));
|
|
56
|
+
if (!body.ok)
|
|
57
|
+
return sendJson(res, body.status, { error: body.error });
|
|
58
|
+
const parsed = ManagedRecordCreateRequestSchema.safeParse(body.value);
|
|
59
|
+
if (!parsed.success)
|
|
60
|
+
return invalid(res, parsed.error);
|
|
61
|
+
let payload;
|
|
62
|
+
try {
|
|
63
|
+
creationPayload(publicCollection, parsed.data.payload, true);
|
|
64
|
+
payload = validateManagedPayload(parsed.data.payload);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
if (!(error instanceof PayloadValidationError))
|
|
68
|
+
throw error;
|
|
69
|
+
return sendJson(res, 400, {
|
|
70
|
+
error: error.message,
|
|
71
|
+
code: error.code,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
const origin = { kind: 'embedded', reference: 'public-intake' };
|
|
75
|
+
const requestInput = {
|
|
76
|
+
scope: installation.scope,
|
|
77
|
+
collectionKey: ref.collection,
|
|
78
|
+
idempotencyKey,
|
|
79
|
+
payload,
|
|
80
|
+
origin,
|
|
81
|
+
actorSubject: 'anonymous',
|
|
82
|
+
};
|
|
83
|
+
const completed = await deps.store.probeRequest(requestInput);
|
|
84
|
+
if (completed.disposition === 'conflict')
|
|
85
|
+
return idempotencyConflict(res);
|
|
86
|
+
if (completed.disposition === 'replayed') {
|
|
87
|
+
return sendJson(res, 200, {
|
|
88
|
+
ok: true,
|
|
89
|
+
data: { recordId: completed.record.id, receivedAt: completed.record.createdAt },
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
const quota = await consumePublicIntakeQuota(req, ref.publicId, {
|
|
93
|
+
key: `solution-intake:logical:${ref.publicId}:${idempotencyDigest(idempotencyKey)}`,
|
|
94
|
+
fingerprint: requestFingerprint({
|
|
95
|
+
collectionKey: ref.collection,
|
|
96
|
+
payload,
|
|
97
|
+
origin,
|
|
98
|
+
actorSubject: 'anonymous',
|
|
99
|
+
}),
|
|
100
|
+
}, deps, {
|
|
101
|
+
surfaceId: ref.publicId,
|
|
102
|
+
installationId: installation.scope.installationId,
|
|
103
|
+
route: new URL(req.url ?? '/', 'http://localhost').pathname,
|
|
104
|
+
method: 'POST',
|
|
105
|
+
idempotencyKey,
|
|
106
|
+
requestDigest: publicAdmissionRequestDigest(JSON.stringify(body.value)),
|
|
107
|
+
});
|
|
108
|
+
if (!quota.allowed) {
|
|
109
|
+
if (quota.reason === 'invalid_attribution')
|
|
110
|
+
return sendJson(res, 403, {
|
|
111
|
+
error: 'public admission attribution is invalid',
|
|
112
|
+
code: 'invalid_attribution',
|
|
113
|
+
});
|
|
114
|
+
if (quota.reason === 'admission_unavailable') {
|
|
115
|
+
return sendJson(res, 503, {
|
|
116
|
+
error: 'public intake admission is temporarily unavailable',
|
|
117
|
+
code: 'admission_unavailable',
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
if (quota.reason === 'idempotency_conflict')
|
|
121
|
+
return idempotencyConflict(res);
|
|
122
|
+
res.setHeader('retry-after', String(Math.max(1, Math.ceil((quota.resetAt.getTime() - now(deps).getTime()) / 1000))));
|
|
123
|
+
return sendJson(res, 429, {
|
|
124
|
+
error: 'public intake limit exceeded',
|
|
125
|
+
code: 'quota_exceeded',
|
|
126
|
+
limits: quota.limits.map((limit) => ({ ...limit, resetAt: limit.resetAt.toISOString() })),
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
const result = await createNativeRecord(res, deps, {
|
|
130
|
+
installation,
|
|
131
|
+
collection: requestInput.collectionKey,
|
|
132
|
+
idempotencyKey: requestInput.idempotencyKey,
|
|
133
|
+
payload: requestInput.payload,
|
|
134
|
+
origin: requestInput.origin,
|
|
135
|
+
actorSubject: requestInput.actorSubject,
|
|
136
|
+
});
|
|
137
|
+
if (result === undefined)
|
|
138
|
+
return;
|
|
139
|
+
if (result.disposition === 'conflict')
|
|
140
|
+
return idempotencyConflict(res);
|
|
141
|
+
if (result.disposition === 'paused') {
|
|
142
|
+
return sendJson(res, 503, { error: 'public intake is paused', code: 'intake_paused' });
|
|
143
|
+
}
|
|
144
|
+
return sendJson(res, result.disposition === 'created' ? 201 : 200, {
|
|
145
|
+
ok: true,
|
|
146
|
+
data: { recordId: result.record.id, receivedAt: result.record.createdAt },
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
return methodNotAllowed(res);
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=business-information-public.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { sendJson } from '@noodle-borg/transport-http';
|
|
2
|
+
import { proveManagedReaderFloor } from '../business-information/reader-floor.js';
|
|
3
|
+
import { authorizeControlPlane } from './control-plane.js';
|
|
4
|
+
/** Release-only compatibility proof. The response exposes counts and a digest, never tenant identities. */
|
|
5
|
+
export async function handleBusinessInformationReaderFloor(req, res, deps) {
|
|
6
|
+
if (req.method !== 'GET') {
|
|
7
|
+
return sendJson(res, 405, { error: 'method not allowed' });
|
|
8
|
+
}
|
|
9
|
+
const identity = await authorizeControlPlane(req, res, deps.gate, { requireIdentity: true });
|
|
10
|
+
if (identity === false)
|
|
11
|
+
return;
|
|
12
|
+
const proof = await proveManagedReaderFloor(deps.store);
|
|
13
|
+
sendJson(res, 200, { ok: true, ...proof });
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=business-information-reader-floor.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { sendJson } from '@noodle-borg/transport-http';
|
|
2
|
+
import { PayloadValidationError, } from '../business-information/portable.js';
|
|
3
|
+
export async function createNativeRecord(res, deps, input) {
|
|
4
|
+
try {
|
|
5
|
+
const request = {
|
|
6
|
+
scope: input.installation.scope,
|
|
7
|
+
collectionKey: input.collection,
|
|
8
|
+
idempotencyKey: input.idempotencyKey,
|
|
9
|
+
payload: input.payload,
|
|
10
|
+
origin: input.origin,
|
|
11
|
+
actorSubject: input.actorSubject,
|
|
12
|
+
};
|
|
13
|
+
if (input.admit) {
|
|
14
|
+
const receipt = await deps.store.probeRequest(request);
|
|
15
|
+
if (receipt.disposition !== 'missing')
|
|
16
|
+
return receipt;
|
|
17
|
+
if (!(await input.admit()))
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
return await deps.store.createRequest(request);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
if (!(error instanceof PayloadValidationError))
|
|
24
|
+
throw error;
|
|
25
|
+
sendJson(res, 400, { error: error.message, code: error.code });
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=business-information-record-create.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { sendJson } from '@noodle-borg/transport-http';
|
|
2
|
+
import { NativeQueryError } from '../business-information/native-query.js';
|
|
3
|
+
import { CursorValidationError } from '../business-information/validation.js';
|
|
4
|
+
import { parseBusinessPaging } from './business-information-request.js';
|
|
5
|
+
import { activityToWire } from './business-information-wire.js';
|
|
6
|
+
export async function sendNativeRecordActivity(res, url, scope, collection, id, store) {
|
|
7
|
+
const paging = parseBusinessPaging(url, 100);
|
|
8
|
+
if (!paging.ok)
|
|
9
|
+
return sendJson(res, 400, { error: paging.error });
|
|
10
|
+
const history = await cursorRequest(res, () => store.listActivity(scope, collection, id, paging.value));
|
|
11
|
+
if (history === undefined)
|
|
12
|
+
return;
|
|
13
|
+
return sendJson(res, 200, {
|
|
14
|
+
ok: true,
|
|
15
|
+
data: { ...history, activities: history.activities.map(activityToWire) },
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
export async function cursorRequest(res, request) {
|
|
19
|
+
try {
|
|
20
|
+
return await request();
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
if (error instanceof NativeQueryError) {
|
|
24
|
+
sendJson(res, error.code === 'query_limit_exceeded' ? 422 : 400, {
|
|
25
|
+
error: error.message,
|
|
26
|
+
code: error.code,
|
|
27
|
+
});
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
if (!(error instanceof CursorValidationError))
|
|
31
|
+
throw error;
|
|
32
|
+
sendJson(res, 400, { error: 'cursor is invalid', code: 'invalid_cursor' });
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=business-information-record-reads.js.map
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { ManagedRecordQuerySchema } from '@noodle-borg/wire-contracts';
|
|
2
|
+
export function mutationPermission(operation) {
|
|
3
|
+
if (operation === 'migrate-schema')
|
|
4
|
+
return 'installation:administer';
|
|
5
|
+
if (operation === 'assign')
|
|
6
|
+
return 'records:assign';
|
|
7
|
+
if (operation === 'set-status')
|
|
8
|
+
return 'records:status';
|
|
9
|
+
if (operation === 'add-note')
|
|
10
|
+
return 'records:note';
|
|
11
|
+
return 'records:update';
|
|
12
|
+
}
|
|
13
|
+
export function requestIdempotencyKey(req) {
|
|
14
|
+
const value = req.headers['idempotency-key'];
|
|
15
|
+
if (typeof value !== 'string' || value.length < 1 || value.length > 128)
|
|
16
|
+
return undefined;
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
export function expectedRevision(value) {
|
|
20
|
+
if (value === null || typeof value !== 'object')
|
|
21
|
+
return undefined;
|
|
22
|
+
const revision = value.expectedRevision;
|
|
23
|
+
return typeof revision === 'number' && Number.isInteger(revision) && revision > 0
|
|
24
|
+
? revision
|
|
25
|
+
: undefined;
|
|
26
|
+
}
|
|
27
|
+
export function parseBusinessPaging(url, maximum) {
|
|
28
|
+
const cursor = url.searchParams.get('cursor') ?? undefined;
|
|
29
|
+
const rawLimit = url.searchParams.get('limit');
|
|
30
|
+
if (rawLimit === null)
|
|
31
|
+
return { ok: true, value: cursor === undefined ? {} : { cursor } };
|
|
32
|
+
const limit = Number(rawLimit);
|
|
33
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > maximum) {
|
|
34
|
+
return { ok: false, error: `limit must be an integer from 1 to ${maximum}` };
|
|
35
|
+
}
|
|
36
|
+
return { ok: true, value: { ...(cursor === undefined ? {} : { cursor }), limit } };
|
|
37
|
+
}
|
|
38
|
+
export function parseNativeRecordQuery(url) {
|
|
39
|
+
try {
|
|
40
|
+
const raw = {};
|
|
41
|
+
for (const key of ['filters', 'sortField', 'sortDirection', 'createdAtFrom', 'createdAtTo']) {
|
|
42
|
+
const values = url.searchParams.getAll(key);
|
|
43
|
+
if (values.length > 1)
|
|
44
|
+
throw new Error();
|
|
45
|
+
const value = values[0];
|
|
46
|
+
if (value === undefined)
|
|
47
|
+
continue;
|
|
48
|
+
if (value.length > 32768)
|
|
49
|
+
throw new Error();
|
|
50
|
+
raw[key] = key === 'filters' ? JSON.parse(value) : value;
|
|
51
|
+
}
|
|
52
|
+
const parsed = ManagedRecordQuerySchema.safeParse(raw);
|
|
53
|
+
if (!parsed.success)
|
|
54
|
+
throw new Error();
|
|
55
|
+
return { ok: true, value: parsed.data };
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return {
|
|
59
|
+
ok: false,
|
|
60
|
+
error: 'Invalid collection query. Use declared scalar filters, sort fields and valid creation date bounds.',
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=business-information-request.js.map
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { readJsonBody, sendJson } from '@noodle-borg/transport-http';
|
|
2
|
+
import { ApplicationSettingsResponseSchema, ApplicationSettingsSaveRequestSchema, } from '@noodle-borg/wire-contracts';
|
|
3
|
+
import { ApplicationSettings, installationSettingsTarget, SettingsError, } from '../application-settings.js';
|
|
4
|
+
import { resolveSettingsTargets } from '../application-settings-targets.js';
|
|
5
|
+
import { businessGrantAllows } from '../business-information/model.js';
|
|
6
|
+
import { requireIdentity, requireInstallationPermission, } from './business-information.js';
|
|
7
|
+
export async function handleBusinessSettings(req, res, ref, deps) {
|
|
8
|
+
if (req.method !== 'GET' && req.method !== 'PATCH') {
|
|
9
|
+
res.setHeader('allow', 'GET, PATCH');
|
|
10
|
+
return sendJson(res, 405, { error: 'method not allowed' });
|
|
11
|
+
}
|
|
12
|
+
const identity = await requireIdentity(req, res, deps);
|
|
13
|
+
if (identity === false)
|
|
14
|
+
return;
|
|
15
|
+
const authorized = await requireInstallationPermission(res, ref, identity, req.method === 'PATCH' ? 'installation:administer' : 'records:read', deps);
|
|
16
|
+
if (authorized === undefined)
|
|
17
|
+
return;
|
|
18
|
+
if (deps.configStore?.transactConfig === undefined)
|
|
19
|
+
return sendJson(res, 503, {
|
|
20
|
+
code: 'settings_unavailable',
|
|
21
|
+
error: 'Atomic configuration storage is unavailable.',
|
|
22
|
+
});
|
|
23
|
+
const target = installationSettingsTarget(authorized.installation);
|
|
24
|
+
const settings = new ApplicationSettings(deps.configStore);
|
|
25
|
+
const canEdit = businessGrantAllows(authorized.grant, 'installation:administer');
|
|
26
|
+
res.setHeader('cache-control', 'private, no-store');
|
|
27
|
+
try {
|
|
28
|
+
if (req.method === 'GET') {
|
|
29
|
+
await settings.initialize(target);
|
|
30
|
+
return sendJson(res, 200, ApplicationSettingsResponseSchema.parse({
|
|
31
|
+
ok: true,
|
|
32
|
+
data: await settings.read(target, canEdit),
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
const body = await readJsonBody(req, deps.maxBody);
|
|
36
|
+
if (!body.ok)
|
|
37
|
+
return sendJson(res, body.status, { error: body.error });
|
|
38
|
+
const parsed = ApplicationSettingsSaveRequestSchema.safeParse(body.value);
|
|
39
|
+
if (!parsed.success)
|
|
40
|
+
return sendJson(res, 400, { code: 'settings_invalid', error: 'Invalid settings update.' });
|
|
41
|
+
const registry = deps.registry;
|
|
42
|
+
const data = await settings.save(target, parsed.data, identity.subject, registry ? () => resolveSettingsTargets(registry, target.scope, deps.store) : undefined);
|
|
43
|
+
await deps.audit?.emit({
|
|
44
|
+
eventType: 'config.variable.business_settings_changed',
|
|
45
|
+
org: authorized.scope.org,
|
|
46
|
+
app: authorized.scope.app,
|
|
47
|
+
env: authorized.scope.env,
|
|
48
|
+
actorSubject: identity.subject,
|
|
49
|
+
details: {
|
|
50
|
+
revision: data.revision,
|
|
51
|
+
changedKeys: [...Object.keys(parsed.data.values), ...(parsed.data.resetKeys ?? [])]
|
|
52
|
+
.sort()
|
|
53
|
+
.join(','),
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
sendJson(res, 200, ApplicationSettingsResponseSchema.parse({ ok: true, data }));
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (!(error instanceof SettingsError))
|
|
60
|
+
throw error;
|
|
61
|
+
sendJson(res, error.code === 'settings_conflict' ? 409 : error.code === 'settings_unavailable' ? 503 : 400, { code: error.code, error: error.message });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=business-information-settings.js.map
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { readJsonBody, sendJson } from '@noodle-borg/transport-http';
|
|
3
|
+
import { CollectionSourceConfigureRequestSchema, CollectionSourceRefreshRequestSchema, CollectionSourceRevisionRequestSchema, } from '@noodle-borg/wire-contracts';
|
|
4
|
+
import { SourceCapacityError } from '../business-information/source-custody-budget.js';
|
|
5
|
+
import { sourceOperationSignatureDigest } from '../business-information/source-ingestion-validation.js';
|
|
6
|
+
import { enabledCollection, invalid, methodNotAllowed, mutationFailure, now, requireIdentity, requireInstallationPermission, } from './business-information.js';
|
|
7
|
+
/** Operate a collection's generic external source without introducing provider-specific routes. */
|
|
8
|
+
export async function handleCollectionSource(req, res, ref, deps) {
|
|
9
|
+
const identity = await requireIdentity(req, res, deps);
|
|
10
|
+
if (identity === false)
|
|
11
|
+
return;
|
|
12
|
+
const sourcePermission = req.method === 'GET'
|
|
13
|
+
? 'records:read'
|
|
14
|
+
: ref.sourceAction === 'refresh'
|
|
15
|
+
? 'records:update'
|
|
16
|
+
: 'installation:administer';
|
|
17
|
+
const authorized = await requireInstallationPermission(res, ref, identity, sourcePermission, deps);
|
|
18
|
+
if (authorized === undefined || ref.collection === undefined)
|
|
19
|
+
return;
|
|
20
|
+
const collection = enabledCollection(res, authorized.installation, ref.collection);
|
|
21
|
+
if (collection === undefined)
|
|
22
|
+
return;
|
|
23
|
+
if (collection.authority.authority !== 'external') {
|
|
24
|
+
return sendJson(res, 405, {
|
|
25
|
+
error: 'native collections do not have source controls',
|
|
26
|
+
code: 'operation_not_supported',
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
if (deps.sourceStore === undefined) {
|
|
30
|
+
return sendJson(res, 503, { error: 'collection source persistence is unavailable' });
|
|
31
|
+
}
|
|
32
|
+
const key = sourceBindingKey(authorized.installation, collection);
|
|
33
|
+
const current = await deps.sourceStore.getBinding(key);
|
|
34
|
+
if (ref.sourceAction === undefined && req.method === 'GET') {
|
|
35
|
+
return sendJson(res, 200, {
|
|
36
|
+
ok: true,
|
|
37
|
+
data: { source: collectionSourceToWire(authorized.installation, collection, current) },
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
if (ref.sourceAction === undefined && req.method === 'PATCH') {
|
|
41
|
+
const definitionReference = authorized.installation.definition.reference;
|
|
42
|
+
if (definitionReference.kind === 'private' &&
|
|
43
|
+
authorized.installation.scope.org !== definitionReference.publisherOrg) {
|
|
44
|
+
return sendJson(res, 409, {
|
|
45
|
+
error: 'cross-organization source account binding is unavailable',
|
|
46
|
+
code: 'source_cross_org_binding_unavailable',
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const body = await readJsonBody(req, deps.maxBody);
|
|
50
|
+
if (!body.ok)
|
|
51
|
+
return sendJson(res, body.status, { error: body.error });
|
|
52
|
+
const parsed = CollectionSourceConfigureRequestSchema.safeParse(body.value);
|
|
53
|
+
if (!parsed.success)
|
|
54
|
+
return invalid(res, parsed.error);
|
|
55
|
+
const expected = current?.revision ?? authorized.installation.revision;
|
|
56
|
+
if (parsed.data.expectedRevision !== expected) {
|
|
57
|
+
return sendJson(res, 409, {
|
|
58
|
+
error: 'source revision conflict',
|
|
59
|
+
code: 'revision_conflict',
|
|
60
|
+
currentRevision: expected,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
const bindingInput = {
|
|
64
|
+
...key,
|
|
65
|
+
bindingReference: parsed.data.binding.reference,
|
|
66
|
+
configurationReference: parsed.data.configurationReference,
|
|
67
|
+
generation: parsed.data.binding.generation,
|
|
68
|
+
schemaVersion: collection.schemaVersion,
|
|
69
|
+
schemaDigest: collection.schemaDigest.replace(/^sha256:/, ''),
|
|
70
|
+
queryFingerprint: createHash('sha256')
|
|
71
|
+
.update(parsed.data.binding.reference)
|
|
72
|
+
.update('\0')
|
|
73
|
+
.update(parsed.data.configurationReference)
|
|
74
|
+
.digest('hex'),
|
|
75
|
+
scan: {
|
|
76
|
+
connector: collection.authority.connectorId,
|
|
77
|
+
connectorVersion: collection.authority.connectorVersion,
|
|
78
|
+
operation: collection.authority.scanOperation,
|
|
79
|
+
signatureDigest: sourceOperationSignatureDigest(collection.authority.scanSignatureHash),
|
|
80
|
+
},
|
|
81
|
+
retentionDays: authorized.installation.retentionDays,
|
|
82
|
+
pollIntervalMs: 60_000,
|
|
83
|
+
};
|
|
84
|
+
let binding;
|
|
85
|
+
try {
|
|
86
|
+
if (current === undefined) {
|
|
87
|
+
if (parsed.data.replace === true) {
|
|
88
|
+
return sendJson(res, 404, { error: 'source is not configured' });
|
|
89
|
+
}
|
|
90
|
+
binding = await deps.sourceStore.createBinding(bindingInput);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
if (parsed.data.replace !== true) {
|
|
94
|
+
return sendJson(res, 409, {
|
|
95
|
+
error: 'source replacement requires explicit replace consent',
|
|
96
|
+
code: 'source_replacement_required',
|
|
97
|
+
currentRevision: current.revision,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
const replaced = await deps.sourceStore.replaceBinding({
|
|
101
|
+
...bindingInput,
|
|
102
|
+
expectedRevision: parsed.data.expectedRevision,
|
|
103
|
+
now: now(deps),
|
|
104
|
+
});
|
|
105
|
+
if (!replaced.ok)
|
|
106
|
+
return mutationFailure(res, replaced);
|
|
107
|
+
binding = replaced.binding;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
if (!isSourceConfigurationConflict(error))
|
|
112
|
+
throw error;
|
|
113
|
+
return sendJson(res, 409, {
|
|
114
|
+
error: 'source configuration conflict',
|
|
115
|
+
code: 'source_configuration_conflict',
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return sendJson(res, current === undefined ? 201 : 200, {
|
|
119
|
+
ok: true,
|
|
120
|
+
data: { source: collectionSourceToWire(authorized.installation, collection, binding) },
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
if ((ref.sourceAction === 'pause' || ref.sourceAction === 'resume') && req.method === 'POST') {
|
|
124
|
+
const body = await readJsonBody(req, deps.maxBody);
|
|
125
|
+
if (!body.ok)
|
|
126
|
+
return sendJson(res, body.status, { error: body.error });
|
|
127
|
+
const parsed = CollectionSourceRevisionRequestSchema.safeParse(body.value);
|
|
128
|
+
if (!parsed.success)
|
|
129
|
+
return invalid(res, parsed.error);
|
|
130
|
+
const result = await deps.sourceStore.setBindingState({
|
|
131
|
+
...key,
|
|
132
|
+
expectedRevision: parsed.data.expectedRevision,
|
|
133
|
+
state: ref.sourceAction === 'pause' ? 'paused' : 'active',
|
|
134
|
+
now: now(deps),
|
|
135
|
+
});
|
|
136
|
+
if (!result.ok)
|
|
137
|
+
return mutationFailure(res, result);
|
|
138
|
+
return sendJson(res, 200, {
|
|
139
|
+
ok: true,
|
|
140
|
+
data: {
|
|
141
|
+
source: collectionSourceToWire(authorized.installation, collection, result.binding),
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
if (ref.sourceAction === 'refresh' && req.method === 'POST') {
|
|
146
|
+
const body = await readJsonBody(req, deps.maxBody);
|
|
147
|
+
if (!body.ok)
|
|
148
|
+
return sendJson(res, body.status, { error: body.error });
|
|
149
|
+
const parsed = CollectionSourceRefreshRequestSchema.safeParse(body.value);
|
|
150
|
+
if (!parsed.success)
|
|
151
|
+
return invalid(res, parsed.error);
|
|
152
|
+
if (current === undefined)
|
|
153
|
+
return sendJson(res, 404, { error: 'source is not configured' });
|
|
154
|
+
const refresh = await deps.sourceStore.requestRefresh({
|
|
155
|
+
...key,
|
|
156
|
+
expectedRevision: parsed.data.expectedRevision,
|
|
157
|
+
idempotencyKey: parsed.data.idempotencyKey,
|
|
158
|
+
now: now(deps),
|
|
159
|
+
});
|
|
160
|
+
if (!refresh.ok)
|
|
161
|
+
return mutationFailure(res, refresh);
|
|
162
|
+
const runSourceIngestion = deps.runSourceIngestion;
|
|
163
|
+
if (runSourceIngestion !== undefined) {
|
|
164
|
+
res.once('finish', () => {
|
|
165
|
+
setImmediate(() => void runSourceIngestion().catch(() => undefined));
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
sendJson(res, 202, {
|
|
169
|
+
ok: true,
|
|
170
|
+
data: {
|
|
171
|
+
source: collectionSourceToWire(authorized.installation, collection, refresh.binding),
|
|
172
|
+
job: refresh.receipt,
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
return methodNotAllowed(res);
|
|
178
|
+
}
|
|
179
|
+
function isSourceConfigurationConflict(error) {
|
|
180
|
+
return (error instanceof Error &&
|
|
181
|
+
error.message === 'source binding already exists with different immutable configuration');
|
|
182
|
+
}
|
|
183
|
+
function sourceBindingKey(installation, collection) {
|
|
184
|
+
return {
|
|
185
|
+
scope: installation.scope,
|
|
186
|
+
collectionKey: collection.key,
|
|
187
|
+
id: collection.key,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
function collectionSourceToWire(installation, collection, binding) {
|
|
191
|
+
const common = {
|
|
192
|
+
installationId: installation.scope.installationId,
|
|
193
|
+
collection: collection.key,
|
|
194
|
+
authority: 'external',
|
|
195
|
+
};
|
|
196
|
+
if (binding === undefined) {
|
|
197
|
+
return { ...common, revision: installation.revision, state: 'unconfigured' };
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
...common,
|
|
201
|
+
revision: binding.revision,
|
|
202
|
+
state: binding.state === 'paused'
|
|
203
|
+
? 'paused'
|
|
204
|
+
: binding.health === 'failed' || binding.health === 'reauth_required'
|
|
205
|
+
? 'error'
|
|
206
|
+
: 'active',
|
|
207
|
+
binding: {
|
|
208
|
+
reference: binding.bindingReference ?? binding.id,
|
|
209
|
+
generation: binding.generation,
|
|
210
|
+
},
|
|
211
|
+
configurationReference: binding.configurationReference ?? binding.id,
|
|
212
|
+
enabled: true,
|
|
213
|
+
health: binding.health === 'initializing'
|
|
214
|
+
? 'pending'
|
|
215
|
+
: binding.health === 'current'
|
|
216
|
+
? 'healthy'
|
|
217
|
+
: binding.health === 'stale'
|
|
218
|
+
? 'degraded'
|
|
219
|
+
: binding.health === 'reauth_required'
|
|
220
|
+
? 'authorization_required'
|
|
221
|
+
: binding.health === 'paused'
|
|
222
|
+
? 'paused'
|
|
223
|
+
: 'unavailable',
|
|
224
|
+
completeness: binding.scanMode !== undefined
|
|
225
|
+
? 'rebuilding'
|
|
226
|
+
: binding.completeness === 'complete'
|
|
227
|
+
? 'complete'
|
|
228
|
+
: binding.lastSuccessfulSyncAt === undefined
|
|
229
|
+
? 'unknown'
|
|
230
|
+
: 'partial',
|
|
231
|
+
...(binding.lastSuccessfulSyncAt === undefined
|
|
232
|
+
? {}
|
|
233
|
+
: { lastCompletedSyncAt: binding.lastSuccessfulSyncAt }),
|
|
234
|
+
...(binding.nextAttemptAt === undefined ? {} : { nextRefreshAt: binding.nextAttemptAt }),
|
|
235
|
+
...(binding.errorCode === undefined
|
|
236
|
+
? {}
|
|
237
|
+
: {
|
|
238
|
+
error: {
|
|
239
|
+
code: binding.errorCode,
|
|
240
|
+
message: binding.errorCode === 'source_capacity_exceeded'
|
|
241
|
+
? new SourceCapacityError().message
|
|
242
|
+
: 'The external source could not be refreshed.',
|
|
243
|
+
retryable: binding.health !== 'reauth_required' &&
|
|
244
|
+
binding.errorCode !== 'source_capacity_exceeded',
|
|
245
|
+
},
|
|
246
|
+
}),
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=business-information-source.js.map
|