@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.
- package/dist/banner.d.ts +6 -0
- package/dist/banner.d.ts.map +1 -0
- package/dist/banner.js +29 -0
- package/dist/banner.js.map +1 -0
- 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/project-setup.d.ts.map +1 -1
- package/dist/commands/project-setup.js +2 -0
- package/dist/commands/project-setup.js.map +1 -1
- 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/first-run.d.ts.map +1 -1
- package/dist/first-run.js +2 -0
- package/dist/first-run.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/index.d.ts +1 -0
- package/node_modules/@noodle-borg/agent-kit/dist/index.js +1 -0
- package/node_modules/@noodle-borg/agent-kit/dist/plugin-bootstrap-skill.js +10 -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/dist/welcome-wordmark.d.ts +3 -0
- package/node_modules/@noodle-borg/agent-kit/dist/welcome-wordmark.js +10 -0
- 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/assistant-gateway/package.json +1 -1
- 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 +4 -1
- package/node_modules/@noodle-borg/control-plane/dist/deploy-gates.js +1 -0
- 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 +22 -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 +33 -234
- 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/node_modules/@noodleseed/assistant/package.json +1 -1
- package/package.json +2 -2
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto';
|
|
2
|
-
import { clientAddressBucket, } from '@noodle-borg/admission-limits/portable';
|
|
3
1
|
import { readJsonBody, sendJson } from '@noodle-borg/transport-http';
|
|
4
|
-
import { BusinessGrantCreateRequestSchema, formatWireError, ManagedRecordCreateRequestSchema, ManagedRecordMutationRequestSchema, ManagedRecordStatusSchema, SolutionInstallationCreateRequestSchema, } from '@noodle-borg/wire-contracts';
|
|
5
|
-
import {
|
|
2
|
+
import { BusinessGrantCreateRequestSchema, formatWireError, ManagedRecordCreateRequestSchema, ManagedRecordMutationRequestSchema, ManagedRecordStatusSchema, SolutionInstallationCreateRequestSchema, SolutionInstallationIntakeRequestSchema, } from '@noodle-borg/wire-contracts';
|
|
3
|
+
import { admitBusinessMutation, admitBusinessTarget, authorizeBusinessApi, } from '../business-api-admission.js';
|
|
4
|
+
import { BUILT_IN_SOLUTION_PROFILES, businessGrantAllows, MANAGED_SOLUTION_PROFILE_KEYS, PayloadValidationError, validateCollectionEnabled, } from '../business-information/portable.js';
|
|
6
5
|
import { sendForbidden } from '../http-util.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { loadExternalRecord, sendExternalRecordPage, sourceBindingKey, unsupportedExternalOperation, } from './business-information-external.js';
|
|
7
|
+
import { resolveInstallDefinition, stableInstallationId, } from './business-information-installation.js';
|
|
8
|
+
import { createNativeRecord } from './business-information-record-create.js';
|
|
9
|
+
import { cursorRequest, sendNativeRecordActivity } from './business-information-record-reads.js';
|
|
10
|
+
import { expectedRevision, mutationPermission, parseNativeRecordQuery, parseBusinessPaging as parsePaging, requestIdempotencyKey, } from './business-information-request.js';
|
|
11
|
+
import { collectionToWire, externalRecordToWire, grantToWire, installationToWire, profileToWire, recordDetailToWire, recordToWire, } from './business-information-wire.js';
|
|
9
12
|
import { canManageMembers } from './org-admin.js';
|
|
10
13
|
export function handleSolutionCatalog(req, res) {
|
|
11
14
|
if (req.method !== 'GET') {
|
|
@@ -14,7 +17,9 @@ export function handleSolutionCatalog(req, res) {
|
|
|
14
17
|
}
|
|
15
18
|
sendJson(res, 200, {
|
|
16
19
|
ok: true,
|
|
17
|
-
data: {
|
|
20
|
+
data: {
|
|
21
|
+
profiles: MANAGED_SOLUTION_PROFILE_KEYS.map((key) => profileToWire(BUILT_IN_SOLUTION_PROFILES[key])),
|
|
22
|
+
},
|
|
18
23
|
});
|
|
19
24
|
}
|
|
20
25
|
export async function handleSolutionInstallations(req, res, ref, deps) {
|
|
@@ -25,13 +30,21 @@ export async function handleSolutionInstallations(req, res, ref, deps) {
|
|
|
25
30
|
if (!(await canManageMembers(deps.controlPlane, ref.org, identity))) {
|
|
26
31
|
return sendForbidden(res, 'organization owner required');
|
|
27
32
|
}
|
|
33
|
+
if (!(await admitBusinessTarget(res, ref)))
|
|
34
|
+
return;
|
|
28
35
|
const body = await readJsonBody(req, deps.maxBody);
|
|
29
36
|
if (!body.ok)
|
|
30
37
|
return sendJson(res, body.status, { error: body.error });
|
|
31
38
|
const parsed = SolutionInstallationCreateRequestSchema.safeParse(body.value);
|
|
32
39
|
if (!parsed.success)
|
|
33
40
|
return invalid(res, parsed.error);
|
|
34
|
-
const
|
|
41
|
+
const definition = await resolveInstallDefinition(parsed.data.definition, ref.org, deps.resolvePrivateDefinition);
|
|
42
|
+
if (definition === undefined) {
|
|
43
|
+
return sendJson(res, 404, {
|
|
44
|
+
error: 'solution definition is unavailable',
|
|
45
|
+
code: 'definition_unavailable',
|
|
46
|
+
});
|
|
47
|
+
}
|
|
35
48
|
const installationId = stableInstallationId(ref.org, parsed.data.appSlug, parsed.data.environment);
|
|
36
49
|
const result = await deps.store.createInstallation({
|
|
37
50
|
scope: {
|
|
@@ -40,8 +53,10 @@ export async function handleSolutionInstallations(req, res, ref, deps) {
|
|
|
40
53
|
env: parsed.data.environment,
|
|
41
54
|
installationId,
|
|
42
55
|
},
|
|
43
|
-
|
|
44
|
-
|
|
56
|
+
...(parsed.data.definition.kind === 'managed'
|
|
57
|
+
? { profileKey: parsed.data.definition.profileId }
|
|
58
|
+
: { definition }),
|
|
59
|
+
managedCollections: definition.collections.map((collection) => collection.key),
|
|
45
60
|
retentionDays: parsed.data.retentionDays,
|
|
46
61
|
actorSubject: identity.subject,
|
|
47
62
|
actorEmail: identity.email,
|
|
@@ -56,10 +71,32 @@ export async function handleSolutionInstallations(req, res, ref, deps) {
|
|
|
56
71
|
if (grant === undefined || grant.revokedAt !== undefined) {
|
|
57
72
|
return sendForbidden(res, 'business grant required');
|
|
58
73
|
}
|
|
74
|
+
if (parsed.data.businessNotice &&
|
|
75
|
+
!(await deps.store.getBusinessNotice(result.installation.scope))) {
|
|
76
|
+
await deps.store.setBusinessNotice({
|
|
77
|
+
scope: result.installation.scope,
|
|
78
|
+
expectedRevision: 0,
|
|
79
|
+
notice: parsed.data.businessNotice,
|
|
80
|
+
actorSubject: identity.subject,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
const activated = await deps.activateInstallation?.({
|
|
84
|
+
installation: result.installation,
|
|
85
|
+
actor: identity,
|
|
86
|
+
});
|
|
87
|
+
if (activated === undefined || !activated.ok) {
|
|
88
|
+
return sendJson(res, activated?.status ?? 503, {
|
|
89
|
+
ok: false,
|
|
90
|
+
code: activated?.code ?? 'installation_activation_unavailable',
|
|
91
|
+
error: activated?.message ??
|
|
92
|
+
'The installation is saved, but application activation is unavailable. Retry installation when the service is ready.',
|
|
93
|
+
installationId: result.installation.scope.installationId,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
59
96
|
return sendJson(res, result.disposition === 'created' ? 201 : 200, {
|
|
60
97
|
ok: true,
|
|
61
98
|
data: {
|
|
62
|
-
installation: installationToWire(result.installation,
|
|
99
|
+
installation: installationToWire(result.installation, grant.role),
|
|
63
100
|
},
|
|
64
101
|
});
|
|
65
102
|
}
|
|
@@ -72,10 +109,12 @@ export async function handleSolutionInstallations(req, res, ref, deps) {
|
|
|
72
109
|
permitted.push({ installation, role: grant.role });
|
|
73
110
|
}
|
|
74
111
|
}
|
|
112
|
+
if (permitted.length > 0 && !(await admitBusinessTarget(res, ref)))
|
|
113
|
+
return;
|
|
75
114
|
return sendJson(res, 200, {
|
|
76
115
|
ok: true,
|
|
77
116
|
data: {
|
|
78
|
-
installations: permitted.map(({ installation, role }) => installationToWire(installation,
|
|
117
|
+
installations: permitted.map(({ installation, role }) => installationToWire(installation, role)),
|
|
79
118
|
},
|
|
80
119
|
});
|
|
81
120
|
}
|
|
@@ -86,10 +125,33 @@ export async function handleSolutionInstallations(req, res, ref, deps) {
|
|
|
86
125
|
return sendJson(res, 200, {
|
|
87
126
|
ok: true,
|
|
88
127
|
data: {
|
|
89
|
-
installation: installationToWire(authorized.installation,
|
|
128
|
+
installation: installationToWire(authorized.installation, authorized.grant.role),
|
|
90
129
|
},
|
|
91
130
|
});
|
|
92
131
|
}
|
|
132
|
+
if (req.method === 'PATCH' && ref.installationId !== undefined) {
|
|
133
|
+
const authorized = await requireInstallationPermission(res, ref, identity, 'installation:administer', deps);
|
|
134
|
+
if (authorized === undefined)
|
|
135
|
+
return;
|
|
136
|
+
const body = await readJsonBody(req, deps.maxBody);
|
|
137
|
+
if (!body.ok)
|
|
138
|
+
return sendJson(res, body.status, { error: body.error });
|
|
139
|
+
const parsed = SolutionInstallationIntakeRequestSchema.safeParse(body.value);
|
|
140
|
+
if (!parsed.success)
|
|
141
|
+
return invalid(res, parsed.error);
|
|
142
|
+
const result = await deps.store.setIntakeState({
|
|
143
|
+
scope: authorized.scope,
|
|
144
|
+
expectedRevision: parsed.data.expectedRevision,
|
|
145
|
+
active: parsed.data.active,
|
|
146
|
+
actorSubject: identity.subject,
|
|
147
|
+
});
|
|
148
|
+
if (!result.ok)
|
|
149
|
+
return mutationFailure(res, result);
|
|
150
|
+
return sendJson(res, 200, {
|
|
151
|
+
ok: true,
|
|
152
|
+
data: { installation: installationToWire(result.installation, authorized.grant.role) },
|
|
153
|
+
});
|
|
154
|
+
}
|
|
93
155
|
return methodNotAllowed(res);
|
|
94
156
|
}
|
|
95
157
|
export async function handleBusinessGrants(req, res, ref, deps) {
|
|
@@ -101,7 +163,7 @@ export async function handleBusinessGrants(req, res, ref, deps) {
|
|
|
101
163
|
return;
|
|
102
164
|
const { scope } = authorized.installation;
|
|
103
165
|
if (req.method === 'GET' && ref.subject === undefined) {
|
|
104
|
-
const grants =
|
|
166
|
+
const grants = await deps.store.listGrants(scope);
|
|
105
167
|
return sendJson(res, 200, { ok: true, data: { grants: grants.map(grantToWire) } });
|
|
106
168
|
}
|
|
107
169
|
if (req.method === 'POST' && ref.subject === undefined) {
|
|
@@ -157,23 +219,27 @@ export async function handleManagedRecords(req, res, url, ref, deps) {
|
|
|
157
219
|
const authorized = await requireInstallationPermission(res, ref, identity, 'records:read', deps);
|
|
158
220
|
if (authorized === undefined)
|
|
159
221
|
return;
|
|
160
|
-
|
|
222
|
+
const definition = enabledCollection(res, authorized.installation, collection);
|
|
223
|
+
if (definition === undefined)
|
|
161
224
|
return;
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
});
|
|
225
|
+
if (definition.authority.authority === 'external') {
|
|
226
|
+
return sendJson(res, 200, { ok: true, data: { activities: [] } });
|
|
227
|
+
}
|
|
228
|
+
return sendNativeRecordActivity(res, url, authorized.installation.scope, collection, ref.recordId, deps.store);
|
|
167
229
|
}
|
|
168
230
|
if (ref.action === 'export' && req.method === 'GET') {
|
|
169
231
|
const authorized = await requireInstallationPermission(res, ref, identity, 'records:export', deps);
|
|
170
232
|
if (authorized === undefined)
|
|
171
233
|
return;
|
|
172
|
-
|
|
234
|
+
const definition = enabledCollection(res, authorized.installation, collection);
|
|
235
|
+
if (definition === undefined)
|
|
173
236
|
return;
|
|
174
237
|
const paging = parsePaging(url, 500);
|
|
175
238
|
if (!paging.ok)
|
|
176
239
|
return sendJson(res, 400, { error: paging.error });
|
|
240
|
+
if (definition.authority.authority === 'external') {
|
|
241
|
+
return sendExternalRecordPage(res, authorized.installation, definition, { ...paging.value, limit: paging.value.limit ?? 500 }, deps);
|
|
242
|
+
}
|
|
177
243
|
const page = await cursorRequest(res, () => deps.store.exportRequests({
|
|
178
244
|
scope: authorized.installation.scope,
|
|
179
245
|
collectionKey: collection,
|
|
@@ -185,7 +251,10 @@ export async function handleManagedRecords(req, res, url, ref, deps) {
|
|
|
185
251
|
return sendJson(res, 200, {
|
|
186
252
|
ok: true,
|
|
187
253
|
data: {
|
|
188
|
-
records: page.records.map(
|
|
254
|
+
records: page.records.map((record) => ({
|
|
255
|
+
...recordToWire(record),
|
|
256
|
+
...(record.content ? { notes: record.content.notes } : {}),
|
|
257
|
+
})),
|
|
189
258
|
...(page.nextCursor === undefined ? {} : { nextCursor: page.nextCursor }),
|
|
190
259
|
},
|
|
191
260
|
});
|
|
@@ -194,11 +263,23 @@ export async function handleManagedRecords(req, res, url, ref, deps) {
|
|
|
194
263
|
const authorized = await requireInstallationPermission(res, ref, identity, 'records:read', deps);
|
|
195
264
|
if (authorized === undefined)
|
|
196
265
|
return;
|
|
197
|
-
|
|
266
|
+
const definition = enabledCollection(res, authorized.installation, collection);
|
|
267
|
+
if (definition === undefined)
|
|
198
268
|
return;
|
|
199
269
|
const paging = parsePaging(url, 100);
|
|
200
270
|
if (!paging.ok)
|
|
201
271
|
return sendJson(res, 400, { error: paging.error });
|
|
272
|
+
const query = parseNativeRecordQuery(url);
|
|
273
|
+
if (!query.ok)
|
|
274
|
+
return sendJson(res, 400, { error: query.error, code: 'invalid_query' });
|
|
275
|
+
if (definition.authority.authority === 'external') {
|
|
276
|
+
if (Object.keys(query.value).length > 0)
|
|
277
|
+
return sendJson(res, 400, {
|
|
278
|
+
error: 'Field and date queries currently require a native collection.',
|
|
279
|
+
code: 'invalid_query',
|
|
280
|
+
});
|
|
281
|
+
return sendExternalRecordPage(res, authorized.installation, definition, paging.value, deps);
|
|
282
|
+
}
|
|
202
283
|
const statusValue = url.searchParams.get('status');
|
|
203
284
|
const status = statusValue === null ? undefined : ManagedRecordStatusSchema.safeParse(statusValue);
|
|
204
285
|
if (status !== undefined && !status.success)
|
|
@@ -208,6 +289,7 @@ export async function handleManagedRecords(req, res, url, ref, deps) {
|
|
|
208
289
|
scope: authorized.installation.scope,
|
|
209
290
|
collectionKey: collection,
|
|
210
291
|
...paging.value,
|
|
292
|
+
...query.value,
|
|
211
293
|
...(status === undefined ? {} : { status: status.data }),
|
|
212
294
|
...(assigneeSubject === undefined ? {} : { assigneeSubject }),
|
|
213
295
|
includeDeleted: url.searchParams.get('includeDeleted') === 'true',
|
|
@@ -226,8 +308,12 @@ export async function handleManagedRecords(req, res, url, ref, deps) {
|
|
|
226
308
|
const authorized = await requireInstallationPermission(res, ref, identity, 'records:create', deps);
|
|
227
309
|
if (authorized === undefined)
|
|
228
310
|
return;
|
|
229
|
-
|
|
311
|
+
const definition = enabledCollection(res, authorized.installation, collection);
|
|
312
|
+
if (definition === undefined)
|
|
230
313
|
return;
|
|
314
|
+
if (definition.authority.authority === 'external') {
|
|
315
|
+
return unsupportedExternalOperation(res, 'create');
|
|
316
|
+
}
|
|
231
317
|
const idempotencyKey = requestIdempotencyKey(req);
|
|
232
318
|
if (idempotencyKey === undefined) {
|
|
233
319
|
return sendJson(res, 400, { error: 'Idempotency-Key header is required (1-128 characters)' });
|
|
@@ -238,19 +324,25 @@ export async function handleManagedRecords(req, res, url, ref, deps) {
|
|
|
238
324
|
const parsed = ManagedRecordCreateRequestSchema.safeParse(body.value);
|
|
239
325
|
if (!parsed.success)
|
|
240
326
|
return invalid(res, parsed.error);
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
const result = await deps.store.createRequest({
|
|
245
|
-
scope: authorized.installation.scope,
|
|
246
|
-
collectionKey: collection,
|
|
327
|
+
const result = await createNativeRecord(res, deps, {
|
|
328
|
+
installation: authorized.installation,
|
|
329
|
+
collection,
|
|
247
330
|
idempotencyKey,
|
|
248
|
-
payload,
|
|
331
|
+
payload: parsed.data.payload,
|
|
249
332
|
origin: { kind: 'portal' },
|
|
250
333
|
actorSubject: identity.subject,
|
|
334
|
+
admit: () => admitBusinessMutation(res, authorized.scope),
|
|
251
335
|
});
|
|
336
|
+
if (result === undefined)
|
|
337
|
+
return;
|
|
252
338
|
if (result.disposition === 'conflict')
|
|
253
339
|
return idempotencyConflict(res);
|
|
340
|
+
if (result.disposition === 'paused') {
|
|
341
|
+
return sendJson(res, 503, {
|
|
342
|
+
error: 'Record creation requires an active application.',
|
|
343
|
+
code: 'application_unavailable',
|
|
344
|
+
});
|
|
345
|
+
}
|
|
254
346
|
return sendJson(res, result.disposition === 'created' ? 201 : 200, {
|
|
255
347
|
ok: true,
|
|
256
348
|
data: { record: recordToWire(result.record) },
|
|
@@ -260,12 +352,30 @@ export async function handleManagedRecords(req, res, url, ref, deps) {
|
|
|
260
352
|
const authorized = await requireInstallationPermission(res, ref, identity, 'records:read', deps);
|
|
261
353
|
if (authorized === undefined)
|
|
262
354
|
return;
|
|
263
|
-
|
|
355
|
+
const definition = enabledCollection(res, authorized.installation, collection);
|
|
356
|
+
if (definition === undefined)
|
|
264
357
|
return;
|
|
358
|
+
if (definition.authority.authority === 'external') {
|
|
359
|
+
const loaded = await loadExternalRecord(authorized.installation, definition, ref.recordId, deps);
|
|
360
|
+
if (loaded === undefined)
|
|
361
|
+
return sendJson(res, 503, { error: 'collection source unavailable' });
|
|
362
|
+
if (loaded.record === undefined)
|
|
363
|
+
return sendJson(res, 404, { error: 'record not found' });
|
|
364
|
+
return sendJson(res, 200, {
|
|
365
|
+
ok: true,
|
|
366
|
+
data: {
|
|
367
|
+
record: externalRecordToWire(loaded.record, loaded.binding),
|
|
368
|
+
collection: collectionToWire(definition),
|
|
369
|
+
},
|
|
370
|
+
});
|
|
371
|
+
}
|
|
265
372
|
const record = await deps.store.getRequest(authorized.installation.scope, collection, ref.recordId);
|
|
266
373
|
if (record === undefined)
|
|
267
374
|
return sendJson(res, 404, { error: 'record not found' });
|
|
268
|
-
return sendJson(res, 200, {
|
|
375
|
+
return sendJson(res, 200, {
|
|
376
|
+
ok: true,
|
|
377
|
+
data: recordDetailToWire(authorized.installation, record),
|
|
378
|
+
});
|
|
269
379
|
}
|
|
270
380
|
if (ref.recordId !== undefined && req.method === 'PATCH') {
|
|
271
381
|
const body = await readJsonBody(req, deps.maxBody);
|
|
@@ -278,20 +388,31 @@ export async function handleManagedRecords(req, res, url, ref, deps) {
|
|
|
278
388
|
const authorized = await requireInstallationPermission(res, ref, identity, permission, deps);
|
|
279
389
|
if (authorized === undefined)
|
|
280
390
|
return;
|
|
281
|
-
|
|
391
|
+
const definition = enabledCollection(res, authorized.installation, collection);
|
|
392
|
+
if (definition === undefined)
|
|
282
393
|
return;
|
|
394
|
+
if (definition.authority.authority === 'external') {
|
|
395
|
+
return unsupportedExternalOperation(res, parsed.data.operation);
|
|
396
|
+
}
|
|
397
|
+
if (parsed.data.operation === 'migrate-schema') {
|
|
398
|
+
const result = await deps.store.migrateLegacyRequest({
|
|
399
|
+
scope: authorized.installation.scope,
|
|
400
|
+
collectionKey: collection,
|
|
401
|
+
id: ref.recordId,
|
|
402
|
+
expectedRevision: parsed.data.expectedRevision,
|
|
403
|
+
actorSubject: identity.subject,
|
|
404
|
+
});
|
|
405
|
+
if (!result.ok)
|
|
406
|
+
return mutationFailure(res, result);
|
|
407
|
+
return sendJson(res, 200, { ok: true, data: { record: recordToWire(result.record) } });
|
|
408
|
+
}
|
|
283
409
|
let operation;
|
|
284
410
|
if (parsed.data.operation === 'update') {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
...parsed.data.patch,
|
|
291
|
-
});
|
|
292
|
-
if (payload === undefined)
|
|
293
|
-
return;
|
|
294
|
-
operation = { kind: 'update', payload };
|
|
411
|
+
operation = {
|
|
412
|
+
kind: 'update',
|
|
413
|
+
payload: parsed.data.patch,
|
|
414
|
+
...(parsed.data.unset ? { unset: parsed.data.unset } : {}),
|
|
415
|
+
};
|
|
295
416
|
}
|
|
296
417
|
else if (parsed.data.operation === 'assign') {
|
|
297
418
|
if (parsed.data.assigneeSubject !== null) {
|
|
@@ -316,14 +437,23 @@ export async function handleManagedRecords(req, res, url, ref, deps) {
|
|
|
316
437
|
else {
|
|
317
438
|
operation = { kind: 'add_note', note: parsed.data.note };
|
|
318
439
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
440
|
+
let result;
|
|
441
|
+
try {
|
|
442
|
+
result = await deps.store.mutateRequest({
|
|
443
|
+
scope: authorized.installation.scope,
|
|
444
|
+
collectionKey: collection,
|
|
445
|
+
id: ref.recordId,
|
|
446
|
+
expectedRevision: parsed.data.expectedRevision,
|
|
447
|
+
actorSubject: identity.subject,
|
|
448
|
+
operation,
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
catch (error) {
|
|
452
|
+
if (error instanceof PayloadValidationError) {
|
|
453
|
+
return sendJson(res, 400, { error: error.message, code: error.code });
|
|
454
|
+
}
|
|
455
|
+
throw error;
|
|
456
|
+
}
|
|
327
457
|
if (!result.ok)
|
|
328
458
|
return mutationFailure(res, result);
|
|
329
459
|
return sendJson(res, 200, { ok: true, data: { record: recordToWire(result.record) } });
|
|
@@ -332,7 +462,8 @@ export async function handleManagedRecords(req, res, url, ref, deps) {
|
|
|
332
462
|
const authorized = await requireInstallationPermission(res, ref, identity, 'records:delete', deps);
|
|
333
463
|
if (authorized === undefined)
|
|
334
464
|
return;
|
|
335
|
-
|
|
465
|
+
const definition = enabledCollection(res, authorized.installation, collection);
|
|
466
|
+
if (definition === undefined)
|
|
336
467
|
return;
|
|
337
468
|
const body = await readJsonBody(req, deps.maxBody);
|
|
338
469
|
if (!body.ok)
|
|
@@ -341,6 +472,37 @@ export async function handleManagedRecords(req, res, url, ref, deps) {
|
|
|
341
472
|
if (revision === undefined) {
|
|
342
473
|
return sendJson(res, 400, { error: 'expectedRevision must be a positive integer' });
|
|
343
474
|
}
|
|
475
|
+
if (definition.authority.authority === 'external') {
|
|
476
|
+
const loaded = await loadExternalRecord(authorized.installation, definition, ref.recordId, deps);
|
|
477
|
+
if (loaded === undefined)
|
|
478
|
+
return sendJson(res, 503, { error: 'collection source unavailable' });
|
|
479
|
+
if (loaded.record === undefined)
|
|
480
|
+
return sendJson(res, 404, { error: 'record not found' });
|
|
481
|
+
const { record } = loaded;
|
|
482
|
+
if (record.revision !== revision) {
|
|
483
|
+
return sendJson(res, 409, {
|
|
484
|
+
error: 'record revision conflict',
|
|
485
|
+
code: 'revision_conflict',
|
|
486
|
+
currentRevision: record.revision,
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
await deps.sourceStore?.suppressExternalRecord({
|
|
490
|
+
...sourceBindingKey(authorized.installation, definition),
|
|
491
|
+
sourceId: record.source.id,
|
|
492
|
+
reason: 'customer_request',
|
|
493
|
+
now: now(deps),
|
|
494
|
+
});
|
|
495
|
+
const deletedAt = now(deps).toISOString();
|
|
496
|
+
return sendJson(res, 200, {
|
|
497
|
+
ok: true,
|
|
498
|
+
data: {
|
|
499
|
+
recordId: record.id,
|
|
500
|
+
authority: 'external',
|
|
501
|
+
disposition: 'suppressed',
|
|
502
|
+
deletedAt,
|
|
503
|
+
},
|
|
504
|
+
});
|
|
505
|
+
}
|
|
344
506
|
const result = await deps.store.deleteRequest({
|
|
345
507
|
scope: authorized.installation.scope,
|
|
346
508
|
collectionKey: collection,
|
|
@@ -351,72 +513,22 @@ export async function handleManagedRecords(req, res, url, ref, deps) {
|
|
|
351
513
|
});
|
|
352
514
|
if (!result.ok)
|
|
353
515
|
return mutationFailure(res, result);
|
|
354
|
-
return sendJson(res, 200, {
|
|
355
|
-
ok: true,
|
|
356
|
-
data: { recordId: result.record.id, deletedAt: result.record.deletedAt },
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
return methodNotAllowed(res);
|
|
360
|
-
}
|
|
361
|
-
export async function handlePublicSolutionIntake(req, res, ref, deps) {
|
|
362
|
-
const installation = await deps.store.resolveInstallationByPublicId(ref.publicId);
|
|
363
|
-
if (installation === undefined)
|
|
364
|
-
return sendJson(res, 404, { error: 'solution not found' });
|
|
365
|
-
const profile = BUILT_IN_SOLUTION_PROFILES[installation.profileKey];
|
|
366
|
-
if (req.method === 'GET' && ref.collection === undefined) {
|
|
367
|
-
const wire = profileToWire(profile);
|
|
368
516
|
return sendJson(res, 200, {
|
|
369
517
|
ok: true,
|
|
370
518
|
data: {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
519
|
+
recordId: result.record.id,
|
|
520
|
+
authority: 'native',
|
|
521
|
+
disposition: 'deleted',
|
|
522
|
+
deletedAt: result.record.deletedAt,
|
|
375
523
|
},
|
|
376
524
|
});
|
|
377
525
|
}
|
|
378
|
-
if (req.method === 'POST' && ref.collection !== undefined) {
|
|
379
|
-
if (!collectionEnabled(res, installation, ref.collection))
|
|
380
|
-
return;
|
|
381
|
-
const quota = await consumePublicIntakeQuota(req, ref.publicId, deps);
|
|
382
|
-
if (!quota.allowed) {
|
|
383
|
-
res.setHeader('retry-after', String(Math.max(1, Math.ceil((quota.resetAt.getTime() - now(deps).getTime()) / 1000))));
|
|
384
|
-
return sendJson(res, 429, { error: 'public intake limit exceeded', code: 'quota_exceeded' });
|
|
385
|
-
}
|
|
386
|
-
const idempotencyKey = requestIdempotencyKey(req);
|
|
387
|
-
if (idempotencyKey === undefined) {
|
|
388
|
-
return sendJson(res, 400, { error: 'Idempotency-Key header is required (1-128 characters)' });
|
|
389
|
-
}
|
|
390
|
-
const body = await readJsonBody(req, deps.maxBody);
|
|
391
|
-
if (!body.ok)
|
|
392
|
-
return sendJson(res, body.status, { error: body.error });
|
|
393
|
-
const parsed = ManagedRecordCreateRequestSchema.safeParse(body.value);
|
|
394
|
-
if (!parsed.success)
|
|
395
|
-
return invalid(res, parsed.error);
|
|
396
|
-
const payload = profilePayload(res, installation, ref.collection, parsed.data.payload);
|
|
397
|
-
if (payload === undefined)
|
|
398
|
-
return;
|
|
399
|
-
const result = await deps.store.createRequest({
|
|
400
|
-
scope: installation.scope,
|
|
401
|
-
collectionKey: ref.collection,
|
|
402
|
-
idempotencyKey,
|
|
403
|
-
payload,
|
|
404
|
-
origin: { kind: 'embedded', reference: 'public-intake' },
|
|
405
|
-
actorSubject: 'anonymous',
|
|
406
|
-
});
|
|
407
|
-
if (result.disposition === 'conflict')
|
|
408
|
-
return idempotencyConflict(res);
|
|
409
|
-
return sendJson(res, result.disposition === 'created' ? 201 : 200, {
|
|
410
|
-
ok: true,
|
|
411
|
-
data: { recordId: result.record.id, receivedAt: result.record.createdAt },
|
|
412
|
-
});
|
|
413
|
-
}
|
|
414
526
|
return methodNotAllowed(res);
|
|
415
527
|
}
|
|
416
|
-
async function requireIdentity(req, res, deps) {
|
|
417
|
-
return
|
|
528
|
+
export async function requireIdentity(req, res, deps) {
|
|
529
|
+
return authorizeBusinessApi(req, res, deps);
|
|
418
530
|
}
|
|
419
|
-
async function requireInstallationGrant(res, ref, identity, deps) {
|
|
531
|
+
export async function requireInstallationGrant(res, ref, identity, deps, permission) {
|
|
420
532
|
if (ref.installationId === undefined)
|
|
421
533
|
return undefined;
|
|
422
534
|
const installation = await deps.store.getInstallationById(ref.org, ref.installationId);
|
|
@@ -429,59 +541,21 @@ async function requireInstallationGrant(res, ref, identity, deps) {
|
|
|
429
541
|
sendForbidden(res, 'business grant required');
|
|
430
542
|
return undefined;
|
|
431
543
|
}
|
|
432
|
-
|
|
433
|
-
}
|
|
434
|
-
async function requireInstallationPermission(res, ref, identity, permission, deps) {
|
|
435
|
-
const authorized = await requireInstallationGrant(res, ref, identity, deps);
|
|
436
|
-
if (authorized === undefined)
|
|
437
|
-
return undefined;
|
|
438
|
-
if (!businessGrantAllows(authorized.grant, permission)) {
|
|
544
|
+
if (permission && !businessGrantAllows(grant, permission)) {
|
|
439
545
|
sendForbidden(res, `business permission required: ${permission}`);
|
|
440
546
|
return undefined;
|
|
441
547
|
}
|
|
442
|
-
|
|
443
|
-
}
|
|
444
|
-
function stableInstallationId(org, app, env) {
|
|
445
|
-
return `ins-${createHash('sha256').update(`${org}\0${app}\0${env}`).digest('hex').slice(0, 24)}`;
|
|
446
|
-
}
|
|
447
|
-
function requestIdempotencyKey(req) {
|
|
448
|
-
const value = req.headers['idempotency-key'];
|
|
449
|
-
if (typeof value !== 'string' || value.length < 1 || value.length > 128)
|
|
548
|
+
if (!(await admitBusinessTarget(res, installation.scope)))
|
|
450
549
|
return undefined;
|
|
451
|
-
return
|
|
452
|
-
}
|
|
453
|
-
function expectedRevision(value) {
|
|
454
|
-
if (value === null || typeof value !== 'object')
|
|
455
|
-
return undefined;
|
|
456
|
-
const revision = value.expectedRevision;
|
|
457
|
-
return typeof revision === 'number' && Number.isInteger(revision) && revision > 0
|
|
458
|
-
? revision
|
|
459
|
-
: undefined;
|
|
460
|
-
}
|
|
461
|
-
function parsePaging(url, maximum) {
|
|
462
|
-
const cursor = url.searchParams.get('cursor') ?? undefined;
|
|
463
|
-
const rawLimit = url.searchParams.get('limit');
|
|
464
|
-
if (rawLimit === null)
|
|
465
|
-
return { ok: true, value: cursor === undefined ? {} : { cursor } };
|
|
466
|
-
const limit = Number(rawLimit);
|
|
467
|
-
if (!Number.isInteger(limit) || limit < 1 || limit > maximum) {
|
|
468
|
-
return { ok: false, error: `limit must be an integer from 1 to ${maximum}` };
|
|
469
|
-
}
|
|
470
|
-
return { ok: true, value: { ...(cursor === undefined ? {} : { cursor }), limit } };
|
|
550
|
+
return { installation, scope: installation.scope, grant };
|
|
471
551
|
}
|
|
472
|
-
function
|
|
473
|
-
|
|
474
|
-
return 'records:assign';
|
|
475
|
-
if (operation === 'set-status')
|
|
476
|
-
return 'records:status';
|
|
477
|
-
if (operation === 'add-note')
|
|
478
|
-
return 'records:note';
|
|
479
|
-
return 'records:update';
|
|
552
|
+
export async function requireInstallationPermission(res, ref, identity, permission, deps) {
|
|
553
|
+
return requireInstallationGrant(res, ref, identity, deps, permission);
|
|
480
554
|
}
|
|
481
|
-
function mutationFailure(res, result) {
|
|
555
|
+
export function mutationFailure(res, result) {
|
|
482
556
|
const status = result.reason === 'not_found'
|
|
483
557
|
? 404
|
|
484
|
-
:
|
|
558
|
+
: ['conflict', 'last_administrator', 'application_unavailable'].includes(result.reason)
|
|
485
559
|
? 409
|
|
486
560
|
: 422;
|
|
487
561
|
sendJson(res, status, {
|
|
@@ -490,62 +564,29 @@ function mutationFailure(res, result) {
|
|
|
490
564
|
currentRevision: result.currentRevision,
|
|
491
565
|
});
|
|
492
566
|
}
|
|
493
|
-
function
|
|
494
|
-
if (installation.managedCollections.includes(collection))
|
|
495
|
-
return true;
|
|
496
|
-
sendJson(res, 404, { error: 'collection not found' });
|
|
497
|
-
return false;
|
|
498
|
-
}
|
|
499
|
-
function profilePayload(res, installation, collection, value) {
|
|
500
|
-
try {
|
|
501
|
-
return validateProfilePayload(installation.profileKey, collection, value);
|
|
502
|
-
}
|
|
503
|
-
catch (error) {
|
|
504
|
-
if (!(error instanceof PayloadValidationError))
|
|
505
|
-
throw error;
|
|
506
|
-
sendJson(res, 400, { error: error.message, code: error.code });
|
|
507
|
-
return undefined;
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
async function cursorRequest(res, request) {
|
|
567
|
+
export function enabledCollection(res, installation, collection) {
|
|
511
568
|
try {
|
|
512
|
-
return
|
|
569
|
+
return validateCollectionEnabled(installation, collection);
|
|
513
570
|
}
|
|
514
|
-
catch
|
|
515
|
-
|
|
516
|
-
throw error;
|
|
517
|
-
sendJson(res, 400, { error: 'cursor is invalid', code: 'invalid_cursor' });
|
|
571
|
+
catch {
|
|
572
|
+
sendJson(res, 404, { error: 'collection not found' });
|
|
518
573
|
return undefined;
|
|
519
574
|
}
|
|
520
575
|
}
|
|
521
|
-
|
|
522
|
-
const timestamp = now(deps);
|
|
523
|
-
const address = deps.trustProxy
|
|
524
|
-
? typeof req.headers['x-forwarded-for'] === 'string'
|
|
525
|
-
? req.headers['x-forwarded-for']
|
|
526
|
-
: undefined
|
|
527
|
-
: req.socket.remoteAddress;
|
|
528
|
-
const bucket = clientAddressBucket(address);
|
|
529
|
-
if (bucket !== undefined) {
|
|
530
|
-
const addressOutcome = await deps.publicCounters.consume({ key: `solution-intake:address:${publicId}:${bucket}`, limit: 60, window: 'hour' }, timestamp);
|
|
531
|
-
if (!addressOutcome.allowed)
|
|
532
|
-
return addressOutcome;
|
|
533
|
-
}
|
|
534
|
-
return deps.publicCounters.consume({ key: `solution-intake:surface:${publicId}`, limit: 10_000, window: 'day' }, timestamp);
|
|
535
|
-
}
|
|
536
|
-
function now(deps) {
|
|
576
|
+
export function now(deps) {
|
|
537
577
|
return deps.now?.() ?? new Date();
|
|
538
578
|
}
|
|
539
|
-
function invalid(res, error) {
|
|
579
|
+
export function invalid(res, error) {
|
|
540
580
|
sendJson(res, 400, { error: formatWireError(error) });
|
|
541
581
|
}
|
|
542
|
-
function idempotencyConflict(res) {
|
|
582
|
+
export function idempotencyConflict(res) {
|
|
543
583
|
sendJson(res, 409, {
|
|
544
584
|
error: 'the idempotency key was already used with different content',
|
|
545
585
|
code: 'idempotency_conflict',
|
|
546
586
|
});
|
|
547
587
|
}
|
|
548
|
-
function methodNotAllowed(res) {
|
|
588
|
+
export function methodNotAllowed(res) {
|
|
549
589
|
sendJson(res, 405, { error: 'method not allowed' });
|
|
550
590
|
}
|
|
591
|
+
export { createNativeRecord } from './business-information-record-create.js';
|
|
551
592
|
//# sourceMappingURL=business-information.js.map
|
|
@@ -25,7 +25,7 @@ export function dispatchConfigValueRequest(req, res, url, deps) {
|
|
|
25
25
|
deps.applySecurityHeaders(res, deps.tls);
|
|
26
26
|
if (deps.enforceHttps(req, res, deps.tls))
|
|
27
27
|
return true;
|
|
28
|
-
handleConfigValues(req, res, deps.gate, deps.controlPlane, deps.configStore, deps.registry, deps.maxBody, ref, deps.audit, deps.developerGrants).catch(() => {
|
|
28
|
+
handleConfigValues(req, res, deps.gate, deps.controlPlane, deps.configStore, deps.registry, deps.maxBody, ref, deps.audit, deps.developerGrants, deps.installations).catch(() => {
|
|
29
29
|
if (!res.headersSent)
|
|
30
30
|
deps.sendJson(res, 500, { error: 'internal error' });
|
|
31
31
|
});
|