@vxil/cli 0.22.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import type { DeclaredRlPolicy, DeclaredWebhookSubscription } from './_vxil-feature-configs.js';
1
+ import type { DeclaredOrgRole, DeclaredRlPolicy, DeclaredWebhookSubscription } from './_vxil-feature-configs.js';
2
2
  /** The target_url path markers of the platform's function-delivery lanes
3
3
  * (control-plane fnCmsHooks.ts FN_CMSHOOK_PATH / FN_AUTHHOOK_PATH /
4
4
  * FN_WEBHOOK_TRIGGER_PATH — mirrored here because this package is
@@ -6,7 +6,7 @@ import type { DeclaredRlPolicy, DeclaredWebhookSubscription } from './_vxil-feat
6
6
  * manifest by the deploy reconciler: never declarable, never "undeclared". */
7
7
  export declare const FN_TRIGGER_TARGET_MARKERS: readonly ["/v1/internal/fn/cms-hook/", "/v1/internal/fn/auth-hook/", "/v1/internal/fn/trigger/"];
8
8
  export declare function isFnTriggerSubscriptionUrl(targetUrl: string): boolean;
9
- export type ApiStateDatum = 'policies' | 'subscriptions' | 'templates';
9
+ export type ApiStateDatum = 'policies' | 'subscriptions' | 'templates' | 'roles';
10
10
  /** feature → the declared-API-state datum its config block may carry. */
11
11
  export declare const API_STATE_DATUMS: ReadonlyArray<{
12
12
  feature: string;
@@ -126,6 +126,27 @@ export interface AiTemplatePlan {
126
126
  unknownContent: string[];
127
127
  }
128
128
  export declare function planAiTemplates(declared: readonly HashedDeclaredAiTemplate[], live: readonly LiveAiTemplate[]): AiTemplatePlan;
129
+ /** ONE CUSTOM row of GET /v1/orgs/roles (`data.custom`; the `data.builtin`
130
+ * sets are fixed and never planned). */
131
+ export interface LiveOrgRole {
132
+ role_key: string;
133
+ name: string;
134
+ permissions: string[];
135
+ rank?: number | null;
136
+ }
137
+ export interface OrgRolePlan {
138
+ create: DeclaredOrgRole[];
139
+ /** name / permission SET / rank differs — POST /v1/orgs/roles upserts on
140
+ * role_key in place (members keep the role), so never destructive-shaped */
141
+ update: Array<{
142
+ role: DeclaredOrgRole;
143
+ changed: string[];
144
+ }>;
145
+ unchanged: string[];
146
+ /** live custom roles the config does not declare (left in place by default) */
147
+ undeclared: string[];
148
+ }
149
+ export declare function planOrgRoles(declared: readonly DeclaredOrgRole[], live: readonly LiveOrgRole[]): OrgRolePlan;
129
150
  export interface ApiStateSummary {
130
151
  datum: ApiStateDatum;
131
152
  created: string[];
@@ -174,6 +195,13 @@ export declare const API_STATE_DISABLED_NOTE = "feature disabled \u2014 declarat
174
195
  * converge and the CLI's read-only plan refuse with this message instead. */
175
196
  export declare function rlPolicyListCapError(liveCount: number): string | null;
176
197
  export declare const RL_POLICY_LIST_CAP = 100;
198
+ /** `orgs.roles[]` is declared with at most this many entries (OrgsConfigSchema
199
+ * maxItems), but orgs-v1 defineRole has NO per-tenant cap — a tenant past it
200
+ * cannot round-trip its catalog through the config block. `vxil pull`
201
+ * (2026-10-11) refuses to write the leaf rather than emit a config that fails
202
+ * validation. */
203
+ export declare function orgRoleListCapError(liveCount: number): string | null;
204
+ export declare const ORG_ROLE_DECLARED_CAP = 100;
177
205
  /** `+2 created · ~1 updated · =3 unchanged · 1 undeclared (left in place)` —
178
206
  * the one-line summary `vxil push` prints and the apply journal notes. */
179
207
  export declare function formatApiStateSummary(s: ApiStateSummary): string;
@@ -0,0 +1,7 @@
1
+ /** The three feed groups every tenant has without config. A declared
2
+ * `feedGroups` entry is MERGED over these by name at read time (the worker's
3
+ * feedTypeFor), so declaring a custom group never drops the built-ins. */
4
+ export declare const ACTIVITY_FEED_BUILTIN_GROUPS: Record<string, {
5
+ type: 'flat' | 'aggregated' | 'notification';
6
+ aggregation?: string;
7
+ }>;
@@ -1,4 +1,5 @@
1
1
  import { type Static, type TSchema } from '@sinclair/typebox';
2
+ import { ACTIVITY_FEED_BUILTIN_GROUPS } from './_vxil-feature-configs-feedGroups.js';
2
3
  export { AI_THINKING_LEVELS, geminiThinkingLevelError, minimalThinkingLevel, type GeminiThinkingLevel } from './_vxil-feature-configs-geminiThinking.js';
3
4
  export * from './_vxil-feature-configs-hooks.js';
4
5
  export * from './_vxil-feature-configs-readmodels.js';
@@ -15,6 +16,16 @@ export declare const RESERVED_CREDIT_TYPES: ReadonlySet<string>;
15
16
  * Read by the schema, the deploy clamp and the CLI. */
16
17
  export declare const FN_RETRY_MAX_ATTEMPTS = 5;
17
18
  export declare const FN_RETRY_BINDING_KINDS: ReadonlySet<string>;
19
+ /** An `http` binding's caps (2026-10-11; rules at fnForwardHeadersError /
20
+ * fnServerScopesError). Up here because the schema below reads them. */
21
+ export declare const FN_FORWARD_HEADERS_MAX = 8;
22
+ export declare const FN_FORWARD_HEADER_VALUE_MAX = 256;
23
+ export declare const FN_SERVER_SCOPES_MAX = 32;
24
+ /** G-37 (2026-10-11): a function's plain `vars` (never secret) — at most
25
+ * FN_VARS_MAX names of FN_VAR_NAME_RE, FN_VARS_MAX_BYTES of JSON in all
26
+ * (rules at fnVarsError). Delivered on the envelope as `vars`. */
27
+ export declare const FN_VARS_MAX = 32;
28
+ export declare const FN_VARS_MAX_BYTES = 4096;
18
29
  /** True when a credit_type is a vxil-COGS reserved type (grant/consume/config
19
30
  * of which is restricted to internal platform machinery). */
20
31
  export declare function isReservedCreditType(creditType: string): boolean;
@@ -513,13 +524,38 @@ export declare const PresenceConfigSchema: import("@sinclair/typebox").TObject<{
513
524
  enabled: import("@sinclair/typebox").TBoolean;
514
525
  }>;
515
526
  export type PresenceConfig = Static<typeof PresenceConfigSchema>;
527
+ /** The orgs-v1 built-in role keys (core.ts ROLE_RANK): fixed sets that are
528
+ * never declared, redefined or deleted — a custom role picks another key. */
529
+ export declare const ORG_BUILTIN_ROLE_KEYS: readonly ["owner", "admin", "member", "viewer"];
530
+ /** One declared custom org role (G-31, 2026-10-11) — the POST /v1/orgs/roles
531
+ * body (orgs-v1 core.ts RoleBody), converged by `role_key` by `vxil push` /
532
+ * `POST /v1/apply` (control-plane handlers/apiState.ts). */
533
+ export declare const DeclaredOrgRoleSchema: import("@sinclair/typebox").TObject<{
534
+ role_key: import("@sinclair/typebox").TString;
535
+ name: import("@sinclair/typebox").TString;
536
+ permissions: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
537
+ rank: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
538
+ }>;
539
+ export type DeclaredOrgRole = Static<typeof DeclaredOrgRoleSchema>;
516
540
  export declare const OrgsConfigSchema: import("@sinclair/typebox").TObject<{
517
541
  enabled: import("@sinclair/typebox").TBoolean;
518
542
  maxOrgsPerTenant: import("@sinclair/typebox").TInteger;
519
543
  maxMembersPerOrg: import("@sinclair/typebox").TInteger;
520
544
  invitationTtlHours: import("@sinclair/typebox").TInteger;
545
+ roles: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
546
+ role_key: import("@sinclair/typebox").TString;
547
+ name: import("@sinclair/typebox").TString;
548
+ permissions: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
549
+ rank: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
550
+ }>>>;
521
551
  }>;
522
552
  export type OrgsConfig = Static<typeof OrgsConfigSchema>;
553
+ export { ACTIVITY_FEED_BUILTIN_GROUPS };
554
+ /** Config-write errors for activity-feed feedGroups (FEED-HYGIENE). */
555
+ export declare function validateFeedGroups(groups: Record<string, {
556
+ type?: string;
557
+ aggregation?: string;
558
+ }> | undefined): string[];
523
559
  export declare const ActivityFeedConfigSchema: import("@sinclair/typebox").TObject<{
524
560
  enabled: import("@sinclair/typebox").TBoolean;
525
561
  feedGroups: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TObject<{
@@ -530,8 +566,6 @@ export declare const ActivityFeedConfigSchema: import("@sinclair/typebox").TObje
530
566
  fanout: import("@sinclair/typebox").TObject<{
531
567
  celebrityThreshold: import("@sinclair/typebox").TInteger;
532
568
  maxFanoutPerJob: import("@sinclair/typebox").TInteger;
533
- maxConcurrentTasks: import("@sinclair/typebox").TInteger;
534
- pendingCeiling: import("@sinclair/typebox").TInteger;
535
569
  }>;
536
570
  follow: import("@sinclair/typebox").TObject<{
537
571
  copyLimit: import("@sinclair/typebox").TInteger;
@@ -541,7 +575,6 @@ export declare const ActivityFeedConfigSchema: import("@sinclair/typebox").TObje
541
575
  enabled: import("@sinclair/typebox").TBoolean;
542
576
  }>;
543
577
  crossChannel: import("@sinclair/typebox").TObject<{
544
- enabled: import("@sinclair/typebox").TBoolean;
545
578
  digestCadence: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"off">, import("@sinclair/typebox").TLiteral<"hourly">, import("@sinclair/typebox").TLiteral<"daily">]>;
546
579
  }>;
547
580
  }>;
@@ -710,6 +743,7 @@ export declare const PaymentsConfigSchema: import("@sinclair/typebox").TObject<{
710
743
  amount: import("@sinclair/typebox").TInteger;
711
744
  period: import("@sinclair/typebox").TString;
712
745
  mode: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"add">, import("@sinclair/typebox").TLiteral<"reset">]>>;
746
+ expireOnEnd: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
713
747
  }>>>;
714
748
  }>>;
715
749
  priceMap: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TString>>;
@@ -744,10 +778,13 @@ export declare const FunctionsConfigSchema: import("@sinclair/typebox").TObject<
744
778
  maxAttempts: import("@sinclair/typebox").TInteger;
745
779
  }>>;
746
780
  overlap: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"allow">, import("@sinclair/typebox").TLiteral<"skip">]>>;
781
+ forwardHeaders: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
782
+ serverScopes: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
747
783
  }>>>;
748
784
  scriptRef: import("@sinclair/typebox").TString;
749
785
  scopes: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
750
786
  secrets: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
787
+ vars: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TString>>;
751
788
  egressAllow: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
752
789
  runtime: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
753
790
  compatibilityDate: import("@sinclair/typebox").TString;
@@ -869,10 +906,21 @@ export declare const MCP_MAX_PROMPTS = 32;
869
906
  * stays ALLOWED (fn→fn composition). Source of truth for both the config-write
870
907
  * validation below and the control-plane deploy clamp. */
871
908
  export declare const DENY_FUNCTION_SCOPES: Set<string>;
909
+ export declare function fnForwardHeadersError(raw: unknown): string | null;
910
+ /** G-37: a function's `vars` — a plain-text string map (never a secret: it
911
+ * sits in the published manifest and every config version). */
912
+ export declare function fnVarsError(raw: unknown): string | null;
913
+ /** FN-SERVER-SCOPES: an `http` binding's `serverScopes` — the scopes of the
914
+ * tenant-only tokens (`server_jwts`) minted next to the caller-bound ones.
915
+ * Each must be one of the function's own `scopes` (pass `fnScopes` once they
916
+ * are known; undefined checks the shape only), so a caller can never reach
917
+ * more than the author granted the function. */
918
+ export declare function fnServerScopesError(raw: unknown, fnScopes?: readonly string[]): string | null;
872
919
  /** `{var}` names of a rate-limit key template (rate-limits-v1 core.ts
873
920
  * templateVars parity). */
874
921
  export declare function rlTemplateVars(template: string): string[];
875
922
  export declare function validateDeclaredRlPolicies(policies: readonly DeclaredRlPolicy[] | undefined): string[];
923
+ export declare function validateDeclaredOrgRoles(roles: readonly DeclaredOrgRole[] | undefined): string[];
876
924
  export declare function validateDeclaredWebhookSubscriptions(subscriptions: readonly DeclaredWebhookSubscription[] | undefined, maxSubscriptions: number | undefined): string[];
877
925
  /** The stored-template `schema` bounds — MIRRORED from @vxil/runtime
878
926
  * (AI_TEMPLATE_SCHEMA_MAX_BYTES / AI_TEMPLATE_SCHEMA_MAX_DEPTH; this package is
package/dist/config.d.ts CHANGED
@@ -178,10 +178,18 @@ export interface FunctionTriggerRetry {
178
178
  /** A function trigger (guide ch. 8). cmsHook fires on a CMS write;
179
179
  * authHook fires on ONE auth lifecycle event (default `user.created` — the
180
180
  * post-signup hook; at-least-once, ~1min fanout latency). */
181
- export type FunctionTrigger = {
181
+ export type FunctionTrigger =
182
+ /** `http` (2026-10-11): `forwardHeaders` — up to 8 `x-…` request header
183
+ * names copied into the envelope's `client.headers` (caller-asserted: never
184
+ * for authorization); `serverScopes` — scopes (each one of the function's
185
+ * own `scopes`) of extra tenant-only tokens, `server_jwts`, for writes the
186
+ * end user must not make. */
187
+ {
182
188
  kind: 'http';
183
189
  path?: string;
184
190
  retry?: FunctionTriggerRetry;
191
+ forwardHeaders?: string[];
192
+ serverScopes?: string[];
185
193
  }
186
194
  /** `overlap: 'skip'` (2026-10-01): a due tick fires nothing while the
187
195
  * previous tick's run is still open (queued / running / retrying / waiting /
@@ -248,8 +256,16 @@ export interface FunctionDef {
248
256
  * functions:write, secrets:write rejected; payments:write / notifications:send /
249
257
  * users:* allowed as owner-granted business scopes). */
250
258
  scopes?: string[];
251
- /** Names of tenant secrets injected into the function at invoke time. */
259
+ /** Names of tenant secrets injected into the function at invoke time. A
260
+ * trailing `?` (`'stripe_key?'`) marks one optional: unset, it is
261
+ * simply absent from `secrets`; an unset required one answers 409
262
+ * `secret_missing` on every invoke. */
252
263
  secrets?: string[];
264
+ /** Plain settings delivered on the envelope as `vars` — a dashboard
265
+ * URL, a pinned org slug, a threshold. Plain text stored in the published
266
+ * config, NEVER a secret (use `secrets` for those). At most 32 names of
267
+ * `[A-Za-z_][A-Za-z0-9_]{0,63}`, 4 096 bytes of JSON in all. */
268
+ vars?: Record<string, string>;
253
269
  /** Outbound host allowlist (deny-by-default egress guard). */
254
270
  egressAllow?: string[];
255
271
  /** Per-function resource declarations. Both optional; both clamped server-side.
@@ -294,10 +310,16 @@ export interface SecretRef {
294
310
  feature: string;
295
311
  description?: string;
296
312
  }
297
- /** Optional deterministic seed, applied via the per-feature import bundle. */
313
+ /** Optional deterministic seed, applied by `vxil seed` as per-item
314
+ * `POST /v1/cms/items/:collection` creates (one per row). */
298
315
  export interface SeedSpec {
316
+ /** `status`: what every item of the block is created as —
317
+ * `'published'` lands seed rows live on a `draftPublish` collection.
318
+ * Absent = the collection's default (draft under draftPublish). Set on
319
+ * the block, not the item, so a field named `status` stays your data. */
299
320
  cms?: {
300
321
  collection: string;
322
+ status?: 'draft' | 'published';
301
323
  items: Record<string, unknown>[];
302
324
  }[];
303
325
  users?: {