@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,6 +1,9 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { projectManagedCollectionControls, validateJsonSchema, validateManagedCollectionControls, } from '@noodle-borg/compiler';
|
|
3
|
+
import { collectionControlEnabled, creationPayload, patchedPayload, } from './collection-controls.js';
|
|
4
|
+
import { collectionForStoredRecord, resolveManagedInstallation, } from './managed-releases.js';
|
|
5
|
+
import { builtInDefinition } from './profiles.js';
|
|
6
|
+
import { PayloadValidationError, validateEmail, validateManagedPayload, validateRetentionDays, validateRevision, validateScalar, validateScope, } from './validation.js';
|
|
4
7
|
const ROLE_PERMISSIONS = {
|
|
5
8
|
administrator: [
|
|
6
9
|
'installation:administer',
|
|
@@ -46,16 +49,30 @@ export function businessGrantAllows(grant, permission) {
|
|
|
46
49
|
}
|
|
47
50
|
export function normalizeInstallationInput(input) {
|
|
48
51
|
const scope = { ...validateScope(input.scope) };
|
|
49
|
-
|
|
52
|
+
if ((input.profileKey === undefined) === (input.definition === undefined)) {
|
|
53
|
+
throw new Error('installation requires exactly one managed profile or private definition');
|
|
54
|
+
}
|
|
55
|
+
const definition = input.definition ??
|
|
56
|
+
builtInDefinition(input.profileKey);
|
|
57
|
+
validateDefinition(definition);
|
|
50
58
|
const managedCollections = [...new Set(input.managedCollections)].sort();
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
59
|
+
for (const collectionKey of managedCollections) {
|
|
60
|
+
if (!definition.collections.some((collection) => collection.key === collectionKey)) {
|
|
61
|
+
throw new Error(`collection "${collectionKey}" is not declared by the installed definition`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const profileKey = input.profileKey ??
|
|
65
|
+
(definition.reference.kind === 'private'
|
|
66
|
+
? definition.reference.app
|
|
67
|
+
: definition.reference.definitionId);
|
|
68
|
+
const profileVersion = definition.reference.kind === 'private'
|
|
69
|
+
? parseDefinitionVersion(definition.reference.version)
|
|
70
|
+
: definition.reference.release;
|
|
55
71
|
return {
|
|
56
72
|
scope,
|
|
57
|
-
profileKey
|
|
58
|
-
profileVersion
|
|
73
|
+
profileKey,
|
|
74
|
+
profileVersion,
|
|
75
|
+
definition: structuredClone(definition),
|
|
59
76
|
managedCollections,
|
|
60
77
|
retentionDays: validateRetentionDays(input.retentionDays),
|
|
61
78
|
actorSubject: validateScalar('actor subject', input.actorSubject, 256),
|
|
@@ -63,16 +80,32 @@ export function normalizeInstallationInput(input) {
|
|
|
63
80
|
};
|
|
64
81
|
}
|
|
65
82
|
export function installationFingerprint(input) {
|
|
83
|
+
const definitionIntent = input.definition.reference.kind === 'managed'
|
|
84
|
+
? { managedDefinitionId: input.definition.reference.definitionId }
|
|
85
|
+
: { profileVersion: input.profileVersion, definition: input.definition };
|
|
66
86
|
return digest({
|
|
67
87
|
scope: input.scope,
|
|
68
88
|
profileKey: input.profileKey,
|
|
69
|
-
|
|
89
|
+
...definitionIntent,
|
|
70
90
|
managedCollections: input.managedCollections,
|
|
71
91
|
retentionDays: input.retentionDays,
|
|
72
92
|
actorSubject: input.actorSubject,
|
|
73
|
-
actorEmail: input.actorEmail,
|
|
93
|
+
...(input.definition.reference.kind === 'managed' ? {} : { actorEmail: input.actorEmail }),
|
|
74
94
|
});
|
|
75
95
|
}
|
|
96
|
+
/** Compatibility for rows whose pre-update fingerprint included the resolved managed release. */
|
|
97
|
+
export function managedInstallationIntentMatches(existing, input) {
|
|
98
|
+
const existingReference = existing.definition.reference;
|
|
99
|
+
const inputReference = input.definition.reference;
|
|
100
|
+
return (existingReference.kind === 'managed' &&
|
|
101
|
+
inputReference.kind === 'managed' &&
|
|
102
|
+
existingReference.definitionId === inputReference.definitionId &&
|
|
103
|
+
digest(existing.scope) === digest(input.scope) &&
|
|
104
|
+
existing.profileKey === input.profileKey &&
|
|
105
|
+
digest([...existing.managedCollections].sort()) === digest(input.managedCollections) &&
|
|
106
|
+
existing.retentionDays === input.retentionDays &&
|
|
107
|
+
existing.createdBySubject === input.actorSubject);
|
|
108
|
+
}
|
|
76
109
|
export function requestFingerprint(input) {
|
|
77
110
|
return digest(input);
|
|
78
111
|
}
|
|
@@ -84,23 +117,29 @@ export function validateCollectionEnabled(installation, collectionKey) {
|
|
|
84
117
|
if (!installation.managedCollections.includes(normalized)) {
|
|
85
118
|
throw new Error(`managed collection "${normalized}" is not enabled for this installation`);
|
|
86
119
|
}
|
|
87
|
-
|
|
120
|
+
const collection = installation.definition.collections.find((candidate) => candidate.key === normalized);
|
|
121
|
+
if (collection === undefined)
|
|
122
|
+
throw new Error(`managed collection "${normalized}" is missing from the installed definition`);
|
|
123
|
+
return collection;
|
|
88
124
|
}
|
|
89
125
|
export function initialRecord(input) {
|
|
90
|
-
const
|
|
91
|
-
|
|
126
|
+
const collection = validateCollectionEnabled(input.installation, input.collectionKey);
|
|
127
|
+
if (collection.authority.authority !== 'native') {
|
|
128
|
+
throw new Error(`managed collection "${collection.key}" is externally authoritative and read-only`);
|
|
129
|
+
}
|
|
130
|
+
const payload = creationPayload(collection, input.payload, input.publicInput === true || input.origin.kind === 'embedded');
|
|
92
131
|
const actor = validateScalar('actor subject', input.actorSubject, 256);
|
|
93
132
|
const id = validateScalar('record id', input.id, 128);
|
|
94
133
|
const createdAt = input.now.toISOString();
|
|
95
134
|
return {
|
|
96
135
|
scope: { ...input.installation.scope },
|
|
97
|
-
collectionKey:
|
|
136
|
+
collectionKey: collection.key,
|
|
98
137
|
id,
|
|
99
138
|
profileKey: input.installation.profileKey,
|
|
100
139
|
profileVersion: input.installation.profileVersion,
|
|
101
|
-
schemaVersion:
|
|
102
|
-
schemaDigest:
|
|
103
|
-
status: 'new',
|
|
140
|
+
schemaVersion: collection.schemaVersion,
|
|
141
|
+
schemaDigest: collection.schemaDigest,
|
|
142
|
+
...(collection.behavior?.kind === 'request' ? { status: 'new' } : {}),
|
|
104
143
|
origin: normalizeOrigin(input.origin),
|
|
105
144
|
revision: 1,
|
|
106
145
|
retentionExpiresAt: new Date(input.now.getTime() + input.installation.retentionDays * 24 * 60 * 60 * 1000).toISOString(),
|
|
@@ -111,14 +150,16 @@ export function initialRecord(input) {
|
|
|
111
150
|
content: { payload, notes: [] },
|
|
112
151
|
};
|
|
113
152
|
}
|
|
114
|
-
export function applyRequestOperation(current, operation, actorSubject, now, noteId) {
|
|
153
|
+
export function applyRequestOperation(current, collection, operation, actorSubject, now, noteId) {
|
|
115
154
|
if (current.deletedAt !== undefined || current.content === undefined)
|
|
116
155
|
return undefined;
|
|
156
|
+
if (collection.authority.authority !== 'native')
|
|
157
|
+
return undefined;
|
|
117
158
|
const actor = validateScalar('actor subject', actorSubject, 256);
|
|
118
159
|
const revision = current.revision + 1;
|
|
119
160
|
const updatedAt = now.toISOString();
|
|
120
161
|
if (operation.kind === 'update') {
|
|
121
|
-
const payload =
|
|
162
|
+
const payload = validateCollectionPayload(collection, patchedPayload(collection, current.content.payload, operation.payload, operation.unset));
|
|
122
163
|
return {
|
|
123
164
|
record: cloneRecord({
|
|
124
165
|
...current,
|
|
@@ -131,6 +172,8 @@ export function applyRequestOperation(current, operation, actorSubject, now, not
|
|
|
131
172
|
};
|
|
132
173
|
}
|
|
133
174
|
if (operation.kind === 'assign') {
|
|
175
|
+
if (!collectionControlEnabled(collection, 'assignment'))
|
|
176
|
+
return undefined;
|
|
134
177
|
const assignee = operation.assigneeSubject === undefined
|
|
135
178
|
? undefined
|
|
136
179
|
: validateScalar('assignee subject', operation.assigneeSubject, 256);
|
|
@@ -148,6 +191,8 @@ export function applyRequestOperation(current, operation, actorSubject, now, not
|
|
|
148
191
|
};
|
|
149
192
|
}
|
|
150
193
|
if (operation.kind === 'set_status') {
|
|
194
|
+
if (collection.behavior?.kind !== 'request' || current.status === undefined)
|
|
195
|
+
return undefined;
|
|
151
196
|
if (!validStatusTransition(current.status, operation.status))
|
|
152
197
|
return undefined;
|
|
153
198
|
return {
|
|
@@ -161,9 +206,11 @@ export function applyRequestOperation(current, operation, actorSubject, now, not
|
|
|
161
206
|
activityKind: 'status_changed',
|
|
162
207
|
};
|
|
163
208
|
}
|
|
209
|
+
if (!collectionControlEnabled(collection, 'notes'))
|
|
210
|
+
return undefined;
|
|
164
211
|
const note = validateNote(operation.note);
|
|
165
212
|
if (current.content.notes.length >= 50)
|
|
166
|
-
throw new
|
|
213
|
+
throw new PayloadValidationError('array_too_large', 'A record cannot have more than 50 notes.');
|
|
167
214
|
return {
|
|
168
215
|
record: cloneRecord({
|
|
169
216
|
...current,
|
|
@@ -186,6 +233,12 @@ export function applyRequestOperation(current, operation, actorSubject, now, not
|
|
|
186
233
|
activityKind: 'note_added',
|
|
187
234
|
};
|
|
188
235
|
}
|
|
236
|
+
export function validateStoredRecord(installation, record) {
|
|
237
|
+
const collection = collectionForStoredRecord(installation, record);
|
|
238
|
+
if (record.content !== undefined)
|
|
239
|
+
validateCollectionPayload(collection, record.content.payload);
|
|
240
|
+
return collection;
|
|
241
|
+
}
|
|
189
242
|
export function deletedRecord(current, actorSubject, now, reason) {
|
|
190
243
|
const actor = validateScalar('actor subject', actorSubject, 256);
|
|
191
244
|
const deletedAt = now.toISOString();
|
|
@@ -208,7 +261,7 @@ export function activityFromRecord(record, kind) {
|
|
|
208
261
|
recordId: record.id,
|
|
209
262
|
revision: record.revision,
|
|
210
263
|
kind,
|
|
211
|
-
status: record.status,
|
|
264
|
+
...(record.status === undefined ? {} : { status: record.status }),
|
|
212
265
|
...(record.assigneeSubject === undefined ? {} : { assigneeSubject: record.assigneeSubject }),
|
|
213
266
|
occurredAt: record.updatedAt,
|
|
214
267
|
actorSubject: record.updatedBySubject,
|
|
@@ -218,6 +271,9 @@ export function activityFromRecord(record, kind) {
|
|
|
218
271
|
export function cloneRecord(record) {
|
|
219
272
|
return {
|
|
220
273
|
...record,
|
|
274
|
+
...(record.originalSchema === undefined
|
|
275
|
+
? {}
|
|
276
|
+
: { originalSchema: { ...record.originalSchema } }),
|
|
221
277
|
scope: { ...record.scope },
|
|
222
278
|
origin: { ...record.origin },
|
|
223
279
|
...(record.content === undefined ? {} : { content: cloneContent(record.content) }),
|
|
@@ -234,8 +290,17 @@ export function cloneInstallation(installation) {
|
|
|
234
290
|
...installation,
|
|
235
291
|
scope: { ...installation.scope },
|
|
236
292
|
managedCollections: [...installation.managedCollections],
|
|
293
|
+
definition: structuredClone(installation.definition),
|
|
237
294
|
};
|
|
238
295
|
}
|
|
296
|
+
/**
|
|
297
|
+
* Managed verticals are one centrally released application definition. Existing installations keep
|
|
298
|
+
* identity, grants, records and retention while compatible catalog releases update their effective
|
|
299
|
+
* collections for every customer on the next read. Private and legacy definitions stay pinned.
|
|
300
|
+
*/
|
|
301
|
+
export function effectiveInstallation(installation, resolveCurrent) {
|
|
302
|
+
return resolveManagedInstallation(installation, resolveCurrent);
|
|
303
|
+
}
|
|
239
304
|
export function cloneGrant(grant) {
|
|
240
305
|
return { ...grant, scope: { ...grant.scope } };
|
|
241
306
|
}
|
|
@@ -261,7 +326,9 @@ function normalizeOrigin(origin) {
|
|
|
261
326
|
};
|
|
262
327
|
}
|
|
263
328
|
function validateNote(note) {
|
|
264
|
-
const normalized =
|
|
329
|
+
const normalized = note.trim();
|
|
330
|
+
if (!normalized || normalized.length > 4_000 || normalized.includes('\0'))
|
|
331
|
+
throw new PayloadValidationError('string_too_long', 'A note must contain 1 to 4,000 characters.');
|
|
265
332
|
validateManagedPayload({ note: normalized });
|
|
266
333
|
return normalized;
|
|
267
334
|
}
|
|
@@ -274,6 +341,40 @@ function validStatusTransition(from, to) {
|
|
|
274
341
|
return to === 'in_progress' || to === 'closed';
|
|
275
342
|
return to === 'new' || to === 'in_progress' || to === 'resolved' || to === 'closed';
|
|
276
343
|
}
|
|
344
|
+
export function validateCollectionPayload(collection, value) {
|
|
345
|
+
const payload = validateManagedPayload(value);
|
|
346
|
+
const issues = validateJsonSchema(collection.recordSchema, payload);
|
|
347
|
+
if (issues.length > 0) {
|
|
348
|
+
throw new PayloadValidationError('invalid_json', `managed payload does not match collection schema: ${issues[0]?.message ?? 'invalid value'}`);
|
|
349
|
+
}
|
|
350
|
+
return payload;
|
|
351
|
+
}
|
|
352
|
+
function validateDefinition(definition) {
|
|
353
|
+
validateScalar('definition title', definition.title, 120);
|
|
354
|
+
validateScalar('definition description', definition.description, 1000);
|
|
355
|
+
if (definition.collections.length > 16) {
|
|
356
|
+
throw new Error('definition may declare at most sixteen collections');
|
|
357
|
+
}
|
|
358
|
+
const keys = new Set();
|
|
359
|
+
for (const collection of definition.collections) {
|
|
360
|
+
const issues = [];
|
|
361
|
+
validateManagedCollectionControls(projectManagedCollectionControls(collection), collection.recordSchema, collection.authority.authority === 'external', `collections.${collection.key}`, issues);
|
|
362
|
+
if (issues.length > 0)
|
|
363
|
+
throw new Error(issues[0]?.message ?? 'invalid collection controls');
|
|
364
|
+
validateScalar('collection key', collection.key, 64);
|
|
365
|
+
if (keys.has(collection.key))
|
|
366
|
+
throw new Error(`duplicate collection "${collection.key}"`);
|
|
367
|
+
keys.add(collection.key);
|
|
368
|
+
if (!/^[a-f0-9]{64}$/.test(collection.schemaDigest.replace(/^sha256:/, ''))) {
|
|
369
|
+
throw new Error(`collection "${collection.key}" has an invalid schema digest`);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
function parseDefinitionVersion(version) {
|
|
374
|
+
const [major] = version.split('.');
|
|
375
|
+
const parsed = Number(major);
|
|
376
|
+
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : 1;
|
|
377
|
+
}
|
|
277
378
|
function digest(value) {
|
|
278
379
|
return createHash('sha256').update(stableJson(value)).digest('hex');
|
|
279
380
|
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { canonicalJson, validateJsonSchema } from '@noodle-borg/compiler';
|
|
3
|
+
import { MANAGED_RECORD_QUERY_SCAN_LIMIT, ManagedRecordQuerySchema, } from '@noodle-borg/wire-contracts';
|
|
4
|
+
import { cloneRecord } from './model.js';
|
|
5
|
+
import { compareRecords, scopeKey } from './pagination.js';
|
|
6
|
+
import { boundedPageSize, CursorValidationError } from './validation.js';
|
|
7
|
+
export class NativeQueryError extends Error {
|
|
8
|
+
code;
|
|
9
|
+
constructor(code, message) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.code = code;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export async function planNativeQuery(input, collection, now, loadAnchor) {
|
|
15
|
+
const parsed = ManagedRecordQuerySchema.safeParse({
|
|
16
|
+
...(input.filters === undefined ? {} : { filters: input.filters }),
|
|
17
|
+
...(input.sortField === undefined ? {} : { sortField: input.sortField }),
|
|
18
|
+
...(input.sortDirection === undefined ? {} : { sortDirection: input.sortDirection }),
|
|
19
|
+
...(input.createdAtFrom === undefined ? {} : { createdAtFrom: input.createdAtFrom }),
|
|
20
|
+
...(input.createdAtTo === undefined ? {} : { createdAtTo: input.createdAtTo }),
|
|
21
|
+
});
|
|
22
|
+
if (!parsed.success)
|
|
23
|
+
throw new NativeQueryError('invalid_query', 'Invalid bounded collection query.');
|
|
24
|
+
const properties = collection.recordSchema.properties;
|
|
25
|
+
for (const filter of parsed.data.filters ?? []) {
|
|
26
|
+
if (!collection.filterFields?.includes(filter.field))
|
|
27
|
+
throw new NativeQueryError('invalid_query', 'Filter field must be declared in filterFields.');
|
|
28
|
+
if (validateJsonSchema(properties?.[filter.field], filter.value)
|
|
29
|
+
.length > 0)
|
|
30
|
+
throw new NativeQueryError('invalid_query', 'Filter value must match its field schema.');
|
|
31
|
+
}
|
|
32
|
+
if (input.sortField !== undefined && !collection.sortFields?.includes(input.sortField))
|
|
33
|
+
throw new NativeQueryError('invalid_query', 'Sort field must be declared in sortFields.');
|
|
34
|
+
const normalized = {
|
|
35
|
+
...input,
|
|
36
|
+
filters: [...(parsed.data.filters ?? [])].sort((a, b) => a.field.localeCompare(b.field)),
|
|
37
|
+
...(input.sortField === undefined
|
|
38
|
+
? {}
|
|
39
|
+
: { sortDirection: input.sortDirection ?? 'asc' }),
|
|
40
|
+
...(input.createdAtFrom === undefined
|
|
41
|
+
? {}
|
|
42
|
+
: { createdAtFrom: new Date(input.createdAtFrom).toISOString() }),
|
|
43
|
+
...(input.createdAtTo === undefined
|
|
44
|
+
? {}
|
|
45
|
+
: { createdAtTo: new Date(input.createdAtTo).toISOString() }),
|
|
46
|
+
};
|
|
47
|
+
const limit = boundedPageSize(input.limit);
|
|
48
|
+
const digest = createHash('sha256')
|
|
49
|
+
.update(canonicalJson({
|
|
50
|
+
scope: scopeKey(input.scope),
|
|
51
|
+
collection: collection.key,
|
|
52
|
+
schema: collection.schemaDigest,
|
|
53
|
+
filters: normalized.filters,
|
|
54
|
+
sortField: input.sortField ?? null,
|
|
55
|
+
sortDirection: normalized.sortDirection ?? null,
|
|
56
|
+
createdAtFrom: normalized.createdAtFrom ?? null,
|
|
57
|
+
createdAtTo: normalized.createdAtTo ?? null,
|
|
58
|
+
status: input.status ?? null,
|
|
59
|
+
assigneeSubject: input.assigneeSubject ?? null,
|
|
60
|
+
includeDeleted: input.includeDeleted === true,
|
|
61
|
+
}))
|
|
62
|
+
.digest('hex');
|
|
63
|
+
const cursor = input.cursor === undefined ? undefined : readQueryCursor(input.cursor, digest, now);
|
|
64
|
+
const anchor = cursor === undefined ? undefined : await loadAnchor(cursor.lastId);
|
|
65
|
+
if (cursor !== undefined && (anchor === undefined || anchor.revision !== cursor.lastRevision))
|
|
66
|
+
throw new CursorValidationError('cursor anchor changed or was deleted; restart this query');
|
|
67
|
+
return {
|
|
68
|
+
input: normalized,
|
|
69
|
+
limit,
|
|
70
|
+
digest,
|
|
71
|
+
payloadQuery: normalized.filters.length > 0 || input.sortField !== undefined,
|
|
72
|
+
snapshotAt: cursor?.snapshotAt ?? now.toISOString(),
|
|
73
|
+
...(anchor === undefined ? {} : { anchor }),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function readQueryCursor(encoded, digest, now) {
|
|
77
|
+
try {
|
|
78
|
+
if (encoded.length > 2048)
|
|
79
|
+
throw new Error();
|
|
80
|
+
const value = JSON.parse(Buffer.from(encoded, 'base64url').toString());
|
|
81
|
+
if (value === null || typeof value !== 'object')
|
|
82
|
+
throw new Error();
|
|
83
|
+
const cursor = value;
|
|
84
|
+
if (cursor.version !== 2 ||
|
|
85
|
+
cursor.digest !== digest ||
|
|
86
|
+
typeof cursor.lastId !== 'string' ||
|
|
87
|
+
cursor.lastId.length > 128 ||
|
|
88
|
+
typeof cursor.lastRevision !== 'number' ||
|
|
89
|
+
!Number.isSafeInteger(cursor.lastRevision) ||
|
|
90
|
+
cursor.lastRevision < 1 ||
|
|
91
|
+
typeof cursor.snapshotAt !== 'string' ||
|
|
92
|
+
!Number.isFinite(Date.parse(cursor.snapshotAt)) ||
|
|
93
|
+
Date.parse(cursor.snapshotAt) > now.getTime())
|
|
94
|
+
throw new Error();
|
|
95
|
+
return cursor;
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
throw new CursorValidationError('cursor does not belong to this query and schema');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
export function matchesNativeQueryMetadata(record, plan, now) {
|
|
102
|
+
const input = plan.input;
|
|
103
|
+
return (scopeKey(record.scope) === scopeKey(input.scope) &&
|
|
104
|
+
record.collectionKey === input.collectionKey &&
|
|
105
|
+
(input.includeDeleted === true || record.deletedAt === undefined) &&
|
|
106
|
+
(record.deletedAt !== undefined || record.retentionExpiresAt > now.toISOString()) &&
|
|
107
|
+
(input.status === undefined || record.status === input.status) &&
|
|
108
|
+
(input.assigneeSubject === undefined || record.assigneeSubject === input.assigneeSubject) &&
|
|
109
|
+
record.createdAt <= plan.snapshotAt &&
|
|
110
|
+
(input.createdAtFrom === undefined || record.createdAt >= input.createdAtFrom) &&
|
|
111
|
+
(input.createdAtTo === undefined || record.createdAt <= input.createdAtTo));
|
|
112
|
+
}
|
|
113
|
+
/** Source is already scoped/date filtered and createdAt/id ordered; retains only page + one candidates. */
|
|
114
|
+
export async function runNativeQuery(plan, source) {
|
|
115
|
+
const selected = [];
|
|
116
|
+
let scanned = 0;
|
|
117
|
+
for await (const record of source) {
|
|
118
|
+
if (plan.payloadQuery && ++scanned > MANAGED_RECORD_QUERY_SCAN_LIMIT)
|
|
119
|
+
throw new NativeQueryError('query_limit_exceeded', 'This query exceeds 10,000 scanned records. Narrow createdAtFrom/createdAtTo and retry.');
|
|
120
|
+
if (!plan.input.filters?.every((filter) => record.content?.payload[filter.field] === filter.value))
|
|
121
|
+
continue;
|
|
122
|
+
if (plan.anchor !== undefined && compareQueryRecords(record, plan.anchor, plan) <= 0)
|
|
123
|
+
continue;
|
|
124
|
+
selected.push(record);
|
|
125
|
+
selected.sort((a, b) => compareQueryRecords(a, b, plan));
|
|
126
|
+
if (selected.length > plan.limit + 1)
|
|
127
|
+
selected.pop();
|
|
128
|
+
if (!plan.payloadQuery && selected.length > plan.limit)
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
const records = selected.slice(0, plan.limit).map(cloneRecord);
|
|
132
|
+
const last = records.at(-1);
|
|
133
|
+
return {
|
|
134
|
+
records,
|
|
135
|
+
...(selected.length > plan.limit && last !== undefined
|
|
136
|
+
? {
|
|
137
|
+
nextCursor: Buffer.from(JSON.stringify({
|
|
138
|
+
version: 2,
|
|
139
|
+
digest: plan.digest,
|
|
140
|
+
snapshotAt: plan.snapshotAt,
|
|
141
|
+
lastId: last.id,
|
|
142
|
+
lastRevision: last.revision,
|
|
143
|
+
})).toString('base64url'),
|
|
144
|
+
}
|
|
145
|
+
: {}),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function compareQueryRecords(a, b, plan) {
|
|
149
|
+
const field = plan.input.sortField;
|
|
150
|
+
if (field === undefined)
|
|
151
|
+
return compareRecords(a, b);
|
|
152
|
+
const left = a.content?.payload[field];
|
|
153
|
+
const right = b.content?.payload[field];
|
|
154
|
+
// Missing historical/optional fields sort last in both directions.
|
|
155
|
+
if (left === undefined || left === null)
|
|
156
|
+
return right === undefined || right === null ? compareRecords(a, b) : 1;
|
|
157
|
+
if (right === undefined || right === null)
|
|
158
|
+
return -1;
|
|
159
|
+
const compared = left === right ? 0 : left < right ? -1 : 1;
|
|
160
|
+
return (plan.input.sortDirection === 'desc' ? -compared : compared) || compareRecords(a, b);
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=native-query.js.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** Engineering bound, not a commercial storage allowance or estimate of disk/WAL usage. */
|
|
2
|
+
export const NATIVE_RETAINED_BYTES_LIMIT = 1024 ** 3;
|
|
3
|
+
/** Prepaid by every live record; funds the bounded terminal receipt even at the ceiling. */
|
|
4
|
+
export const NATIVE_TERMINAL_RESERVE_BYTES = 16 * 1024;
|
|
5
|
+
export class NativeStorageLimitError extends Error {
|
|
6
|
+
code = 'managed_record_storage_limit';
|
|
7
|
+
constructor() {
|
|
8
|
+
super('Managed record storage is full. Erase retained records to reclaim capacity.');
|
|
9
|
+
this.name = 'NativeStorageLimitError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** Local/test accounting uses its plaintext serialized representation; PostgreSQL counts ciphertext. */
|
|
13
|
+
export function nativeCustodyBytes(value) {
|
|
14
|
+
return (Buffer.byteLength(JSON.stringify(value), 'utf8') +
|
|
15
|
+
('retentionExpiresAt' in value && value.deletedAt === undefined
|
|
16
|
+
? NATIVE_TERMINAL_RESERVE_BYTES
|
|
17
|
+
: 0));
|
|
18
|
+
}
|
|
19
|
+
export class NativeStorageBudget {
|
|
20
|
+
maximum;
|
|
21
|
+
#totals = new Map();
|
|
22
|
+
constructor(maximum = NATIVE_RETAINED_BYTES_LIMIT) {
|
|
23
|
+
this.maximum = maximum;
|
|
24
|
+
}
|
|
25
|
+
replace(scope, previousBytes, nextBytes) {
|
|
26
|
+
const current = this.#totals.get(scope) ?? 0;
|
|
27
|
+
const delta = nextBytes - previousBytes;
|
|
28
|
+
const next = current + delta;
|
|
29
|
+
if (!Number.isSafeInteger(next) || next < 0)
|
|
30
|
+
throw new Error('Invalid native custody accounting');
|
|
31
|
+
if (delta > 0 && next > this.maximum)
|
|
32
|
+
throw new NativeStorageLimitError();
|
|
33
|
+
this.#totals.set(scope, next);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** Commit checks precede every map mutation, including history and the caller's idempotency insert. */
|
|
37
|
+
export function commitNativeMemoryRecord(records, activities, budget, key, record, activity) {
|
|
38
|
+
const previous = records.get(key);
|
|
39
|
+
const history = activities.get(key) ?? [];
|
|
40
|
+
let previousBytes = previous === undefined ? 0 : nativeCustodyBytes(previous);
|
|
41
|
+
let nextBytes = nativeCustodyBytes(record) + nativeCustodyBytes(activity);
|
|
42
|
+
let retainedHistory = history;
|
|
43
|
+
if (record.deletedAt !== undefined) {
|
|
44
|
+
retainedHistory = history.map((entry) => {
|
|
45
|
+
const { content: ignored, ...metadata } = entry;
|
|
46
|
+
void ignored;
|
|
47
|
+
previousBytes += nativeCustodyBytes(entry);
|
|
48
|
+
nextBytes += nativeCustodyBytes(metadata);
|
|
49
|
+
return metadata;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
const scope = record.scope;
|
|
53
|
+
budget.replace(`${scope.org}\0${scope.app}\0${scope.env}\0${scope.installationId}`, previousBytes, nextBytes);
|
|
54
|
+
records.set(key, record);
|
|
55
|
+
if (retainedHistory !== history || previous === undefined)
|
|
56
|
+
activities.set(key, [...retainedHistory, activity]);
|
|
57
|
+
else
|
|
58
|
+
history.push(activity);
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=native-storage-budget.js.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { cloneRecord } from './model.js';
|
|
1
2
|
import { CursorValidationError, validateScalar } from './validation.js';
|
|
2
3
|
export function scopeKey(scope) {
|
|
3
4
|
return `${scope.org}\0${scope.app}\0${scope.env}\0${scope.installationId}`;
|
|
@@ -47,4 +48,31 @@ function isCursor(value) {
|
|
|
47
48
|
function validTimestamp(value) {
|
|
48
49
|
return typeof value === 'string' && Number.isFinite(Date.parse(value));
|
|
49
50
|
}
|
|
51
|
+
export function page(records, limit, kind, scope, collectionKey, snapshotAt) {
|
|
52
|
+
const selected = records.slice(0, limit).map(cloneRecord);
|
|
53
|
+
const last = selected.at(-1);
|
|
54
|
+
const hasMore = records.length > limit;
|
|
55
|
+
return {
|
|
56
|
+
records: selected,
|
|
57
|
+
...(hasMore && last !== undefined
|
|
58
|
+
? {
|
|
59
|
+
nextCursor: encodeCursor({
|
|
60
|
+
version: 1,
|
|
61
|
+
kind,
|
|
62
|
+
scope: scopeKey(scope),
|
|
63
|
+
collectionKey,
|
|
64
|
+
lastCreatedAt: last.createdAt,
|
|
65
|
+
lastId: last.id,
|
|
66
|
+
...(snapshotAt === undefined ? {} : { snapshotAt }),
|
|
67
|
+
}),
|
|
68
|
+
}
|
|
69
|
+
: {}),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export function installationIdKey(org, installationId) {
|
|
73
|
+
return `${org}\0${installationId}`;
|
|
74
|
+
}
|
|
75
|
+
export function grantKey(scope, subject) {
|
|
76
|
+
return `${scopeKey(scope)}\0${validateScalar('grant subject', subject, 256)}`;
|
|
77
|
+
}
|
|
50
78
|
//# sourceMappingURL=pagination.js.map
|
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
export * from './collection-controls.js';
|
|
1
2
|
export * from './contracts.js';
|
|
3
|
+
export * from './definition-resolver.js';
|
|
2
4
|
export * from './in-memory-store.js';
|
|
5
|
+
export * from './legacy-request-migration.js';
|
|
6
|
+
export * from './managed-releases.js';
|
|
3
7
|
export * from './model.js';
|
|
4
8
|
export * from './profiles.js';
|
|
9
|
+
export * from './reader-floor.js';
|
|
10
|
+
export * from './source-executor.js';
|
|
11
|
+
export * from './source-ingestion-contracts.js';
|
|
12
|
+
export * from './source-ingestion-coordinator.js';
|
|
13
|
+
export * from './source-ingestion-memory-store.js';
|
|
5
14
|
export * from './validation.js';
|
|
6
15
|
//# sourceMappingURL=portable.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type ModuleSqlTransaction, type PlatformHumanIdentityContribution } from '@noodle-borg/module';
|
|
2
|
+
import type { BusinessGrant } from './contracts.js';
|
|
3
|
+
export type BusinessPrincipalProvider = Pick<PlatformHumanIdentityContribution, 'principalResolver' | 'assertActivePrincipal'>;
|
|
4
|
+
/** Uses the host's canonical authority; it never creates a second principal status store. */
|
|
5
|
+
export declare class BusinessPrincipalAuthority {
|
|
6
|
+
#private;
|
|
7
|
+
configure(provider: BusinessPrincipalProvider | undefined): void;
|
|
8
|
+
allows(subject: string, transaction?: ModuleSqlTransaction): Promise<boolean>;
|
|
9
|
+
eligible(grants: readonly BusinessGrant[]): Promise<readonly BusinessGrant[]>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=principal-authority.d.ts.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { PlatformIdentityError, } from '@noodle-borg/module';
|
|
2
|
+
/** Uses the host's canonical authority; it never creates a second principal status store. */
|
|
3
|
+
export class BusinessPrincipalAuthority {
|
|
4
|
+
#provider;
|
|
5
|
+
configure(provider) {
|
|
6
|
+
this.#provider = provider;
|
|
7
|
+
}
|
|
8
|
+
async allows(subject, transaction) {
|
|
9
|
+
const provider = this.#provider;
|
|
10
|
+
if (provider === undefined)
|
|
11
|
+
return true;
|
|
12
|
+
try {
|
|
13
|
+
if (transaction === undefined)
|
|
14
|
+
await provider.principalResolver.assertActive(subject);
|
|
15
|
+
else {
|
|
16
|
+
if (provider.assertActivePrincipal === undefined) {
|
|
17
|
+
throw new Error('Business assignment requires transactional principal authority');
|
|
18
|
+
}
|
|
19
|
+
await provider.assertActivePrincipal(transaction, subject);
|
|
20
|
+
}
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
if (error instanceof PlatformIdentityError && error.code === 'principal_suspended') {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async eligible(grants) {
|
|
31
|
+
const result = [];
|
|
32
|
+
for (const grant of grants) {
|
|
33
|
+
if (grant.revokedAt === undefined &&
|
|
34
|
+
grant.role !== 'viewer' &&
|
|
35
|
+
grant.email !== undefined &&
|
|
36
|
+
(await this.allows(grant.subject)))
|
|
37
|
+
result.push(grant);
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=principal-authority.js.map
|