primitive-admin 1.0.61 → 1.0.63
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/README.md +125 -69
- package/assets/skill/skills/primitive-platform/SKILL.md +336 -37
- package/dist/bin/primitive.js +25 -14
- package/dist/bin/primitive.js.map +1 -1
- package/dist/src/commands/analytics.js +36 -16
- package/dist/src/commands/analytics.js.map +1 -1
- package/dist/src/commands/apps.js +52 -188
- package/dist/src/commands/apps.js.map +1 -1
- package/dist/src/commands/blob-buckets.js +13 -153
- package/dist/src/commands/blob-buckets.js.map +1 -1
- package/dist/src/commands/collection-type-configs.js +14 -100
- package/dist/src/commands/collection-type-configs.js.map +1 -1
- package/dist/src/commands/collections.js +47 -8
- package/dist/src/commands/collections.js.map +1 -1
- package/dist/src/commands/config.d.ts +46 -0
- package/dist/src/commands/config.js +479 -0
- package/dist/src/commands/config.js.map +1 -0
- package/dist/src/commands/connections.js +12 -7
- package/dist/src/commands/connections.js.map +1 -1
- package/dist/src/commands/cron-triggers.js +84 -176
- package/dist/src/commands/cron-triggers.js.map +1 -1
- package/dist/src/commands/database-type-configs.d.ts +2 -0
- package/dist/src/commands/database-type-configs.js +171 -0
- package/dist/src/commands/database-type-configs.js.map +1 -0
- package/dist/src/commands/database-types.js +4 -4
- package/dist/src/commands/database-types.js.map +1 -1
- package/dist/src/commands/databases.d.ts +63 -0
- package/dist/src/commands/databases.js +649 -87
- package/dist/src/commands/databases.js.map +1 -1
- package/dist/src/commands/documents.js +869 -12
- package/dist/src/commands/documents.js.map +1 -1
- package/dist/src/commands/email-templates.js +21 -128
- package/dist/src/commands/email-templates.js.map +1 -1
- package/dist/src/commands/env.d.ts +12 -1
- package/dist/src/commands/env.js +115 -26
- package/dist/src/commands/env.js.map +1 -1
- package/dist/src/commands/feature-flags.d.ts +14 -0
- package/dist/src/commands/feature-flags.js +116 -0
- package/dist/src/commands/feature-flags.js.map +1 -0
- package/dist/src/commands/group-type-configs.js +14 -109
- package/dist/src/commands/group-type-configs.js.map +1 -1
- package/dist/src/commands/init.d.ts +24 -1
- package/dist/src/commands/init.js +1194 -279
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/integrations.js +166 -435
- package/dist/src/commands/integrations.js.map +1 -1
- package/dist/src/commands/metadata-category-configs.d.ts +12 -0
- package/dist/src/commands/metadata-category-configs.js +112 -0
- package/dist/src/commands/metadata-category-configs.js.map +1 -0
- package/dist/src/commands/metadata.js +33 -141
- package/dist/src/commands/metadata.js.map +1 -1
- package/dist/src/commands/prompts.js +206 -563
- package/dist/src/commands/prompts.js.map +1 -1
- package/dist/src/commands/rule-sets.d.ts +1 -1
- package/dist/src/commands/rule-sets.js +16 -132
- package/dist/src/commands/rule-sets.js.map +1 -1
- package/dist/src/commands/scripts.d.ts +10 -0
- package/dist/src/commands/scripts.js +203 -241
- package/dist/src/commands/scripts.js.map +1 -1
- package/dist/src/commands/sessions.js +17 -5
- package/dist/src/commands/sessions.js.map +1 -1
- package/dist/src/commands/sync-app-settings.d.ts +113 -70
- package/dist/src/commands/sync-app-settings.js +193 -242
- package/dist/src/commands/sync-app-settings.js.map +1 -1
- package/dist/src/commands/sync.d.ts +1904 -51
- package/dist/src/commands/sync.js +9468 -1790
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/commands/tokens.js +8 -2
- package/dist/src/commands/tokens.js.map +1 -1
- package/dist/src/commands/users.js +92 -1
- package/dist/src/commands/users.js.map +1 -1
- package/dist/src/commands/vars.js +44 -58
- package/dist/src/commands/vars.js.map +1 -1
- package/dist/src/commands/webhooks.js +318 -156
- package/dist/src/commands/webhooks.js.map +1 -1
- package/dist/src/commands/workflows.d.ts +49 -12
- package/dist/src/commands/workflows.js +652 -1086
- package/dist/src/commands/workflows.js.map +1 -1
- package/dist/src/lib/access-rule-display.d.ts +21 -0
- package/dist/src/lib/access-rule-display.js +34 -0
- package/dist/src/lib/access-rule-display.js.map +1 -0
- package/dist/src/lib/api-client.d.ts +541 -61
- package/dist/src/lib/api-client.js +559 -102
- package/dist/src/lib/api-client.js.map +1 -1
- package/dist/src/lib/app-settings-descriptor.d.ts +180 -25
- package/dist/src/lib/app-settings-descriptor.js +403 -82
- package/dist/src/lib/app-settings-descriptor.js.map +1 -1
- package/dist/src/lib/canonical-json.d.ts +12 -0
- package/dist/src/lib/canonical-json.js +35 -0
- package/dist/src/lib/canonical-json.js.map +1 -0
- package/dist/src/lib/cli-manifest.d.ts +8 -0
- package/dist/src/lib/cli-manifest.js +1 -0
- package/dist/src/lib/cli-manifest.js.map +1 -1
- package/dist/src/lib/codegen-shared/generatedFiles.d.ts +6 -2
- package/dist/src/lib/codegen-shared/generatedFiles.js +9 -2
- package/dist/src/lib/codegen-shared/generatedFiles.js.map +1 -1
- package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.d.ts +6 -6
- package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js +8 -8
- package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js.map +1 -1
- package/dist/src/lib/config-object-descriptor.d.ts +127 -0
- package/dist/src/lib/config-object-descriptor.js +658 -0
- package/dist/src/lib/config-object-descriptor.js.map +1 -0
- package/dist/src/lib/config-payload.d.ts +85 -0
- package/dist/src/lib/config-payload.js +116 -0
- package/dist/src/lib/config-payload.js.map +1 -0
- package/dist/src/lib/config-surface.d.ts +130 -0
- package/dist/src/lib/config-surface.js +300 -0
- package/dist/src/lib/config-surface.js.map +1 -0
- package/dist/src/lib/credentials-store.d.ts +10 -0
- package/dist/src/lib/credentials-store.js +23 -0
- package/dist/src/lib/credentials-store.js.map +1 -1
- package/dist/src/lib/data-input.d.ts +23 -0
- package/dist/src/lib/data-input.js +50 -0
- package/dist/src/lib/data-input.js.map +1 -0
- package/dist/src/lib/db-codegen/dbTemplates.js +1 -1
- package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -1
- package/dist/src/lib/db-codegen/dbTypeIR.d.ts +1 -1
- package/dist/src/lib/env-resolver-core.d.ts +187 -0
- package/dist/src/lib/env-resolver-core.js +325 -0
- package/dist/src/lib/env-resolver-core.js.map +1 -0
- package/dist/src/lib/env-resolver.d.ts +28 -6
- package/dist/src/lib/env-resolver.js +44 -32
- package/dist/src/lib/env-resolver.js.map +1 -1
- package/dist/src/lib/generated-allowlist.js +12 -0
- package/dist/src/lib/generated-allowlist.js.map +1 -1
- package/dist/src/lib/generated-config-surfaces.d.ts +682 -0
- package/dist/src/lib/generated-config-surfaces.js +4058 -0
- package/dist/src/lib/generated-config-surfaces.js.map +1 -0
- package/dist/src/lib/generated-template-lint.d.ts +212 -0
- package/dist/src/lib/generated-template-lint.js +624 -0
- package/dist/src/lib/generated-template-lint.js.map +1 -0
- package/dist/src/lib/init-adopt.d.ts +16 -0
- package/dist/src/lib/init-adopt.js +34 -0
- package/dist/src/lib/init-adopt.js.map +1 -0
- package/dist/src/lib/init-assets.d.ts +39 -0
- package/dist/src/lib/init-assets.js +97 -0
- package/dist/src/lib/init-assets.js.map +1 -0
- package/dist/src/lib/init-client-platforms.d.ts +14 -0
- package/dist/src/lib/init-client-platforms.js +71 -0
- package/dist/src/lib/init-client-platforms.js.map +1 -0
- package/dist/src/lib/init-config.d.ts +44 -5
- package/dist/src/lib/init-config.js +80 -7
- package/dist/src/lib/init-config.js.map +1 -1
- package/dist/src/lib/init-email-redirect-uris.d.ts +37 -0
- package/dist/src/lib/init-email-redirect-uris.js +46 -0
- package/dist/src/lib/init-email-redirect-uris.js.map +1 -0
- package/dist/src/lib/init-ios-links.d.ts +90 -0
- package/dist/src/lib/init-ios-links.js +218 -0
- package/dist/src/lib/init-ios-links.js.map +1 -0
- package/dist/src/lib/init-plan.d.ts +80 -0
- package/dist/src/lib/init-plan.js +95 -0
- package/dist/src/lib/init-plan.js.map +1 -0
- package/dist/src/lib/init-production-env.d.ts +48 -0
- package/dist/src/lib/init-production-env.js +59 -0
- package/dist/src/lib/init-production-env.js.map +1 -0
- package/dist/src/lib/init-schema.d.ts +74 -0
- package/dist/src/lib/init-schema.js +358 -0
- package/dist/src/lib/init-schema.js.map +1 -0
- package/dist/src/lib/init-xcode.d.ts +33 -0
- package/dist/src/lib/init-xcode.js +114 -0
- package/dist/src/lib/init-xcode.js.map +1 -0
- package/dist/src/lib/integration-request-config.d.ts +30 -0
- package/dist/src/lib/integration-request-config.js +145 -0
- package/dist/src/lib/integration-request-config.js.map +1 -0
- package/dist/src/lib/integration-selector.d.ts +42 -0
- package/dist/src/lib/integration-selector.js +46 -0
- package/dist/src/lib/integration-selector.js.map +1 -0
- package/dist/src/lib/local-state.d.ts +55 -0
- package/dist/src/lib/local-state.js +167 -0
- package/dist/src/lib/local-state.js.map +1 -0
- package/dist/src/lib/local-test-cases.d.ts +63 -0
- package/dist/src/lib/local-test-cases.js +135 -0
- package/dist/src/lib/local-test-cases.js.map +1 -0
- package/dist/src/lib/log-inspection.d.ts +568 -0
- package/dist/src/lib/log-inspection.js +639 -0
- package/dist/src/lib/log-inspection.js.map +1 -0
- package/dist/src/lib/migration-nag.d.ts +2 -2
- package/dist/src/lib/migration-nag.js +3 -3
- package/dist/src/lib/object-status-filter.d.ts +22 -0
- package/dist/src/lib/object-status-filter.js +45 -0
- package/dist/src/lib/object-status-filter.js.map +1 -0
- package/dist/src/lib/output.d.ts +24 -1
- package/dist/src/lib/output.js +42 -1
- package/dist/src/lib/output.js.map +1 -1
- package/dist/src/lib/package-manager.d.ts +140 -0
- package/dist/src/lib/package-manager.js +305 -0
- package/dist/src/lib/package-manager.js.map +1 -0
- package/dist/src/lib/paginate.d.ts +50 -0
- package/dist/src/lib/paginate.js +53 -0
- package/dist/src/lib/paginate.js.map +1 -1
- package/dist/src/lib/platform-owned.d.ts +29 -3
- package/dist/src/lib/platform-owned.js +42 -3
- package/dist/src/lib/platform-owned.js.map +1 -1
- package/dist/src/lib/project-config.d.ts +8 -0
- package/dist/src/lib/project-config.js +30 -5
- package/dist/src/lib/project-config.js.map +1 -1
- package/dist/src/lib/query-operators.d.ts +1 -1
- package/dist/src/lib/query-operators.js +1 -1
- package/dist/src/lib/record-filter.d.ts +18 -0
- package/dist/src/lib/record-filter.js +55 -0
- package/dist/src/lib/record-filter.js.map +1 -0
- package/dist/src/lib/resolve-init-dev-port.d.ts +56 -0
- package/dist/src/lib/resolve-init-dev-port.js +55 -0
- package/dist/src/lib/resolve-init-dev-port.js.map +1 -0
- package/dist/src/lib/resolve-init-server.d.ts +64 -0
- package/dist/src/lib/resolve-init-server.js +77 -0
- package/dist/src/lib/resolve-init-server.js.map +1 -0
- package/dist/src/lib/resolve-platform.d.ts +43 -14
- package/dist/src/lib/resolve-platform.js +74 -12
- package/dist/src/lib/resolve-platform.js.map +1 -1
- package/dist/src/lib/run-status.d.ts +19 -0
- package/dist/src/lib/run-status.generated.d.ts +39 -0
- package/dist/src/lib/run-status.generated.js +66 -0
- package/dist/src/lib/run-status.generated.js.map +1 -0
- package/dist/src/lib/run-status.js +19 -0
- package/dist/src/lib/run-status.js.map +1 -0
- package/dist/src/lib/server-text-normalization.d.ts +51 -0
- package/dist/src/lib/server-text-normalization.js +90 -0
- package/dist/src/lib/server-text-normalization.js.map +1 -0
- package/dist/src/lib/server-url.d.ts +22 -0
- package/dist/src/lib/server-url.js +33 -0
- package/dist/src/lib/server-url.js.map +1 -0
- package/dist/src/lib/signing-secret-status.d.ts +81 -0
- package/dist/src/lib/signing-secret-status.js +116 -0
- package/dist/src/lib/signing-secret-status.js.map +1 -0
- package/dist/src/lib/skill-installer.js +6 -3
- package/dist/src/lib/skill-installer.js.map +1 -1
- package/dist/src/lib/snapshots.d.ts +2 -2
- package/dist/src/lib/snapshots.js +2 -2
- package/dist/src/lib/swift-codegen/dbGenerator.d.ts +15 -2
- package/dist/src/lib/swift-codegen/dbGenerator.js +250 -18
- package/dist/src/lib/swift-codegen/dbGenerator.js.map +1 -1
- package/dist/src/lib/swift-codegen/generator.d.ts +11 -2
- package/dist/src/lib/swift-codegen/generator.js +181 -7
- package/dist/src/lib/swift-codegen/generator.js.map +1 -1
- package/dist/src/lib/swift-codegen/siblingSymbols.d.ts +7 -3
- package/dist/src/lib/swift-codegen/siblingSymbols.js +4 -1
- package/dist/src/lib/swift-codegen/siblingSymbols.js.map +1 -1
- package/dist/src/lib/sync-dir-selector.d.ts +21 -0
- package/dist/src/lib/sync-dir-selector.js +30 -0
- package/dist/src/lib/sync-dir-selector.js.map +1 -0
- package/dist/src/lib/sync-paths.d.ts +39 -0
- package/dist/src/lib/sync-paths.js +70 -2
- package/dist/src/lib/sync-paths.js.map +1 -1
- package/dist/src/lib/sync-resource-types.d.ts +138 -31
- package/dist/src/lib/sync-resource-types.js +241 -47
- package/dist/src/lib/sync-resource-types.js.map +1 -1
- package/dist/src/lib/sync-selectors.d.ts +95 -0
- package/dist/src/lib/sync-selectors.js +228 -0
- package/dist/src/lib/sync-selectors.js.map +1 -0
- package/dist/src/lib/template.d.ts +62 -4
- package/dist/src/lib/template.js +147 -39
- package/dist/src/lib/template.js.map +1 -1
- package/dist/src/lib/test-case-file-names.d.ts +40 -0
- package/dist/src/lib/test-case-file-names.js +91 -0
- package/dist/src/lib/test-case-file-names.js.map +1 -0
- package/dist/src/lib/test-case-keys.d.ts +29 -0
- package/dist/src/lib/test-case-keys.js +55 -0
- package/dist/src/lib/test-case-keys.js.map +1 -0
- package/dist/src/lib/test-case-variables.d.ts +15 -0
- package/dist/src/lib/test-case-variables.js +29 -0
- package/dist/src/lib/test-case-variables.js.map +1 -0
- package/dist/src/lib/toml-database-config.d.ts +4 -4
- package/dist/src/lib/toml-database-config.js +27 -34
- package/dist/src/lib/toml-database-config.js.map +1 -1
- package/dist/src/lib/toml-metadata-config.d.ts +9 -5
- package/dist/src/lib/toml-metadata-config.js +40 -45
- package/dist/src/lib/toml-metadata-config.js.map +1 -1
- package/dist/src/lib/toml-native-form.d.ts +1 -1
- package/dist/src/lib/toml-native-form.js +1 -1
- package/dist/src/lib/toml-params-validator.d.ts +1 -1
- package/dist/src/lib/toml-params-validator.js +1 -1
- package/dist/src/lib/toml-scalar-edit.d.ts +43 -0
- package/dist/src/lib/toml-scalar-edit.js +283 -0
- package/dist/src/lib/toml-scalar-edit.js.map +1 -0
- package/dist/src/lib/user-selector.d.ts +24 -0
- package/dist/src/lib/user-selector.js +33 -0
- package/dist/src/lib/user-selector.js.map +1 -0
- package/dist/src/lib/version-check.d.ts +25 -0
- package/dist/src/lib/version-check.js +77 -8
- package/dist/src/lib/version-check.js.map +1 -1
- package/dist/src/lib/watch.d.ts +121 -0
- package/dist/src/lib/watch.js +169 -0
- package/dist/src/lib/watch.js.map +1 -0
- package/dist/src/lib/web-url.d.ts +40 -0
- package/dist/src/lib/web-url.js +76 -0
- package/dist/src/lib/web-url.js.map +1 -0
- package/dist/src/lib/workflow-apply.d.ts +69 -45
- package/dist/src/lib/workflow-apply.js +99 -72
- package/dist/src/lib/workflow-apply.js.map +1 -1
- package/dist/src/lib/workflow-codegen/generator.js +4 -4
- package/dist/src/lib/workflow-codegen/generator.js.map +1 -1
- package/dist/src/lib/workflow-codegen/invokerIR.d.ts +11 -0
- package/dist/src/lib/workflow-codegen/invokerIR.js +5 -0
- package/dist/src/lib/workflow-codegen/invokerIR.js.map +1 -1
- package/dist/src/lib/workflow-config-apply.d.ts +70 -0
- package/dist/src/lib/workflow-config-apply.js +137 -0
- package/dist/src/lib/workflow-config-apply.js.map +1 -0
- package/dist/src/lib/workflow-config-sidecar.d.ts +63 -0
- package/dist/src/lib/workflow-config-sidecar.js +96 -0
- package/dist/src/lib/workflow-config-sidecar.js.map +1 -0
- package/dist/src/lib/workflow-defaults.d.ts +29 -0
- package/dist/src/lib/workflow-defaults.js +41 -0
- package/dist/src/lib/workflow-defaults.js.map +1 -0
- package/dist/src/lib/workflow-include-preserve.d.ts +76 -0
- package/dist/src/lib/workflow-include-preserve.js +286 -0
- package/dist/src/lib/workflow-include-preserve.js.map +1 -0
- package/dist/src/lib/workflow-payload.d.ts +31 -20
- package/dist/src/lib/workflow-payload.js +100 -110
- package/dist/src/lib/workflow-payload.js.map +1 -1
- package/dist/src/lib/workflow-toml-validator.d.ts +37 -16
- package/dist/src/lib/workflow-toml-validator.js +141 -16
- package/dist/src/lib/workflow-toml-validator.js.map +1 -1
- package/dist/src/types/index.d.ts +78 -22
- package/dist/src/validators.d.ts +7 -7
- package/dist/src/validators.js +6 -6
- package/package.json +11 -6
- package/dist/src/commands/settings.d.ts +0 -15
- package/dist/src/commands/settings.js +0 -102
- package/dist/src/commands/settings.js.map +0 -1
|
@@ -0,0 +1,682 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED FILE — DO NOT EDIT BY HAND.
|
|
3
|
+
*
|
|
4
|
+
* Vendored from the canonical server modules under `src/config-surface/` — the
|
|
5
|
+
* ONE definition per configuration object (issue #2644). The server's
|
|
6
|
+
* create/update handlers and this copy read the same field surface, so the CLI's
|
|
7
|
+
* push payloads, pull serializers and TOML key validation cannot drift from what
|
|
8
|
+
* the server accepts.
|
|
9
|
+
*
|
|
10
|
+
* Regenerate with:
|
|
11
|
+
* node cli/scripts/gen-config-surfaces.mjs (runs automatically at CLI prebuild)
|
|
12
|
+
*
|
|
13
|
+
* A freshness guard (`gen-config-surfaces.mjs --check`, asserted by
|
|
14
|
+
* `cli/tests/unit/config-surface-drift-guard.test.ts`) fails if this committed
|
|
15
|
+
* copy does not match the source.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* The one definition per configuration object (issue #2644).
|
|
19
|
+
*
|
|
20
|
+
* A "configuration object" is anything `primitive config` round-trips as
|
|
21
|
+
* config-as-code: workflows, prompts, integrations, webhooks, cron triggers,
|
|
22
|
+
* blob buckets, database types, rule sets, email templates, and the type
|
|
23
|
+
* configs. Every one of them used to write its field surface out by hand in at
|
|
24
|
+
* least three places — the server's create/update handler, the CLI's push
|
|
25
|
+
* payload builder, and the CLI's pull serializer — so adding a field to one and
|
|
26
|
+
* not the others failed silently: the field was simply absent, `config diff` could
|
|
27
|
+
* not see it, and a pull → push cycle cleared it server-side (#571, #807, #1081,
|
|
28
|
+
* #1172, #1177, #1972, #2635).
|
|
29
|
+
*
|
|
30
|
+
* These types describe that surface ONCE. The definitions live here on the
|
|
31
|
+
* server; the CLI vendors them at build time into
|
|
32
|
+
* `cli/src/lib/generated-config-surfaces.ts`
|
|
33
|
+
* (`cli/scripts/gen-config-surfaces.mjs`), the same server→CLI vendoring
|
|
34
|
+
* `gen-operation-def-descriptor.mjs` (#1544) already uses, so the published CLI
|
|
35
|
+
* still imports no server code at runtime.
|
|
36
|
+
*
|
|
37
|
+
* ── Scope: declarative classification and coverage ONLY ──────────────────
|
|
38
|
+
* Decision of record (#1976, 2026-07-23, carried forward at #2644's design
|
|
39
|
+
* gate): a definition records WHICH fields exist, whether each is part of the
|
|
40
|
+
* TOML surface, which modes the server accepts it in, and — for a field with
|
|
41
|
+
* real behavior — the NAME of the handler that owns that behavior. It never
|
|
42
|
+
* encodes the behavior itself, and no handler source is ever regex-scanned for
|
|
43
|
+
* field names. `pickWritableFields` replaces the key list, not the validation.
|
|
44
|
+
*
|
|
45
|
+
* ── Purity ───────────────────────────────────────────────────────────────
|
|
46
|
+
* Everything under `src/config-surface/` must stay importable by a build-time
|
|
47
|
+
* Node script with no Workers runtime: no `getAppModels`, no `withAppContext`,
|
|
48
|
+
* no `src/do-routing.ts`, no `env`. `cli/tests/unit/config-surface-drift-guard.test.ts`
|
|
49
|
+
* asserts the directory's import graph stays empty of those modules.
|
|
50
|
+
*/
|
|
51
|
+
/** Value shape of a field on the wire and in TOML. Descriptive, not a parser. */
|
|
52
|
+
export type FieldType = "string" | "number" | "boolean" | "string[]" | "json";
|
|
53
|
+
/**
|
|
54
|
+
* Why a persisted field is not part of the TOML surface. `note` is required —
|
|
55
|
+
* absence from a hand-written list is never a decision (#2644 criterion 4).
|
|
56
|
+
*/
|
|
57
|
+
export type NotExposed = {
|
|
58
|
+
kind: "server-owned";
|
|
59
|
+
note: string;
|
|
60
|
+
} | {
|
|
61
|
+
kind: "structural";
|
|
62
|
+
note: string;
|
|
63
|
+
/**
|
|
64
|
+
* Which create/update modes carry this key IN THE REQUEST BODY — the same
|
|
65
|
+
* statement `ConfigField.writableOn` makes about a field, for a key that
|
|
66
|
+
* is not part of the TOML field surface.
|
|
67
|
+
*
|
|
68
|
+
* Omitted means both, the common case for a sub-tree the body always
|
|
69
|
+
* carries (`rules`, `metadataManifest`, `config`). `[]` says the key
|
|
70
|
+
* never travels in the body at all: it is in the URL path or comes from
|
|
71
|
+
* the file name, so no request schema admits it. Being structural is a
|
|
72
|
+
* statement about the TOML surface and does not by itself make a key
|
|
73
|
+
* writable — a mode whose handler never reads the key is not declared
|
|
74
|
+
* for it, or the schema would accept a key the handler drops, which is
|
|
75
|
+
* the silent 200 criterion 9 exists to end.
|
|
76
|
+
*/
|
|
77
|
+
requestModes?: readonly ("create" | "update")[];
|
|
78
|
+
} | {
|
|
79
|
+
kind: "secret";
|
|
80
|
+
note: string;
|
|
81
|
+
} | {
|
|
82
|
+
kind: "deprecated";
|
|
83
|
+
note: string;
|
|
84
|
+
};
|
|
85
|
+
export interface ConfigField {
|
|
86
|
+
/** `models.yaml` field name === the wire key on create/update. */
|
|
87
|
+
field: string;
|
|
88
|
+
/** Key inside the TOML table (often identical to `field`). */
|
|
89
|
+
tomlKey: string;
|
|
90
|
+
type: FieldType;
|
|
91
|
+
/** "whenSet" omits the key on pull when the value is empty; see #1033's `emit`. */
|
|
92
|
+
emit: "always" | "whenSet";
|
|
93
|
+
/**
|
|
94
|
+
* Modes the SERVER accepts the field in — a statement about the handler's
|
|
95
|
+
* `hasOwnProperty` branches and nothing else. `["create"]` means update
|
|
96
|
+
* genuinely rejects/ignores it (e.g. an immutable key). It is NOT a place to
|
|
97
|
+
* record CLI call ordering: `syncCallable` is accepted on both create and
|
|
98
|
+
* update (`src/admin-api.ts` `createAppWorkflow` / `updateAppWorkflow`); the
|
|
99
|
+
* CLI's create-only send is a *sequencing* invariant owned by
|
|
100
|
+
* `applyWorkflowBody` (#807 — the deferred second PATCH is itself an update
|
|
101
|
+
* call, and would break if update rejected the field).
|
|
102
|
+
*/
|
|
103
|
+
writableOn: readonly ("create" | "update")[];
|
|
104
|
+
/**
|
|
105
|
+
* Classification, not dispatch. "passthrough" = the accepted value is stored
|
|
106
|
+
* as-is. Otherwise the named handler owns validation, normalization and
|
|
107
|
+
* serialization for this field; the guard only asserts the export exists.
|
|
108
|
+
*
|
|
109
|
+
* A handler is named `"<repo-relative module path>#<exported name>"`, e.g.
|
|
110
|
+
* `"src/workflows/config/workflow-field-handlers.ts#normalizeWorkflowStatus"`.
|
|
111
|
+
* `cli/tests/unit/config-surface-drift-guard.test.ts` fails when the module or
|
|
112
|
+
* the export is missing (#2644 behavior 2b).
|
|
113
|
+
*/
|
|
114
|
+
validation: "passthrough" | {
|
|
115
|
+
handler: string;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* This field's declared type genuinely admits more than one TOML spelling
|
|
119
|
+
* (#2880 criterion 5).
|
|
120
|
+
*
|
|
121
|
+
* The declared type is the contract: a quoted number for a declared number
|
|
122
|
+
* is a validation error `config diff` and `config push` report identically,
|
|
123
|
+
* and neither coerces. A handful of fields are genuinely dual-encoded
|
|
124
|
+
* anyway — `temperature` and `topP` are `StringField`s the server stores as
|
|
125
|
+
* strings and returns parsed (#2869), so `"0.2"` and `0.2` describe one
|
|
126
|
+
* value — and for those the two spellings must compare EQUAL, or diff
|
|
127
|
+
* reports a `Modified` no push can clear.
|
|
128
|
+
*
|
|
129
|
+
* Recorded here rather than inferred from the type, so the carve-out is a
|
|
130
|
+
* decision with a reason attached instead of a rule that quietly widens to
|
|
131
|
+
* every number in the surface.
|
|
132
|
+
*/
|
|
133
|
+
dualEncoded?: {
|
|
134
|
+
note: string;
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* The value the SERVER materializes when a create omits this key (#2880
|
|
138
|
+
* DSO-002).
|
|
139
|
+
*
|
|
140
|
+
* A hand-authored file that omits an optional field the server defaults —
|
|
141
|
+
* an integration's `timeoutMs`, a cron trigger's `timezone` — creates fine
|
|
142
|
+
* and then reads `Modified` forever: the server holds the default, the file
|
|
143
|
+
* holds nothing, and push's payload builder drops the absent key so the
|
|
144
|
+
* difference can never converge. Recording the default here lets the LOCAL
|
|
145
|
+
* side of the comparison apply the same value the server did.
|
|
146
|
+
*
|
|
147
|
+
* Only for a default the server assigns on CREATE and returns on read.
|
|
148
|
+
*/
|
|
149
|
+
serverDefault?: string | number | boolean;
|
|
150
|
+
}
|
|
151
|
+
export interface ConfigTable {
|
|
152
|
+
/** TOML path, e.g. ["workflow"] for [workflow], ["configs"] for [[configs]]. */
|
|
153
|
+
tomlPath: readonly string[];
|
|
154
|
+
repeated: boolean;
|
|
155
|
+
/** The `models.yaml` model backing this table — the coverage anchor. */
|
|
156
|
+
model: string;
|
|
157
|
+
fields: readonly ConfigField[];
|
|
158
|
+
/** Every model field not in `fields`, with its reason. Coverage is exhaustive. */
|
|
159
|
+
notExposed: Readonly<Record<string, NotExposed>>;
|
|
160
|
+
/**
|
|
161
|
+
* TOML keys accepted inside this table that are NOT part of the write field
|
|
162
|
+
* surface — an author writes them, but some other machinery consumes them.
|
|
163
|
+
* Declared here so `config push`'s unrecognized-key rejection (#2644 criterion
|
|
164
|
+
* 6) does not reject a key the CLI itself emits, and so the reason is visible
|
|
165
|
+
* rather than implied.
|
|
166
|
+
*/
|
|
167
|
+
tomlOnlyKeys: Readonly<Record<string, NotExposed>>;
|
|
168
|
+
/**
|
|
169
|
+
* Keys the create/update BODY carries that are not `models.yaml` fields at
|
|
170
|
+
* all — protocol keys such as the `expectedModifiedAt` optimistic-concurrency
|
|
171
|
+
* token. Declared here so phase 5's generated request schemas
|
|
172
|
+
* (`request-schema.ts`) accept them, with the reason visible rather than
|
|
173
|
+
* implied. Optional: most objects have none.
|
|
174
|
+
*
|
|
175
|
+
* `modes` records which handlers actually read the key, the same statement
|
|
176
|
+
* `ConfigField.writableOn` makes about a field. Omitted means both — the
|
|
177
|
+
* common case. A key the handler in this mode does not read is NOT declared
|
|
178
|
+
* for that mode: the schema would accept it and the handler would drop it,
|
|
179
|
+
* which is the silent 200 criterion 9 exists to end.
|
|
180
|
+
*/
|
|
181
|
+
requestOnlyKeys?: Readonly<Record<string, {
|
|
182
|
+
note: string;
|
|
183
|
+
modes?: readonly ("create" | "update")[];
|
|
184
|
+
}>>;
|
|
185
|
+
/**
|
|
186
|
+
* Keys the server's GET response carries that are not `models.yaml` fields —
|
|
187
|
+
* derived flags and related payloads. Declared here so `config pull`'s
|
|
188
|
+
* unrecognized-key warning (#2644 criterion 6) reports genuinely unknown keys
|
|
189
|
+
* rather than every computed one.
|
|
190
|
+
*/
|
|
191
|
+
responseOnlyKeys: Readonly<Record<string, NotExposed>>;
|
|
192
|
+
}
|
|
193
|
+
export interface ConfigObjectSurface {
|
|
194
|
+
/** Matches the CLI's `SyncResourceType.label` — e.g. "workflow", "prompt". */
|
|
195
|
+
label: string;
|
|
196
|
+
tables: readonly ConfigTable[];
|
|
197
|
+
/**
|
|
198
|
+
* Top-level TOML keys the object's FILE carries besides its field tables —
|
|
199
|
+
* the authored sub-trees that travel on their own channel (`[[steps]]`,
|
|
200
|
+
* `[requestConfig]`, `[rules]`, `[models.*]`) and the declared-access
|
|
201
|
+
* manifest's `[metadata]` / `secrets` / `vars` fragments.
|
|
202
|
+
*
|
|
203
|
+
* `tomlOnlyKeys` says which keys are accepted INSIDE a table; this says which
|
|
204
|
+
* keys are accepted at the document root. Together they make `config push`'s
|
|
205
|
+
* rejection total (design gate, 2026-08-12: push rejects everything
|
|
206
|
+
* unrecognized): without it a typo'd table header — `[integraton]` — parsed
|
|
207
|
+
* to a root key nothing checked, so the file pushed as though the real table
|
|
208
|
+
* were empty and the TOML-owned fields inside it were CLEARED server-side.
|
|
209
|
+
*
|
|
210
|
+
* Every entry carries its reason, the same rule `notExposed` follows: a table
|
|
211
|
+
* that is simply absent from this map must not read as a decision.
|
|
212
|
+
*/
|
|
213
|
+
tomlDocumentKeys: Readonly<Record<string, NotExposed>>;
|
|
214
|
+
/**
|
|
215
|
+
* Declares that this object HAS no TOML field table, with the reason —
|
|
216
|
+
* required when `tables` is empty and forbidden otherwise.
|
|
217
|
+
*
|
|
218
|
+
* `transform` is the case: a `.rhai` file's authored surface is the script
|
|
219
|
+
* body, so there is no key/value table to define. Saying so here is the same
|
|
220
|
+
* rule `notExposed` applies to a field, one level up: "absent from the
|
|
221
|
+
* registry" and "deliberately fieldless" must not look the same (#2644
|
|
222
|
+
* criterion 4).
|
|
223
|
+
*/
|
|
224
|
+
noFieldTable?: {
|
|
225
|
+
note: string;
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Shared spellings used by every configuration-object definition (issue #2644).
|
|
230
|
+
*
|
|
231
|
+
* These live in one module for a mechanical reason as much as a stylistic one:
|
|
232
|
+
* `cli/scripts/gen-config-surfaces.mjs` concatenates the whole directory into a
|
|
233
|
+
* single vendored artifact, so a `const handler = …` declared per definition
|
|
234
|
+
* module would collide as a duplicate identifier the moment a second object was
|
|
235
|
+
* migrated.
|
|
236
|
+
*
|
|
237
|
+
* Pure: no models, no tenant context, no `env` (see `types.ts` §Purity).
|
|
238
|
+
*/
|
|
239
|
+
/** Both write modes — the common case, spelled once. */
|
|
240
|
+
export declare const BOTH: readonly ("create" | "update")[];
|
|
241
|
+
/** Create only: an immutable key or a field the update handler ignores. */
|
|
242
|
+
export declare const CREATE_ONLY: readonly ("create" | "update")[];
|
|
243
|
+
/** Update only: a field the create handler assigns itself. */
|
|
244
|
+
export declare const UPDATE_ONLY: readonly ("create" | "update")[];
|
|
245
|
+
/**
|
|
246
|
+
* Name the handler that owns a field's validation, normalization and
|
|
247
|
+
* serialization, as `"<repo-relative module>#<export>"`. Classification only —
|
|
248
|
+
* the definition never dispatches through it (#1976 decision of record); the
|
|
249
|
+
* guard asserts the export exists so a renamed handler fails the CLI unit suite
|
|
250
|
+
* instead of leaving a dangling reference (#2644 behavior 2b).
|
|
251
|
+
*/
|
|
252
|
+
export declare function handledBy(modulePath: string, exportName: string): ConfigField["validation"];
|
|
253
|
+
/**
|
|
254
|
+
* The declared-access manifest's top-level TOML keys (#1304, #1364).
|
|
255
|
+
*
|
|
256
|
+
* Five objects carry the same three-key fragment beside their field table —
|
|
257
|
+
* workflows, database types, and the group / collection / metadata-category
|
|
258
|
+
* configs — parsed by the one `parseDeclaredAccessManifestToml`. Spelling it
|
|
259
|
+
* once here keeps `config push`'s document-level rejection from disagreeing with
|
|
260
|
+
* itself object by object.
|
|
261
|
+
*/
|
|
262
|
+
export declare const DECLARED_ACCESS_MANIFEST_KEYS: Readonly<Record<string, NotExposed>>;
|
|
263
|
+
/**
|
|
264
|
+
* The accepted-key half of a configuration object's definition (issue #2644).
|
|
265
|
+
*
|
|
266
|
+
* `pickWritableFields` answers exactly one question — "is this key writable on
|
|
267
|
+
* this object in this mode" — so a server handler stops naming the keys it
|
|
268
|
+
* accepts. What a present key MEANS stays with the per-field handler the
|
|
269
|
+
* definition names (spec §Contracts, decision of record #1976): the workflow
|
|
270
|
+
* `status` enum, the non-negative-integer coercion of the queue limits,
|
|
271
|
+
* `runAs`'s caller|system check, `parseWorkflowLock`, the `capabilities` array
|
|
272
|
+
* shape and the CEL parse of `accessRule` all stay where they are. The
|
|
273
|
+
* mechanical win is that a field can no longer be *absent* from the accepted
|
|
274
|
+
* set.
|
|
275
|
+
*
|
|
276
|
+
* Pure: no models, no tenant context, no `env` (see `types.ts` §Purity).
|
|
277
|
+
*/
|
|
278
|
+
export type WriteMode = "create" | "update";
|
|
279
|
+
/** The field names this table accepts on the wire in `mode`, in declaration order. */
|
|
280
|
+
export declare function writableFieldNames(table: ConfigTable, mode: WriteMode): string[];
|
|
281
|
+
/**
|
|
282
|
+
* The field names the server PERSISTS for this table in `mode`: the writable
|
|
283
|
+
* fields, plus the `deprecated` classifications — "still writable, superseded
|
|
284
|
+
* by another field" is what that kind means (`types.ts`), so a superseded key
|
|
285
|
+
* a handler still honors (`accessPolicy`, `passkeyRpId`) belongs in every
|
|
286
|
+
* accepted set, and a field that is NOT writable belongs in none of them.
|
|
287
|
+
*
|
|
288
|
+
* Stated once here because three consumers need the same answer: the generated
|
|
289
|
+
* request schemas, `PUT /settings`'s write allow-list, and the guards.
|
|
290
|
+
*/
|
|
291
|
+
export declare function acceptedWriteFieldNames(table: ConfigTable, mode: WriteMode): string[];
|
|
292
|
+
/**
|
|
293
|
+
* Split a request body into the keys this table accepts in `mode` and the keys
|
|
294
|
+
* it does not.
|
|
295
|
+
*
|
|
296
|
+
* `accepted` preserves the caller's values verbatim — including an explicit
|
|
297
|
+
* `null` or `false`, which are meaningful (clear / opt-out) and must not be
|
|
298
|
+
* coalesced away. Only keys the body actually carries appear, so a handler can
|
|
299
|
+
* keep using presence (`hasOwnProperty`) to distinguish "leave unset" from
|
|
300
|
+
* "set to null".
|
|
301
|
+
*
|
|
302
|
+
* `rejected` is every other key the body carried. Today it is informational;
|
|
303
|
+
* #2644 phase 5 turns it into a 400 through the generated request schemas.
|
|
304
|
+
*/
|
|
305
|
+
export declare function pickWritableFields(body: Record<string, unknown>, table: ConfigTable, mode: WriteMode): {
|
|
306
|
+
accepted: Record<string, unknown>;
|
|
307
|
+
rejected: string[];
|
|
308
|
+
};
|
|
309
|
+
/**
|
|
310
|
+
* The PASSTHROUGH half of the accepted body: the keys this table declares
|
|
311
|
+
* `validation: "passthrough"`, writable in `mode`, that the body actually
|
|
312
|
+
* carries — with their values verbatim.
|
|
313
|
+
*
|
|
314
|
+
* This is what makes criterion 1 true rather than aspirational. A handler that
|
|
315
|
+
* only picked its accepted set still had to name each field again when it built
|
|
316
|
+
* the row to persist, so a scalar field added to a definition alone was
|
|
317
|
+
* accepted on the wire and then dropped on the floor. Handlers spread this into
|
|
318
|
+
* the create/update payload FIRST, so a field with real behavior still lands
|
|
319
|
+
* through its named handler (whose assignment comes after and wins), and a
|
|
320
|
+
* plain scalar needs no handler edit at all.
|
|
321
|
+
*
|
|
322
|
+
* Values are passed through untouched — including an explicit `null` or
|
|
323
|
+
* `false`, which are meaningful (clear / opt-out). "Stored as-is" is exactly
|
|
324
|
+
* what the `passthrough` classification promises.
|
|
325
|
+
*/
|
|
326
|
+
export declare function passthroughFields(body: Record<string, unknown>, table: ConfigTable, mode: WriteMode, options?: {
|
|
327
|
+
/**
|
|
328
|
+
* Fields whose PRESENCE semantics this handler owns — it decides, per
|
|
329
|
+
* value, whether the key is written at all (a falsy `displayName` that
|
|
330
|
+
* means "leave the stored name alone"). Listing one here keeps the generic
|
|
331
|
+
* copy from changing what it means.
|
|
332
|
+
*
|
|
333
|
+
* This is never a place to list a field the handler does not assign: a
|
|
334
|
+
* field named here and dropped by the handler is written nowhere, which is
|
|
335
|
+
* the silent loss the definition exists to prevent. A NEW field needs no
|
|
336
|
+
* entry — omission is what makes it flow through.
|
|
337
|
+
*/
|
|
338
|
+
handledHere?: readonly string[];
|
|
339
|
+
}): Record<string, unknown>;
|
|
340
|
+
/** `true` when the body carries `field` and this table accepts it in `mode`. */
|
|
341
|
+
export declare function hasWritableField(accepted: Record<string, unknown>, field: string): boolean;
|
|
342
|
+
/**
|
|
343
|
+
* Coverage checks over a configuration object's definition (issue #2644,
|
|
344
|
+
* criteria 2 and 4).
|
|
345
|
+
*
|
|
346
|
+
* A definition claims to describe its model's WHOLE field surface. These
|
|
347
|
+
* functions are what make that claim mean something: every `models.yaml` field
|
|
348
|
+
* is either exposed in TOML or classified `notExposed` with a reason, in both
|
|
349
|
+
* directions — a new field nobody classified, and a classification for a field
|
|
350
|
+
* that no longer exists. `cli/tests/unit/config-surface-drift-guard.test.ts`
|
|
351
|
+
* asserts them over every registered object, so coverage follows from being a
|
|
352
|
+
* configuration object rather than from someone adding a per-type guard.
|
|
353
|
+
*
|
|
354
|
+
* Pure: no models, no tenant context, no `env` (see `types.ts` §Purity).
|
|
355
|
+
*/
|
|
356
|
+
/**
|
|
357
|
+
* `models.yaml` field names per model — the coverage anchor, passed in rather
|
|
358
|
+
* than read here so this module stays pure (the CLI's vendored artifact carries
|
|
359
|
+
* it as `GENERATED_CONFIG_MODEL_FIELDS`).
|
|
360
|
+
*/
|
|
361
|
+
export type ModelFieldMap = Readonly<Record<string, readonly string[]>>;
|
|
362
|
+
/**
|
|
363
|
+
* Whether a value counts as unset for an `emit: "whenSet"` field, so `config pull`
|
|
364
|
+
* omits the key instead of writing a noisy empty one (and `config diff` does not
|
|
365
|
+
* report a difference that is not there).
|
|
366
|
+
*
|
|
367
|
+
* Carried over verbatim from #1033's shipped app-settings descriptor
|
|
368
|
+
* (`cli/src/lib/app-settings-descriptor.ts`): an empty array and an empty
|
|
369
|
+
* object are unset, while `false` and `0` are meaningful values and never are.
|
|
370
|
+
*/
|
|
371
|
+
export declare function isEmptyForEmit(value: unknown, type: ConfigField["type"]): boolean;
|
|
372
|
+
/**
|
|
373
|
+
* A field name whose shape says it carries a credential. Such a field must be
|
|
374
|
+
* classified explicitly — exposed with a stated reference-only contract, or
|
|
375
|
+
* `notExposed: { kind: "secret" }` — because a mechanical generalization that
|
|
376
|
+
* merely omits it would read as "not decided" (#2254, #2256).
|
|
377
|
+
*/
|
|
378
|
+
export declare const SECRETISH_FIELD: RegExp;
|
|
379
|
+
/** Model fields the table neither exposes nor classifies. Non-empty is a failure. */
|
|
380
|
+
export declare function findUnclassifiedFields(table: ConfigTable, modelFields: readonly string[]): string[];
|
|
381
|
+
/**
|
|
382
|
+
* Classifications that no longer correspond to a model field — i.e. a field
|
|
383
|
+
* removed from `models.yaml` while the definition still names it. Also a
|
|
384
|
+
* failure: a stale classification must not silently pass, or the coverage claim
|
|
385
|
+
* quietly stops meaning anything.
|
|
386
|
+
*/
|
|
387
|
+
export declare function findStaleClassifications(table: ConfigTable, modelFields: readonly string[]): string[];
|
|
388
|
+
/** The models this surface's tables project, in declaration order, deduped. */
|
|
389
|
+
export declare function surfaceModels(surface: ConfigObjectSurface): string[];
|
|
390
|
+
/**
|
|
391
|
+
* Model fields the whole surface neither exposes nor classifies. Non-empty is
|
|
392
|
+
* a failure: the CLI would silently ignore them and a pull → push cycle would
|
|
393
|
+
* clear them (#2644 criterion 2).
|
|
394
|
+
*/
|
|
395
|
+
export declare function findUnclassifiedSurfaceFields(surface: ConfigObjectSurface, modelFields: ModelFieldMap): string[];
|
|
396
|
+
/**
|
|
397
|
+
* Classifications naming a field the model no longer has — the other direction,
|
|
398
|
+
* and equally a failure: a stale entry quietly stops meaning anything.
|
|
399
|
+
*/
|
|
400
|
+
export declare function findStaleSurfaceClassifications(surface: ConfigObjectSurface, modelFields: ModelFieldMap): string[];
|
|
401
|
+
/** Fields the surface both exposes and classifies `notExposed`. Ambiguous. */
|
|
402
|
+
export declare function findDoubleClassifiedSurfaceFields(surface: ConfigObjectSurface): string[];
|
|
403
|
+
/**
|
|
404
|
+
* Secret-adjacent model fields the surface leaves undecided — neither exposed
|
|
405
|
+
* with a stated contract nor classified `notExposed` (#2254, #2256).
|
|
406
|
+
*/
|
|
407
|
+
export declare function findUnclassifiedSecretishSurfaceFields(surface: ConfigObjectSurface, modelFields: ModelFieldMap): string[];
|
|
408
|
+
/** Fields classified twice — exposed AND `notExposed`. Ambiguous, so a failure. */
|
|
409
|
+
export declare function findDoubleClassifiedFields(table: ConfigTable): string[];
|
|
410
|
+
/**
|
|
411
|
+
* `notExposed` / `tomlOnlyKeys` / `responseOnlyKeys` entries whose `note` is
|
|
412
|
+
* missing or blank. A reason is the whole point of the classification.
|
|
413
|
+
*/
|
|
414
|
+
export declare function findReasonlessClassifications(table: ConfigTable): string[];
|
|
415
|
+
/**
|
|
416
|
+
* Secret-adjacent model fields with no explicit decision — neither an exposed
|
|
417
|
+
* entry nor a `notExposed` classification. A bare omission is the failure mode
|
|
418
|
+
* this catches.
|
|
419
|
+
*/
|
|
420
|
+
export declare function findUnclassifiedSecretishFields(table: ConfigTable, modelFields: readonly string[]): string[];
|
|
421
|
+
/**
|
|
422
|
+
* Every distinct handler reference the table names, as
|
|
423
|
+
* `"<repo-relative module>#<export>"`. The guard resolves each one and fails
|
|
424
|
+
* when the module or the export is missing (#2644 behavior 2b).
|
|
425
|
+
*/
|
|
426
|
+
export declare function handlerReferences(table: ConfigTable): string[];
|
|
427
|
+
/** TOML keys this table accepts: the exposed fields plus the declared extras. */
|
|
428
|
+
export declare function acceptedTomlKeys(table: ConfigTable): Set<string>;
|
|
429
|
+
/** Top-level TOML keys this object's file accepts: its tables plus the extras. */
|
|
430
|
+
export declare function acceptedTomlDocumentKeys(surface: ConfigObjectSurface): Set<string>;
|
|
431
|
+
/**
|
|
432
|
+
* `tomlDocumentKeys` entries with no reason, and any that merely restate a
|
|
433
|
+
* field table. Both are failures: a reason is the whole point of the
|
|
434
|
+
* classification, and a duplicate would let a table's shape check be bypassed
|
|
435
|
+
* by declaring it twice.
|
|
436
|
+
*/
|
|
437
|
+
export declare function findBadDocumentKeyDeclarations(surface: ConfigObjectSurface): string[];
|
|
438
|
+
/** Root keys of `tomlData` the surface does not declare. `config push` rejects these. */
|
|
439
|
+
export declare function findUnknownTomlDocumentKeys(surface: ConfigObjectSurface, tomlData: unknown): string[];
|
|
440
|
+
export declare function findMisshapenTomlTables(surface: ConfigObjectSurface, tomlData: unknown): Array<{
|
|
441
|
+
key: string;
|
|
442
|
+
expected: "table" | "array of tables";
|
|
443
|
+
}>;
|
|
444
|
+
/**
|
|
445
|
+
* Server-response keys this table recognizes: every model field (exposed or
|
|
446
|
+
* not) plus the declared response-only keys. `config pull` warns about anything
|
|
447
|
+
* else instead of dropping it silently (#2644 criterion 6).
|
|
448
|
+
*/
|
|
449
|
+
export declare function recognizedResponseKeys(table: ConfigTable, modelFields: readonly string[]): Set<string>;
|
|
450
|
+
/**
|
|
451
|
+
* Request schemas generated from the configuration-object definitions
|
|
452
|
+
* (issue #2644, phase 5 / criterion 9).
|
|
453
|
+
*
|
|
454
|
+
* Every create/update handler in this family used to drop, in silence, any body
|
|
455
|
+
* key it did not read. A client sending `timoutMs` for `timeoutMs` got a 200 and
|
|
456
|
+
* no timeout change. These schemas close that: one per object and mode,
|
|
457
|
+
* `additionalProperties: false`, properties = the keys that object accepts on
|
|
458
|
+
* the wire in that mode, so an unknown key is a 400 naming it.
|
|
459
|
+
*
|
|
460
|
+
* **Breaking change, named**: a client that sends a stray key and gets a 200
|
|
461
|
+
* today will get a 400. The CLI never hits it — `config push` already rejects
|
|
462
|
+
* unrecognized TOML keys locally (criterion 6).
|
|
463
|
+
*
|
|
464
|
+
* ── What the schema says, and what it deliberately does not ──────────────
|
|
465
|
+
* It states the KEY SET only: each property is the empty schema, so no value is
|
|
466
|
+
* type-checked here. That is the decision of record (#1976, carried forward at
|
|
467
|
+
* #2644's design gate): the definition classifies, handlers behave. The
|
|
468
|
+
* `status` enum, the queue limits' integer coercion, `runAs`'s caller|system
|
|
469
|
+
* check, the CEL parse of `accessRule` — all stay in the handlers the
|
|
470
|
+
* definition names, with their existing messages. Adding type gates here would
|
|
471
|
+
* duplicate them and start rejecting values the handlers accept.
|
|
472
|
+
*
|
|
473
|
+
* ── Which keys are in the set ────────────────────────────────────────────
|
|
474
|
+
* Derived, not listed:
|
|
475
|
+
*
|
|
476
|
+
* - every field the definition says is writable in this mode;
|
|
477
|
+
* - every field classified `structural` — the authored sub-trees that travel
|
|
478
|
+
* on their own channel (`rules`, `steps`, `metadataManifest`, `schema`,
|
|
479
|
+
* `triggers`) but are still sent in the body — in the modes that entry
|
|
480
|
+
* declares (`requestModes`; omitted means both, `[]` means the key travels
|
|
481
|
+
* in the URL path and no schema admits it);
|
|
482
|
+
* - every field classified `deprecated` — still writable server-side, by
|
|
483
|
+
* definition of that classification;
|
|
484
|
+
* - the table's `requestOnlyKeys`, in the modes each declares: protocol keys
|
|
485
|
+
* that are not model fields at all, such as the `expectedModifiedAt`
|
|
486
|
+
* optimistic-concurrency token or a create-only alias.
|
|
487
|
+
*
|
|
488
|
+
* `server-owned` and `secret` classifications are the two the schema excludes:
|
|
489
|
+
* the first is assigned by the server, the second never travels in readable
|
|
490
|
+
* form.
|
|
491
|
+
*
|
|
492
|
+
* Pure: no models, no tenant context, no `env` (see `types.ts` §Purity).
|
|
493
|
+
*/
|
|
494
|
+
/**
|
|
495
|
+
* A generated request schema. Shaped for the app API's `meta.request` slot and
|
|
496
|
+
* the runtime validator it feeds (`src/app-api/request-validation.ts`), which
|
|
497
|
+
* reports an unknown key as `value.<key> is not allowed`.
|
|
498
|
+
*/
|
|
499
|
+
export interface ConfigRequestSchema {
|
|
500
|
+
type: "object";
|
|
501
|
+
properties: Record<string, Record<string, never>>;
|
|
502
|
+
additionalProperties: false;
|
|
503
|
+
/**
|
|
504
|
+
* Structural-typing escape hatch: the app API's `meta.request` slot is a
|
|
505
|
+
* `Record<string, unknown>` (`JsonSchema`), and an interface with no index
|
|
506
|
+
* signature is not assignable to one. Declaring the index here keeps the
|
|
507
|
+
* generated schema usable as a route schema without an `as any` at every
|
|
508
|
+
* call site.
|
|
509
|
+
*/
|
|
510
|
+
[key: string]: unknown;
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Protocol keys every config UPDATE accepts, whichever object it is.
|
|
514
|
+
*
|
|
515
|
+
* `expectedModifiedAt` is the optimistic-concurrency token `config push` attaches
|
|
516
|
+
* to an update body when it has a baseline from the last pull; a handler that
|
|
517
|
+
* does not implement conflict detection ignores it. It is a property of the
|
|
518
|
+
* sync protocol rather than of any one object, which is why it is stated once
|
|
519
|
+
* here instead of in thirteen definitions.
|
|
520
|
+
*/
|
|
521
|
+
export declare const UPDATE_PROTOCOL_KEYS: readonly string[];
|
|
522
|
+
/** The body keys this table accepts in `mode`, in a stable order. */
|
|
523
|
+
export declare function requestSchemaKeys(table: ConfigTable, mode: "create" | "update"): string[];
|
|
524
|
+
/**
|
|
525
|
+
* The request schema for one object and mode. Generated from the definition, so
|
|
526
|
+
* a schema permitting a key the definition does not is unrepresentable: there
|
|
527
|
+
* is no place to write one.
|
|
528
|
+
*/
|
|
529
|
+
export declare function configRequestSchema(table: ConfigTable, mode: "create" | "update"): ConfigRequestSchema;
|
|
530
|
+
/**
|
|
531
|
+
* The retired-key guidance for a generated schema, keyed by body key — or
|
|
532
|
+
* `undefined` when the schema's object has none. Consumed by the app API's
|
|
533
|
+
* request validator (`src/app-api/request-validation.ts`).
|
|
534
|
+
*/
|
|
535
|
+
export declare function retiredRequestKeys(schema: object | undefined): Readonly<Record<string, string>> | undefined;
|
|
536
|
+
/**
|
|
537
|
+
* One schema for an endpoint whose body spans MORE than one table.
|
|
538
|
+
*
|
|
539
|
+
* `POST …/prompts` is the case: it creates the prompt AND seeds its first
|
|
540
|
+
* config, so the body carries `[prompt]` fields and `[[configs]]` fields
|
|
541
|
+
* together. Both halves still come from their definitions — this only says the
|
|
542
|
+
* endpoint accepts the union, in the one place that is true.
|
|
543
|
+
*/
|
|
544
|
+
export declare function mergeRequestSchemas(...schemas: readonly ConfigRequestSchema[]): ConfigRequestSchema;
|
|
545
|
+
/**
|
|
546
|
+
* The body keys `table` does not accept in `mode` — the 400's subject.
|
|
547
|
+
*
|
|
548
|
+
* Used by the admin API, which has no request-schema middleware: its handlers
|
|
549
|
+
* call this directly so both APIs reject the same key set for the same object.
|
|
550
|
+
*/
|
|
551
|
+
export declare function unknownRequestKeys(body: unknown, table: ConfigTable, mode: "create" | "update"): string[];
|
|
552
|
+
/** The 400 message naming the unknown key(s), shared by both APIs. */
|
|
553
|
+
export declare function unknownRequestKeysMessage(keys: readonly string[]): string;
|
|
554
|
+
/**
|
|
555
|
+
* Keys deliberately RETIRED from a configuration object's write surface.
|
|
556
|
+
*
|
|
557
|
+
* A retired key is not an unknown key. The generic hint for an unrecognized
|
|
558
|
+
* TOML key — "check the spelling, or upgrade the CLI" — is exactly backwards
|
|
559
|
+
* for one this CLI removed on purpose, and the generic 400 for an unaccepted
|
|
560
|
+
* request key says only that the key is not allowed, not where the value moved
|
|
561
|
+
* to. Both surfaces need the same sentence, and neither should invent it.
|
|
562
|
+
*
|
|
563
|
+
* So the guidance lives here, next to the definitions, with one entry per
|
|
564
|
+
* retired key: the TOML wording for `config push` (which can tell the author to
|
|
565
|
+
* delete a line) and the request wording for the API handlers (which cannot).
|
|
566
|
+
*
|
|
567
|
+
* Keyed by the table's TOML path prefix (`workflow`, `cronTrigger`, …), because
|
|
568
|
+
* that is the identifier both consumers already have in hand.
|
|
569
|
+
*
|
|
570
|
+
* Pure: no models, no tenant context, no `env` (see `types.ts` §Purity).
|
|
571
|
+
*/
|
|
572
|
+
export interface RetiredConfigKey {
|
|
573
|
+
/** What `config push` says about a file that still carries the key. */
|
|
574
|
+
toml: string;
|
|
575
|
+
/** What a create/update handler says about a body that still sends it. */
|
|
576
|
+
request: string;
|
|
577
|
+
}
|
|
578
|
+
export declare const RETIRED_CONFIG_KEYS: Record<string, Record<string, RetiredConfigKey>>;
|
|
579
|
+
/** The retired-key entry for `key` under `prefix`, or null when it is simply unknown. */
|
|
580
|
+
export declare function retiredConfigKey(prefix: string, key: string): RetiredConfigKey | null;
|
|
581
|
+
export declare const WORKFLOW_SURFACE: ConfigObjectSurface;
|
|
582
|
+
export declare const PROMPT_SURFACE: ConfigObjectSurface;
|
|
583
|
+
export declare const INTEGRATION_SURFACE: ConfigObjectSurface;
|
|
584
|
+
export declare const WEBHOOK_SURFACE: ConfigObjectSurface;
|
|
585
|
+
export declare const CRON_TRIGGER_SURFACE: ConfigObjectSurface;
|
|
586
|
+
export declare const BLOB_BUCKET_SURFACE: ConfigObjectSurface;
|
|
587
|
+
/**
|
|
588
|
+
* The `email-template` configuration object's definition (issue #2644, phase 2).
|
|
589
|
+
*
|
|
590
|
+
* `email-templates/<emailType>.toml` carries a single `[template]` table. The
|
|
591
|
+
* object is an OVERRIDE of a built-in template: the detail response is
|
|
592
|
+
* `{ emailType, hasOverride, override: {...}, default: {...} }`, and only the
|
|
593
|
+
* `override` half is a field surface — the `default` half is what the platform
|
|
594
|
+
* ships. Both are declared as response-only keys so `config pull`'s
|
|
595
|
+
* unrecognized-key warning reports genuinely unknown fields rather than the
|
|
596
|
+
* envelope.
|
|
597
|
+
*
|
|
598
|
+
* There is one write endpoint (`PUT …/email-templates/{emailType}`, an upsert),
|
|
599
|
+
* so every field is writable on both modes.
|
|
600
|
+
*/
|
|
601
|
+
/**
|
|
602
|
+
* Email types RETIRED by #2884, kept named rather than simply deleted.
|
|
603
|
+
*
|
|
604
|
+
* Email sign-in sends ONE email from the `email-sign-in` template, so
|
|
605
|
+
* `magic-link` and `otp` are no longer rendered by any code path — which is
|
|
606
|
+
* what makes deleting the link block from an `email-sign-in` override an
|
|
607
|
+
* actual guarantee rather than a hope about which endpoint ran.
|
|
608
|
+
*
|
|
609
|
+
* A stored override for a retired type is NOT deleted: it stays listed and
|
|
610
|
+
* readable (labelled retired, with the guidance below) so an app can find its
|
|
611
|
+
* customization and migrate it, and deleting it still works. Everything that
|
|
612
|
+
* would author one — the admin write/preview/test endpoints, `config create`,
|
|
613
|
+
* a `config push --only` selector — refuses by name instead. Silent
|
|
614
|
+
* non-rendering is the outcome all of that exists to avoid.
|
|
615
|
+
*
|
|
616
|
+
* It lives in the config surface, not beside the default templates, because
|
|
617
|
+
* the CLI vendors this directory and needs the same sentence.
|
|
618
|
+
*/
|
|
619
|
+
export declare const RETIRED_EMAIL_TYPES: readonly ["magic-link", "otp"];
|
|
620
|
+
export type RetiredEmailType = (typeof RETIRED_EMAIL_TYPES)[number];
|
|
621
|
+
/** True when `emailType` is one of the retired sign-in types. */
|
|
622
|
+
export declare function isRetiredEmailType(emailType: string): emailType is RetiredEmailType;
|
|
623
|
+
/** What every surface says about a retired type, in one sentence. */
|
|
624
|
+
export declare function retiredEmailTypeGuidance(emailType: string): string;
|
|
625
|
+
export declare const EMAIL_TEMPLATE_SURFACE: ConfigObjectSurface;
|
|
626
|
+
export declare const DATABASE_TYPE_SURFACE: ConfigObjectSurface;
|
|
627
|
+
export declare const RULE_SET_SURFACE: ConfigObjectSurface;
|
|
628
|
+
export declare const GROUP_TYPE_CONFIG_SURFACE: ConfigObjectSurface;
|
|
629
|
+
export declare const COLLECTION_TYPE_CONFIG_SURFACE: ConfigObjectSurface;
|
|
630
|
+
export declare const METADATA_CATEGORY_CONFIG_SURFACE: ConfigObjectSurface;
|
|
631
|
+
/**
|
|
632
|
+
* The `transform` configuration object's definition (issue #2644, phase 3).
|
|
633
|
+
*
|
|
634
|
+
* Transforms are the one synced type with NO TOML field table: a transform is
|
|
635
|
+
* `transforms/<name>.rhai`, a Rhai source file, and its whole authored surface
|
|
636
|
+
* is the script body. `config pull` writes the active `ScriptConfig`'s body and
|
|
637
|
+
* `config push` sends it back; there is no key/value table to define, and the
|
|
638
|
+
* `Script` / `ScriptConfig` scalars around it (name, description, inputSchema,
|
|
639
|
+
* limits, status) are not authorable through the sync slot today.
|
|
640
|
+
*
|
|
641
|
+
* The entry exists so that is a DECISION rather than an absence. Criterion 3's
|
|
642
|
+
* registry guard reads `SYNC_RESOURCE_TYPES` and requires a surface per label;
|
|
643
|
+
* without this module `transform` would have to sit in an exemption list, which
|
|
644
|
+
* is precisely the "absent from a hand-written list" failure mode this epic
|
|
645
|
+
* exists to end.
|
|
646
|
+
*/
|
|
647
|
+
export declare const TRANSFORM_SURFACE: ConfigObjectSurface;
|
|
648
|
+
export declare const TEST_CASE_SURFACE: ConfigObjectSurface;
|
|
649
|
+
export declare const APP_SETTINGS_SURFACE: ConfigObjectSurface;
|
|
650
|
+
/**
|
|
651
|
+
* The configuration-object registry (issue #2644).
|
|
652
|
+
*
|
|
653
|
+
* `CONFIG_SURFACES` holds one entry per synced configuration object type. The
|
|
654
|
+
* registry — not a per-type test — is what makes coverage follow from existing:
|
|
655
|
+
* `cli/tests/unit/config-surface-drift-guard.test.ts` reads the CLI's
|
|
656
|
+
* `SYNC_RESOURCE_TYPES` labels and fails when a label has no surface here.
|
|
657
|
+
*
|
|
658
|
+
* `CONFIG_SURFACES` is the write authority. `SYNC_RESOURCE_TYPES` keeps its
|
|
659
|
+
* documented role — directory/state/prune/diff layout metadata, explicitly "not
|
|
660
|
+
* a write framework" — and gains no write-surface fields; the two are
|
|
661
|
+
* cross-checked, not merged.
|
|
662
|
+
*/
|
|
663
|
+
/**
|
|
664
|
+
* Every configuration object whose field surface is defined here.
|
|
665
|
+
*
|
|
666
|
+
* One entry per `SYNC_RESOURCE_TYPES` label, plus the two surfaces that
|
|
667
|
+
* round-trip without being a per-entity file: `app-settings` (`app.toml`) and
|
|
668
|
+
* `test-case` (`<key>.tests/`). Nothing that syncs sits outside the registry —
|
|
669
|
+
* `PENDING_MIGRATION`, the migration's temporary exemption list, is gone as of
|
|
670
|
+
* phase 3, so a new synced type has nowhere to be parked and fails the registry
|
|
671
|
+
* guard until it is defined (#2644 criterion 3).
|
|
672
|
+
*/
|
|
673
|
+
export declare const CONFIG_SURFACES: readonly ConfigObjectSurface[];
|
|
674
|
+
/** The surface for a `SyncResourceType.label`, or undefined when unmigrated. */
|
|
675
|
+
export declare function getConfigSurface(label: string): ConfigObjectSurface | undefined;
|
|
676
|
+
/** One table of one surface, addressed by its TOML path. */
|
|
677
|
+
export declare function getConfigTable(label: string, tomlPath: readonly string[]): ConfigTable | undefined;
|
|
678
|
+
/**
|
|
679
|
+
* Every field of every `models.yaml` model a configuration-object definition
|
|
680
|
+
* names, in declaration order — the coverage guard's anchor (#2644 criterion 2).
|
|
681
|
+
*/
|
|
682
|
+
export declare const GENERATED_CONFIG_MODEL_FIELDS: Readonly<Record<string, readonly string[]>>;
|