@vxil/sdk 0.12.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -475,7 +475,7 @@ export interface RateLimitOverride {
475
475
  created_at: string;
476
476
  updated_at?: string;
477
477
  }
478
- /** A payments provider webhook delivery in the event log (payments.md §7).
478
+ /** A payments provider webhook delivery in the event log (guide ch. 6, payments).
479
479
  * `payload` and `raw_body` are only populated on the detail read. */
480
480
  export interface PaymentsWebhookEvent {
481
481
  event_id: string;
@@ -508,7 +508,7 @@ export interface PaymentsWebhookEvent {
508
508
  raw_body?: string | null;
509
509
  provider_event_ts?: string | null;
510
510
  }
511
- /** The outcome of a provider re-sync / Restore Purchases (payments.md §7d). */
511
+ /** The outcome of a provider re-sync / Restore Purchases (guide ch. 6, payments). */
512
512
  export interface PaymentsSyncOutcome {
513
513
  provider: string;
514
514
  synced: number;
@@ -523,7 +523,7 @@ export interface PaymentsSyncOutcome {
523
523
  }>;
524
524
  dry_run?: boolean;
525
525
  }
526
- /** A lifecycle simulation run (payments.md §7d; mock/dev tenants only). */
526
+ /** A lifecycle simulation run (guide ch. 6, payments; mock/dev tenants only). */
527
527
  export interface PaymentsSimulationResult {
528
528
  scenario: string;
529
529
  run_id: string;
@@ -545,8 +545,8 @@ export interface PaymentsSimulationResult {
545
545
  pass: boolean;
546
546
  };
547
547
  }
548
- /** The ONE complete entitlement read (GET /v1/payments/entitlements; payments.md
549
- * §3a). `until` is the winning subscription's current_period_end (+ the
548
+ /** The ONE complete entitlement read (GET /v1/payments/entitlements; guide ch. 6,
549
+ * payments). `until` is the winning subscription's current_period_end (+ the
550
550
  * configured grace window when it is past_due); null on the free baseline. */
551
551
  export interface PaymentsEntitlementView {
552
552
  user_id: string;
@@ -581,7 +581,7 @@ export interface PaymentsEntitlementView {
581
581
  * `completed` (Paddle paid → completed). Handle `succeeded` gated on
582
582
  * `provider_status === 'completed'` plus `completed` to act once per charge. */
583
583
  export type PaymentsProviderChargeStatus = 'paid' | 'completed';
584
- /** A charge row as listed by GET /v1/payments/charges (payments.md §3). */
584
+ /** A charge row as listed by GET /v1/payments/charges (guide ch. 6, payments). */
585
585
  export interface PaymentsCharge {
586
586
  /** the vxil charge id (`chg_…`) — what refunds and a charge-linked grant key on */
587
587
  charge_id: string;
@@ -630,8 +630,8 @@ export interface PaymentsRefund {
630
630
  source: 'api' | 'webhook';
631
631
  created_at: string | null;
632
632
  }
633
- /** A subscription row as listed by GET /v1/payments/subscriptions (payments.md
634
- * §3) — provider subscriptions, manual grants and purchase passes alike.
633
+ /** A subscription row as listed by GET /v1/payments/subscriptions (guide ch. 6,
634
+ * payments) — provider subscriptions, manual grants and purchase passes alike.
635
635
  * `current_period_start` (2026-09-25) is the row's own window start: for a
636
636
  * purchase pass (`provider_sub_id: 'purchase:<charge_id>'`) the day its access
637
637
  * begins, which is in the FUTURE for a pass queued behind a live one; for a
@@ -662,8 +662,8 @@ export interface FileObject {
662
662
  status: 'pending' | 'available' | 'deleted';
663
663
  created_at: string;
664
664
  }
665
- /** A live shared link as listed by GET /v1/files/{id}/shared-links (files.md
666
- * §6). `downloads` is the burn-on-read counter; `max_downloads` null =
665
+ /** A live shared link as listed by GET /v1/files/{id}/shared-links (guide ch. 6,
666
+ * files). `downloads` is the burn-on-read counter; `max_downloads` null =
667
667
  * unlimited (1 = a one-time link). A link that hit its cap, expired, or was
668
668
  * revoked no longer lists. */
669
669
  export interface FileSharedLink {
@@ -682,7 +682,7 @@ export interface CreateSharedLinkOptions {
682
682
  expires_at?: string;
683
683
  max_downloads?: number | null;
684
684
  }
685
- /** One recognized OCR text block (files.md §1.1). bbox is [x, y, w, h] in the
685
+ /** One recognized OCR text block (guide ch. 6, files). bbox is [x, y, w, h] in the
686
686
  * provider's unit space; page is 1-based. confidence is 0..1 normalized per
687
687
  * provider (Textract native 0..100 divided by 100; mock pins 0.95); absent
688
688
  * when the provider supplied none. */
@@ -923,7 +923,7 @@ export interface AiGenerationRecord {
923
923
  * generation) */
924
924
  result_state: 'stored' | 'purged' | 'not_recorded';
925
925
  }
926
- /** The `data` of `job.generation.queued` (jobs.md §11): the run was accepted. */
926
+ /** The `data` of `job.generation.queued` (guide ch. 6, jobs): the run was accepted. */
927
927
  export interface JobGenerationQueuedEventPayload {
928
928
  run_id: string;
929
929
  job_name: string;
@@ -1510,7 +1510,7 @@ export interface RagSearchHit {
1510
1510
  * vector-search (−1…1; null when retrieval used no query vector). */
1511
1511
  similarity?: number | null;
1512
1512
  /** the effective post-boost score results are RANKED by — present only when
1513
- * metadata boosts applied (rag.md §2f). */
1513
+ * metadata boosts applied (guide ch. 6, rag). */
1514
1514
  boosted_score?: number;
1515
1515
  metadata?: Record<string, unknown>;
1516
1516
  }
@@ -1527,7 +1527,7 @@ export interface RagSearchResult {
1527
1527
  };
1528
1528
  }
1529
1529
  /** A replayed frame page from the rag-native resume endpoint (proxies the ai
1530
- * §2a replay buffer: every recorded frame with seq > since, plus done). */
1530
+ * feature's replay buffer: every recorded frame with seq > since, plus done). */
1531
1531
  export interface RagResumePage {
1532
1532
  generation_id: string;
1533
1533
  since: number;
@@ -1751,7 +1751,7 @@ export interface DmConfigState {
1751
1751
  version: number;
1752
1752
  configured: boolean;
1753
1753
  }
1754
- /** The safe query subset the keyless cms public lane admits (roadmap §4.4): the
1754
+ /** The safe query subset the keyless cms public lane admits (guide ch. 4): the
1755
1755
  * same bounded filter/sort/limit/cursor as the authored list, minus anything
1756
1756
  * owner- or lifecycle-scoped (the lane FORCES status='published'). `filter` is a
1757
1757
  * JSON object, serialized to the wire `filter=` param. */
@@ -1773,7 +1773,7 @@ export interface CmsPublicRow {
1773
1773
  published_at: string | null;
1774
1774
  }
1775
1775
  /** Build the anonymous, KEYLESS public-delivery URL for a collection's PUBLISHED
1776
- * items (roadmap §4.4) — `{base}/v1/cms/public/:tenantId/:collection[?…]`. This is
1776
+ * items (guide ch. 4, "Draft and publish") — `{base}/v1/cms/public/:tenantId/:collection[?…]`. This is
1777
1777
  * the reader path a public blog/storefront/docs site hits with NO api key: the
1778
1778
  * edge mints a restricted read-only inner token bound to the URL tenant, forces
1779
1779
  * `status='published'`, and strips the collection's owner_field. PURE (no
@@ -1784,7 +1784,7 @@ export declare function cmsPublicUrl(tenantId: string, collection: string, query
1784
1784
  baseUrl?: string;
1785
1785
  }): string;
1786
1786
  /** Fetch a page of a collection's PUBLISHED items over the KEYLESS public lane
1787
- * (roadmap §4.4) — NO api key, no `Vxil` client, no auth of any kind. This is the
1787
+ * (guide ch. 4) — NO api key, no `Vxil` client, no auth of any kind. This is the
1788
1788
  * anonymous reader path (a blog/storefront/docs front-end). Returns the same
1789
1789
  * `{ items, next_cursor }` envelope the authed list does, but rows are stripped
1790
1790
  * to the public surface (`CmsPublicRow`) — drafts and the owner_field are never
@@ -1952,12 +1952,12 @@ type DisabledFeatures<S extends VxilSchemaShape> = {
1952
1952
  [P in keyof FeatureMap]: FeatureMap[P] extends S['features'] ? never : P;
1953
1953
  }[keyof FeatureMap];
1954
1954
  /** The feature-narrowed client: feature namespaces the tenant hasn't enabled become
1955
- * a compile error (the design's §4.4 headline). `Vxil.connect<VxilSchema>()`
1955
+ * a compile error. `Vxil.connect<VxilSchema>()`
1956
1956
  * returns it; plain `new Vxil<VxilSchema>()` stays un-narrowed for back-compat. */
1957
1957
  export type EnabledVxil<S extends VxilSchemaShape> = Omit<Vxil<S>, DisabledFeatures<S>> & {
1958
1958
  [P in DisabledFeatures<S>]: DisabledFeature<FeatureMap[P] & string>;
1959
1959
  };
1960
- /** One config-declared per-record ACTION (cms.md §17): a button on a record row
1960
+ /** One config-declared per-record ACTION (guide ch. 4): a button on a record row
1961
1961
  * that invokes the deployed tenant function `fn` ONCE with `{ collection,
1962
1962
  * item_id, action, actor, item }`. Exactly one human-initiated step — no
1963
1963
  * conditions, no chaining, no scheduling. ≤8 per collection. */
@@ -1969,7 +1969,7 @@ export interface CmsActionDef {
1969
1969
  /** the deployed function name (/^[a-z][a-z0-9-]{0,47}$/) */
1970
1970
  fn: string;
1971
1971
  }
1972
- /** One live item referencing another through a relation field (cms.md §11.1). */
1972
+ /** One live item referencing another through a relation field (guide ch. 4). */
1973
1973
  export interface CmsBacklink {
1974
1974
  collection: string;
1975
1975
  field: string;
@@ -1986,7 +1986,7 @@ export interface CmsBacklinksPage {
1986
1986
  has_more: boolean;
1987
1987
  limit: number;
1988
1988
  }
1989
- /** ONE page of the slot re-index (cms.md §19). Loop while `complete` is false,
1989
+ /** ONE page of the slot re-index (guide ch. 4). Loop while `complete` is false,
1990
1990
  * feeding `next_cursor` back in. `skipped` counts rows a concurrent write moved
1991
1991
  * under the page — the re-index never overwrites them (their own writer
1992
1992
  * re-projected them), but a `$inc` or a cascade `set_null` only re-projects its
@@ -1999,8 +1999,14 @@ export interface CmsReindexPage {
1999
1999
  skipped: number;
2000
2000
  next_cursor: string | null;
2001
2001
  complete: boolean;
2002
- }
2003
- /** The result of a bounded filtered delete (cms.md §20). `matched` counts the
2002
+ /** Present when this page certified an index (the last page of a pass over
2003
+ * a collection whose equality / owner index was not armed): 'armed',
2004
+ * 'pending' (rows changed during the pass — run another) or 'timeout' (the
2005
+ * check ran out of time — the index stays unarmed; filters stay correct
2006
+ * but unaccelerated). */
2007
+ index_certify?: 'armed' | 'pending' | 'timeout';
2008
+ }
2009
+ /** The result of a bounded filtered delete (guide ch. 4). `matched` counts the
2004
2010
  * rows this page selected (≤ `limit`); `deleted` counts the ones actually
2005
2011
  * removed (a row that vanished between the match and the delete is skipped).
2006
2012
  * Loop while `deleted > 0` — the filter re-evaluates against live rows.
@@ -2020,33 +2026,33 @@ export interface CmsBulkDeleteResult {
2020
2026
  complete: boolean;
2021
2027
  next_cursor: string | null;
2022
2028
  }
2023
- /** A write guard (cms.md §10): "after this write, at most `max` live items
2029
+ /** A write guard (guide ch. 4): "after this write, at most `max` live items
2024
2030
  * match `filter`". Requires `lock` — an unlocked guard is racy by construction. */
2025
2031
  export interface CmsGuard {
2026
2032
  filter: Record<string, unknown>;
2027
2033
  max: number;
2028
2034
  }
2029
- /** One guard of a `guards[]` multi-invariant write (cms.md §10). Same
2035
+ /** One guard of a `guards[]` multi-invariant write (guide ch. 4). Same
2030
2036
  * { filter, max } as CmsGuard plus an optional custom 409 `message` surfaced on
2031
2037
  * the FIRST violation. */
2032
2038
  export interface CmsGuardTerm extends CmsGuard {
2033
2039
  /** Custom guard_failed message (≤200 chars) for THIS invariant. */
2034
2040
  message?: string;
2035
2041
  }
2036
- /** Concurrency options shared by the cms write methods (cms.md §9–10). */
2042
+ /** Concurrency options shared by the cms write methods (guide ch. 4). */
2037
2043
  export interface CmsWriteOpts {
2038
2044
  /** Optimistic CAS: sent as `If-Match: <version>`; mismatch → 409 version_conflict. */
2039
2045
  ifVersion?: number;
2040
2046
  /** Bounded field precondition checked against the locked row (≤4 terms;
2041
2047
  * `{field: null}` = "absent or null" — the slot-claim shape). 409 precondition_failed. */
2042
2048
  if?: Record<string, unknown>;
2043
- /** Per-(tenant,collection,key) advisory lock — serializes same-key writers. */
2049
+ /** A per-(project, collection, key) lock — serializes same-key writers. */
2044
2050
  lock?: string;
2045
2051
  /** Declarative capacity/overlap invariant; requires `lock`. 409 guard_failed.
2046
2052
  * Mutually exclusive with `guards`. */
2047
2053
  guard?: CmsGuard;
2048
2054
  /** Multiple capacity/overlap invariants evaluated co-atomically under the ONE
2049
- * `lock` (≤4; requires `lock`; cms.md §10). Mutually exclusive with `guard`.
2055
+ * `lock` (≤4; requires `lock`; guide ch. 4). Mutually exclusive with `guard`.
2050
2056
  * The FIRST failing guard's optional `message` rides the 409 guard_failed. */
2051
2057
  guards?: CmsGuardTerm[];
2052
2058
  }
@@ -2062,7 +2068,7 @@ export interface CmsWindow {
2062
2068
  since?: string;
2063
2069
  until?: string;
2064
2070
  }
2065
- /** cms-rel B2: the aggregate request body (cms.md §12.1). */
2071
+ /** the aggregate request body (guide ch. 4). */
2066
2072
  export interface CmsAggregateBody {
2067
2073
  /** 1–4 exprs; fn ∈ count|sum|min|max|avg (sum/avg need an n*-slot field). */
2068
2074
  aggregates: Array<{
@@ -2080,7 +2086,7 @@ export interface CmsAggregateBody {
2080
2086
  /** group rows returned; clamped to 500. */
2081
2087
  limit?: number;
2082
2088
  }
2083
- /** cms-rel B3: the rank request body (cms.md §12.2). */
2089
+ /** the rank request body (guide ch. 4). */
2084
2090
  export interface CmsRankBody {
2085
2091
  /** REQUIRED: the ranked entity — a slot-bound own field (often a relation). */
2086
2092
  groupBy: string;
@@ -2097,7 +2103,7 @@ export interface CmsRankBody {
2097
2103
  window?: CmsWindow;
2098
2104
  limit?: number;
2099
2105
  }
2100
- /** cms-rel B4: one transaction step (cms.md §13). `$where` = the bounded CAS
2106
+ /** one transaction step (guide ch. 4). `$where` = the bounded CAS
2101
2107
  * precondition (the PATCH `if` grammar: ≤4 terms, scalar / null /
2102
2108
  * {$eq $ne $gt $gte $lt $lte $in}). */
2103
2109
  export type CmsTxStep = {
@@ -2117,7 +2123,7 @@ export type CmsTxStep = {
2117
2123
  item_id: string;
2118
2124
  $where?: Record<string, unknown>;
2119
2125
  };
2120
- /** One op of `vx.cms.batch` (cms.md §21) — the single route's own body keys,
2126
+ /** One op of `vx.cms.batch` (guide ch. 4) — the single route's own body keys,
2121
2127
  * typed by op. `ref` is an opaque tag echoed on the matching result. */
2122
2128
  export type CmsBatchOp = {
2123
2129
  op: 'get';
@@ -2216,7 +2222,7 @@ export interface CmsBatchResponse<T extends readonly CmsBatchOp[]> {
2216
2222
  };
2217
2223
  }
2218
2224
  /** One CMS item as the API returns it — the envelope `$expand` inlines in place
2219
- * of a stored relation id (cms.md §6.2). `R` is the target collection's Row. */
2225
+ * of a stored relation id (guide ch. 4). `R` is the target collection's Row. */
2220
2226
  export interface CmsItemEnvelope<R> {
2221
2227
  item_id: string;
2222
2228
  collection: string;
@@ -2232,7 +2238,7 @@ export interface CmsFileRef {
2232
2238
  object_id: string;
2233
2239
  $ref: 'files';
2234
2240
  }
2235
- /** Every shape an expanded member can take (cms.md §6.2, all four verified in
2241
+ /** Every shape an expanded member can take (guide ch. 4, all four verified in
2236
2242
  * cms-v1 core.ts): the full envelope; a `{ object_id, $ref: 'files' }` stub for
2237
2243
  * a file field; the BARE id when the expansion hit a cycle or the depth budget;
2238
2244
  * `null` when the target is soft-deleted, not visible to this caller, or owned
@@ -2276,7 +2282,7 @@ export interface CollectionClient<C extends VxilSchemaShape['cms'][string], S ex
2276
2282
  version: number;
2277
2283
  data: C['Row'];
2278
2284
  }>;
2279
- /** `expand` inlines the named relation/file fields (cms.md §6.2) — the names
2285
+ /** `expand` inlines the named relation/file fields (guide ch. 4) — the names
2280
2286
  * come from the generated `Relations`, so a typo is a compile error. Bounds
2281
2287
  * (worker-clamped regardless of config): depth 1 (ceiling 2), ≤5 fields
2282
2288
  * (ceiling 25). Omit it and the result type is exactly today's `Row`. */
@@ -2311,12 +2317,12 @@ export interface CollectionClient<C extends VxilSchemaShape['cms'][string], S ex
2311
2317
  items: C['Row'][];
2312
2318
  next_cursor: string | null;
2313
2319
  }>;
2314
- /** `SELECT count(*)` under the same bounded filter grammar (cms.md §9.4).
2320
+ /** `SELECT count(*)` under the same bounded filter grammar (guide ch. 4).
2315
2321
  * Refused (422) on collections with beforeRead visibility hooks. */
2316
2322
  count(filter?: Partial<C['Filterable']>): Promise<number>;
2317
2323
  patch(itemId: string, data: C['Patch'], opts?: CmsWriteOpts): Promise<C['Row']>;
2318
2324
  /** Atomic in-database increment — ONE conditional UPDATE; never
2319
- * read-modify-write (cms.md §9.3). Delta keys are the numeric Row fields. */
2325
+ * read-modify-write (guide ch. 4). Delta keys are the numeric Row fields. */
2320
2326
  inc(itemId: string, incs: Partial<Record<NumericKeys<C['Row']> & string, number>>, opts?: Pick<CmsWriteOpts, 'ifVersion' | 'if'>): Promise<C['Row']>;
2321
2327
  delete(itemId: string, opts?: Pick<CmsWriteOpts, 'ifVersion'>): Promise<{
2322
2328
  item_id: string;
@@ -2324,7 +2330,7 @@ export interface CollectionClient<C extends VxilSchemaShape['cms'][string], S ex
2324
2330
  cascaded: number;
2325
2331
  set_null: number;
2326
2332
  }>;
2327
- /** cms.md §20: bounded filtered delete over the generated `Filterable` — a
2333
+ /** Bounded filtered delete over the generated `Filterable` — a
2328
2334
  * filter is required, ≤100 rows per call, `dryRun` previews. Loop while
2329
2335
  * `deleted > 0`. */
2330
2336
  deleteMany(q: {
@@ -2334,7 +2340,7 @@ export interface CollectionClient<C extends VxilSchemaShape['cms'][string], S ex
2334
2340
  dryRun?: boolean;
2335
2341
  }): Promise<CmsBulkDeleteResult>;
2336
2342
  publish(itemId: string): Promise<C['Row']>;
2337
- /** cms-rel B2: bounded group-by aggregate (spec §7 `groupBy()` surface).
2343
+ /** Bounded group-by aggregate (guide ch. 4).
2338
2344
  * groupBy/field names are typed over the Row's keys; slot-existence stays a
2339
2345
  * runtime check — exactly like `query`. Joins stay expressed as dotted
2340
2346
  * filter keys (no `.join()` builder — one grammar, not two). */
@@ -2351,7 +2357,7 @@ export interface CollectionClient<C extends VxilSchemaShape['cms'][string], S ex
2351
2357
  }>;
2352
2358
  scanned: number;
2353
2359
  }>;
2354
- /** cms-rel B3: window ranking over the aggregate. */
2360
+ /** Window ranking over the aggregate (guide ch. 4). */
2355
2361
  rank(q: Omit<CmsRankBody, 'groupBy' | 'partitionBy' | 'metric'> & {
2356
2362
  groupBy: keyof C['Row'] & string;
2357
2363
  partitionBy?: keyof C['Row'] & string;
@@ -2407,12 +2413,12 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
2407
2413
  * `Vxil.connect<VxilSchema>({ apiKey }).rag` won't type-check if `rag` is off.
2408
2414
  * Runtime is identical to `new Vxil`; this only adds the compile-time gate. */
2409
2415
  static connect<S extends VxilSchemaShape = VxilSchemaShape>(opts: VxilOptions): EnabledVxil<S>;
2410
- /** Typed per-collection CMS handle (design §4.8). A thin wrapper over the
2416
+ /** Typed per-collection CMS handle (guide ch. 5). A thin wrapper over the
2411
2417
  * generic `cms.items.*` methods — the wire calls are identical; the generated
2412
2418
  * `VxilSchema` supplies the field types. `vx.cms.items.*` stays as the
2413
2419
  * always-available un-generic fallback. */
2414
2420
  from<C extends keyof S['cms'] & string>(collection: C): CollectionClient<S['cms'][C], S>;
2415
- /** Typed function invoke (design §4.5). `vx.fn.<name>(payload)` POSTs to
2421
+ /** Typed function invoke (guide ch. 8). `vx.fn.<name>(payload)` POSTs to
2416
2422
  * /v1/fn/<name>; the generated `VxilSchema` types Input/Output (Level-0
2417
2423
  * opaque until a function declares a signature). A Proxy gives the
2418
2424
  * `vx.fn.<name>` accessor shape without enumerating names at runtime.
@@ -2451,7 +2457,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
2451
2457
  * (email/display_name/avatar_url/attributes) is scrubbed, while the id is
2452
2458
  * kept so cross-feature references stay intact. NOTE: a full account-delete
2453
2459
  * flow also calls the auth half — POST /v1/auth/users/:id/erase — to erase
2454
- * the credential/session identity (see features/tenant-users.md §3).
2460
+ * the credential/session identity (see guide ch. 6, auth).
2455
2461
  */
2456
2462
  delete: (id: string, opts?: {
2457
2463
  erase?: boolean;
@@ -2488,7 +2494,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
2488
2494
  readonly notifications: {
2489
2495
  send: (input: {
2490
2496
  user_id: string;
2491
- /** The four shipped template ids (notifications.md §7). */
2497
+ /** The four shipped template ids (guide ch. 6, notifications). */
2492
2498
  template: "magic-link" | "otp-code" | "welcome" | "transactional";
2493
2499
  data: Record<string, unknown>;
2494
2500
  /** Explicit wins; otherwise the recipient's stored `locale` attribute
@@ -2584,7 +2590,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
2584
2590
  user_id?: string;
2585
2591
  status?: string;
2586
2592
  limit?: number;
2587
- /** A7: only deliveries that reached this engagement state */
2593
+ /** only deliveries that reached this engagement state */
2588
2594
  engagement?: "delivered" | "opened" | "clicked";
2589
2595
  }) => Promise<Delivery[]>;
2590
2596
  suppressions: {
@@ -2637,7 +2643,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
2637
2643
  * does not cover them, so an "unsubscribe from everything" click can never
2638
2644
  * lock a user out of its own account. Muteable ids: `welcome`,
2639
2645
  * `transactional`. (Password-reset mail rides `transactional`, which stays
2640
- * muteable — see the notifications feature doc §6c.)
2646
+ * muteable — see guide ch. 6, notifications.)
2641
2647
  *
2642
2648
  * SCOPES: with an end-user token both calls are confined to the verified
2643
2649
  * principal and take `notifications:read` (a browser key that can mute its
@@ -2681,7 +2687,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
2681
2687
  };
2682
2688
  /** A single delivery by id (the list is `deliveries()`). */
2683
2689
  delivery: (deliveryId: string) => Promise<Delivery>;
2684
- /** Email broadcast campaigns (notifications.md §11b): audience-ref fan-out
2690
+ /** Email broadcast campaigns (guide ch. 6, notifications): audience-ref fan-out
2685
2691
  * with quiet-hours + frequency-cap policy. `schedule_cron` sets a recurring
2686
2692
  * send (status `scheduled`); omit it for a `draft`. */
2687
2693
  campaigns: {
@@ -2748,12 +2754,12 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
2748
2754
  /** The tenant's enabled-feature summary (GET /v1/features). Privilege-
2749
2755
  * independent: any valid key may read it — it leaks no secrets, only which
2750
2756
  * features the tenant has turned on. Mirrors what the MCP tool-list
2751
- * aggregation sees. (audit #113) */
2757
+ * aggregation sees. */
2752
2758
  list: () => Promise<string[]>;
2753
2759
  /** The FULL enabled-feature summary: `features` + `api_versions` (released
2754
2760
  * API majors per feature) + the additive `key` block — the CALLING key's
2755
2761
  * identity and per-tool MCP permissions (allowed_tools/denied_tools
2756
- * patterns, api_keys 0057; mcp.md §6.7). `key` is absent for non-key
2762
+ * patterns; guide ch. 10). `key` is absent for non-key
2757
2763
  * callers and for keys without explicit tool perms. `list()` stays the
2758
2764
  * stable flat-array shorthand. */
2759
2765
  summary: () => Promise<{
@@ -2859,7 +2865,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
2859
2865
  }>;
2860
2866
  count: number;
2861
2867
  }>;
2862
- /** Enqueue a long-running EXTERNAL generation run (jobs.md §11): Vxil calls
2868
+ /** Enqueue a long-running EXTERNAL generation run (guide ch. 6, jobs): Vxil calls
2863
2869
  * the provider (BYO key), tracks completion via poll/webhook, mirrors a typed
2864
2870
  * generation_status onto a tenant record, enforces a built-in timeout, and
2865
2871
  * (on failure) fires the payments credit-reversal.
@@ -2868,7 +2874,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
2868
2874
  * of the same `idempotency_key` (`deduplicated: true`) carries the run's
2869
2875
  * status NOW (`processing`, `completed` or `failed` too).
2870
2876
  *
2871
- * `reserve_credits` (§11.8) takes a PROVISIONAL held credit debit at enqueue
2877
+ * `reserve_credits` takes a PROVISIONAL held credit debit at enqueue
2872
2878
  * (linked to the run), committed on `completed` and reversed on
2873
2879
  * failed/timeout/DLQ. `amount` is positive-only and CLAMPED to the platform
2874
2880
  * `config.generation.maxReserveCredits` cap; in end-user mode `user_id` is
@@ -3425,9 +3431,9 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
3425
3431
  createPolicy: (input: {
3426
3432
  name: string;
3427
3433
  key_template: string;
3428
- /** omitted ⇒ seeded from the tenant's rate-limits config `defaults` (F8-54) */
3434
+ /** omitted ⇒ seeded from the tenant's rate-limits config `defaults` */
3429
3435
  limit?: number;
3430
- /** omitted ⇒ seeded from the tenant's rate-limits config `defaults` (F8-54) */
3436
+ /** omitted ⇒ seeded from the tenant's rate-limits config `defaults` */
3431
3437
  window_seconds?: number;
3432
3438
  behavior?: "block" | "shape";
3433
3439
  }) => Promise<RateLimitPolicy>;
@@ -3501,7 +3507,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
3501
3507
  }>;
3502
3508
  /** Per-identifier overrides layered over a policy: `pattern` matches the
3503
3509
  * RENDERED key (exact, or a `*`-glob where the longest literal prefix
3504
- * wins). Propagates to the check path within ≤30s (KV cacheTtl). */
3510
+ * wins). Propagates to the check path within ≤30s (cache TTL). */
3505
3511
  overrides: {
3506
3512
  list: (policyId: string) => Promise<RateLimitOverride[]>;
3507
3513
  create: (policyId: string, input: {
@@ -3533,7 +3539,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
3533
3539
  * end-user principal (default-deny) in end-user mode; a no-op in
3534
3540
  * server-caller mode. Omit for shared/reference collections. */
3535
3541
  owner_field?: string;
3536
- /** Public delivery (roadmap §4.4): when true, this collection's PUBLISHED
3542
+ /** Public delivery (guide ch. 4): when true, this collection's PUBLISHED
3537
3543
  * items become KEYLESS-readable through the anonymous public lane —
3538
3544
  * `GET {base}/v1/cms/public/:tenantId/:collection` with NO api key. Drafts
3539
3545
  * and the owner_field are never exposed. Optional; defaults false. Use the
@@ -3551,15 +3557,15 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
3551
3557
  };
3552
3558
  index_slot?: "s1" | "s2" | "s3" | "s4" | "n1" | "n2" | "t1" | "t2";
3553
3559
  relation_to?: string;
3554
- /** Value uniqueness across the collection's LIVE items (cms.md §9.3);
3560
+ /** Value uniqueness across the collection's LIVE items (guide ch. 4);
3555
3561
  * scalar-valued types only. Concurrent duplicates → 409 unique_violation. */
3556
3562
  unique?: boolean;
3557
3563
  /** relation fields only: what a delete of the referenced item does to
3558
- * this one — cascade / set_null (bounded fan-out, cms.md §11) or
3559
- * `restrict` (§11.1: the delete is refused with 409 `referenced`
3564
+ * this one — cascade / set_null (bounded fan-out, guide ch. 4) or
3565
+ * `restrict` (the delete is refused with 409 `referenced`
3560
3566
  * while a live reference exists). */
3561
3567
  on_delete?: "cascade" | "set_null" | "restrict";
3562
- /** FIELD-LEVEL read security (cms.md §18): the end-user ORG ROLE slugs
3568
+ /** FIELD-LEVEL read security (guide ch. 4): the end-user ORG ROLE slugs
3563
3569
  * allowed to READ this field. Omitted/`[]` = ungated. A non-empty list
3564
3570
  * is FAIL-SAFE — in verified end-user mode the field is OMITTED from
3565
3571
  * every read (get / list / query / `$expand` / the write-response echo)
@@ -3569,8 +3575,14 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
3569
3575
  * session) still sees every field. Writes are unaffected. ≤16 entries,
3570
3576
  * each `^[a-z0-9][a-z0-9_-]{0,31}$` (the `orgs` role alphabet). */
3571
3577
  read_roles?: string[];
3578
+ /** Equality index for an UNSLOTTED field (guide ch. 4 "Indexed
3579
+ * equality"): `=` / `$eq` / `$in` filters on it are index-served
3580
+ * instead of a bounded scan — results are identical either way. ≤4
3581
+ * per collection; not with `index_slot` (a slot already indexes
3582
+ * equality) and not on a computed field. */
3583
+ indexed?: boolean;
3572
3584
  }>;
3573
- /** Per-record action buttons (cms.md §17): `[{ key, label, fn }]` —
3585
+ /** Per-record action buttons (guide ch. 4): `[{ key, label, fn }]` —
3574
3586
  * exactly ONE human-initiated step each; `fn` names a deployed tenant
3575
3587
  * function invoked by `items.runAction`. ≤8 per collection. */
3576
3588
  actions?: CmsActionDef[];
@@ -3588,7 +3600,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
3588
3600
  owner_field?: string | null;
3589
3601
  }>>;
3590
3602
  addField: (collection: string, field: Record<string, unknown>) => Promise<void>;
3591
- /** Set (or clear, with `null`/`[]`) a field's READ-ROLE gate (cms.md §18) —
3603
+ /** Set (or clear, with `null`/`[]`) a field's READ-ROLE gate (guide ch. 4) —
3592
3604
  * the same-type in-place alter on the fields route. Re-sends the field's
3593
3605
  * `type` (required by the alter path); every OTHER attribute the field
3594
3606
  * carries is re-sent from `rest`, because the alter overwrites the whole
@@ -3596,17 +3608,29 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
3596
3608
  * read unless the session's verified roles intersect `roles`; server-caller
3597
3609
  * reads and ALL writes are unaffected. */
3598
3610
  setFieldReadRoles: (collection: string, field: string, type: "string" | "text" | "int" | "float" | "bool" | "datetime" | "json" | "relation" | "file", roles: string[] | null, rest?: Record<string, unknown>) => Promise<void>;
3611
+ /** Turn a field's EQUALITY INDEX on or off (guide ch. 4 "Indexed equality")
3612
+ * — the same-type in-place alter on the fields route; `indexed` is
3613
+ * present-key, so no other attribute moves. Only for UNSLOTTED,
3614
+ * non-computed fields, ≤4 per collection (422 `eq_index_budget`).
3615
+ * `index_ready: false` + `reindex_required: true` on a collection over
3616
+ * 2,000 live items: run `reindexAll` (until then filters stay on the
3617
+ * bounded scan — never wrong, only slower). */
3618
+ setFieldIndexed: (collection: string, field: string, type: "string" | "text" | "int" | "float" | "bool" | "datetime" | "json" | "relation" | "file", indexed: boolean) => Promise<{
3619
+ indexed: boolean;
3620
+ index_ready: boolean;
3621
+ reindex_required: boolean;
3622
+ }>;
3599
3623
  /** Set (or clear, with `null`) the collection's end-user owner-scope flag
3600
- * (design §5.1). Names an existing `string` field that holds the owner id. */
3624
+ * (guide ch. 4, "`ownerField`"). Names an existing `string` field that holds the owner id. */
3601
3625
  setOwnerField: (collection: string, ownerField: string | null) => Promise<void>;
3602
- /** Toggle the collection's PUBLIC-delivery flag (roadmap §4.4). When `true`,
3626
+ /** Toggle the collection's PUBLIC-delivery flag (guide ch. 4). When `true`,
3603
3627
  * its PUBLISHED items become KEYLESS-readable via the anonymous public lane
3604
3628
  * (`GET {base}/v1/cms/public/:tenantId/:collection` — no api key); drafts and
3605
3629
  * the owner_field are never exposed. `false` closes the lane (and purges the
3606
3630
  * edge cache). Read the public side with `cmsPublicUrl` / `listCmsPublic`. */
3607
3631
  setPublic: (collection: string, isPublic: boolean) => Promise<void>;
3608
3632
  /** Re-project the collection's index slots after an `index_slot` move
3609
- * (cms.md §19). Slots are projected on WRITE only, so until this runs,
3633
+ * (guide ch. 4). Slots are projected on WRITE only, so until this runs,
3610
3634
  * stored rows keep their OLD projection: the new slot is NULL and the
3611
3635
  * VACATED slot still holds the old field's values — range/sort on the
3612
3636
  * moved field returns the WRONG rows, not merely missing ones. ONE page
@@ -3633,16 +3657,17 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
3633
3657
  updated: number;
3634
3658
  skipped: number;
3635
3659
  pages: number;
3660
+ index_certify?: CmsReindexPage["index_certify"];
3636
3661
  }>;
3637
- /** Replace the collection's per-record ACTION list (cms.md §17) — the
3662
+ /** Replace the collection's per-record ACTION list (guide ch. 4) — the
3638
3663
  * `{ actions }` fields-route meta-op; `[]` clears. Each action is ONE
3639
3664
  * human-initiated step: the dashboard renders it as a button per record,
3640
3665
  * and `items.runAction` invokes its deployed function. */
3641
3666
  setActions: (collection: string, actions: CmsActionDef[]) => Promise<void>;
3642
3667
  };
3643
3668
  items: {
3644
- /** `lock` serializes same-key writers (per-tenant advisory lock); `guard`
3645
- * is the declarative capacity/overlap invariant (requires lock) — cms.md §10. */
3669
+ /** `lock` serializes same-key writers (a per-key lock); `guard`
3670
+ * is the declarative capacity/overlap invariant (requires lock) — guide ch. 4. */
3646
3671
  create: (collection: string, input: {
3647
3672
  data: Record<string, unknown>;
3648
3673
  status?: "draft" | "published";
@@ -3655,7 +3680,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
3655
3680
  version: number;
3656
3681
  data: Record<string, unknown>;
3657
3682
  }>;
3658
- /** `expand` inlines relation/file fields into `data` (cms.md §6.2): the
3683
+ /** `expand` inlines relation/file fields into `data` (guide ch. 4): the
3659
3684
  * full item envelope, a `{ object_id, $ref: 'files' }` stub for a file,
3660
3685
  * the bare id on a cycle/depth cut, `null` for an invisible target. */
3661
3686
  get: (collection: string, itemId: string, opts?: {
@@ -3689,19 +3714,19 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
3689
3714
  items: Array<Record<string, unknown>>;
3690
3715
  next_cursor: string | null;
3691
3716
  }>;
3692
- /** Merge-patch data keys; null clears a key. Concurrency opts (cms.md §9):
3717
+ /** Merge-patch data keys; null clears a key. Concurrency opts (guide ch. 4):
3693
3718
  * `ifVersion` → If-Match CAS; `if` → bounded field precondition against
3694
- * the locked row; `lock`/`guard` → the §10 serialization primitives. */
3719
+ * the locked row; `lock`/`guard` → the write-serialization primitives (guide ch. 4). */
3695
3720
  patch: (collection: string, itemId: string, data: Record<string, unknown>, opts?: CmsWriteOpts) => Promise<Record<string, unknown>>;
3696
3721
  /** Atomic in-database increment — PATCH `{ $inc: {field: delta} }`, ONE
3697
3722
  * conditional UPDATE guarded by the field's validation min/max (the quota
3698
3723
  * shape), the optional `if` precondition, and If-Match. 409
3699
- * inc_out_of_bounds when the guard refuses (cms.md §9.3). */
3724
+ * inc_out_of_bounds when the guard refuses (guide ch. 4). */
3700
3725
  inc: (collection: string, itemId: string, incs: Record<string, number>, opts?: Pick<CmsWriteOpts, "ifVersion" | "if">) => Promise<Record<string, unknown>>;
3701
- /** `{ count }` under the same bounded filter grammar (cms.md §9.4). 422
3726
+ /** `{ count }` under the same bounded filter grammar (guide ch. 4). 422
3702
3727
  * count_unavailable_with_read_hooks on beforeRead-hooked collections. */
3703
3728
  count: (collection: string, filter?: Record<string, unknown>) => Promise<number>;
3704
- /** Returns the cascade tally (cms.md §11); `ifVersion` rides If-Match and
3729
+ /** Returns the cascade tally (guide ch. 4); `ifVersion` rides If-Match and
3705
3730
  * a conflict aborts BEFORE any cascade side-effect. */
3706
3731
  delete: (collection: string, itemId: string, opts?: Pick<CmsWriteOpts, "ifVersion">) => Promise<{
3707
3732
  item_id: string;
@@ -3709,7 +3734,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
3709
3734
  cascaded: number;
3710
3735
  set_null: number;
3711
3736
  }>;
3712
- /** N-22 (cms.md §20): BOUNDED FILTERED delete — soft-delete up to `limit`
3737
+ /** BOUNDED FILTERED delete — soft-delete up to `limit`
3713
3738
  * items (1–100, default 25) matching `filter`, newest id first. A filter
3714
3739
  * is REQUIRED (an unselected sweep is refused 422). Each matched row runs
3715
3740
  * the SAME single-item delete path (restrict refusal, cascade budget,
@@ -3729,7 +3754,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
3729
3754
  dryRun?: boolean;
3730
3755
  }) => Promise<CmsBulkDeleteResult>;
3731
3756
  publish: (collection: string, itemId: string) => Promise<Record<string, unknown>>;
3732
- /** P1-12 (cms.md §11.1): the BOUNDED reverse read — which live items
3757
+ /** The BOUNDED reverse read — which live items
3733
3758
  * reference this one, through which relation field. Owner-scoped in
3734
3759
  * end-user mode like `get`. `count` is the page returned (≤ limit, max
3735
3760
  * 100), never a total; `has_more` says the cap was hit. A DELETE refused
@@ -3738,7 +3763,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
3738
3763
  backlinks: (collection: string, itemId: string, opts?: {
3739
3764
  limit?: number;
3740
3765
  }) => Promise<CmsBacklinksPage>;
3741
- /** P1-7 (cms.md §17): run ONE declared per-record action — invokes the
3766
+ /** Run ONE declared per-record action — invokes the
3742
3767
  * action's deployed function with `{ collection, item_id, action, actor,
3743
3768
  * item }` and returns its result. 404 when the key is not declared;
3744
3769
  * 502 `action_failed` (with `upstream.code` = the function's error
@@ -3750,7 +3775,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
3750
3775
  fn: string;
3751
3776
  result: unknown;
3752
3777
  }>;
3753
- /** cms-rel B2 (cms.md §12): bounded group-by aggregate. fns count|sum|
3778
+ /** Bounded group-by aggregate. fns count|sum|
3754
3779
  * min|max|avg over index-slot-bound fields; groupBy ≤2 slot-bound
3755
3780
  * fields; filter = the full query DSL incl. ONE-hop dotted join terms
3756
3781
  * ({"channel.visibility":"public"}); scan capped at 50k rows → 422
@@ -3761,7 +3786,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
3761
3786
  }>;
3762
3787
  scanned: number;
3763
3788
  }>;
3764
- /** cms-rel B3 (cms.md §12): window ranking over the aggregate — rank ∈
3789
+ /** Window ranking over the aggregate — rank ∈
3765
3790
  * row_number|rank|percent_rank, computed over ≤500 aggregated groups
3766
3791
  * (never raw rows), optional partitionBy. Same scan cap as aggregate. */
3767
3792
  rank: (collection: string, body: CmsRankBody) => Promise<{
@@ -3789,7 +3814,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
3789
3814
  done: boolean;
3790
3815
  }>;
3791
3816
  };
3792
- /** cms-rel B4 (cms.md §13): atomic multi-collection transaction — 1–5
3817
+ /** Atomic multi-collection transaction — 1–5
3793
3818
  * steps over ≤3 collections, per-step `$where` CAS preconditions (the
3794
3819
  * PATCH `if` grammar). All-or-nothing: any failed precondition/validation
3795
3820
  * rolls the WHOLE transaction back (409 precondition_failed names the
@@ -3805,7 +3830,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
3805
3830
  committed: boolean;
3806
3831
  tx_id: string;
3807
3832
  }>;
3808
- /** P1-1 (cms.md §21): several get / query / create / patch / delete ops in
3833
+ /** Several get / query / create / patch / delete ops in
3809
3834
  * ONE round trip — the function-chain shape ("read 3 rows → patch 2 →
3810
3835
  * create 1" is one call, not six). ≤25 ops, each run through the SAME path
3811
3836
  * its single route uses (scopes, owner-scoping, hooks, guards, `if`,
@@ -3819,7 +3844,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
3819
3844
  batch: <T extends readonly CmsBatchOp[]>(ops: readonly [...T], opts?: {
3820
3845
  atomic?: boolean;
3821
3846
  }) => Promise<CmsBatchResponse<T>>;
3822
- /** cms-rel B5 (cms.md §12.4): declared read-models (config `readModels`
3847
+ /** Declared read-models (config `readModels`
3823
3848
  * bag) — list with last-run status, and "run now" materialization into
3824
3849
  * the rollup collection. */
3825
3850
  readModels: {
@@ -3924,7 +3949,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
3924
3949
  /** Read the resolved DM config (defaults merged with the stored partial). */
3925
3950
  getConfig: () => Promise<DmConfigState>;
3926
3951
  /** Write the DM master config — a partial merge (omitted leaves keep their
3927
- * current value), version-bumped and republished to the gate's KV key. */
3952
+ * current value), version-bumped and republished to the gate's cache. */
3928
3953
  setConfig: (patch: {
3929
3954
  enabled?: boolean;
3930
3955
  maxParticipants?: number;
@@ -4057,7 +4082,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
4057
4082
  /** The MCP aggregation surface (the `mcp` feature). */
4058
4083
  readonly mcp: {
4059
4084
  /** Per-tenant secret for verifying the X-Vxil-Mcp-Signature header on custom
4060
- * MCP tool calls (mcp.md §6.5) — the mirror of jobs.signingSecret(). */
4085
+ * MCP tool calls (guide ch. 10) — the mirror of jobs.signingSecret(). */
4061
4086
  signingSecret: () => Promise<string>;
4062
4087
  };
4063
4088
  /**
@@ -4154,7 +4179,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
4154
4179
  ids?: string[];
4155
4180
  before?: string;
4156
4181
  }) => Promise<FeedBadge>;
4157
- /** The badge: { unseen, unread, total } (KV-cached over the authority). */
4182
+ /** The badge: { unseen, unread, total } (cached, recomputed on a miss). */
4158
4183
  unreadCount: (userId: string) => Promise<FeedBadge>;
4159
4184
  };
4160
4185
  /**
@@ -4269,7 +4294,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
4269
4294
  ids?: string[];
4270
4295
  before?: string;
4271
4296
  }) => Promise<FeedBadge>;
4272
- /** The badge: { unseen, unread, total } (KV-cached over the authority). */
4297
+ /** The badge: { unseen, unread, total } (cached, recomputed on a miss). */
4273
4298
  unreadCount: (userId: string) => Promise<FeedBadge>;
4274
4299
  };
4275
4300
  /**
@@ -4520,7 +4545,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
4520
4545
  pending?: boolean;
4521
4546
  }>>;
4522
4547
  };
4523
- /** Custom tenant roles (permission-sets; migration orgs/0019). A custom role
4548
+ /** Custom tenant roles (permission-sets). A custom role
4524
4549
  * is a named set of permissions assignable like any built-in; the four
4525
4550
  * built-ins reproduce the fixed owner>admin>member>viewer lattice. */
4526
4551
  roles: {
@@ -4554,7 +4579,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
4554
4579
  /** Delete a custom role (built-in roles cannot be deleted). */
4555
4580
  delete: (roleKey: string) => Promise<void>;
4556
4581
  };
4557
- /** Per-org/user resource ACL grants (migration orgs/0019): grant a permission
4582
+ /** Per-org/user resource ACL grants: grant a permission
4558
4583
  * on a specific resource string; `check(...,{ resource })` consults them. */
4559
4584
  acl: {
4560
4585
  grant: (orgId: string, input: {
@@ -4696,7 +4721,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
4696
4721
  };
4697
4722
  available: Record<string, number | null>;
4698
4723
  }>;
4699
- /** OCR / text extraction (files.md §1.1, BYO-key add-on). Small/mock inputs
4724
+ /** OCR / text extraction (guide ch. 6, files, BYO-key add-on). Small/mock inputs
4700
4725
  * extract inline (status `available`); large inputs (or `async:true`) return
4701
4726
  * 202 with a `job_id` — poll `getText()`. */
4702
4727
  extractText: (objectId: string, opts?: {
@@ -4850,7 +4875,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
4850
4875
  * The AI substrate (the `ai` feature): store prompt TEMPLATES (config-as-code),
4851
4876
  * then generate (sync or streamed) and embed across providers. 'mock' is the
4852
4877
  * deterministic default; the real providers (openai/anthropic/gemini/azure/
4853
- * openrouter) route via BYO keys in tenant_secrets. `images` on the generate
4878
+ * openrouter) route via BYO keys in your project secrets. `images` on the generate
4854
4879
  * inputs takes up to 8 vision refs: a public https:// URL, a
4855
4880
  * data:image/...;base64 URL, or file:<object_id> (a files-feature object) —
4856
4881
  * fetched images are capped at 4 MiB each; `documents` (pdf/text, ≤10 MiB
@@ -5062,7 +5087,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
5062
5087
  * outlives the ≤300s realtime token TTL); reconnect with `?since=<seq>`. */
5063
5088
  remintToken: (generationId: string) => Promise<AiStreamToken>;
5064
5089
  /** Resume a streamed generation after a dropped socket: every recorded frame
5065
- * with seq > `since` plus `done` (the §2a replay buffer — plain JSON, not
5090
+ * with seq > `since` plus `done` (the replay buffer — plain JSON, not
5066
5091
  * an SSE stream; the buffer lives 1 h). A settled JOB-lane generation is
5067
5092
  * served from its stored answer instead (30 days). `status` says where the
5068
5093
  * generation is; `expired: true` means it settled but its frames are gone
@@ -5159,7 +5184,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
5159
5184
  user_id?: string;
5160
5185
  input?: Record<string, unknown>;
5161
5186
  }) => Promise<RagStreamHandle>;
5162
- /** Retrieval-only grounding preview (rag.md §1c): the exact chunks `answer`
5187
+ /** Retrieval-only grounding preview (guide ch. 6, rag): the exact chunks `answer`
5163
5188
  * would ground on, with rerank + metadata boosts applied — no generation,
5164
5189
  * no token spend. `boosts`/`rerank`/`min_score` override the rag config.
5165
5190
  * `min_score` floors the EFFECTIVE `score`, which is a RANK value (about
@@ -5287,7 +5312,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
5287
5312
  * `quota` inlines one quota, `creditType` inlines the same owner-bound
5288
5313
  * balance `getBalance` returns — ONE call for a thin client's paywall.
5289
5314
  * A non-2xx answer means UNKNOWN: render the last cached answer, never
5290
- * free (payments.md §3a).
5315
+ * free (guide ch. 6, payments).
5291
5316
  *
5292
5317
  * OVERLAPPING SUBSCRIPTIONS — what `until` means. The WINNER is the
5293
5318
  * entitled subscription with the highest `tierMap[tier].rank` (default 0);
@@ -5431,7 +5456,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
5431
5456
  status?: string;
5432
5457
  }) => Promise<PaymentsSubscription[]>;
5433
5458
  /**
5434
- * Create a hosted-checkout session (payments.md §3). Redirect the buyer to
5459
+ * Create a hosted-checkout session (guide ch. 6, payments). Redirect the buyer to
5435
5460
  * the returned `url`; completion lands server-side via the provider webhook
5436
5461
  * (the matching session flips to completed, the charge/grant is folded).
5437
5462
  * Idempotency-Key REQUIRED — a retry replays the SAME session verbatim.
@@ -5455,7 +5480,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
5455
5480
  url: string;
5456
5481
  }>;
5457
5482
  /**
5458
- * Refund a charge at-most-once (payments.md §6a). Omit `amount_cents` to
5483
+ * Refund a charge at-most-once (guide ch. 6, payments). Omit `amount_cents` to
5459
5484
  * refund the full un-refunded remainder. Idempotency-Key REQUIRED — a retry
5460
5485
  * replays the recorded refund (never a second provider refund); a refund can
5461
5486
  * NEVER exceed the charge (422 refund_exceeds_charge).
@@ -5652,7 +5677,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
5652
5677
  }) => Promise<{
5653
5678
  refunds: PaymentsRefund[];
5654
5679
  }>;
5655
- /** Provider webhook event log (payments.md §7 "Event log & replay"):
5680
+ /** Provider webhook event log (guide ch. 6, payments "Event log & replay"):
5656
5681
  * operator visibility over every delivery — incl. persisted signature
5657
5682
  * failures — plus an idempotent reprocess verb. Needs payments:read
5658
5683
  * (reprocess: payments:write).
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // (code/message/hint/fixUrl + request id) so callers — humans or agents —
4
4
  // can self-correct.
5
5
  /** The released API majors, as a CLOSED union — one per released major (docs/
6
- * feature-versioning.md §3). `'v1'` is the only released major, so pinning
6
+ * guide ch. 5). `'v1'` is the only released major, so pinning
7
7
  * anything else (`apiVersion: 'v2'`) is a COMPILE error until a v2 GAs and
8
8
  * widens this union. Every path the SDK builds is major-versioned; the default
9
9
  * is the compile-time constant `'v1'` (never a floating `latest` alias). */
@@ -136,7 +136,7 @@ function resolveBase(explicit) {
136
136
  return (explicit ?? envBase ?? DEFAULT_BASE).replace(/\/$/, '');
137
137
  }
138
138
  /** Build the anonymous, KEYLESS public-delivery URL for a collection's PUBLISHED
139
- * items (roadmap §4.4) — `{base}/v1/cms/public/:tenantId/:collection[?…]`. This is
139
+ * items (guide ch. 4, "Draft and publish") — `{base}/v1/cms/public/:tenantId/:collection[?…]`. This is
140
140
  * the reader path a public blog/storefront/docs site hits with NO api key: the
141
141
  * edge mints a restricted read-only inner token bound to the URL tenant, forces
142
142
  * `status='published'`, and strips the collection's owner_field. PURE (no
@@ -155,7 +155,7 @@ export function cmsPublicUrl(tenantId, collection, query, opts) {
155
155
  return `${base}${path}${s}`;
156
156
  }
157
157
  /** Fetch a page of a collection's PUBLISHED items over the KEYLESS public lane
158
- * (roadmap §4.4) — NO api key, no `Vxil` client, no auth of any kind. This is the
158
+ * (guide ch. 4) — NO api key, no `Vxil` client, no auth of any kind. This is the
159
159
  * anonymous reader path (a blog/storefront/docs front-end). Returns the same
160
160
  * `{ items, next_cursor }` envelope the authed list does, but rows are stripped
161
161
  * to the public surface (`CmsPublicRow`) — drafts and the owner_field are never
@@ -254,7 +254,7 @@ export class Vxil {
254
254
  static connect(opts) {
255
255
  return new Vxil(opts);
256
256
  }
257
- /** Typed per-collection CMS handle (design §4.8). A thin wrapper over the
257
+ /** Typed per-collection CMS handle (guide ch. 5). A thin wrapper over the
258
258
  * generic `cms.items.*` methods — the wire calls are identical; the generated
259
259
  * `VxilSchema` supplies the field types. `vx.cms.items.*` stays as the
260
260
  * always-available un-generic fallback. */
@@ -291,7 +291,7 @@ export class Vxil {
291
291
  rank: (q) => this.cms.items.rank(c, q),
292
292
  };
293
293
  }
294
- /** Typed function invoke (design §4.5). `vx.fn.<name>(payload)` POSTs to
294
+ /** Typed function invoke (guide ch. 8). `vx.fn.<name>(payload)` POSTs to
295
295
  * /v1/fn/<name>; the generated `VxilSchema` types Input/Output (Level-0
296
296
  * opaque until a function declares a signature). A Proxy gives the
297
297
  * `vx.fn.<name>` accessor shape without enumerating names at runtime.
@@ -359,7 +359,7 @@ export class Vxil {
359
359
  });
360
360
  // An empty body on a 2xx is a valid "no content" success (e.g. 204 from
361
361
  // DELETE/markRead) — never an error. Only parse when there are bytes; a
362
- // void-returning caller ignores `data` anyway. (audit #115)
362
+ // void-returning caller ignores `data` anyway.
363
363
  let parsed = {};
364
364
  if (text.length > 0) {
365
365
  try {
@@ -395,7 +395,7 @@ export class Vxil {
395
395
  * (email/display_name/avatar_url/attributes) is scrubbed, while the id is
396
396
  * kept so cross-feature references stay intact. NOTE: a full account-delete
397
397
  * flow also calls the auth half — POST /v1/auth/users/:id/erase — to erase
398
- * the credential/session identity (see features/tenant-users.md §3).
398
+ * the credential/session identity (see guide ch. 6, auth).
399
399
  */
400
400
  delete: async (id, opts) => {
401
401
  await this.call('DELETE', `/v1/users/${encodeURIComponent(id)}${opts?.erase ? '?erase=true' : ''}`);
@@ -497,7 +497,7 @@ export class Vxil {
497
497
  * does not cover them, so an "unsubscribe from everything" click can never
498
498
  * lock a user out of its own account. Muteable ids: `welcome`,
499
499
  * `transactional`. (Password-reset mail rides `transactional`, which stays
500
- * muteable — see the notifications feature doc §6c.)
500
+ * muteable — see guide ch. 6, notifications.)
501
501
  *
502
502
  * SCOPES: with an end-user token both calls are confined to the verified
503
503
  * principal and take `notifications:read` (a browser key that can mute its
@@ -524,7 +524,7 @@ export class Vxil {
524
524
  },
525
525
  /** A single delivery by id (the list is `deliveries()`). */
526
526
  delivery: async (deliveryId) => (await this.call('GET', `/v1/notifications/deliveries/${encodeURIComponent(deliveryId)}`)).data,
527
- /** Email broadcast campaigns (notifications.md §11b): audience-ref fan-out
527
+ /** Email broadcast campaigns (guide ch. 6, notifications): audience-ref fan-out
528
528
  * with quiet-hours + frequency-cap policy. `schedule_cron` sets a recurring
529
529
  * send (status `scheduled`); omit it for a `draft`. */
530
530
  campaigns: {
@@ -557,12 +557,12 @@ export class Vxil {
557
557
  /** The tenant's enabled-feature summary (GET /v1/features). Privilege-
558
558
  * independent: any valid key may read it — it leaks no secrets, only which
559
559
  * features the tenant has turned on. Mirrors what the MCP tool-list
560
- * aggregation sees. (audit #113) */
560
+ * aggregation sees. */
561
561
  list: async () => (await this.call('GET', '/v1/features')).data.features,
562
562
  /** The FULL enabled-feature summary: `features` + `api_versions` (released
563
563
  * API majors per feature) + the additive `key` block — the CALLING key's
564
564
  * identity and per-tool MCP permissions (allowed_tools/denied_tools
565
- * patterns, api_keys 0057; mcp.md §6.7). `key` is absent for non-key
565
+ * patterns; guide ch. 10). `key` is absent for non-key
566
566
  * callers and for keys without explicit tool perms. `list()` stays the
567
567
  * stable flat-array shorthand. */
568
568
  summary: async () => (await this.call('GET', '/v1/features')).data,
@@ -610,7 +610,7 @@ export class Vxil {
610
610
  if (!res.ok) {
611
611
  // Preserve the structured error envelope on failure — the export path
612
612
  // is hand-rolled (no this.call), so without this a 403/429 would lose
613
- // its code/hint/requestId. (audit #119)
613
+ // its code/hint/requestId.
614
614
  let env = {};
615
615
  try {
616
616
  env = JSON.parse(text);
@@ -621,7 +621,7 @@ export class Vxil {
621
621
  }
622
622
  // Skip blank lines AND tolerate a single malformed NDJSON line rather
623
623
  // than aborting the whole batch (e.g. a truncated final line on a large
624
- // page) — collect parse failures so the caller can decide. (audit #116)
624
+ // page) — collect parse failures so the caller can decide.
625
625
  const events = [];
626
626
  const parseErrors = [];
627
627
  text.split('\n').forEach((l, i) => {
@@ -657,7 +657,7 @@ export class Vxil {
657
657
  * batch). Each item = the enqueue input, incl. per-item idempotency_key
658
658
  * and deliver_after/delay_seconds. Results align with the input order. */
659
659
  enqueueBatch: async (items) => (await this.call('POST', '/v1/jobs/enqueue-batch', { jobs: items })).data,
660
- /** Enqueue a long-running EXTERNAL generation run (jobs.md §11): Vxil calls
660
+ /** Enqueue a long-running EXTERNAL generation run (guide ch. 6, jobs): Vxil calls
661
661
  * the provider (BYO key), tracks completion via poll/webhook, mirrors a typed
662
662
  * generation_status onto a tenant record, enforces a built-in timeout, and
663
663
  * (on failure) fires the payments credit-reversal.
@@ -666,7 +666,7 @@ export class Vxil {
666
666
  * of the same `idempotency_key` (`deduplicated: true`) carries the run's
667
667
  * status NOW (`processing`, `completed` or `failed` too).
668
668
  *
669
- * `reserve_credits` (§11.8) takes a PROVISIONAL held credit debit at enqueue
669
+ * `reserve_credits` takes a PROVISIONAL held credit debit at enqueue
670
670
  * (linked to the run), committed on `completed` and reversed on
671
671
  * failed/timeout/DLQ. `amount` is positive-only and CLAMPED to the platform
672
672
  * `config.generation.maxReserveCredits` cap; in end-user mode `user_id` is
@@ -1059,7 +1059,7 @@ export class Vxil {
1059
1059
  check: async (input) => (await this.call('POST', '/v1/rate-limits/check', input)).data,
1060
1060
  /** Per-identifier overrides layered over a policy: `pattern` matches the
1061
1061
  * RENDERED key (exact, or a `*`-glob where the longest literal prefix
1062
- * wins). Propagates to the check path within ≤30s (KV cacheTtl). */
1062
+ * wins). Propagates to the check path within ≤30s (cache TTL). */
1063
1063
  overrides: {
1064
1064
  list: async (policyId) => (await this.call('GET', `/v1/rate-limits/policies/${encodeURIComponent(policyId)}/overrides`)).data.overrides,
1065
1065
  create: async (policyId, input) => (await this.call('POST', `/v1/rate-limits/policies/${encodeURIComponent(policyId)}/overrides`, input)).data,
@@ -1078,7 +1078,7 @@ export class Vxil {
1078
1078
  addField: async (collection, field) => {
1079
1079
  await this.call('POST', `/v1/cms/collections/${encodeURIComponent(collection)}/fields`, field);
1080
1080
  },
1081
- /** Set (or clear, with `null`/`[]`) a field's READ-ROLE gate (cms.md §18) —
1081
+ /** Set (or clear, with `null`/`[]`) a field's READ-ROLE gate (guide ch. 4) —
1082
1082
  * the same-type in-place alter on the fields route. Re-sends the field's
1083
1083
  * `type` (required by the alter path); every OTHER attribute the field
1084
1084
  * carries is re-sent from `rest`, because the alter overwrites the whole
@@ -1088,12 +1088,35 @@ export class Vxil {
1088
1088
  setFieldReadRoles: async (collection, field, type, roles, rest = {}) => {
1089
1089
  await this.call('POST', `/v1/cms/collections/${encodeURIComponent(collection)}/fields`, { ...rest, field, type, read_roles: roles ?? [] });
1090
1090
  },
1091
+ /** Turn a field's EQUALITY INDEX on or off (guide ch. 4 "Indexed equality")
1092
+ * — the same-type in-place alter on the fields route; `indexed` is
1093
+ * present-key, so no other attribute moves. Only for UNSLOTTED,
1094
+ * non-computed fields, ≤4 per collection (422 `eq_index_budget`).
1095
+ * `index_ready: false` + `reindex_required: true` on a collection over
1096
+ * 2,000 live items: run `reindexAll` (until then filters stay on the
1097
+ * bounded scan — never wrong, only slower). */
1098
+ setFieldIndexed: async (collection, field, type, indexed) => {
1099
+ try {
1100
+ const d = (await this.call('POST', `/v1/cms/collections/${encodeURIComponent(collection)}/fields`, { field, type, indexed })).data ?? {};
1101
+ return { indexed: d.indexed ?? indexed, index_ready: d.index_ready ?? indexed, reindex_required: d.reindex_required === true };
1102
+ }
1103
+ catch (e) {
1104
+ // 409 already_exists = the field is already in that state (the
1105
+ // idempotent re-POST); read its readiness from the collection list.
1106
+ if (!(e instanceof VxilError) || e.status !== 409)
1107
+ throw e;
1108
+ const colls = (await this.call('GET', '/v1/cms/collections')).data.collections;
1109
+ const f = colls.find((c) => c.collection === collection)?.fields.find((x) => x.field === field);
1110
+ const ready = f?.index_ready === true;
1111
+ return { indexed: f?.indexed === true, index_ready: ready, reindex_required: f?.indexed === true && !ready };
1112
+ }
1113
+ },
1091
1114
  /** Set (or clear, with `null`) the collection's end-user owner-scope flag
1092
- * (design §5.1). Names an existing `string` field that holds the owner id. */
1115
+ * (guide ch. 4, "`ownerField`"). Names an existing `string` field that holds the owner id. */
1093
1116
  setOwnerField: async (collection, ownerField) => {
1094
1117
  await this.call('POST', `/v1/cms/collections/${encodeURIComponent(collection)}/fields`, { owner_field: ownerField });
1095
1118
  },
1096
- /** Toggle the collection's PUBLIC-delivery flag (roadmap §4.4). When `true`,
1119
+ /** Toggle the collection's PUBLIC-delivery flag (guide ch. 4). When `true`,
1097
1120
  * its PUBLISHED items become KEYLESS-readable via the anonymous public lane
1098
1121
  * (`GET {base}/v1/cms/public/:tenantId/:collection` — no api key); drafts and
1099
1122
  * the owner_field are never exposed. `false` closes the lane (and purges the
@@ -1102,7 +1125,7 @@ export class Vxil {
1102
1125
  await this.call('POST', `/v1/cms/collections/${encodeURIComponent(collection)}/fields`, { public: isPublic });
1103
1126
  },
1104
1127
  /** Re-project the collection's index slots after an `index_slot` move
1105
- * (cms.md §19). Slots are projected on WRITE only, so until this runs,
1128
+ * (guide ch. 4). Slots are projected on WRITE only, so until this runs,
1106
1129
  * stored rows keep their OLD projection: the new slot is NULL and the
1107
1130
  * VACATED slot still holds the old field's values — range/sort on the
1108
1131
  * moved field returns the WRONG rows, not merely missing ones. ONE page
@@ -1126,6 +1149,7 @@ export class Vxil {
1126
1149
  let updated = 0;
1127
1150
  let skipped = 0;
1128
1151
  let pages = 0;
1152
+ let indexCertify;
1129
1153
  for (;;) {
1130
1154
  let page = await this.cms.collections.reindex(collection, {
1131
1155
  ...(opts?.field ? { field: opts.field } : {}),
@@ -1148,13 +1172,15 @@ export class Vxil {
1148
1172
  opts?.onPage?.(page);
1149
1173
  }
1150
1174
  skipped += page.skipped ?? 0;
1175
+ if (page.index_certify)
1176
+ indexCertify = page.index_certify;
1151
1177
  if (page.complete || !page.next_cursor)
1152
1178
  break;
1153
1179
  cursor = page.next_cursor;
1154
1180
  }
1155
- return { scanned, updated, skipped, pages };
1181
+ return { scanned, updated, skipped, pages, ...(indexCertify ? { index_certify: indexCertify } : {}) };
1156
1182
  },
1157
- /** Replace the collection's per-record ACTION list (cms.md §17) — the
1183
+ /** Replace the collection's per-record ACTION list (guide ch. 4) — the
1158
1184
  * `{ actions }` fields-route meta-op; `[]` clears. Each action is ONE
1159
1185
  * human-initiated step: the dashboard renders it as a button per record,
1160
1186
  * and `items.runAction` invokes its deployed function. */
@@ -1163,10 +1189,10 @@ export class Vxil {
1163
1189
  },
1164
1190
  },
1165
1191
  items: {
1166
- /** `lock` serializes same-key writers (per-tenant advisory lock); `guard`
1167
- * is the declarative capacity/overlap invariant (requires lock) — cms.md §10. */
1192
+ /** `lock` serializes same-key writers (a per-key lock); `guard`
1193
+ * is the declarative capacity/overlap invariant (requires lock) — guide ch. 4. */
1168
1194
  create: async (collection, input) => (await this.call('POST', `/v1/cms/items/${encodeURIComponent(collection)}`, input)).data,
1169
- /** `expand` inlines relation/file fields into `data` (cms.md §6.2): the
1195
+ /** `expand` inlines relation/file fields into `data` (guide ch. 4): the
1170
1196
  * full item envelope, a `{ object_id, $ref: 'files' }` stub for a file,
1171
1197
  * the bare id on a cycle/depth cut, `null` for an invisible target. */
1172
1198
  get: async (collection, itemId, opts) => {
@@ -1198,9 +1224,9 @@ export class Vxil {
1198
1224
  });
1199
1225
  return (await this.call('GET', `/v1/cms/items/${encodeURIComponent(collection)}${s}`)).data;
1200
1226
  },
1201
- /** Merge-patch data keys; null clears a key. Concurrency opts (cms.md §9):
1227
+ /** Merge-patch data keys; null clears a key. Concurrency opts (guide ch. 4):
1202
1228
  * `ifVersion` → If-Match CAS; `if` → bounded field precondition against
1203
- * the locked row; `lock`/`guard` → the §10 serialization primitives. */
1229
+ * the locked row; `lock`/`guard` → the write-serialization primitives (guide ch. 4). */
1204
1230
  patch: async (collection, itemId, data, opts) => (await this.call('PATCH', `/v1/cms/items/${encodeURIComponent(collection)}/${encodeURIComponent(itemId)}`, {
1205
1231
  data,
1206
1232
  ...(opts?.if ? { if: opts.if } : {}),
@@ -1211,18 +1237,18 @@ export class Vxil {
1211
1237
  /** Atomic in-database increment — PATCH `{ $inc: {field: delta} }`, ONE
1212
1238
  * conditional UPDATE guarded by the field's validation min/max (the quota
1213
1239
  * shape), the optional `if` precondition, and If-Match. 409
1214
- * inc_out_of_bounds when the guard refuses (cms.md §9.3). */
1240
+ * inc_out_of_bounds when the guard refuses (guide ch. 4). */
1215
1241
  inc: async (collection, itemId, incs, opts) => (await this.call('PATCH', `/v1/cms/items/${encodeURIComponent(collection)}/${encodeURIComponent(itemId)}`, { $inc: incs, ...(opts?.if ? { if: opts.if } : {}) }, opts?.ifVersion !== undefined ? { 'if-match': String(opts.ifVersion) } : {})).data,
1216
- /** `{ count }` under the same bounded filter grammar (cms.md §9.4). 422
1242
+ /** `{ count }` under the same bounded filter grammar (guide ch. 4). 422
1217
1243
  * count_unavailable_with_read_hooks on beforeRead-hooked collections. */
1218
1244
  count: async (collection, filter) => {
1219
1245
  const s = qs({ count: 'true', filter: filter ? JSON.stringify(filter) : undefined });
1220
1246
  return (await this.call('GET', `/v1/cms/items/${encodeURIComponent(collection)}${s}`)).data.count;
1221
1247
  },
1222
- /** Returns the cascade tally (cms.md §11); `ifVersion` rides If-Match and
1248
+ /** Returns the cascade tally (guide ch. 4); `ifVersion` rides If-Match and
1223
1249
  * a conflict aborts BEFORE any cascade side-effect. */
1224
1250
  delete: async (collection, itemId, opts) => (await this.call('DELETE', `/v1/cms/items/${encodeURIComponent(collection)}/${encodeURIComponent(itemId)}`, undefined, opts?.ifVersion !== undefined ? { 'if-match': String(opts.ifVersion) } : {})).data,
1225
- /** N-22 (cms.md §20): BOUNDED FILTERED delete — soft-delete up to `limit`
1251
+ /** BOUNDED FILTERED delete — soft-delete up to `limit`
1226
1252
  * items (1–100, default 25) matching `filter`, newest id first. A filter
1227
1253
  * is REQUIRED (an unselected sweep is refused 422). Each matched row runs
1228
1254
  * the SAME single-item delete path (restrict refusal, cascade budget,
@@ -1242,7 +1268,7 @@ export class Vxil {
1242
1268
  ...(q.dryRun !== undefined ? { dry_run: q.dryRun } : {}),
1243
1269
  })).data,
1244
1270
  publish: async (collection, itemId) => (await this.call('POST', `/v1/cms/items/${encodeURIComponent(collection)}/${encodeURIComponent(itemId)}/publish`)).data,
1245
- /** P1-12 (cms.md §11.1): the BOUNDED reverse read — which live items
1271
+ /** The BOUNDED reverse read — which live items
1246
1272
  * reference this one, through which relation field. Owner-scoped in
1247
1273
  * end-user mode like `get`. `count` is the page returned (≤ limit, max
1248
1274
  * 100), never a total; `has_more` says the cap was hit. A DELETE refused
@@ -1252,19 +1278,19 @@ export class Vxil {
1252
1278
  const qs = opts?.limit !== undefined ? `?limit=${encodeURIComponent(String(opts.limit))}` : '';
1253
1279
  return (await this.call('GET', `/v1/cms/items/${encodeURIComponent(collection)}/${encodeURIComponent(itemId)}/backlinks${qs}`)).data;
1254
1280
  },
1255
- /** P1-7 (cms.md §17): run ONE declared per-record action — invokes the
1281
+ /** Run ONE declared per-record action — invokes the
1256
1282
  * action's deployed function with `{ collection, item_id, action, actor,
1257
1283
  * item }` and returns its result. 404 when the key is not declared;
1258
1284
  * 502 `action_failed` (with `upstream.code` = the function's error
1259
1285
  * class) when the function fails. Requires cms:write. */
1260
1286
  runAction: async (collection, itemId, key) => (await this.call('POST', `/v1/cms/items/${encodeURIComponent(collection)}/${encodeURIComponent(itemId)}/actions/${encodeURIComponent(key)}`)).data,
1261
- /** cms-rel B2 (cms.md §12): bounded group-by aggregate. fns count|sum|
1287
+ /** Bounded group-by aggregate. fns count|sum|
1262
1288
  * min|max|avg over index-slot-bound fields; groupBy ≤2 slot-bound
1263
1289
  * fields; filter = the full query DSL incl. ONE-hop dotted join terms
1264
1290
  * ({"channel.visibility":"public"}); scan capped at 50k rows → 422
1265
1291
  * window_too_large (narrow the window or materialize a read-model). */
1266
1292
  aggregate: async (collection, body) => (await this.call('POST', `/v1/cms/items/${encodeURIComponent(collection)}/aggregate`, body)).data,
1267
- /** cms-rel B3 (cms.md §12): window ranking over the aggregate — rank ∈
1293
+ /** Window ranking over the aggregate — rank ∈
1268
1294
  * row_number|rank|percent_rank, computed over ≤500 aggregated groups
1269
1295
  * (never raw rows), optional partitionBy. Same scan cap as aggregate. */
1270
1296
  rank: async (collection, body) => (await this.call('POST', `/v1/cms/items/${encodeURIComponent(collection)}/rank`, body)).data,
@@ -1278,13 +1304,13 @@ export class Vxil {
1278
1304
  * merge, the event is the backstop. Emits one `cms.items.rekeyed`. */
1279
1305
  reKey: async (input) => (await this.call('POST', '/v1/cms/items/re-key', input)).data,
1280
1306
  },
1281
- /** cms-rel B4 (cms.md §13): atomic multi-collection transaction — 1–5
1307
+ /** Atomic multi-collection transaction — 1–5
1282
1308
  * steps over ≤3 collections, per-step `$where` CAS preconditions (the
1283
1309
  * PATCH `if` grammar). All-or-nothing: any failed precondition/validation
1284
1310
  * rolls the WHOLE transaction back (409 precondition_failed names the
1285
1311
  * step). cms-internal only — no cross-feature effects inside the tx. */
1286
1312
  transaction: async (steps) => (await this.call('POST', '/v1/cms/transactions', { steps })).data,
1287
- /** P1-1 (cms.md §21): several get / query / create / patch / delete ops in
1313
+ /** Several get / query / create / patch / delete ops in
1288
1314
  * ONE round trip — the function-chain shape ("read 3 rows → patch 2 →
1289
1315
  * create 1" is one call, not six). ≤25 ops, each run through the SAME path
1290
1316
  * its single route uses (scopes, owner-scoping, hooks, guards, `if`,
@@ -1299,7 +1325,7 @@ export class Vxil {
1299
1325
  ops: ops.map((o) => ('expand' in o && o.expand !== undefined ? { ...o, expand: expandParam(o.expand) } : o)),
1300
1326
  ...(opts?.atomic !== undefined ? { atomic: opts.atomic } : {}),
1301
1327
  })).data,
1302
- /** cms-rel B5 (cms.md §12.4): declared read-models (config `readModels`
1328
+ /** Declared read-models (config `readModels`
1303
1329
  * bag) — list with last-run status, and "run now" materialization into
1304
1330
  * the rollup collection. */
1305
1331
  readModels: {
@@ -1347,7 +1373,7 @@ export class Vxil {
1347
1373
  /** Read the resolved DM config (defaults merged with the stored partial). */
1348
1374
  getConfig: async () => (await this.call('GET', '/v1/dm/config')).data,
1349
1375
  /** Write the DM master config — a partial merge (omitted leaves keep their
1350
- * current value), version-bumped and republished to the gate's KV key. */
1376
+ * current value), version-bumped and republished to the gate's cache. */
1351
1377
  setConfig: async (patch) => (await this.call('PUT', '/v1/dm/config', patch)).data,
1352
1378
  conversations: {
1353
1379
  /** Open (or, for a direct pair, return the existing) conversation. A
@@ -1410,7 +1436,7 @@ export class Vxil {
1410
1436
  /** The MCP aggregation surface (the `mcp` feature). */
1411
1437
  mcp = {
1412
1438
  /** Per-tenant secret for verifying the X-Vxil-Mcp-Signature header on custom
1413
- * MCP tool calls (mcp.md §6.5) — the mirror of jobs.signingSecret(). */
1439
+ * MCP tool calls (guide ch. 10) — the mirror of jobs.signingSecret(). */
1414
1440
  signingSecret: async () => (await this.call('GET', '/v1/mcp/signing-secret')).data.signing_secret,
1415
1441
  };
1416
1442
  /**
@@ -1495,7 +1521,7 @@ export class Vxil {
1495
1521
  markAll: async (userId) => this.feedsMark(userId, 'read'),
1496
1522
  /** Archive/dismiss groups (hidden from inbox + dropped from the badge). */
1497
1523
  archive: async (userId, scope) => this.feedsMark(userId, 'archive', scope),
1498
- /** The badge: { unseen, unread, total } (KV-cached over the authority). */
1524
+ /** The badge: { unseen, unread, total } (cached, recomputed on a miss). */
1499
1525
  unreadCount: async (userId) => (await this.call('GET', `/v1/feeds/notification/${encodeURIComponent(userId)}/count`)).data,
1500
1526
  },
1501
1527
  /**
@@ -1623,7 +1649,7 @@ export class Vxil {
1623
1649
  /** List an org's pending invitations. */
1624
1650
  list: async (orgId) => (await this.call('GET', `/v1/orgs/${encodeURIComponent(orgId)}/invitations`)).data.invitations,
1625
1651
  },
1626
- /** Custom tenant roles (permission-sets; migration orgs/0019). A custom role
1652
+ /** Custom tenant roles (permission-sets). A custom role
1627
1653
  * is a named set of permissions assignable like any built-in; the four
1628
1654
  * built-ins reproduce the fixed owner>admin>member>viewer lattice. */
1629
1655
  roles: {
@@ -1636,7 +1662,7 @@ export class Vxil {
1636
1662
  await this.call('DELETE', `/v1/orgs/roles/${encodeURIComponent(roleKey)}`);
1637
1663
  },
1638
1664
  },
1639
- /** Per-org/user resource ACL grants (migration orgs/0019): grant a permission
1665
+ /** Per-org/user resource ACL grants: grant a permission
1640
1666
  * on a specific resource string; `check(...,{ resource })` consults them. */
1641
1667
  acl: {
1642
1668
  grant: async (orgId, input) => (await this.call('POST', `/v1/orgs/${encodeURIComponent(orgId)}/acl`, input)).data,
@@ -1709,7 +1735,7 @@ export class Vxil {
1709
1735
  },
1710
1736
  /** Aggregate storage usage vs quotas (the FilesManager Storage panel). */
1711
1737
  usage: async () => (await this.call('GET', '/v1/files/usage')).data,
1712
- /** OCR / text extraction (files.md §1.1, BYO-key add-on). Small/mock inputs
1738
+ /** OCR / text extraction (guide ch. 6, files, BYO-key add-on). Small/mock inputs
1713
1739
  * extract inline (status `available`); large inputs (or `async:true`) return
1714
1740
  * 202 with a `job_id` — poll `getText()`. */
1715
1741
  extractText: async (objectId, opts) => (await this.call('POST', `/v1/files/${encodeURIComponent(objectId)}/extract-text`, opts ?? {})).data,
@@ -1792,7 +1818,7 @@ export class Vxil {
1792
1818
  * The AI substrate (the `ai` feature): store prompt TEMPLATES (config-as-code),
1793
1819
  * then generate (sync or streamed) and embed across providers. 'mock' is the
1794
1820
  * deterministic default; the real providers (openai/anthropic/gemini/azure/
1795
- * openrouter) route via BYO keys in tenant_secrets. `images` on the generate
1821
+ * openrouter) route via BYO keys in your project secrets. `images` on the generate
1796
1822
  * inputs takes up to 8 vision refs: a public https:// URL, a
1797
1823
  * data:image/...;base64 URL, or file:<object_id> (a files-feature object) —
1798
1824
  * fetched images are capped at 4 MiB each; `documents` (pdf/text, ≤10 MiB
@@ -1852,7 +1878,7 @@ export class Vxil {
1852
1878
  * outlives the ≤300s realtime token TTL); reconnect with `?since=<seq>`. */
1853
1879
  remintToken: async (generationId) => (await this.call('GET', `/v1/ai/generations/${encodeURIComponent(generationId)}/token`)).data,
1854
1880
  /** Resume a streamed generation after a dropped socket: every recorded frame
1855
- * with seq > `since` plus `done` (the §2a replay buffer — plain JSON, not
1881
+ * with seq > `since` plus `done` (the replay buffer — plain JSON, not
1856
1882
  * an SSE stream; the buffer lives 1 h). A settled JOB-lane generation is
1857
1883
  * served from its stored answer instead (30 days). `status` says where the
1858
1884
  * generation is; `expired: true` means it settled but its frames are gone
@@ -1903,7 +1929,7 @@ export class Vxil {
1903
1929
  /** Streamed grounded answer: citations + the channel handle up front, tokens
1904
1930
  * over the realtime channel. */
1905
1931
  stream: async (input) => (await this.call('POST', '/v1/rag/answer', { ...input, stream: true })).data,
1906
- /** Retrieval-only grounding preview (rag.md §1c): the exact chunks `answer`
1932
+ /** Retrieval-only grounding preview (guide ch. 6, rag): the exact chunks `answer`
1907
1933
  * would ground on, with rerank + metadata boosts applied — no generation,
1908
1934
  * no token spend. `boosts`/`rerank`/`min_score` override the rag config.
1909
1935
  * `min_score` floors the EFFECTIVE `score`, which is a RANK value (about
@@ -2002,7 +2028,7 @@ export class Vxil {
2002
2028
  * `quota` inlines one quota, `creditType` inlines the same owner-bound
2003
2029
  * balance `getBalance` returns — ONE call for a thin client's paywall.
2004
2030
  * A non-2xx answer means UNKNOWN: render the last cached answer, never
2005
- * free (payments.md §3a).
2031
+ * free (guide ch. 6, payments).
2006
2032
  *
2007
2033
  * OVERLAPPING SUBSCRIPTIONS — what `until` means. The WINNER is the
2008
2034
  * entitled subscription with the highest `tierMap[tier].rank` (default 0);
@@ -2088,14 +2114,14 @@ export class Vxil {
2088
2114
  return (await this.call('GET', `/v1/payments/subscriptions${s}`)).data.subscriptions;
2089
2115
  },
2090
2116
  /**
2091
- * Create a hosted-checkout session (payments.md §3). Redirect the buyer to
2117
+ * Create a hosted-checkout session (guide ch. 6, payments). Redirect the buyer to
2092
2118
  * the returned `url`; completion lands server-side via the provider webhook
2093
2119
  * (the matching session flips to completed, the charge/grant is folded).
2094
2120
  * Idempotency-Key REQUIRED — a retry replays the SAME session verbatim.
2095
2121
  */
2096
2122
  createCheckoutSession: async (input, opts) => (await this.call('POST', '/v1/payments/checkout-sessions', input, { 'idempotency-key': opts.idempotencyKey })).data,
2097
2123
  /**
2098
- * Refund a charge at-most-once (payments.md §6a). Omit `amount_cents` to
2124
+ * Refund a charge at-most-once (guide ch. 6, payments). Omit `amount_cents` to
2099
2125
  * refund the full un-refunded remainder. Idempotency-Key REQUIRED — a retry
2100
2126
  * replays the recorded refund (never a second provider refund); a refund can
2101
2127
  * NEVER exceed the charge (422 refund_exceeds_charge).
@@ -2215,7 +2241,7 @@ export class Vxil {
2215
2241
  });
2216
2242
  return (await this.call('GET', `/v1/payments/refunds${suffix}`)).data;
2217
2243
  },
2218
- /** Provider webhook event log (payments.md §7 "Event log & replay"):
2244
+ /** Provider webhook event log (guide ch. 6, payments "Event log & replay"):
2219
2245
  * operator visibility over every delivery — incl. persisted signature
2220
2246
  * failures — plus an idempotent reprocess verb. Needs payments:read
2221
2247
  * (reprocess: payments:write).
@@ -2250,5 +2276,5 @@ export class Vxil {
2250
2276
  };
2251
2277
  }
2252
2278
  // Failure reporting for tenant functions — the Sentry-envelope forwarder
2253
- // (roadmap §4.11 P0-4e). Zero dependencies; see reporting.ts.
2279
+ // (guide ch. 8). Zero dependencies; see reporting.ts.
2254
2280
  export { withReporting, report, buildEnvelope, parseDsn, exceptionEvent, reportServerErrors, REPORT_TIMEOUT_MS, } from './reporting.js';
package/dist/qs.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // Query-string builder — the SDK's replacement for the WHATWG `URLSearchParams`
2
- // at every call site (F7-44, the React-Native-clean SDK).
2
+ // at every call site (the React-Native-clean SDK).
3
3
  //
4
4
  // WHY (implementation note; `//` comments never reach the shipped .d.ts):
5
5
  // React Native supplies its own URLSearchParams polyfill, and up to RN 0.79
package/dist/reporting.js CHANGED
@@ -1,6 +1,5 @@
1
1
  // withReporting — forward a tenant function's failure to the tenant's OWN
2
- // error reporter over the Sentry envelope HTTP format (roadmap §4.11 P0-4e,
3
- // techmaker evaluation P0-5's "SDK half", 2026-09-23).
2
+ // error reporter over the Sentry envelope HTTP format.
4
3
  //
5
4
  // NOT a Sentry SDK and NOT a dependency on one: the function sandbox is
6
5
  // Web-standard fetch/crypto only, so this is the plain ingestion envelope
package/dist/retry.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // The request seam: retry + timeout + hooks around the ONE `fetch` every SDK
2
- // request goes through (parity P1 #9), and the `Retry-After` parser
3
- // `VxilError.retryAfter` shares (F7-44). DEFAULT OFF — with no `retry`,
2
+ // request goes through, and the `Retry-After` parser
3
+ // `VxilError.retryAfter` shares. DEFAULT OFF — with no `retry`,
4
4
  // `timeoutMs` or `hooks` option the transport is a single `fetch` + `text()`,
5
5
  // exactly what `call()` did before.
6
6
  //
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vxil/sdk",
3
- "version": "0.12.0",
3
+ "version": "0.13.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Typed client for the Vxil REST API (notifications, auth, jobs, files, cms, comments, webhooks, realtime, orgs, rate-limits).",