primitive-admin 1.1.0-alpha.81 → 1.1.0-alpha.83
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/assets/skill/skills/primitive-platform/SKILL.md +12 -0
- package/dist/src/commands/documents.js +455 -22
- package/dist/src/commands/documents.js.map +1 -1
- package/dist/src/commands/functions.js +889 -76
- package/dist/src/commands/functions.js.map +1 -1
- package/dist/src/commands/locks.js +15 -1
- package/dist/src/commands/locks.js.map +1 -1
- package/dist/src/commands/prompts.js +19 -2
- package/dist/src/commands/prompts.js.map +1 -1
- package/dist/src/commands/sync.d.ts +50 -0
- package/dist/src/commands/sync.js +587 -316
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/commands/workflows.d.ts +1 -29
- package/dist/src/commands/workflows.js +8 -109
- package/dist/src/commands/workflows.js.map +1 -1
- package/dist/src/lib/api-client.d.ts +191 -2
- package/dist/src/lib/api-client.js +283 -7
- package/dist/src/lib/api-client.js.map +1 -1
- package/dist/src/lib/config-object-descriptor.js +12 -4
- package/dist/src/lib/config-object-descriptor.js.map +1 -1
- package/dist/src/lib/document-ingest-artifact.d.ts +120 -0
- package/dist/src/lib/document-ingest-artifact.js +505 -0
- package/dist/src/lib/document-ingest-artifact.js.map +1 -0
- package/dist/src/lib/document-ingest-input.d.ts +51 -0
- package/dist/src/lib/document-ingest-input.js +132 -0
- package/dist/src/lib/document-ingest-input.js.map +1 -0
- package/dist/src/lib/document-ingest.d.ts +78 -0
- package/dist/src/lib/document-ingest.js +231 -0
- package/dist/src/lib/document-ingest.js.map +1 -0
- package/dist/src/lib/env-resolver-core.d.ts +2 -2
- package/dist/src/lib/env-resolver-core.js +2 -2
- package/dist/src/lib/function-bundle.d.ts +6 -0
- package/dist/src/lib/function-bundle.js +8 -0
- package/dist/src/lib/function-bundle.js.map +1 -1
- package/dist/src/lib/function-collect.d.ts +1 -1
- package/dist/src/lib/function-collect.js +16 -0
- package/dist/src/lib/function-collect.js.map +1 -1
- package/dist/src/lib/function-db-types.d.ts +4 -0
- package/dist/src/lib/function-db-types.js +46 -2
- package/dist/src/lib/function-db-types.js.map +1 -1
- package/dist/src/lib/function-document-types.d.ts +83 -0
- package/dist/src/lib/function-document-types.js +137 -0
- package/dist/src/lib/function-document-types.js.map +1 -1
- package/dist/src/lib/function-grants-preflight.js +5 -0
- package/dist/src/lib/function-grants-preflight.js.map +1 -1
- package/dist/src/lib/function-log-lines.d.ts +76 -0
- package/dist/src/lib/function-log-lines.js +160 -0
- package/dist/src/lib/function-log-lines.js.map +1 -0
- package/dist/src/lib/function-log-row.d.ts +29 -0
- package/dist/src/lib/function-log-row.js +73 -0
- package/dist/src/lib/function-log-row.js.map +1 -0
- package/dist/src/lib/function-log-tail.d.ts +51 -2
- package/dist/src/lib/function-log-tail.js +160 -13
- package/dist/src/lib/function-log-tail.js.map +1 -1
- package/dist/src/lib/function-run.d.ts +289 -0
- package/dist/src/lib/function-run.js +389 -0
- package/dist/src/lib/function-run.js.map +1 -0
- package/dist/src/lib/function-schema-codegen.d.ts +17 -9
- package/dist/src/lib/function-schema-codegen.js +30 -29
- package/dist/src/lib/function-schema-codegen.js.map +1 -1
- package/dist/src/lib/function-sync.d.ts +226 -30
- package/dist/src/lib/function-sync.js +731 -77
- package/dist/src/lib/function-sync.js.map +1 -1
- package/dist/src/lib/function-versions.d.ts +122 -0
- package/dist/src/lib/function-versions.js +182 -0
- package/dist/src/lib/function-versions.js.map +1 -0
- package/dist/src/lib/generated-config-surfaces.d.ts +561 -91
- package/dist/src/lib/generated-config-surfaces.js +1858 -287
- package/dist/src/lib/generated-config-surfaces.js.map +1 -1
- package/dist/src/lib/generated-sdk-types.d.ts +1 -1
- package/dist/src/lib/generated-sdk-types.js +1 -1
- package/dist/src/lib/generated-sdk-types.js.map +1 -1
- package/dist/src/lib/log-inspection.d.ts +2 -0
- package/dist/src/lib/log-inspection.js +4 -0
- package/dist/src/lib/log-inspection.js.map +1 -1
- package/dist/src/lib/output.d.ts +15 -0
- package/dist/src/lib/output.js +28 -0
- package/dist/src/lib/output.js.map +1 -1
- package/dist/src/lib/prompt-schema-codegen.d.ts +94 -0
- package/dist/src/lib/prompt-schema-codegen.js +212 -0
- package/dist/src/lib/prompt-schema-codegen.js.map +1 -0
- package/dist/src/lib/snapshot-audit-source.d.ts +45 -0
- package/dist/src/lib/snapshot-audit-source.js +58 -0
- package/dist/src/lib/snapshot-audit-source.js.map +1 -0
- package/dist/src/lib/snapshot-audit-store.d.ts +52 -0
- package/dist/src/lib/snapshot-audit-store.js +196 -0
- package/dist/src/lib/snapshot-audit-store.js.map +1 -0
- package/dist/src/lib/snapshot-audit.d.ts +207 -0
- package/dist/src/lib/snapshot-audit.js +431 -0
- package/dist/src/lib/snapshot-audit.js.map +1 -0
- package/dist/src/lib/snapshot-build-rows.d.ts +60 -0
- package/dist/src/lib/snapshot-build-rows.js +87 -0
- package/dist/src/lib/snapshot-build-rows.js.map +1 -0
- package/dist/src/lib/snapshot-manifest-layout.d.ts +61 -0
- package/dist/src/lib/snapshot-manifest-layout.js +70 -0
- package/dist/src/lib/snapshot-manifest-layout.js.map +1 -0
- package/dist/src/lib/step-run-table.d.ts +43 -0
- package/dist/src/lib/step-run-table.js +129 -0
- package/dist/src/lib/step-run-table.js.map +1 -0
- package/dist/src/lib/swift-codegen/functionGenerator.d.ts +26 -13
- package/dist/src/lib/swift-codegen/functionGenerator.js +38 -27
- package/dist/src/lib/swift-codegen/functionGenerator.js.map +1 -1
- package/dist/src/lib/sync-selectors.d.ts +45 -2
- package/dist/src/lib/sync-selectors.js +66 -5
- package/dist/src/lib/sync-selectors.js.map +1 -1
- package/dist/src/lib/workflow-toml-validator.d.ts +9 -5
- package/dist/src/lib/workflow-toml-validator.js +18 -10
- package/dist/src/lib/workflow-toml-validator.js.map +1 -1
- package/package.json +2 -2
|
@@ -110,9 +110,19 @@ export interface ConfigField {
|
|
|
110
110
|
* `"src/workflows/config/workflow-field-handlers.ts#normalizeWorkflowStatus"`.
|
|
111
111
|
* `cli/tests/unit/config-surface-drift-guard.test.ts` fails when the module or
|
|
112
112
|
* the export is missing (#2644 behavior 2b).
|
|
113
|
+
*
|
|
114
|
+
* `stage` says WHEN the handler runs, with exactly the meaning `RuleStage`
|
|
115
|
+
* gives a cross-field rule (#3375). Until this issue the slot named an owner
|
|
116
|
+
* and never said when, so intent criterion 5 — "a rule declared `preflight`
|
|
117
|
+
* is provably reached before the first mutating call" — could not cover a
|
|
118
|
+
* single-field rule at all. It is REQUIRED, so a new field handler cannot be
|
|
119
|
+
* declared without answering the question, and
|
|
120
|
+
* `findMalformedFieldValidationStages` closes the key set at
|
|
121
|
+
* `handler`/`stage`: the slot stays declarative like the field entry itself.
|
|
113
122
|
*/
|
|
114
123
|
validation: "passthrough" | {
|
|
115
124
|
handler: string;
|
|
125
|
+
stage: RuleStage;
|
|
116
126
|
};
|
|
117
127
|
/**
|
|
118
128
|
* This field's declared type genuinely admits more than one TOML spelling
|
|
@@ -207,7 +217,18 @@ export interface ConfigTable {
|
|
|
207
217
|
* CLI call exists would make the registry promise a refusal that in fact lands
|
|
208
218
|
* mid-apply.
|
|
209
219
|
*/
|
|
210
|
-
export type
|
|
220
|
+
export type RuleStage = "preflight" | "apply";
|
|
221
|
+
/**
|
|
222
|
+
* The cross-field spelling of `RuleStage`, kept as an exported alias.
|
|
223
|
+
*
|
|
224
|
+
* #3373 named the type for the only slot that had a stage. #3375 gave
|
|
225
|
+
* `ConfigField.validation` one too, with the same meaning, so the canonical
|
|
226
|
+
* name is the general one — and this alias stays because it is part of the
|
|
227
|
+
* registry's published surface (`CrossFieldRule.stage`, the guard, every
|
|
228
|
+
* `crossFieldRulesForStage` caller) and renaming it would be a breaking change
|
|
229
|
+
* to buy a shorter name.
|
|
230
|
+
*/
|
|
231
|
+
export type CrossFieldRuleStage = RuleStage;
|
|
211
232
|
/**
|
|
212
233
|
* One rule of a configuration object that spans more than one field — `durable
|
|
213
234
|
* = true` beside a webhook trigger, `runAs = "system"` beside a non-empty
|
|
@@ -337,8 +358,15 @@ export declare const UPDATE_ONLY: readonly ("create" | "update")[];
|
|
|
337
358
|
* the definition never dispatches through it (#1976 decision of record); the
|
|
338
359
|
* guard asserts the export exists so a renamed handler fails the CLI unit suite
|
|
339
360
|
* instead of leaving a dangling reference (#2644 behavior 2b).
|
|
361
|
+
*
|
|
362
|
+
* `stage` is REQUIRED (#3375): a field handler that does not say when it runs
|
|
363
|
+
* makes the same empty promise the cross-field slot made before #3373 — it
|
|
364
|
+
* names an owner, and criterion 5 has nothing to check. A `preflight` handler
|
|
365
|
+
* is reached from `cli/src/commands/sync.ts#runConfigPushPreflight` before the
|
|
366
|
+
* first mutating call, which `findUnreachedPreflightRules` proves statically;
|
|
367
|
+
* an `apply` handler is everything else.
|
|
340
368
|
*/
|
|
341
|
-
export declare function handledBy(modulePath: string, exportName: string): ConfigField["validation"];
|
|
369
|
+
export declare function handledBy(modulePath: string, exportName: string, stage: RuleStage): ConfigField["validation"];
|
|
342
370
|
/**
|
|
343
371
|
* Name the ONE export that enforces a cross-field rule, as
|
|
344
372
|
* `"<repo-relative module>#<export>"` — the sibling of `handledBy` for a rule
|
|
@@ -739,6 +767,115 @@ export declare function hasDeclaredCrossFieldRules(surface: ConfigObjectSurface)
|
|
|
739
767
|
* `[]`: "not declared yet" must never be read as "has no rules" (principle 6).
|
|
740
768
|
*/
|
|
741
769
|
export declare function crossFieldRulesForStage(surface: ConfigObjectSurface, stage: CrossFieldRuleStage): readonly CrossFieldRule[];
|
|
770
|
+
/**
|
|
771
|
+
* Is a rule declared `preflight` actually reached before `config push` mutates
|
|
772
|
+
* anything? (issue #3375, project phase 3, intent §Success criteria 5.)
|
|
773
|
+
*
|
|
774
|
+
* #3373 gave a rule a `stage`; #3374 declared three surfaces' rules. Both left
|
|
775
|
+
* the string a PROMISE. "This runs before the first mutating call" was
|
|
776
|
+
* satisfied by typing `preflight` beside a rule that is not on the preflight
|
|
777
|
+
* path at all, because the push preflight was an inline block inside the
|
|
778
|
+
* command's `.action()` callback with no exported symbol — so "reached from the
|
|
779
|
+
* preflight" had nothing to resolve against.
|
|
780
|
+
*
|
|
781
|
+
* #3375 extracts that block into `cli/src/commands/sync.ts#runConfigPushPreflight`
|
|
782
|
+
* and this module answers the question statically, from the declared
|
|
783
|
+
* `<module>#<export>`:
|
|
784
|
+
*
|
|
785
|
+
* - `reachableExports` walks the call graph from one entry symbol over module
|
|
786
|
+
* SOURCE TEXT and returns what it reached — plus what it could NOT resolve,
|
|
787
|
+
* so silence is never a pass.
|
|
788
|
+
* - `findUnreachedPreflightRules` reports every `preflight` declaration,
|
|
789
|
+
* cross-field or single-field, whose handler is missing from that set.
|
|
790
|
+
* - `findMalformedFieldValidationStages` is the field-level twin of #3373's
|
|
791
|
+
* `findMalformedRuleDeclarations`: `ConfigField["validation"]` gained a
|
|
792
|
+
* `stage` here, and it must be well-formed to mean anything.
|
|
793
|
+
*
|
|
794
|
+
* Everything is a PURE function over values and over source text the caller
|
|
795
|
+
* passes in: `cli/tests/unit/config-surface-preflight-staging-3375.test.ts`
|
|
796
|
+
* does the filesystem walk, so this module stays vendorable (`types.ts`
|
|
797
|
+
* §Purity), exactly the split `rules.ts` already uses.
|
|
798
|
+
*
|
|
799
|
+
* ── Two things this check is NOT ──────────────────────────────────────────
|
|
800
|
+
*
|
|
801
|
+
* It is NECESSARY, not sufficient, and there is deliberately no converse. A
|
|
802
|
+
* handler reached on one surface's leg satisfies a `preflight` declaration on
|
|
803
|
+
* another (the residual the intent accepts and #3379 records), and asking "is
|
|
804
|
+
* this `apply` rule reached from the preflight?" would be wrong by
|
|
805
|
+
* construction: `validateSigningSecretDeclaration` IS reached on the function
|
|
806
|
+
* leg and IS correctly `apply` on the webhook surface, where no CLI call
|
|
807
|
+
* exists.
|
|
808
|
+
*
|
|
809
|
+
* The walk is identifier-based over masked source, so it over-approximates in
|
|
810
|
+
* the PASSING direction: a local variable shadowing an imported handler's name
|
|
811
|
+
* reads as a call. That is the safe direction for a guard whose failure mode
|
|
812
|
+
* must be "a promise you did not keep", not "a promise you did keep, reported
|
|
813
|
+
* as broken".
|
|
814
|
+
*/
|
|
815
|
+
/** A field's `validation` object may carry these keys and no others (#3375). */
|
|
816
|
+
export declare const FIELD_VALIDATION_KEYS: readonly string[];
|
|
817
|
+
/**
|
|
818
|
+
* The modules a walk may read, and how a specifier resolves between them.
|
|
819
|
+
*
|
|
820
|
+
* The caller owns resolution because it owns the filesystem: the CLI test maps
|
|
821
|
+
* both spellings of the vendored artifact onto the `src/config-surface/`
|
|
822
|
+
* modules it is a copy of, which is the whole point of DSO-3375-002 — the
|
|
823
|
+
* generator strips every intra-directory import before concatenating, so the
|
|
824
|
+
* artifact itself carries no edges between its sections.
|
|
825
|
+
*/
|
|
826
|
+
export interface StaticModuleGraph {
|
|
827
|
+
/** Repo-relative module path → that module's SOURCE TEXT. */
|
|
828
|
+
modules: ReadonlyMap<string, string>;
|
|
829
|
+
/**
|
|
830
|
+
* Candidate modules a specifier names, seen from `fromModule`.
|
|
831
|
+
*
|
|
832
|
+
* `null` = a bare package specifier: deliberately not followed, and never
|
|
833
|
+
* reported. `[]` = a relative specifier that resolves to no module in the
|
|
834
|
+
* graph, which IS reported — a guard that silently stops looking is worse
|
|
835
|
+
* than no guard.
|
|
836
|
+
*/
|
|
837
|
+
resolve(fromModule: string, specifier: string): readonly string[] | null;
|
|
838
|
+
}
|
|
839
|
+
/** What one walk found, and what it could not resolve on the way. */
|
|
840
|
+
export interface ReachabilityWalk {
|
|
841
|
+
/** `<module>#<export>` for every symbol reached, module = where it is DECLARED. */
|
|
842
|
+
reached: ReadonlySet<string>;
|
|
843
|
+
/** Specifiers and entry symbols the graph could not answer for, sorted. */
|
|
844
|
+
unresolved: string[];
|
|
845
|
+
}
|
|
846
|
+
/**
|
|
847
|
+
* Walk the call graph from `entry` and return every symbol it reaches.
|
|
848
|
+
*
|
|
849
|
+
* An identifier inside a reached declaration's span is followed when it names
|
|
850
|
+
* another top-level declaration of the same module, or a value import — which
|
|
851
|
+
* resolves through the graph to whichever candidate module DECLARES the name,
|
|
852
|
+
* following `export { x } from` and `export * from` on the way. A symbol is
|
|
853
|
+
* recorded under the module that declares it, never under a barrel that merely
|
|
854
|
+
* re-exports it: a declaration that names the barrel is reported unreached,
|
|
855
|
+
* because the point of the string is to name the one implementation.
|
|
856
|
+
*/
|
|
857
|
+
export declare function reachableExports(entry: string, graph: StaticModuleGraph): ReachabilityWalk;
|
|
858
|
+
/**
|
|
859
|
+
* Every fault in one surface's FIELD validation declarations, each naming the
|
|
860
|
+
* surface and the field. `[]` means every field is well-formed.
|
|
861
|
+
*
|
|
862
|
+
* Runs over every surface in the registry, migrated or not: field declarations
|
|
863
|
+
* exist independently of the cross-field slot, so the
|
|
864
|
+
* `CROSS_FIELD_RULES_UNMIGRATED` ratchet does not — and must not — stand
|
|
865
|
+
* between a field-level `preflight` declaration and this check (DSO-3375-001).
|
|
866
|
+
*/
|
|
867
|
+
export declare function findMalformedFieldValidationStages(surface: ConfigObjectSurface): string[];
|
|
868
|
+
/**
|
|
869
|
+
* Every `preflight` declaration on this surface whose handler the walk did not
|
|
870
|
+
* reach, each naming the surface, the rule (or field), the handler and the
|
|
871
|
+
* entry point.
|
|
872
|
+
*
|
|
873
|
+
* The FIELD half runs on every surface. The CROSS-FIELD half runs only where a
|
|
874
|
+
* surface has declared, because `crossFieldRulesForStage` throws for one that
|
|
875
|
+
* has not — "not declared yet" is never "rule-free" (#3373), and asking it
|
|
876
|
+
* here would turn an unmigrated surface into a crash rather than a skip.
|
|
877
|
+
*/
|
|
878
|
+
export declare function findUnreachedPreflightRules(surface: ConfigObjectSurface, reached: ReadonlySet<string>, entry: string): string[];
|
|
742
879
|
/**
|
|
743
880
|
* Request schemas generated from the configuration-object definitions
|
|
744
881
|
* (issue #2644, phase 5 / criterion 9).
|
|
@@ -1239,70 +1376,107 @@ export interface ParsedManifest {
|
|
|
1239
1376
|
*/
|
|
1240
1377
|
export declare function parseFunctionManifest(value: unknown): ParsedManifest;
|
|
1241
1378
|
/**
|
|
1242
|
-
* The
|
|
1243
|
-
* #
|
|
1244
|
-
*
|
|
1245
|
-
*
|
|
1246
|
-
*
|
|
1247
|
-
*
|
|
1248
|
-
*
|
|
1249
|
-
*
|
|
1250
|
-
*
|
|
1251
|
-
*
|
|
1252
|
-
*
|
|
1253
|
-
*
|
|
1254
|
-
*
|
|
1255
|
-
*
|
|
1256
|
-
*
|
|
1257
|
-
*
|
|
1258
|
-
* the
|
|
1259
|
-
*
|
|
1260
|
-
*
|
|
1261
|
-
*
|
|
1262
|
-
*
|
|
1263
|
-
*
|
|
1264
|
-
*
|
|
1265
|
-
*
|
|
1266
|
-
*
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1379
|
+
* The runtime keys a `functions/<key>.toml` no longer decides anything with —
|
|
1380
|
+
* #3482, project `server-functions` phase 4.
|
|
1381
|
+
*
|
|
1382
|
+
* The sponsor settled it on 2026-09-15 (the intent, "Mode vocabulary?",
|
|
1383
|
+
* amended again): the config says NOTHING about how a function runs. A
|
|
1384
|
+
* function is a function; the caller picks the runtime at each call, cron
|
|
1385
|
+
* fires always start a task run, webhook deliveries always run as a request,
|
|
1386
|
+
* and a function that must not run under one runtime tests for it in code with
|
|
1387
|
+
* `assertRuntime`.
|
|
1388
|
+
*
|
|
1389
|
+
* ── Why these keys are accepted, not refused ──────────────────────────────
|
|
1390
|
+
*
|
|
1391
|
+
* Every tree pushed since #3454 that declares a cron trigger carries
|
|
1392
|
+
* `mode = …` ON THE ENTRY, because `cron-trigger-mode-required` demanded it;
|
|
1393
|
+
* plenty carry a top-level `mode` or the older `durable`. Removing the keys
|
|
1394
|
+
* from the accepted set outright would refuse those trees with an unknown-key
|
|
1395
|
+
* error one day after the platform insisted on them, which is the opposite of
|
|
1396
|
+
* principle 5 inside a non-breaking phase.
|
|
1397
|
+
*
|
|
1398
|
+
* So through phase 4 they are ACCEPTED and IGNORED, with one warning per key
|
|
1399
|
+
* naming it and the line to delete; from phase 5 (#3188) they are refused with
|
|
1400
|
+
* the rest of the retirement matrix. The value is not validated — there is
|
|
1401
|
+
* nothing left to validate it against, and refusing a bad value for a key
|
|
1402
|
+
* nobody reads would be a refusal about spelling alone.
|
|
1403
|
+
*
|
|
1404
|
+
* Pure: no models, no tenant context, no `env` (see `types.ts` §Purity). Both
|
|
1405
|
+
* the CLI preflight (vendored by `cli/scripts/gen-config-surfaces.mjs`) and the
|
|
1406
|
+
* admin config-version route read this one scanner, so the warning an author
|
|
1407
|
+
* sees from `config push` is the sentence the API answers with.
|
|
1408
|
+
*/
|
|
1409
|
+
/** The two `[function]` keys that no longer say anything (#3482). */
|
|
1410
|
+
export declare const RETIRED_FUNCTION_RUNTIME_KEYS: readonly ["mode", "durable"];
|
|
1411
|
+
export type RetiredFunctionRuntimeKey = (typeof RETIRED_FUNCTION_RUNTIME_KEYS)[number];
|
|
1412
|
+
/** One ignored key met in a `[function]` table. */
|
|
1413
|
+
export interface IgnoredFunctionKey {
|
|
1274
1414
|
/**
|
|
1275
|
-
*
|
|
1276
|
-
*
|
|
1277
|
-
* reads
|
|
1415
|
+
* Where it was: `mode`, `durable`, or `triggers.cron.<name>.mode`. Never
|
|
1416
|
+
* rendered on its own — a reader that wants to branch reads this, and every
|
|
1417
|
+
* printer reads `message`.
|
|
1278
1418
|
*/
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
};
|
|
1419
|
+
path: string;
|
|
1420
|
+
/** The sentence the author is owed, with no file prefix (the caller adds it). */
|
|
1421
|
+
message: string;
|
|
1422
|
+
}
|
|
1284
1423
|
/**
|
|
1285
|
-
*
|
|
1424
|
+
* Every retired runtime key a `[function]` table still carries.
|
|
1286
1425
|
*
|
|
1287
|
-
*
|
|
1288
|
-
* `
|
|
1289
|
-
*
|
|
1426
|
+
* Reads the table the way the author wrote it: the two top-level keys, and a
|
|
1427
|
+
* `mode` on each `[[function.triggers.cron]]` entry. A cron entry's sentence
|
|
1428
|
+
* says the extra thing its author needs to hear — that the schedule no longer
|
|
1429
|
+
* chooses, because every fire starts a task run (#3334's runner branch is
|
|
1430
|
+
* gone).
|
|
1431
|
+
*
|
|
1432
|
+
* Order is the order an author reads their file in: the top-level keys first,
|
|
1433
|
+
* then the cron entries in declaration order.
|
|
1290
1434
|
*/
|
|
1291
|
-
export declare function
|
|
1292
|
-
mode?: unknown;
|
|
1293
|
-
durable?: unknown;
|
|
1294
|
-
}): DeclaredModeResolution;
|
|
1435
|
+
export declare function ignoredFunctionKeys(functionTable: unknown): IgnoredFunctionKey[];
|
|
1295
1436
|
/**
|
|
1296
|
-
* The
|
|
1437
|
+
* The database types a `[function]` table's retired trigger block names —
|
|
1438
|
+
* #3483.
|
|
1439
|
+
*
|
|
1440
|
+
* Beside `ignoredFunctionKeys` because it answers the same question about the
|
|
1441
|
+
* same table, for the same reader: `config pull` writes a version's AUTHORED
|
|
1442
|
+
* bytes, and a version pushed before the removal carries the block. Without
|
|
1443
|
+
* this the pulled tree would be refused on its next push — a tree an author
|
|
1444
|
+
* cannot get back into a working state, which is the failure D3482-007 already
|
|
1445
|
+
* had to close for the runtime keys.
|
|
1297
1446
|
*
|
|
1298
|
-
*
|
|
1299
|
-
*
|
|
1447
|
+
* This is NOT a refusal and shares nothing with one. The block is refused on
|
|
1448
|
+
* input by `normalizeTriggerDeclaration`; what a strip needs is the list of
|
|
1449
|
+
* entries it is taking out so it can say so, which is why an entry whose
|
|
1450
|
+
* `type` is unreadable still counts as one entry (the empty string). It is the
|
|
1451
|
+
* block's PRESENCE that goes, not its contents.
|
|
1452
|
+
*
|
|
1453
|
+
* TOML spells the block three ways — an array of tables, a single table, and
|
|
1454
|
+
* an inline array — and a scan that missed one would leave a key behind
|
|
1455
|
+
* (CR3482-002's lesson, applied to a whole table).
|
|
1300
1456
|
*/
|
|
1301
|
-
export declare function
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1457
|
+
export declare function retiredDatabaseTriggerTypes(functionTable: unknown): string[];
|
|
1458
|
+
/**
|
|
1459
|
+
* Whether the block is THERE at all — the question a strip has to ask, which
|
|
1460
|
+
* the type list above cannot answer (CR3483-001).
|
|
1461
|
+
*
|
|
1462
|
+
* `database = []` names no type, so the list is empty and a strip that decided
|
|
1463
|
+
* by its length left the key in the pulled file. That file then fails its own
|
|
1464
|
+
* next push: `normalizeTriggerDeclaration` refuses the key by PRESENCE, of any
|
|
1465
|
+
* shape, an empty array included — so the two halves disagreed about what the
|
|
1466
|
+
* block is, and the tree an author pulled was a tree they could not push.
|
|
1467
|
+
* Presence is the one rule both sides read now, spelled the way
|
|
1468
|
+
* `normalizeTriggerDeclaration` spells it — `!== undefined` — so a value one
|
|
1469
|
+
* of them would call a block and the other would not cannot exist.
|
|
1470
|
+
*/
|
|
1471
|
+
export declare function hasRetiredDatabaseTriggerBlock(functionTable: unknown): boolean;
|
|
1472
|
+
/**
|
|
1473
|
+
* The same scan, rendered for one file — the shape `config push` and
|
|
1474
|
+
* `config diff` print and the admin route answers with.
|
|
1475
|
+
*
|
|
1476
|
+
* `label` is what the reader can act on: `functions/<key>.toml` from the CLI,
|
|
1477
|
+
* and the function's key from the API, which has no file to name.
|
|
1478
|
+
*/
|
|
1479
|
+
export declare function ignoredFunctionKeyWarnings(label: string, functionTable: unknown): string[];
|
|
1306
1480
|
/**
|
|
1307
1481
|
* The trigger blocks a function declares, derived from its authored TOML
|
|
1308
1482
|
* (#3181, project `server-functions`, criterion 4).
|
|
@@ -1349,29 +1523,20 @@ export declare function isDurableMode(mode: FunctionMode): boolean;
|
|
|
1349
1523
|
* and the CLI has already parsed its own file by the time it asks.
|
|
1350
1524
|
*/
|
|
1351
1525
|
/**
|
|
1352
|
-
*
|
|
1526
|
+
* Why a webhook trigger is the request runtime, and a cron fire a task run —
|
|
1527
|
+
* #3482, the intent's "Mode vocabulary?" decision of 2026-09-15.
|
|
1353
1528
|
*
|
|
1354
|
-
*
|
|
1355
|
-
*
|
|
1356
|
-
*
|
|
1357
|
-
*
|
|
1358
|
-
*
|
|
1529
|
+
* Neither is a rule about the FUNCTION any more, so neither is a refusal: a
|
|
1530
|
+
* function is a function, and the DOOR decides which runtime runs it. A
|
|
1531
|
+
* webhook delivery runs inside the receiver because the provider is holding
|
|
1532
|
+
* the connection open waiting for an answer; a cron fire starts a task run
|
|
1533
|
+
* because it is waiting for nothing. A function that must not run under one of
|
|
1534
|
+
* them tests for it in code with `assertRuntime`, which is the only lock left.
|
|
1359
1535
|
*
|
|
1360
|
-
*
|
|
1361
|
-
*
|
|
1536
|
+
* What survives here is the SHAPE of a declaration — the keys, the names, the
|
|
1537
|
+
* cron expression, the caps. The retired `mode` keys are accepted and reported
|
|
1538
|
+
* as ignored by `ignoredFunctionKeys` in `function-retired-keys.ts`.
|
|
1362
1539
|
*/
|
|
1363
|
-
export interface TriggerModeOptions {
|
|
1364
|
-
mode?: FunctionMode;
|
|
1365
|
-
}
|
|
1366
|
-
/**
|
|
1367
|
-
* Why a webhook cannot drive a task function, and what to do instead (#3334).
|
|
1368
|
-
*
|
|
1369
|
-
* The first clause is verbatim what it has always been, so sibling pins on the
|
|
1370
|
-
* request-mode prefix (#3281's) keep holding; everything after the dash is the
|
|
1371
|
-
* half that was missing — an author who meets this at the push door could not
|
|
1372
|
-
* previously tell whether it was a limitation or a design, nor what to write.
|
|
1373
|
-
*/
|
|
1374
|
-
export declare const WEBHOOK_ON_TASK_REFUSAL: string;
|
|
1375
1540
|
/** A function's single webhook trigger, normalized. */
|
|
1376
1541
|
export interface WebhookTriggerDeclaration {
|
|
1377
1542
|
verificationScheme: string;
|
|
@@ -1392,15 +1557,9 @@ export interface CronTriggerDeclaration {
|
|
|
1392
1557
|
overlapPolicy?: string;
|
|
1393
1558
|
rootInput?: unknown;
|
|
1394
1559
|
}
|
|
1395
|
-
/** One `[[function.triggers.database]]` entry, normalized (#3184). */
|
|
1396
|
-
export interface DatabaseTriggerDeclaration {
|
|
1397
|
-
/** The database type key whose writes fire this function. */
|
|
1398
|
-
type: string;
|
|
1399
|
-
}
|
|
1400
1560
|
export interface TriggerDeclaration {
|
|
1401
1561
|
webhook: WebhookTriggerDeclaration | null;
|
|
1402
1562
|
cron: CronTriggerDeclaration[];
|
|
1403
|
-
databases: DatabaseTriggerDeclaration[];
|
|
1404
1563
|
}
|
|
1405
1564
|
export declare const EMPTY_TRIGGER_DECLARATION: TriggerDeclaration;
|
|
1406
1565
|
/**
|
|
@@ -1413,14 +1572,22 @@ export declare const EMPTY_TRIGGER_DECLARATION: TriggerDeclaration;
|
|
|
1413
1572
|
*/
|
|
1414
1573
|
export declare const MAX_CRON_TRIGGERS_PER_FUNCTION = 10;
|
|
1415
1574
|
/**
|
|
1416
|
-
* The
|
|
1417
|
-
*
|
|
1418
|
-
*
|
|
1419
|
-
*
|
|
1420
|
-
|
|
1575
|
+
* The rule ids this module owns — one per refusal, declared on the `function`
|
|
1576
|
+
* surface (#3374). The union below closes `refuseTrigger`'s id parameter, so a
|
|
1577
|
+
* twenty-seventh refusal cannot compile without a twenty-seventh id, and that
|
|
1578
|
+
* id fails `cli-unit-tests` until the surface declares it (#3373's anchor).
|
|
1579
|
+
*/
|
|
1580
|
+
export declare const TRIGGER_RULE_IDS: readonly ["triggers-table", "trigger-kind", "database-trigger-removed", "webhook-trigger-single", "webhook-trigger-table", "webhook-trigger-keys", "webhook-trigger-scheme-required", "webhook-trigger-scheme-none", "webhook-trigger-number", "webhook-trigger-dedup-boolean", "webhook-trigger-verification-table", "cron-trigger-cap", "cron-trigger-entry", "cron-trigger-keys", "cron-trigger-name-required", "cron-trigger-name-charset", "cron-trigger-duplicate", "cron-trigger-expression-required", "cron-trigger-overlap-policy"];
|
|
1581
|
+
export type TriggerRuleId = (typeof TRIGGER_RULE_IDS)[number];
|
|
1582
|
+
/**
|
|
1583
|
+
* A broken trigger rule. `ruleId` names which one, for a reader that wants to
|
|
1584
|
+
* branch without matching prose; every existing site reads `message` only.
|
|
1585
|
+
* Optional so `new TriggerDeclarationError(message)` — the CLI's own parse
|
|
1586
|
+
* refusal in `function-sync.ts` — keeps constructing.
|
|
1421
1587
|
*/
|
|
1422
|
-
export declare const MAX_DATABASE_TRIGGERS_PER_FUNCTION = 5;
|
|
1423
1588
|
export declare class TriggerDeclarationError extends Error {
|
|
1589
|
+
readonly ruleId?: TriggerRuleId;
|
|
1590
|
+
constructor(message: string, ruleId?: TriggerRuleId);
|
|
1424
1591
|
}
|
|
1425
1592
|
/** Is anything at all declared? Used to skip work on the common case. */
|
|
1426
1593
|
export declare function hasDeclaredTriggers(declaration: TriggerDeclaration): boolean;
|
|
@@ -1433,11 +1600,20 @@ export declare function hasDeclaredTriggers(declaration: TriggerDeclaration): bo
|
|
|
1433
1600
|
* push boundary can normalize a declaration it read from a stored row without
|
|
1434
1601
|
* re-parsing bytes.
|
|
1435
1602
|
*/
|
|
1436
|
-
export declare function normalizeTriggerDeclaration(functionTable: any
|
|
1603
|
+
export declare function normalizeTriggerDeclaration(functionTable: any): TriggerDeclaration;
|
|
1437
1604
|
/** The stored JSON for `ServerFunctionConfig.triggers`, or null when empty. */
|
|
1438
1605
|
export declare function serializeTriggerDeclaration(declaration: TriggerDeclaration): string | null;
|
|
1439
1606
|
/** Read a stored `ServerFunctionConfig.triggers` value back. */
|
|
1440
1607
|
export declare function parseStoredTriggerDeclaration(stored: unknown): TriggerDeclaration;
|
|
1608
|
+
/**
|
|
1609
|
+
* The database types a STORED declaration used to watch, for a reader that
|
|
1610
|
+
* wants to name them — #3483.
|
|
1611
|
+
*
|
|
1612
|
+
* Pure, and separate from the parse on purpose: the parse answers what the
|
|
1613
|
+
* version means NOW (nothing), and this answers what it said, which is only
|
|
1614
|
+
* ever used to write one log line. Nothing branches on it.
|
|
1615
|
+
*/
|
|
1616
|
+
export declare function storedDatabaseTriggerTypes(stored: unknown): string[];
|
|
1441
1617
|
/** The `CronTrigger.triggerKey` an entry owns. */
|
|
1442
1618
|
export declare function cronTriggerKeyFor(functionKey: string, name: string): string;
|
|
1443
1619
|
/** The entry name a `<functionKey>:<name>` trigger key carries. */
|
|
@@ -1597,12 +1773,24 @@ export declare function requiresSigningSecret(scheme: unknown): boolean;
|
|
|
1597
1773
|
/** The coded refusals, so a client can branch without matching prose. */
|
|
1598
1774
|
export declare const SIGNING_SECRET_MUST_BE_SECRET_REF = "SIGNING_SECRET_MUST_BE_SECRET_REF";
|
|
1599
1775
|
export declare const SIGNING_SECRET_NOT_SUPPORTED_FOR_SCHEME = "SIGNING_SECRET_NOT_SUPPORTED_FOR_SCHEME";
|
|
1776
|
+
/**
|
|
1777
|
+
* The rule ids this module owns, declared on the `function` surface as
|
|
1778
|
+
* `preflight` and on the `webhook` surface as `apply` (#3374) — one rule, two
|
|
1779
|
+
* surfaces, one handler. `whole-secret-reference` is generic on purpose:
|
|
1780
|
+
* `validateWholeSecretReference` is reused by the Google client secret and by
|
|
1781
|
+
* both webhook controllers under their own labels and codes.
|
|
1782
|
+
*/
|
|
1783
|
+
export declare const SIGNING_SECRET_RULE_IDS: readonly ["signing-secret-required", "whole-secret-reference", "signing-secret-not-supported"];
|
|
1784
|
+
type SigningSecretRuleId = (typeof SIGNING_SECRET_RULE_IDS)[number];
|
|
1600
1785
|
/**
|
|
1601
1786
|
* A refusal from this rule. `plain` marks the ones the admin webhook create
|
|
1602
1787
|
* answered as a bare text body rather than coded JSON — an observable
|
|
1603
1788
|
* distinction, so it travels with the error rather than being flattened.
|
|
1789
|
+
* `ruleId` names the rule and never reaches the wire: every reader picks
|
|
1790
|
+
* `message`, `code` and `plain`.
|
|
1604
1791
|
*/
|
|
1605
1792
|
export interface SigningSecretRuleError {
|
|
1793
|
+
ruleId: SigningSecretRuleId;
|
|
1606
1794
|
message: string;
|
|
1607
1795
|
code?: string;
|
|
1608
1796
|
plain?: boolean;
|
|
@@ -1632,7 +1820,288 @@ export declare function validateSigningSecretDeclaration(input: {
|
|
|
1632
1820
|
verificationScheme: string;
|
|
1633
1821
|
signingSecret?: unknown;
|
|
1634
1822
|
}): SigningSecretRuleError | null;
|
|
1823
|
+
/**
|
|
1824
|
+
* The workflow rules two runners share (#3374, project `cli-server-rule-parity`
|
|
1825
|
+
* phase 2; intent §Success criteria 3).
|
|
1826
|
+
*
|
|
1827
|
+
* ── One predicate, two messages ──────────────────────────────────────────
|
|
1828
|
+
*
|
|
1829
|
+
* `runAs = "system"` beside a non-empty `accessRule` is dead config: a system
|
|
1830
|
+
* run can only be started by the system and never evaluates its access rule
|
|
1831
|
+
* (#1258, broadening #1172). The server refused it at save time
|
|
1832
|
+
* (`validateWorkflowIdentityConfig`) and the CLI refused it in the push
|
|
1833
|
+
* preflight (`validateWorkflowIdentity`), and the two carried the conjunction
|
|
1834
|
+
* byte-for-byte as separate copies kept in step by a comment. This module is
|
|
1835
|
+
* the one copy: it decides, and returns a STRUCTURED violation — the rule id
|
|
1836
|
+
* and the server's sentence — that each site renders in its own words. The
|
|
1837
|
+
* server pushes the sentence into its `string[]`; the CLI keeps its own hint,
|
|
1838
|
+
* which names the preflight remedy. Neither message changed.
|
|
1839
|
+
*
|
|
1840
|
+
* ── Why a `*-rules.ts` module ────────────────────────────────────────────
|
|
1841
|
+
*
|
|
1842
|
+
* The registry's unclaimed-export check (`findUnclaimedRuleModuleExports`)
|
|
1843
|
+
* keys on this name under `src/config-surface/`: every exported function here
|
|
1844
|
+
* is a rule, so one no surface declares fails `cli-unit-tests`. Shared
|
|
1845
|
+
* predicates that are not rules live elsewhere (`webhook-signing-secret.ts`).
|
|
1846
|
+
* The module is vendored into the CLI artifact like the rest of the
|
|
1847
|
+
* directory, which is what lets `workflow`'s declaration call the rule
|
|
1848
|
+
* `preflight`.
|
|
1849
|
+
*/
|
|
1850
|
+
/** The rule ids this module owns — the union type below anchors them (#3373). */
|
|
1851
|
+
export declare const WORKFLOW_RULE_IDS: readonly ["system-access-rule"];
|
|
1852
|
+
type WorkflowRuleId = (typeof WORKFLOW_RULE_IDS)[number];
|
|
1853
|
+
/** A violation of one of this module's rules, for a site to render. */
|
|
1854
|
+
export interface WorkflowRuleViolation extends RuleRefusal<WorkflowRuleId> {
|
|
1855
|
+
}
|
|
1856
|
+
/**
|
|
1857
|
+
* `runAs = "system"` with a non-empty string `accessRule`, or null.
|
|
1858
|
+
*
|
|
1859
|
+
* Exactly the conjunction both sites carried: a default, unset, empty or
|
|
1860
|
+
* whitespace-only rule is no rule, and a non-string one (`accessRule = false`)
|
|
1861
|
+
* is malformed input for another check to name, not dead config. The message
|
|
1862
|
+
* is the server's save-time sentence; the CLI renders its own hint from the
|
|
1863
|
+
* same answer.
|
|
1864
|
+
*/
|
|
1865
|
+
export declare function checkWorkflowSystemAccessRule(input: {
|
|
1866
|
+
runAs?: unknown;
|
|
1867
|
+
accessRule?: unknown;
|
|
1868
|
+
}): WorkflowRuleViolation | null;
|
|
1635
1869
|
export declare const WORKFLOW_SURFACE: ConfigObjectSurface;
|
|
1870
|
+
/**
|
|
1871
|
+
* Cron-expression and timezone VALIDITY — the half of `src/cron-parser.ts`
|
|
1872
|
+
* both runners need (#3376, project `cli-server-rule-parity` phase 4).
|
|
1873
|
+
*
|
|
1874
|
+
* ── Why this module exists ───────────────────────────────────────────────
|
|
1875
|
+
*
|
|
1876
|
+
* A malformed cron expression and an unknown timezone are both decidable from
|
|
1877
|
+
* the authored file, so the intent lands both rules `preflight` — which under
|
|
1878
|
+
* this project's vocabulary means the implementation lives here, under
|
|
1879
|
+
* `src/config-surface/`, and is vendored into the CLI artifact.
|
|
1880
|
+
*
|
|
1881
|
+
* It got here by a SPLIT, not a move. `src/cron-parser.ts` is 415 lines, and
|
|
1882
|
+
* roughly 290 of them are timezone-aware scheduling arithmetic — "when does
|
|
1883
|
+
* this expression next fire?" — that only the cron Durable Object runs.
|
|
1884
|
+
* Vendoring is wholesale: the generator concatenates this whole directory, so
|
|
1885
|
+
* moving the file would have shipped that scheduler into the published CLI
|
|
1886
|
+
* package. The validator moved; the scheduler stayed; `src/cron-parser.ts`
|
|
1887
|
+
* re-exports what moved, so no server import changed.
|
|
1888
|
+
*
|
|
1889
|
+
* The scheduler's two entry points are deliberately not NAMED here: a CLI
|
|
1890
|
+
* unit test asserts the artifact does not contain either identifier, which is
|
|
1891
|
+
* how "the artifact carries the validator only" is kept true mechanically
|
|
1892
|
+
* rather than by review.
|
|
1893
|
+
*
|
|
1894
|
+
* ── Not a rules module ───────────────────────────────────────────────────
|
|
1895
|
+
*
|
|
1896
|
+
* `parseCron` THROWS, eight different sentences, and `tests/unit/
|
|
1897
|
+
* cron-parser.test.ts` pins that it throws. A module exporting a `*_RULE_IDS`
|
|
1898
|
+
* list may not contain a `throw` outside its one refusal constructor
|
|
1899
|
+
* (`findUnanchoredRefusals`, #3373), so the rule that renders these answers as
|
|
1900
|
+
* refusals is a separate module, `cron-rules.ts`, and this one is a plain
|
|
1901
|
+
* shared-predicate module — the `webhook-signing-secret.ts` / `function-mode.ts`
|
|
1902
|
+
* precedent.
|
|
1903
|
+
*
|
|
1904
|
+
* Pure: no models, no tenant context, no `env` (see `types.ts` §Purity).
|
|
1905
|
+
* `Intl.DateTimeFormat` is the one platform call, and it is the timezone
|
|
1906
|
+
* question itself.
|
|
1907
|
+
*
|
|
1908
|
+
* Supported fields (standard POSIX order):
|
|
1909
|
+
* minute (0-59)
|
|
1910
|
+
* hour (0-23)
|
|
1911
|
+
* day-of-month (1-31)
|
|
1912
|
+
* month (1-12)
|
|
1913
|
+
* day-of-week (0-6, where 0 = Sunday; 7 also accepted as Sunday)
|
|
1914
|
+
*
|
|
1915
|
+
* Supported syntax per field:
|
|
1916
|
+
* - "*" any value
|
|
1917
|
+
* - "5" exact value
|
|
1918
|
+
* - "5-10" range (inclusive)
|
|
1919
|
+
* - "star/step" every N values within the full range (e.g. "* /5" => 0,5,10,...)
|
|
1920
|
+
* - "a-b/step" every N values within a range
|
|
1921
|
+
* - "1,2,3" comma-separated list of values or ranges
|
|
1922
|
+
*
|
|
1923
|
+
* Not supported: month/day names, "?", "L", "W", "#", last-day modifiers.
|
|
1924
|
+
*/
|
|
1925
|
+
export interface ParsedCron {
|
|
1926
|
+
minutes: Set<number>;
|
|
1927
|
+
hours: Set<number>;
|
|
1928
|
+
daysOfMonth: Set<number>;
|
|
1929
|
+
months: Set<number>;
|
|
1930
|
+
daysOfWeek: Set<number>;
|
|
1931
|
+
dayOfMonthWild: boolean;
|
|
1932
|
+
dayOfWeekWild: boolean;
|
|
1933
|
+
}
|
|
1934
|
+
export declare function parseCron(expr: string): ParsedCron;
|
|
1935
|
+
/**
|
|
1936
|
+
* The message `parseCron` would throw for `expr`, or null when it parses.
|
|
1937
|
+
*
|
|
1938
|
+
* The same grammar, asked as a question instead of as an exception, because
|
|
1939
|
+
* both callers want the sentence rather than the control flow: the CLI's push
|
|
1940
|
+
* preflight collects one message per broken entry, and the standalone cron
|
|
1941
|
+
* routes render theirs into a 400 body. `expr` is typed `unknown` because it
|
|
1942
|
+
* arrives as an authored TOML value, where it can be anything at all.
|
|
1943
|
+
*/
|
|
1944
|
+
export declare function cronExpressionError(expr: unknown): string | null;
|
|
1945
|
+
/**
|
|
1946
|
+
* Whether `Intl.DateTimeFormat` accepts `name` as a timezone.
|
|
1947
|
+
*
|
|
1948
|
+
* This is THE timezone check — before #3376 the identical probe was written
|
|
1949
|
+
* out three times (the function push boundary and the standalone create and
|
|
1950
|
+
* update). Each of those sites keeps its own sentence and its own defaulting;
|
|
1951
|
+
* what they now share is this answer. A non-string is false rather than a
|
|
1952
|
+
* throw, for the same reason as above.
|
|
1953
|
+
*/
|
|
1954
|
+
export declare function isValidTimezone(name: unknown): boolean;
|
|
1955
|
+
/**
|
|
1956
|
+
* The cron schedule rules two runners share (#3376, project
|
|
1957
|
+
* `cli-server-rule-parity` phase 4; intent §Success criteria 6).
|
|
1958
|
+
*
|
|
1959
|
+
* ── One implementation, two runners ──────────────────────────────────────
|
|
1960
|
+
*
|
|
1961
|
+
* A cron expression the grammar refuses, and a timezone `Intl` does not know,
|
|
1962
|
+
* are both decidable from the authored file. Before this issue only the SERVER
|
|
1963
|
+
* decided them, inside the apply loop: a `functions/<key>.toml` carrying
|
|
1964
|
+
* either passed `config push`'s preflight, sibling entities were written, and
|
|
1965
|
+
* the function alone was refused — while the command promises that a refusal
|
|
1966
|
+
* means nothing was applied. Now `cli/src/lib/function-sync.ts` and
|
|
1967
|
+
* `src/services/function-trigger-validation.ts` both call the rule below, and
|
|
1968
|
+
* the sentence an author reads is the same on either side of the wire because
|
|
1969
|
+
* it is built in one place.
|
|
1970
|
+
*
|
|
1971
|
+
* ── Why this is a `*-rules.ts` module and the parser is not ──────────────
|
|
1972
|
+
*
|
|
1973
|
+
* The registry's unclaimed-export check (`findUnclaimedRuleModuleExports`)
|
|
1974
|
+
* keys on this name under `src/config-surface/`: every exported function here
|
|
1975
|
+
* is a rule, so one no surface declares fails `cli-unit-tests`. The anchor
|
|
1976
|
+
* also forbids a `throw` outside the one refusal constructor — and `parseCron`
|
|
1977
|
+
* throws eight different sentences, which `tests/unit/cron-parser.test.ts`
|
|
1978
|
+
* pins. So the grammar and the `Intl` probe live next door in
|
|
1979
|
+
* `cron-expression.ts`, which is a shared-predicate module rather than a rules
|
|
1980
|
+
* module, and this one only decides and renders.
|
|
1981
|
+
*
|
|
1982
|
+
* ── What is NOT shared ───────────────────────────────────────────────────
|
|
1983
|
+
*
|
|
1984
|
+
* The standalone cron routes ask the same two predicates and render their own
|
|
1985
|
+
* `Invalid cron expression: …` / `Invalid timezone: …`, with their own
|
|
1986
|
+
* defaulting (create reads an absent timezone as UTC, update does not). That
|
|
1987
|
+
* is intent assumption 2 in the form its own fallback describes, and the shape
|
|
1988
|
+
* `workflow-rules.ts` set in phase 2: one predicate, each site's message and
|
|
1989
|
+
* defaulting preserved. No refusal message changed anywhere.
|
|
1990
|
+
*/
|
|
1991
|
+
/** The rule ids this module owns — the union type below anchors them (#3373). */
|
|
1992
|
+
export declare const CRON_TRIGGER_RULE_IDS: readonly ["cron-trigger-expression", "cron-trigger-timezone"];
|
|
1993
|
+
type CronTriggerRuleId = (typeof CRON_TRIGGER_RULE_IDS)[number];
|
|
1994
|
+
/** A refused cron entry: the rule and the sentence the site renders. */
|
|
1995
|
+
export type CronTriggerRuleRefusal = RuleRefusal<CronTriggerRuleId>;
|
|
1996
|
+
/**
|
|
1997
|
+
* One `[[function.triggers.cron]]` entry's schedule, or null.
|
|
1998
|
+
*
|
|
1999
|
+
* Expression first, then timezone, which is the order the push boundary ran
|
|
2000
|
+
* them in — so an entry broken both ways still answers with the expression's
|
|
2001
|
+
* refusal, exactly as before. An unset or empty `timezone` reads as UTC, again
|
|
2002
|
+
* exactly as before: the boundary's `entry.timezone || "UTC"`.
|
|
2003
|
+
*/
|
|
2004
|
+
export declare function checkCronTriggerEntry(entry: {
|
|
2005
|
+
name: string;
|
|
2006
|
+
cron: string;
|
|
2007
|
+
timezone?: string;
|
|
2008
|
+
}): CronTriggerRuleRefusal | null;
|
|
2009
|
+
/**
|
|
2010
|
+
* The prompt config's reasoning controls, resolved onto each provider's own
|
|
2011
|
+
* spelling — issue #3358.
|
|
2012
|
+
*
|
|
2013
|
+
* A `[[configs]]` entry states EITHER `reasoningEffort` (a provider-neutral
|
|
2014
|
+
* level, `none` through `high`) or `reasoningBudget` (a token count), never
|
|
2015
|
+
* both. This module is the whole translation: every authored pair either maps
|
|
2016
|
+
* onto the provider's native key or is REFUSED with a message naming the
|
|
2017
|
+
* remedy. Nothing is dropped — that was the trap `providerConfig` already laid
|
|
2018
|
+
* in the tree (stored, serialized, round-tripped, and never read at execution),
|
|
2019
|
+
* and the issue's third success criterion is precisely that a config asking for
|
|
2020
|
+
* something a provider cannot express fails rather than silently doing nothing.
|
|
2021
|
+
*
|
|
2022
|
+
* Pure and dependency-free, like every module under `src/config-surface/`: the
|
|
2023
|
+
* server's create/update handlers, the executor, and the vendored CLI artifact
|
|
2024
|
+
* all read this one copy, so a refusal at push and a refusal at execution
|
|
2025
|
+
* cannot disagree.
|
|
2026
|
+
*
|
|
2027
|
+
* Provider facts this encodes:
|
|
2028
|
+
*
|
|
2029
|
+
* - OpenRouter takes a unified `reasoning` block: `{ effort }`,
|
|
2030
|
+
* `{ max_tokens }`, or `{ enabled: false }` to decline it. `max_tokens` is an
|
|
2031
|
+
* exact bound on budget-native models and is translated to the nearest
|
|
2032
|
+
* effort level on effort-only ones, so it is documented as a bound, not a
|
|
2033
|
+
* guarantee — `metrics.reasoningTokens` is the measure of what was spent.
|
|
2034
|
+
* Default routing lets an endpoint IGNORE a parameter it does not support,
|
|
2035
|
+
* so a request carrying `reasoning` also carries
|
|
2036
|
+
* `provider: { require_parameters: true }`: an endpoint that cannot honor it
|
|
2037
|
+
* is refused by OpenRouter and surfaces as a failed execution rather than a
|
|
2038
|
+
* silent drop.
|
|
2039
|
+
* - Gemini 3.x expresses thinking as a LEVEL
|
|
2040
|
+
* (`thinkingConfig.thinkingLevel`) and cannot turn it off; `thinkingBudget`
|
|
2041
|
+
* is accepted there only for backward compatibility and is translated to a
|
|
2042
|
+
* level rather than honored as a bound, so a numeric budget is refused with
|
|
2043
|
+
* a pointer at `reasoningEffort`.
|
|
2044
|
+
* - Gemini 2.5 expresses it as a numeric BUDGET
|
|
2045
|
+
* (`thinkingConfig.thinkingBudget`); `0` turns thinking off on Flash and
|
|
2046
|
+
* Flash-Lite, while Pro has a floor of 128 and answers 400 for less.
|
|
2047
|
+
* - Gemini 2.0 and earlier have no thinking control at all.
|
|
2048
|
+
*/
|
|
2049
|
+
/** The provider-neutral effort levels a config may state. */
|
|
2050
|
+
export declare const REASONING_EFFORTS: readonly ["none", "minimal", "low", "medium", "high"];
|
|
2051
|
+
export type ReasoningEffort = (typeof REASONING_EFFORTS)[number];
|
|
2052
|
+
/** The smallest budget Gemini 2.5 Pro accepts; it cannot stop thinking. */
|
|
2053
|
+
export declare const GEMINI_PRO_MIN_THINKING_BUDGET = 128;
|
|
2054
|
+
export interface PromptReasoningInput {
|
|
2055
|
+
provider?: string | null;
|
|
2056
|
+
model?: string | null;
|
|
2057
|
+
reasoningEffort?: string | null;
|
|
2058
|
+
reasoningBudget?: number | string | null;
|
|
2059
|
+
}
|
|
2060
|
+
/** What the executor adds to the upstream request, or `null` for "unset". */
|
|
2061
|
+
export type PromptReasoningDirective = {
|
|
2062
|
+
provider: "openrouter";
|
|
2063
|
+
/** The OpenRouter `reasoning` block. */
|
|
2064
|
+
reasoning: Record<string, unknown>;
|
|
2065
|
+
/**
|
|
2066
|
+
* `provider: { require_parameters: true }` — routing restricted to
|
|
2067
|
+
* endpoints that support every parameter in the request.
|
|
2068
|
+
*/
|
|
2069
|
+
requireParameters: true;
|
|
2070
|
+
} | {
|
|
2071
|
+
provider: "gemini";
|
|
2072
|
+
/** The `generationConfig.thinkingConfig` block. */
|
|
2073
|
+
thinkingConfig: Record<string, unknown>;
|
|
2074
|
+
};
|
|
2075
|
+
export type PromptReasoningResolution = {
|
|
2076
|
+
ok: true;
|
|
2077
|
+
directive: PromptReasoningDirective | null;
|
|
2078
|
+
} | {
|
|
2079
|
+
ok: false;
|
|
2080
|
+
error: string;
|
|
2081
|
+
};
|
|
2082
|
+
/**
|
|
2083
|
+
* How a Gemini model spells its thinking control.
|
|
2084
|
+
*
|
|
2085
|
+
* `level` — Gemini 3.x, `thinkingLevel`, cannot be turned off.
|
|
2086
|
+
* `budget` — Gemini 2.5, `thinkingBudget` in tokens.
|
|
2087
|
+
* `none` — Gemini 2.0 and earlier, no control at all.
|
|
2088
|
+
*/
|
|
2089
|
+
export type GeminiReasoningFamily = "level" | "budget" | "none";
|
|
2090
|
+
export declare function geminiReasoningFamily(model: string): GeminiReasoningFamily;
|
|
2091
|
+
/** Gemini Pro: the tier that cannot stop thinking in either family. */
|
|
2092
|
+
export declare function isGeminiProModel(model: string): boolean;
|
|
2093
|
+
/** Is EITHER reasoning key stated on this config? */
|
|
2094
|
+
export declare function hasPromptReasoning(input: PromptReasoningInput): boolean;
|
|
2095
|
+
/**
|
|
2096
|
+
* Resolve an authored pair onto the provider's spelling.
|
|
2097
|
+
*
|
|
2098
|
+
* Returns `{ ok: true, directive: null }` when neither key is set — the case
|
|
2099
|
+
* that must leave the upstream payload byte-identical to what it was before
|
|
2100
|
+
* this issue — a directive when the pair maps, and `{ ok: false, error }` when
|
|
2101
|
+
* it does not. The error text is what `config push` reports as the file's
|
|
2102
|
+
* error and what the admin routes answer 400 with.
|
|
2103
|
+
*/
|
|
2104
|
+
export declare function resolvePromptReasoning(input: PromptReasoningInput): PromptReasoningResolution;
|
|
1636
2105
|
export declare const PROMPT_SURFACE: ConfigObjectSurface;
|
|
1637
2106
|
export declare const INTEGRATION_SURFACE: ConfigObjectSurface;
|
|
1638
2107
|
export declare const WEBHOOK_SURFACE: ConfigObjectSurface;
|
|
@@ -1753,3 +2222,4 @@ export declare function getConfigTable(label: string, tomlPath: readonly string[
|
|
|
1753
2222
|
* names, in declaration order — the coverage guard's anchor (#2644 criterion 2).
|
|
1754
2223
|
*/
|
|
1755
2224
|
export declare const GENERATED_CONFIG_MODEL_FIELDS: Readonly<Record<string, readonly string[]>>;
|
|
2225
|
+
export {};
|