@vxil/sdk 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +482 -42
- package/dist/index.js +226 -29
- package/dist/retry.d.ts +8 -2
- package/dist/retry.js +11 -4
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -160,7 +160,11 @@ export interface Delivery {
|
|
|
160
160
|
template_id: string;
|
|
161
161
|
locale: string;
|
|
162
162
|
to_email: string;
|
|
163
|
-
|
|
163
|
+
/** `test_sink` (2026-10-04): the recipient matched the project's
|
|
164
|
+
* `notifications.suppression.testRecipients` — rendered in full and recorded,
|
|
165
|
+
* but no provider was called and the send is not billed. Read what would
|
|
166
|
+
* have gone out with `notifications.delivery(id)` (`rendered`). */
|
|
167
|
+
status: 'queued' | 'sent' | 'failed' | 'suppressed' | 'test_sink';
|
|
164
168
|
attempts: number;
|
|
165
169
|
provider: string;
|
|
166
170
|
provider_message_id: string | null;
|
|
@@ -185,6 +189,27 @@ export interface Delivery {
|
|
|
185
189
|
* `delivery_id` on the 202.) */
|
|
186
190
|
deliver_after?: string | null;
|
|
187
191
|
}
|
|
192
|
+
/** One delivery by id (`notifications.delivery(id)`): the row plus a render.
|
|
193
|
+
* For a `test_sink` row `rendered` is the FULL render the send produced (its
|
|
194
|
+
* data, its locale — an `ar` template carries `dir="rtl"`) and `rendered_from`
|
|
195
|
+
* is `'send'` — EXCEPT auth mail (the `magic-link` / `otp-code` templates and
|
|
196
|
+
* the auth feature's password-reset / e-mail-verification mail) and a row
|
|
197
|
+
* sunk at delivery time (an address added to `testRecipients` after the send
|
|
198
|
+
* was queued): those are rendered WITHOUT the send's data (`rendered_from:
|
|
199
|
+
* 'send_redacted'`), so a sign-in link, code or reset link is never stored or
|
|
200
|
+
* readable. For every other row the template variables were never stored, so
|
|
201
|
+
* `rendered` is the template re-rendered with no data (`rendered_from:
|
|
202
|
+
* 'template'`), or null when it cannot be rendered. */
|
|
203
|
+
export interface DeliveryDetail extends Delivery {
|
|
204
|
+
last_error_msg?: string | null;
|
|
205
|
+
rendered: {
|
|
206
|
+
subject: string;
|
|
207
|
+
html: string;
|
|
208
|
+
text: string;
|
|
209
|
+
locale: string;
|
|
210
|
+
} | null;
|
|
211
|
+
rendered_from?: 'send' | 'send_redacted' | 'template';
|
|
212
|
+
}
|
|
188
213
|
/** An ADDITIVE, non-fatal note on a 202 send — today only `mock_provider`
|
|
189
214
|
* (the send is recorded but no email leaves vxil). */
|
|
190
215
|
export interface NotificationWarning {
|
|
@@ -403,9 +428,20 @@ export interface JobRun {
|
|
|
403
428
|
* problem (400 / 413 / 422 — e.g. a callback key the collection does not
|
|
404
429
|
* declare) is retried with only the status column (a progress update tries
|
|
405
430
|
* the declared `progress_fields` first), so an undeclared key no longer
|
|
406
|
-
* strands the row; this says what was dropped
|
|
407
|
-
*
|
|
431
|
+
* strands the row; this says what was dropped (`status_written`: whether
|
|
432
|
+
* the record holds the status word). Never flips the run. A later TERMINAL
|
|
433
|
+
* mirror that lands cleanly moves it to `last_mirror_error` (null here
|
|
434
|
+
* again); a non-terminal success leaves it. A write the record refuses
|
|
435
|
+
* because it already holds a terminal word, or because its
|
|
436
|
+
* `status_mirror.fence_field` names another run, is skipped quietly —
|
|
437
|
+
* never a mirror_error. */
|
|
408
438
|
mirror_error?: JobRunMirrorError | null;
|
|
439
|
+
/** the single-run read, generation runs only: the `mirror_error` a later
|
|
440
|
+
* clean terminal mirror healed; null otherwise */
|
|
441
|
+
last_mirror_error?: JobRunMirrorError | null;
|
|
442
|
+
/** the single-run read, generation runs only: when that healing terminal
|
|
443
|
+
* mirror landed (ISO); null otherwise */
|
|
444
|
+
mirror_ok_at?: string | null;
|
|
409
445
|
/** the single-run read only: the enqueue `concurrency_key` this run holds
|
|
410
446
|
* while running or waiting; null for an unkeyed run */
|
|
411
447
|
concurrency_key?: string | null;
|
|
@@ -458,6 +494,7 @@ export interface JobEnqueueResult {
|
|
|
458
494
|
export interface JobRunsQuery {
|
|
459
495
|
job_name?: string;
|
|
460
496
|
state?: JobRun['state'] | string;
|
|
497
|
+
/** exact run_ids, at most 50 distinct (more answers 422 — page in chunks of 50) */
|
|
461
498
|
ids?: string[];
|
|
462
499
|
batch_id?: string;
|
|
463
500
|
/** ISO: runs created at or after */
|
|
@@ -501,13 +538,25 @@ export interface JobRunMirrorError {
|
|
|
501
538
|
code: string | null;
|
|
502
539
|
/** the target's message (≤ 200 chars), e.g. "unknown field 'video_url'" */
|
|
503
540
|
message: string | null;
|
|
541
|
+
/** the target's hint (≤ 200 chars) when it sent one — e.g. the engine
|
|
542
|
+
* detail of a cms validate hook that could not evaluate */
|
|
543
|
+
hint?: string;
|
|
504
544
|
/** when it was refused (ISO) */
|
|
505
545
|
at: string;
|
|
546
|
+
/** whether the record holds `generation_status` after this write: true
|
|
547
|
+
* when a narrower retry carrying the status word landed (or the write left
|
|
548
|
+
* the word out because the record already held it); false when no write
|
|
549
|
+
* carrying it landed — the full write was already the status column alone,
|
|
550
|
+
* the refusal was not a body problem (401 / 403 / 404 / 409 / 429 / 5xx,
|
|
551
|
+
* a timeout), or every narrower retry was refused. Absent on errors
|
|
552
|
+
* recorded before it existed. */
|
|
553
|
+
status_written?: boolean;
|
|
506
554
|
/** present when a narrower retry LANDED: the keys that were not written */
|
|
507
555
|
fields_dropped?: string[];
|
|
508
|
-
/** present when
|
|
509
|
-
* status
|
|
510
|
-
*
|
|
556
|
+
/** present when narrower retries ran and none landed: the LAST one's HTTP
|
|
557
|
+
* status (0 = no answer). The ladder stops at the first refusal that is not
|
|
558
|
+
* a body problem, so read `status_written`, not this, for "did the status
|
|
559
|
+
* word land" */
|
|
511
560
|
retry_status?: number;
|
|
512
561
|
}
|
|
513
562
|
/** A run's latest progress report (`JobRun.progress`): only these keys pass. */
|
|
@@ -748,6 +797,28 @@ export interface PaymentsSimulationResult {
|
|
|
748
797
|
pass: boolean;
|
|
749
798
|
};
|
|
750
799
|
}
|
|
800
|
+
/** `payments.moveSubscriptionUntil` (the test clock) — the moved row and the
|
|
801
|
+
* user's entitlement snapshot after the refold. */
|
|
802
|
+
export interface PaymentsTestClockResult {
|
|
803
|
+
subscription_id: string;
|
|
804
|
+
user_id: string;
|
|
805
|
+
tier: string | null;
|
|
806
|
+
/** 'lapsed' after a move into the past, 'active' after one into the future */
|
|
807
|
+
status: string;
|
|
808
|
+
since: string | null;
|
|
809
|
+
until: string;
|
|
810
|
+
previous_until: string | null;
|
|
811
|
+
/** true when THIS move ended access (payments.subscription.lapsed emitted) */
|
|
812
|
+
lapsed: boolean;
|
|
813
|
+
/** why the project may use the test clock */
|
|
814
|
+
lane: 'mock' | 'sandbox' | 'dev';
|
|
815
|
+
entitlement: {
|
|
816
|
+
tier: string;
|
|
817
|
+
entitlements: string[];
|
|
818
|
+
quotas: Record<string, number>;
|
|
819
|
+
source_sub_id: string | null;
|
|
820
|
+
};
|
|
821
|
+
}
|
|
751
822
|
/** The ONE complete entitlement read (GET /v1/payments/entitlements; guide ch. 6,
|
|
752
823
|
* payments). `until` is the winning subscription's current_period_end (+ the
|
|
753
824
|
* configured grace window when it is past_due); null on the free baseline. */
|
|
@@ -880,6 +951,10 @@ export interface FileUploadUrl {
|
|
|
880
951
|
expires_in: number;
|
|
881
952
|
/** When the OBJECT expires (null = never). */
|
|
882
953
|
expires_at: string | null;
|
|
954
|
+
/** The headers the PUT to `upload_url` must send, exactly — each one is
|
|
955
|
+
* signed into the URL: `content-type`, plus `x-amz-checksum-sha256` when
|
|
956
|
+
* the request declared `checksum_sha256`. */
|
|
957
|
+
upload_headers?: Record<string, string>;
|
|
883
958
|
}
|
|
884
959
|
/** `files.usage` answer. */
|
|
885
960
|
export interface FilesUsage {
|
|
@@ -893,7 +968,15 @@ export interface FilesUsage {
|
|
|
893
968
|
maxObjectBytes?: number;
|
|
894
969
|
maxTotalBytes?: number;
|
|
895
970
|
};
|
|
896
|
-
|
|
971
|
+
/** Headroom left under the quotas. Never negative: when usage sits ABOVE a
|
|
972
|
+
* lowered quota (or a plan downgrade) both read 0 and `over_quota` is true
|
|
973
|
+
* — new uploads answer 422 quota_exceeded until usage drops back under. */
|
|
974
|
+
available: {
|
|
975
|
+
object_slots: number;
|
|
976
|
+
bytes_remaining: number;
|
|
977
|
+
over_quota?: boolean;
|
|
978
|
+
[key: string]: number | boolean | null | undefined;
|
|
979
|
+
};
|
|
897
980
|
/** Your plan's storage ceiling, and whether `quotas.maxTotalBytes` is that
|
|
898
981
|
* ceiling (`plan`) or your own lower value (`config`). */
|
|
899
982
|
storage_plan?: {
|
|
@@ -1361,7 +1444,8 @@ export interface PaymentsSubscriptionStatusEventPayload {
|
|
|
1361
1444
|
current_period_end: string | null;
|
|
1362
1445
|
environment: PaymentsEventEnvironment;
|
|
1363
1446
|
/** what wrote it: the provider event type, `subscription.synced` /
|
|
1364
|
-
* `subscription.restored`, or `
|
|
1447
|
+
* `subscription.restored`, `period_end_enforced`, or `test_clock` (a
|
|
1448
|
+
* `moveSubscriptionUntil` on a non-production project ended the row) */
|
|
1365
1449
|
event_type: string;
|
|
1366
1450
|
slack_hours: number | null;
|
|
1367
1451
|
level: 'info';
|
|
@@ -1502,6 +1586,24 @@ export interface PaymentsConformanceEventPayload {
|
|
|
1502
1586
|
level: 'info' | 'error';
|
|
1503
1587
|
state: 'ok' | 'broken';
|
|
1504
1588
|
}
|
|
1589
|
+
/** `payments.test_clock.moved` — the test clock moved a manual grant's or a
|
|
1590
|
+
* purchase pass's end (`moveSubscriptionUntil`; non-production projects only).
|
|
1591
|
+
* `lapsed` is true when this move ended access (a `payments.subscription.lapsed`
|
|
1592
|
+
* with `event_type: 'test_clock'` follows); `lane` names why the project was
|
|
1593
|
+
* allowed: `mock` provider, a `sandbox` provider environment, or a `dev`
|
|
1594
|
+
* (preview / `vxil dev up`) project. */
|
|
1595
|
+
export interface PaymentsTestClockMovedEventPayload {
|
|
1596
|
+
end_user_id: string;
|
|
1597
|
+
subscription_id: string;
|
|
1598
|
+
provider_sub_id: string;
|
|
1599
|
+
tier: string | null;
|
|
1600
|
+
previous_until: string | null;
|
|
1601
|
+
until: string;
|
|
1602
|
+
lapsed: boolean;
|
|
1603
|
+
lane: 'mock' | 'sandbox' | 'dev';
|
|
1604
|
+
level: 'info';
|
|
1605
|
+
state: 'ok';
|
|
1606
|
+
}
|
|
1505
1607
|
/** Event name → typed `data`, for the events that settle work you started and
|
|
1506
1608
|
* (since 2026-10-01) every `payments.*` event. `VxilEventPayload<'job.generation.failed'>`
|
|
1507
1609
|
* names one; everything else on the catalog is `Record<string, unknown>` until
|
|
@@ -1536,6 +1638,7 @@ export interface VxilEventPayloads {
|
|
|
1536
1638
|
'payments.reconcile.discrepancy': PaymentsReconcileDiscrepancyEventPayload;
|
|
1537
1639
|
'payments.reconcile.ok': PaymentsReconcileOkEventPayload;
|
|
1538
1640
|
'payments.conformance': PaymentsConformanceEventPayload;
|
|
1641
|
+
'payments.test_clock.moved': PaymentsTestClockMovedEventPayload;
|
|
1539
1642
|
}
|
|
1540
1643
|
export type VxilEventPayload<E extends string> = E extends keyof VxilEventPayloads ? VxilEventPayloads[E] : Record<string, unknown>;
|
|
1541
1644
|
/** The `trigger` label on the envelope. The config spells two of them in
|
|
@@ -1543,9 +1646,11 @@ export type VxilEventPayload<E extends string> = E extends keyof VxilEventPayloa
|
|
|
1543
1646
|
export type FunctionEnvelopeTrigger = 'http' | 'cms-hook' | 'auth-hook' | 'queue' | 'cron' | 'webhook';
|
|
1544
1647
|
/** The audiences a function's scoped callback tokens are minted for — one per
|
|
1545
1648
|
* feature its declared scopes reach. `control-plane` carries `users:*` /
|
|
1546
|
-
* `usage:read`
|
|
1547
|
-
*
|
|
1548
|
-
|
|
1649
|
+
* `usage:read` / `audit:read` only; `webhooks` carries `webhooks:read` only (read the inbound
|
|
1650
|
+
* sources and received events — e.g. `GET /v1/webhooks/events?after=`). There
|
|
1651
|
+
* is deliberately no `functions` audience: a function cannot call another
|
|
1652
|
+
* function. */
|
|
1653
|
+
export type FunctionCallbackAudience = 'cms' | 'payments' | 'notifications' | 'comments' | 'files' | 'ai' | 'rag' | 'vector-search' | 'activity-feed' | 'orgs' | 'auth' | 'jobs' | 'realtime' | 'rate-limits' | 'control-plane' | 'webhooks';
|
|
1549
1654
|
/** One short-lived scoped token per audience your scopes imply
|
|
1550
1655
|
* (`env.scoped_jwts.cms`, `env.scoped_jwts['control-plane']`); an audience your
|
|
1551
1656
|
* scopes do not reach is absent. Send it as `Authorization: Bearer …` to
|
|
@@ -1607,6 +1712,43 @@ export interface WebhookTriggerPayload<D = Record<string, unknown>> {
|
|
|
1607
1712
|
truncated: true;
|
|
1608
1713
|
} | null;
|
|
1609
1714
|
}
|
|
1715
|
+
/** The verification parameters of an inbound `hmac` source (`webhooks.sources.create`). */
|
|
1716
|
+
export interface WebhookHmacVerify {
|
|
1717
|
+
/** the header carrying the signature (case-insensitive) */
|
|
1718
|
+
header: string;
|
|
1719
|
+
algorithm?: 'sha256' | 'sha1';
|
|
1720
|
+
encoding?: 'hex' | 'base64';
|
|
1721
|
+
/** stripped before comparing (e.g. `sha256=`); required on the request when set */
|
|
1722
|
+
prefix?: string;
|
|
1723
|
+
/** a header carrying the signing timestamp (unix seconds or ISO 8601): the
|
|
1724
|
+
* signed message becomes `<timestamp><timestamp_separator><body>` */
|
|
1725
|
+
timestamp_header?: string;
|
|
1726
|
+
/** default '.'; '' to concatenate */
|
|
1727
|
+
timestamp_separator?: string;
|
|
1728
|
+
/** default 300, 1..3600 */
|
|
1729
|
+
tolerance_seconds?: number;
|
|
1730
|
+
event_id_header?: string;
|
|
1731
|
+
event_type_header?: string;
|
|
1732
|
+
}
|
|
1733
|
+
/** `payload.data` of a `webhook` invocation fired by an inbound source whose
|
|
1734
|
+
* `target_function` is this function (`payload.event === 'inbound_webhook.received'`). */
|
|
1735
|
+
export interface InboundWebhookTriggerData {
|
|
1736
|
+
vxil_event_id: string;
|
|
1737
|
+
source_id: string;
|
|
1738
|
+
provider: string;
|
|
1739
|
+
provider_event_id: string | null;
|
|
1740
|
+
event_type: string | null;
|
|
1741
|
+
sig_verified: boolean;
|
|
1742
|
+
/** the provider's JSON body; null when it was larger than 48 000 bytes
|
|
1743
|
+
* (`payload_omitted: true`) — read it with
|
|
1744
|
+
* `GET /v1/webhooks/events?event_id=<vxil_event_id>` (scope webhooks:read) */
|
|
1745
|
+
payload: Record<string, unknown> | unknown[] | null;
|
|
1746
|
+
payload_omitted?: true;
|
|
1747
|
+
/** true on a `POST /v1/webhooks/sources/:id/test` probe */
|
|
1748
|
+
test?: true;
|
|
1749
|
+
/** true on a `POST /v1/webhooks/events/:id/replay` */
|
|
1750
|
+
replayed?: true;
|
|
1751
|
+
}
|
|
1610
1752
|
/** `POST /v1/fn/:name`: `payload` is the JSON request body (the query
|
|
1611
1753
|
* parameters on a GET). */
|
|
1612
1754
|
export interface HttpFunctionEnvelope<P = unknown> extends FunctionEnvelopeBase {
|
|
@@ -2744,6 +2886,11 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
2744
2886
|
readonly fn: { [K in keyof S["functions"] & string]: FnInvoker<S["functions"][K]["Input"], S["functions"][K]["Output"]>; };
|
|
2745
2887
|
private call;
|
|
2746
2888
|
readonly users: {
|
|
2889
|
+
/** Create or replace a tenant user by id. Upserting a deleted id brings it
|
|
2890
|
+
* back; upserting an ERASED id re-creates it as a new, empty user
|
|
2891
|
+
* (`erased_at` cleared — the erase already removed the old data). While
|
|
2892
|
+
* the erased user's files are still being erased the call fails with 409
|
|
2893
|
+
* `user_erase_pending`; retry later. `bulk` is all-or-nothing. */
|
|
2747
2894
|
upsert: (user: {
|
|
2748
2895
|
id: string;
|
|
2749
2896
|
email?: string;
|
|
@@ -2758,6 +2905,15 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
2758
2905
|
get: (id: string, opts?: {
|
|
2759
2906
|
includeDeleted?: boolean;
|
|
2760
2907
|
}) => Promise<VxilUser>;
|
|
2908
|
+
/**
|
|
2909
|
+
* Update a user. `email` / `display_name` / `avatar_url` are replaced
|
|
2910
|
+
* (null clears them). `attributes` is DEEP-MERGED into the stored
|
|
2911
|
+
* attributes (RFC 7396 merge patch): objects merge key by key, arrays and
|
|
2912
|
+
* scalars replace, and `null` deletes a key AT ANY DEPTH — including inside
|
|
2913
|
+
* a subtree the row does not have yet, where the null is simply dropped
|
|
2914
|
+
* (`{ attributes: { prefs: { phone: null } } }` never stores a null).
|
|
2915
|
+
* Scope users:write.
|
|
2916
|
+
*/
|
|
2761
2917
|
patch: (id: string, patch: {
|
|
2762
2918
|
email?: string | null;
|
|
2763
2919
|
display_name?: string | null;
|
|
@@ -2780,7 +2936,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
2780
2936
|
* Merge a REGISTRY-ONLY user (a row you created with upsert that never
|
|
2781
2937
|
* signed in) INTO another user of the tenant: its attributes fill the
|
|
2782
2938
|
* survivor's gaps (the survivor wins on conflicts), the merged id is
|
|
2783
|
-
* soft-deleted, its owner-scoped cms / files / payments rows move to the
|
|
2939
|
+
* soft-deleted, its owner-scoped cms / files / payments / jobs rows move to the
|
|
2784
2940
|
* survivor, and `auth.user.merged { from, into, method: 'registry_merge' }`
|
|
2785
2941
|
* is audited. `rekeyed: false` means a re-key could not finish inside the
|
|
2786
2942
|
* request — the event is the backstop (call the feature's re-key route
|
|
@@ -2999,8 +3155,9 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
2999
3155
|
/** Reset the row and re-enqueue the original message. */
|
|
3000
3156
|
replay: (deliveryId: string) => Promise<void>;
|
|
3001
3157
|
};
|
|
3002
|
-
/** A single delivery by id (the list is `deliveries()`)
|
|
3003
|
-
|
|
3158
|
+
/** A single delivery by id (the list is `deliveries()`), with its render —
|
|
3159
|
+
* the full one for a `test_sink` row (see `DeliveryDetail`). */
|
|
3160
|
+
delivery: (deliveryId: string) => Promise<DeliveryDetail>;
|
|
3004
3161
|
/** Email broadcast campaigns (guide ch. 6, notifications): audience-ref fan-out
|
|
3005
3162
|
* with quiet-hours + frequency-cap policy. `schedule_cron` sets a recurring
|
|
3006
3163
|
* send (status `scheduled`); omit it for a `draft`. */
|
|
@@ -3053,6 +3210,9 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
3053
3210
|
skipped_freq_cap: number;
|
|
3054
3211
|
skipped_no_email: number;
|
|
3055
3212
|
already_sent: number;
|
|
3213
|
+
/** recipients in `suppression.testRecipients` on this page: recorded
|
|
3214
|
+
* `test_sink`, never sent, never billed */
|
|
3215
|
+
test_sink?: number;
|
|
3056
3216
|
}>;
|
|
3057
3217
|
};
|
|
3058
3218
|
};
|
|
@@ -3099,11 +3259,23 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
3099
3259
|
brief?: boolean;
|
|
3100
3260
|
}) => Promise<VxilPlan>;
|
|
3101
3261
|
};
|
|
3262
|
+
/** The project audit log. Needs `audit:read` (the narrow read-only scope —
|
|
3263
|
+
* declare it on a function to read the log from its callback token) or
|
|
3264
|
+
* `features:read`. Server-only: a public / thin-client key cannot read it. */
|
|
3102
3265
|
readonly audit: {
|
|
3266
|
+
/**
|
|
3267
|
+
* The audit trail, newest first. `subject` narrows to the events about ONE
|
|
3268
|
+
* thing: a user id (`payload.user_id` / `payload.id`), a cms record
|
|
3269
|
+
* (`payload.item_id` — the record's history), a verified end user
|
|
3270
|
+
* (`payload.end_user_id` — what that person changed through a thin-client
|
|
3271
|
+
* key or a function acting for them, and their payments events), or a
|
|
3272
|
+
* principal (`actor`). Server keys only.
|
|
3273
|
+
*/
|
|
3103
3274
|
list: (q?: {
|
|
3104
3275
|
since?: string;
|
|
3105
3276
|
cursor?: string;
|
|
3106
3277
|
limit?: number;
|
|
3278
|
+
subject?: string;
|
|
3107
3279
|
}) => Promise<Array<{
|
|
3108
3280
|
id: string;
|
|
3109
3281
|
event: string;
|
|
@@ -3121,6 +3293,8 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
3121
3293
|
until?: string;
|
|
3122
3294
|
after_id?: string;
|
|
3123
3295
|
limit?: number;
|
|
3296
|
+
/** the same subject filter as `list` */
|
|
3297
|
+
subject?: string;
|
|
3124
3298
|
}) => Promise<{
|
|
3125
3299
|
events: Array<{
|
|
3126
3300
|
id: string;
|
|
@@ -3225,7 +3399,16 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
3225
3399
|
*
|
|
3226
3400
|
* The answer's `generation_status` is `pending` on a fresh enqueue; a replay
|
|
3227
3401
|
* of the same `idempotency_key` (`deduplicated: true`) carries the run's
|
|
3228
|
-
* status NOW (`processing`, `completed` or `failed` too).
|
|
3402
|
+
* status NOW (`processing`, `completed` or `failed` too). The key is bound
|
|
3403
|
+
* to the request BODY: re-sending it with a different body (another
|
|
3404
|
+
* payload — a rebuilt `deadline_at` included —, provider, completion,
|
|
3405
|
+
* timeout, reserve…) will answer 422 `idempotency_key_reused` naming the
|
|
3406
|
+
* original run (the ai-v1 rule). That check is being rolled out: today a
|
|
3407
|
+
* mismatch is only logged, on every project, and the send is still
|
|
3408
|
+
* deduplicated to the first run; a changelog entry will announce
|
|
3409
|
+
* enforcement — so keep the body deterministic now. A 409 `generation_in_progress`
|
|
3410
|
+
* (Retry-After 5) means the run that key names is still placing its
|
|
3411
|
+
* credit hold.
|
|
3229
3412
|
*
|
|
3230
3413
|
* `reserve_credits` takes a PROVISIONAL held credit debit at enqueue
|
|
3231
3414
|
* (linked to the run), committed on `completed` and reversed on
|
|
@@ -3233,7 +3416,8 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
3233
3416
|
* `config.generation.maxReserveCredits` cap; in end-user mode `user_id` is
|
|
3234
3417
|
* FORCED to the verified end-user (a mismatched user_id → 400). A 402 aborts
|
|
3235
3418
|
* the enqueue (insufficient balance; the run ends with job.generation.failed
|
|
3236
|
-
* `ReserveInsufficient` and the 402 names its `run_id
|
|
3419
|
+
* `ReserveInsufficient` and the 402 names its `run_id`; the key is released,
|
|
3420
|
+
* so the same request after a top-up starts a new run); a runaway over the
|
|
3237
3421
|
* per-tenant outstanding-holds ceiling → 429 (Retry-After 5). Payments
|
|
3238
3422
|
* unreachable at the hold → 503 `payments_unavailable` (Retry-After 15;
|
|
3239
3423
|
* nothing started, nothing held — re-send the same request), unless
|
|
@@ -3254,8 +3438,9 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
3254
3438
|
*
|
|
3255
3439
|
* `opts.retryOnCapacity: { maxWaitMs }` retries a CAPACITY 429
|
|
3256
3440
|
* (`generation_concurrency_exceeded`, `reserve_holds_exceeded`,
|
|
3257
|
-
* `queue_full`)
|
|
3258
|
-
*
|
|
3441
|
+
* `queue_full`), a 503 `payments_unavailable` / `enqueue_interrupted` and a
|
|
3442
|
+
* 409 `generation_in_progress` (the key's run is still placing its credit
|
|
3443
|
+
* hold), honouring Retry-After with jitter, with the SAME
|
|
3259
3444
|
* idempotency_key (one is generated when the input has none), until
|
|
3260
3445
|
* maxWaitMs has passed — then the last 429 is thrown. */
|
|
3261
3446
|
generation: (input: {
|
|
@@ -3299,6 +3484,13 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
3299
3484
|
record_id: string;
|
|
3300
3485
|
column?: string;
|
|
3301
3486
|
progress_fields?: Array<"progress" | "stage" | "message">;
|
|
3487
|
+
/** cms only: a declared string field the mirror stamps with this
|
|
3488
|
+
* run's `run_id` on its first write; every later write of the run
|
|
3489
|
+
* requires it (a cms `if` precondition), so an older run's late
|
|
3490
|
+
* writes never land on a row a newer run has claimed. A write the
|
|
3491
|
+
* record refuses that way — or because it already holds
|
|
3492
|
+
* `completed` / `failed` — is skipped, not a `mirror_error`. */
|
|
3493
|
+
fence_field?: string;
|
|
3302
3494
|
};
|
|
3303
3495
|
timeout?: {
|
|
3304
3496
|
after_ms: number;
|
|
@@ -3376,19 +3568,65 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
3376
3568
|
/** Cancel a run that has not started its current attempt (`queued`,
|
|
3377
3569
|
* `delayed`, `retrying`) or a plain run handed off to its signed callback
|
|
3378
3570
|
* (`waiting` after its handler answered 202 — the callback URL is
|
|
3379
|
-
* consumed). A
|
|
3380
|
-
*
|
|
3381
|
-
*
|
|
3571
|
+
* consumed). A generation's credit hold is released — a STARTED
|
|
3572
|
+
* generation's too (its provider accepted it): it ends `failed`
|
|
3573
|
+
* (`Cancelled`) and a late provider callback is a no-op, but the provider
|
|
3574
|
+
* is NOT told, so its work and its charge may still complete. A plain
|
|
3575
|
+
* `running` run (a delivery in flight), a run waiting on an event, or a
|
|
3576
|
+
* terminal run answers `409 not_cancellable`. */
|
|
3382
3577
|
cancel: (runId: string) => Promise<{
|
|
3383
3578
|
run_id: string;
|
|
3384
3579
|
state: string;
|
|
3385
3580
|
}>;
|
|
3386
3581
|
/** Clone a terminal run into a fresh queued run. A generation run answers
|
|
3387
|
-
* `409 not_replayable` — submit the generation again instead
|
|
3582
|
+
* `409 not_replayable` — submit the generation again instead; a redacted
|
|
3583
|
+
* or erased run answers `409 run_redacted` (its payload is gone). */
|
|
3388
3584
|
replay: (runId: string) => Promise<{
|
|
3389
3585
|
run_id: string;
|
|
3390
3586
|
replayed_from: string;
|
|
3391
3587
|
}>;
|
|
3588
|
+
/** SERVER-ONLY (403 server_only in end-user mode). Account merge: move the
|
|
3589
|
+
* credit-hold owner (`reserve_credits.user_id`) of every run of
|
|
3590
|
+
* `from_user_id`, in any state, onto `into_user_id`, so the surviving
|
|
3591
|
+
* account reads, cancels and replays the generation runs it started as a
|
|
3592
|
+
* guest. ONE bounded page (≤500 runs) per call — call again until `done`
|
|
3593
|
+
* (idempotent: a second call moves 0). The jobs consumer of
|
|
3594
|
+
* `auth.user.merged { from, into }`; auth and `users.merge` call it after
|
|
3595
|
+
* a merge, the event is the backstop. Emits one `jobs.runs.rekeyed` when
|
|
3596
|
+
* a call moved at least one run (none on a zero-move call). Unlike the
|
|
3597
|
+
* files re-key it does not check that `into_user_id` exists.
|
|
3598
|
+
* Scope jobs:write. */
|
|
3599
|
+
reKey: (input: {
|
|
3600
|
+
from_user_id: string;
|
|
3601
|
+
into_user_id: string;
|
|
3602
|
+
}) => Promise<{
|
|
3603
|
+
moved: number;
|
|
3604
|
+
done: boolean;
|
|
3605
|
+
}>;
|
|
3606
|
+
/** SERVER-ONLY (403 server_only in end-user mode). Redact FINISHED runs
|
|
3607
|
+
* that hold personal data: the payload becomes `{ erased: true }`, the
|
|
3608
|
+
* result, progress, callback body and error text are cleared, a
|
|
3609
|
+
* generation's provider request body/headers are dropped and its credit
|
|
3610
|
+
* hold's user id is pseudonymized (unless its settle is still owed). The
|
|
3611
|
+
* row itself stays (state, timings, job_name). The same fields a GDPR
|
|
3612
|
+
* erase clears on the runs it can link to a user — use this for runs
|
|
3613
|
+
* nothing links to one (a plain queue run, an async function call).
|
|
3614
|
+
* `{ run_ids }` (≤500, one call; open runs are left alone and counted in
|
|
3615
|
+
* `skipped_open`) or `{ user_id }` (the generation runs whose credit hold
|
|
3616
|
+
* names that user — ONE page of ≤500 per call, call again until `done`).
|
|
3617
|
+
* Idempotent. Audited as `jobs.runs.redacted` (counts only; none when a
|
|
3618
|
+
* call redacted nothing). NOT cleared: concurrency_key, debounce_key,
|
|
3619
|
+
* idempotency_key and target_url — keep user ids out of those (hash them).
|
|
3620
|
+
* A redacted run does not replay. Scope jobs:write. */
|
|
3621
|
+
redact: (input: {
|
|
3622
|
+
run_ids: string[];
|
|
3623
|
+
} | {
|
|
3624
|
+
user_id: string;
|
|
3625
|
+
}) => Promise<{
|
|
3626
|
+
redacted: number;
|
|
3627
|
+
skipped_open: number;
|
|
3628
|
+
done: boolean;
|
|
3629
|
+
}>;
|
|
3392
3630
|
/**
|
|
3393
3631
|
* Suspend the RUNNING run until an event (call from the executing
|
|
3394
3632
|
* handler, then return 200 — the suspension wins). `state: 'resumed'` =
|
|
@@ -3513,9 +3751,10 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
3513
3751
|
sent: true;
|
|
3514
3752
|
test_link?: string;
|
|
3515
3753
|
}>;
|
|
3516
|
-
/**
|
|
3517
|
-
*
|
|
3518
|
-
*
|
|
3754
|
+
/** An unknown, expired or already-used link answers `401 invalid_token`
|
|
3755
|
+
* (request a new one with `request`). `opts.anonymous_token` is REQUIRED
|
|
3756
|
+
* for a link that was requested with one (the guest claim above): the
|
|
3757
|
+
* same guest session must present it, else `401 invalid_session`. `merged` is true only when the guest was
|
|
3519
3758
|
* folded into an existing account (then `user_id` is that account), and
|
|
3520
3759
|
* `rekeyed` rides beside it: true ⇒ the guest's payments / cms / files
|
|
3521
3760
|
* rows were already moved onto `user_id` when this returned; false ⇒
|
|
@@ -3578,8 +3817,10 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
3578
3817
|
/** On success the guest keeps its user id (`user_id` unchanged).
|
|
3579
3818
|
* If the claimed email ALREADY has an account, the guest is MERGED
|
|
3580
3819
|
* into it: `user_id` is the existing account, `merged: true`, and a
|
|
3581
|
-
* fresh `session.token` (same session
|
|
3582
|
-
* identity — swap it client-side
|
|
3820
|
+
* fresh `session.token` (the same session carried over to the merged
|
|
3821
|
+
* identity under a new session id — swap it client-side: the old
|
|
3822
|
+
* guest token is revoked, the refresh token keeps working; other
|
|
3823
|
+
* guest sessions are revoked).
|
|
3583
3824
|
* `rekeyed` (present on a merge): true ⇒ the guest's payments / cms /
|
|
3584
3825
|
* files rows were already moved onto `user_id` when this returned, so
|
|
3585
3826
|
* the merged user's next request finds them; false ⇒ the move ran
|
|
@@ -3700,7 +3941,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
3700
3941
|
}) => Promise<AuthImportResult>;
|
|
3701
3942
|
/** END-USER MODE ONLY (`endUserToken` / `asEndUser`): the signed-in user
|
|
3702
3943
|
* deep-merges a bounded `attributes` object into its OWN shared identity
|
|
3703
|
-
* row (null deletes a key; ≤8 KB, ≤64 top-level keys, depth ≤8). Profile
|
|
3944
|
+
* row (null deletes a key at any depth — RFC 7396; ≤8 KB, ≤64 top-level keys, depth ≤8). Profile
|
|
3704
3945
|
* fields are not patchable here. In server mode the call throws 422
|
|
3705
3946
|
* `end_user_mode_required` — use `users.patch(id, …)` instead. */
|
|
3706
3947
|
patchMe: (attributes: Record<string, unknown>) => Promise<{
|
|
@@ -3811,15 +4052,34 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
3811
4052
|
verified: true;
|
|
3812
4053
|
}>;
|
|
3813
4054
|
};
|
|
3814
|
-
/** Social sign-in. The web `
|
|
3815
|
-
* (
|
|
3816
|
-
* `GET /v1/auth/oauth/{provider}/start
|
|
3817
|
-
*
|
|
4055
|
+
/** Social sign-in. The web flow: `startUrl` fetches the provider authorize
|
|
4056
|
+
* URL with your key (a browser cannot follow the header-carrying 302 of
|
|
4057
|
+
* `GET /v1/auth/oauth/{provider}/start` itself), you navigate the browser
|
|
4058
|
+
* there, and hand the returned `code`+`state` to `…/callback`; `native`
|
|
3818
4059
|
* is the mobile / broker token-exchange the SDK wraps. `oidc` is the
|
|
3819
4060
|
* tenant's generic OIDC / SSO issuer (auth config `providers.oidc` —
|
|
3820
4061
|
* Okta / Entra / Auth0 / any OpenID Connect IdP, or a SAML broker that
|
|
3821
4062
|
* speaks OIDC); it rides the same three routes. */
|
|
3822
4063
|
oauth: {
|
|
4064
|
+
/** Start the web sign-in from a browser SPA: answers the provider
|
|
4065
|
+
* `authorize_url` (PKCE challenge, one-shot `state`, and for `oidc` a
|
|
4066
|
+
* nonce bound to the flow — all held server-side) for you to navigate
|
|
4067
|
+
* to: `location.assign((await vx.auth.oauth.startUrl('oidc',
|
|
4068
|
+
* { redirect_uri })).authorize_url)`. The provider returns to
|
|
4069
|
+
* `redirect_uri` with `?code&state`, which your page sends to
|
|
4070
|
+
* `GET /v1/auth/oauth/{provider}/callback` for the session. The same
|
|
4071
|
+
* rules as the redirect form apply: `redirect_uri` must match the auth
|
|
4072
|
+
* config `security.allowedRedirectOrigins` when set (else
|
|
4073
|
+
* `422 redirect_not_allowed`), and the state expires after
|
|
4074
|
+
* `expires_in` seconds (600). `anonymous_token` (a guest bearer)
|
|
4075
|
+
* promotes or merges that guest at the callback. */
|
|
4076
|
+
startUrl: (provider: "google" | "apple" | "github" | "facebook" | "mock" | "oidc", input: {
|
|
4077
|
+
redirect_uri: string;
|
|
4078
|
+
anonymous_token?: string;
|
|
4079
|
+
}) => Promise<{
|
|
4080
|
+
authorize_url: string;
|
|
4081
|
+
expires_in: number;
|
|
4082
|
+
}>;
|
|
3823
4083
|
/** Native social sign-in: exchange a provider `id_token`/`access_token`
|
|
3824
4084
|
* for a vxil session (`linked` marks whether the user was created or
|
|
3825
4085
|
* matched to an existing identity). */
|
|
@@ -3970,6 +4230,20 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
3970
4230
|
* (end-user reads and writes are `403 server_only`, even with an
|
|
3971
4231
|
* owner_field). Server keys are never affected. */
|
|
3972
4232
|
end_user_access?: CmsEndUserAccess;
|
|
4233
|
+
/** Role slugs one of which a VERIFIED end user must hold to WRITE this
|
|
4234
|
+
* collection (create / update / $inc / delete / publish / transaction
|
|
4235
|
+
* step / batch / filtered delete, and an end-user delete's cascade into
|
|
4236
|
+
* it) — otherwise `403 role_required`. Reads are unaffected; server keys
|
|
4237
|
+
* are never affected. Omitted/`[]` = ungated. ≤16 entries, each
|
|
4238
|
+
* `^[a-z0-9][a-z0-9_-]{0,31}$` (the `orgs` role alphabet). */
|
|
4239
|
+
write_roles?: string[];
|
|
4240
|
+
/** Retention (guide ch. 4): live items created more than this many days
|
|
4241
|
+
* ago (1..3650) are soft-deleted by the nightly platform sweep — like a
|
|
4242
|
+
* normal delete (no restore; purged at least 30 days later, unique values freed), with ONE
|
|
4243
|
+
* `cms.collection.retention_swept` audit event per collection per night
|
|
4244
|
+
* instead of per-item delete events. A collection another collection
|
|
4245
|
+
* references with an `on_delete` rule is skipped. Omit/null = keep. */
|
|
4246
|
+
retain_days?: number | null;
|
|
3973
4247
|
fields?: Array<{
|
|
3974
4248
|
field: string;
|
|
3975
4249
|
type: "string" | "text" | "int" | "float" | "bool" | "datetime" | "json" | "relation" | "file";
|
|
@@ -4019,6 +4293,10 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
4019
4293
|
actions?: CmsActionDef[];
|
|
4020
4294
|
/** present when not the default 'readwrite' */
|
|
4021
4295
|
end_user_access?: CmsEndUserAccess;
|
|
4296
|
+
/** present when the collection is role-gated for end-user writes */
|
|
4297
|
+
write_roles?: string[];
|
|
4298
|
+
/** present when retention is set */
|
|
4299
|
+
retain_days?: number;
|
|
4022
4300
|
}>;
|
|
4023
4301
|
list: () => Promise<Array<{
|
|
4024
4302
|
collection: string;
|
|
@@ -4027,6 +4305,10 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
4027
4305
|
owner_field?: string | null;
|
|
4028
4306
|
/** the collection's end-user access mode (absent from an older server = 'readwrite') */
|
|
4029
4307
|
end_user_access?: CmsEndUserAccess;
|
|
4308
|
+
/** the roles an end user needs to write it (null / absent = ungated) */
|
|
4309
|
+
write_roles?: string[] | null;
|
|
4310
|
+
/** retention in days (null = keep until deleted; absent from an older server) */
|
|
4311
|
+
retain_days?: number | null;
|
|
4030
4312
|
}>>;
|
|
4031
4313
|
addField: (collection: string, field: Record<string, unknown>) => Promise<void>;
|
|
4032
4314
|
/** Set (or clear, with `null`/`[]`) a field's READ-ROLE gate (guide ch. 4) —
|
|
@@ -4069,6 +4351,25 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
4069
4351
|
collection: string;
|
|
4070
4352
|
end_user_access: CmsEndUserAccess;
|
|
4071
4353
|
}>;
|
|
4354
|
+
/** Set (or clear, with `[]` / `null`) the collection's END-USER WRITE
|
|
4355
|
+
* ROLES (guide ch. 9): a verified end user must hold one of `roles` (the
|
|
4356
|
+
* session's verified role claims — orgs roles) to write the collection,
|
|
4357
|
+
* otherwise every write door answers `403 role_required`. Reads are
|
|
4358
|
+
* unaffected; server keys are never affected. Audited; takes effect on
|
|
4359
|
+
* the next write. */
|
|
4360
|
+
setWriteRoles: (collection: string, roles: string[] | null) => Promise<{
|
|
4361
|
+
collection: string;
|
|
4362
|
+
write_roles: string[];
|
|
4363
|
+
}>;
|
|
4364
|
+
/** Set (1..3650 days) or clear (`null`) the collection's RETENTION (guide
|
|
4365
|
+
* ch. 4): the nightly platform sweep soft-deletes live items created more
|
|
4366
|
+
* than `days` ago — bounded per project per night, no restore, purged at
|
|
4367
|
+
* least 30 days later like any delete, one `cms.collection.retention_swept` audit event
|
|
4368
|
+
* per collection per sweep. Audited (`cms.collection.retain_days.set`). */
|
|
4369
|
+
setRetention: (collection: string, days: number | null) => Promise<{
|
|
4370
|
+
collection: string;
|
|
4371
|
+
retain_days: number | null;
|
|
4372
|
+
}>;
|
|
4072
4373
|
/** Re-project the collection's index slots after an `index_slot` move
|
|
4073
4374
|
* (guide ch. 4). Slots are projected on WRITE only, so until this runs,
|
|
4074
4375
|
* stored rows keep their OLD projection: the new slot is NULL and the
|
|
@@ -4120,6 +4421,29 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
4120
4421
|
version: number;
|
|
4121
4422
|
data: Record<string, unknown>;
|
|
4122
4423
|
}>;
|
|
4424
|
+
/** Upsert by a declared `unique` field (guide ch. 4): creates the item, or
|
|
4425
|
+
* — when a live item already holds `data[field]` — merges `patch` into
|
|
4426
|
+
* THAT item instead (one transaction; update hooks, guards, version bump
|
|
4427
|
+
* and a `cms.item.updated` audit, exactly like `patch`; null clears a
|
|
4428
|
+
* field). `created` tells which happened (201 vs 200). Concurrent upserts
|
|
4429
|
+
* of one key serialize, so they never create a duplicate. */
|
|
4430
|
+
upsert: (collection: string, input: {
|
|
4431
|
+
data: Record<string, unknown>;
|
|
4432
|
+
onConflict: {
|
|
4433
|
+
field: string;
|
|
4434
|
+
patch: Record<string, unknown>;
|
|
4435
|
+
};
|
|
4436
|
+
status?: "draft" | "published";
|
|
4437
|
+
lock?: string;
|
|
4438
|
+
guard?: CmsGuard;
|
|
4439
|
+
guards?: CmsGuardTerm[];
|
|
4440
|
+
}) => Promise<{
|
|
4441
|
+
item_id: string;
|
|
4442
|
+
status: string;
|
|
4443
|
+
version: number;
|
|
4444
|
+
data: Record<string, unknown>;
|
|
4445
|
+
created: boolean;
|
|
4446
|
+
}>;
|
|
4123
4447
|
/** `expand` inlines relation/file fields into `data` (guide ch. 4): the
|
|
4124
4448
|
* full item envelope, a `{ object_id, $ref: 'files' }` stub for a file,
|
|
4125
4449
|
* the bare id on a cycle/depth cut, `null` for an invisible target. */
|
|
@@ -4128,7 +4452,9 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
4128
4452
|
}) => Promise<Record<string, unknown>>;
|
|
4129
4453
|
/**
|
|
4130
4454
|
* The bounded query DSL. filter ops: $eq $ne $gt $gte $lt $lte $in
|
|
4131
|
-
* $
|
|
4455
|
+
* ($ne is NULL-safe: a row whose field is absent or null counts as not
|
|
4456
|
+
* equal; on a dotted join term the row still needs a readable target,
|
|
4457
|
+
* so a null or dangling relation is excluded) $contains $startsWith (LIKE-escaped; substring-searchable on s*-slotted
|
|
4132
4458
|
* fields) $arrayContains/$anyOf (json/relation array containment, indexed);
|
|
4133
4459
|
* range/sort needs slot-indexed fields. This is the
|
|
4134
4460
|
* DELIBERATELY-UNTYPED escape hatch: it accepts everything the server
|
|
@@ -4518,6 +4844,32 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
4518
4844
|
};
|
|
4519
4845
|
warnings?: string[];
|
|
4520
4846
|
}>;
|
|
4847
|
+
/**
|
|
4848
|
+
* Log records of ONE function, one per invocation (outcome, wall/cpu ms,
|
|
4849
|
+
* console lines, exceptions), oldest first. Pass the returned `next_since`
|
|
4850
|
+
* back as `since` to read only newer records (a tail); without it, the most
|
|
4851
|
+
* recent records of the last 24 hours. Kept 14 days. Needs
|
|
4852
|
+
* `functions:read`. (GET /v1/functions/:name/logs)
|
|
4853
|
+
*/
|
|
4854
|
+
logs: (name: string, opts?: {
|
|
4855
|
+
since?: string;
|
|
4856
|
+
}) => Promise<{
|
|
4857
|
+
lines: Array<{
|
|
4858
|
+
ts: string;
|
|
4859
|
+
outcome: string;
|
|
4860
|
+
wall_ms: number | null;
|
|
4861
|
+
cpu_ms: number | null;
|
|
4862
|
+
logs: Array<{
|
|
4863
|
+
level: string;
|
|
4864
|
+
message: string;
|
|
4865
|
+
}>;
|
|
4866
|
+
exceptions: Array<{
|
|
4867
|
+
name: string;
|
|
4868
|
+
message: string;
|
|
4869
|
+
}>;
|
|
4870
|
+
}>;
|
|
4871
|
+
next_since: string | null;
|
|
4872
|
+
}>;
|
|
4521
4873
|
};
|
|
4522
4874
|
/** The MCP aggregation surface (the `mcp` feature). */
|
|
4523
4875
|
readonly mcp: {
|
|
@@ -4813,20 +5165,38 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
4813
5165
|
last_error_msg?: string | null;
|
|
4814
5166
|
}>;
|
|
4815
5167
|
sources: {
|
|
4816
|
-
/** Register an inbound source; the receiver URL is returned ONCE.
|
|
5168
|
+
/** Register an inbound source; the receiver URL is returned ONCE.
|
|
5169
|
+
*
|
|
5170
|
+
* Destination: `forward_url` (your endpoint) OR `target_function` (a
|
|
5171
|
+
* deployed function that declares a bare `trigger: { kind: 'webhook' }`
|
|
5172
|
+
* binding — it receives `payload.event === 'inbound_webhook.received'`
|
|
5173
|
+
* with the inbound envelope as `payload.data`), never both; neither =
|
|
5174
|
+
* store only (read with `events.list`).
|
|
5175
|
+
*
|
|
5176
|
+
* `provider: 'hmac'` is the parameterized preset for any provider that
|
|
5177
|
+
* signs an HMAC of the raw body (Shopify, Intercom, Linear, Zendesk, …):
|
|
5178
|
+
* `verify` says which header, sha256|sha1, hex|base64, an optional prefix
|
|
5179
|
+
* and an optional timestamp header + tolerance. Like stripe/paddle/slack it
|
|
5180
|
+
* fails closed (401) until the source's signing secret is set. */
|
|
4817
5181
|
create: (input: {
|
|
4818
|
-
provider: "stripe" | "paddle" | "github" | "slack" | "revenuecat" | "generic";
|
|
5182
|
+
provider: "stripe" | "paddle" | "github" | "slack" | "revenuecat" | "generic" | "hmac";
|
|
4819
5183
|
name: string;
|
|
4820
5184
|
forward_url?: string;
|
|
5185
|
+
target_function?: string;
|
|
5186
|
+
verify?: WebhookHmacVerify;
|
|
4821
5187
|
}) => Promise<{
|
|
4822
5188
|
source_id: string;
|
|
4823
5189
|
receiver_url_path: string;
|
|
4824
5190
|
provider: string;
|
|
5191
|
+
target_function?: string | null;
|
|
4825
5192
|
}>;
|
|
4826
5193
|
list: () => Promise<Array<{
|
|
4827
5194
|
source_id: string;
|
|
4828
5195
|
provider: string;
|
|
4829
5196
|
name: string;
|
|
5197
|
+
forward_url?: string | null;
|
|
5198
|
+
target_function?: string | null;
|
|
5199
|
+
verify?: WebhookHmacVerify | null;
|
|
4830
5200
|
}>>;
|
|
4831
5201
|
delete: (sourceId: string) => Promise<void>;
|
|
4832
5202
|
/** Send a sample envelope to the source's forward_url through the real
|
|
@@ -4841,20 +5211,38 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
4841
5211
|
}>;
|
|
4842
5212
|
};
|
|
4843
5213
|
events: {
|
|
5214
|
+
/** Received events. Newest first, paged with `cursor`; or — with `after`
|
|
5215
|
+
* (your watermark, an event id) — OLDEST first from just after it, the
|
|
5216
|
+
* drain shape: store `next_after` and pass it back, `has_more` says
|
|
5217
|
+
* another page waits. The `after` drain answers only events received
|
|
5218
|
+
* at least 10 s ago (ids are not strictly arrival-ordered, so a fresher
|
|
5219
|
+
* event could otherwise commit below a stored watermark and be
|
|
5220
|
+
* skipped); `cursor` and `event_id` reads are not lagged. `event_id`
|
|
5221
|
+
* reads exactly one event. `cursor` and `after` are exclusive. */
|
|
4844
5222
|
list: (q?: {
|
|
4845
5223
|
source_id?: string;
|
|
4846
5224
|
status?: string;
|
|
4847
5225
|
cursor?: string;
|
|
4848
5226
|
limit?: number;
|
|
5227
|
+
after?: string;
|
|
5228
|
+
event_id?: string;
|
|
4849
5229
|
}) => Promise<{
|
|
4850
5230
|
events: Array<{
|
|
4851
5231
|
event_id: string;
|
|
5232
|
+
source_id: string;
|
|
5233
|
+
provider: string;
|
|
5234
|
+
provider_event_id: string | null;
|
|
4852
5235
|
event_type: string | null;
|
|
4853
5236
|
payload: Record<string, unknown>;
|
|
4854
5237
|
sig_verified: boolean;
|
|
4855
5238
|
status: string;
|
|
5239
|
+
received_at: string;
|
|
4856
5240
|
}>;
|
|
4857
5241
|
next_cursor: string | null;
|
|
5242
|
+
/** `after` pages only */
|
|
5243
|
+
next_after?: string | null;
|
|
5244
|
+
/** `after` pages only */
|
|
5245
|
+
has_more?: boolean;
|
|
4858
5246
|
}>;
|
|
4859
5247
|
replay: (eventId: string) => Promise<void>;
|
|
4860
5248
|
/** The Svix message-attempt view: delivery state/attempts/DLQ flag for
|
|
@@ -5075,8 +5463,14 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
5075
5463
|
* matching its TokenProvider type *structurally* (no import — a static
|
|
5076
5464
|
* import would break the single-file served sdk.mjs) that re-mints via
|
|
5077
5465
|
* POST /v1/realtime/tokens with `defaults` merged over the channel the
|
|
5078
|
-
* client asks for.
|
|
5079
|
-
*
|
|
5466
|
+
* client asks for. Two safe ways to use it:
|
|
5467
|
+
* - on a server, with a server key (`user_id` names the subject); or
|
|
5468
|
+
* - in a browser / mobile app, with a PUBLIC `end_user_required` key and
|
|
5469
|
+
* the signed-in user's session (`endUserToken` on the client): the mint
|
|
5470
|
+
* runs in end-user mode and the token's subject is FORCED to the
|
|
5471
|
+
* verified user (any `user_id` you pass is overridden), so no
|
|
5472
|
+
* backend of your own is needed.
|
|
5473
|
+
* Never ship a server key to a browser. */
|
|
5080
5474
|
tokenProvider: (defaults: {
|
|
5081
5475
|
user_id: string;
|
|
5082
5476
|
ttl_seconds?: number;
|
|
@@ -5107,16 +5501,27 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
5107
5501
|
* long after the mint, whether or not `files.ttl` is enabled; `null` =
|
|
5108
5502
|
* never. The answer's `expires_in` is the UPLOAD URL's life in seconds;
|
|
5109
5503
|
* `expires_at` is when the object expires (null = never). `user_id` is
|
|
5110
|
-
* required with a server key and omitted in end-user mode.
|
|
5504
|
+
* required with a server key and omitted in end-user mode.
|
|
5505
|
+
* `checksum_sha256` (the SHA-256 of the bytes, 64 hex or 44 base64
|
|
5506
|
+
* characters) is signed into the URL (send the answer's `upload_headers`
|
|
5507
|
+
* on the PUT) and kept with the upload: `complete` compares it with the
|
|
5508
|
+
* SHA-256 the store reports for the bytes — 409 `checksum_mismatch` when
|
|
5509
|
+
* they differ, 409 `checksum_unverified` when the store reports none —
|
|
5510
|
+
* and on success answers the verified `checksum_sha256`. */
|
|
5111
5511
|
createUploadUrl: (input: {
|
|
5112
5512
|
user_id?: string;
|
|
5113
5513
|
filename: string;
|
|
5114
5514
|
content_type: string;
|
|
5115
5515
|
size_bytes: number;
|
|
5116
5516
|
expiresInSeconds?: number | null;
|
|
5517
|
+
checksum_sha256?: string;
|
|
5117
5518
|
}) => Promise<FileUploadUrl>;
|
|
5118
5519
|
/** Confirm the PUT (bytes verified, object → available). Answers the
|
|
5119
|
-
* object's `expires_at` (null = never)
|
|
5520
|
+
* object's `expires_at` (null = never) and `checksum_sha256` (hex; null
|
|
5521
|
+
* when the store reported none) — a repeated complete answers the same.
|
|
5522
|
+
* When the upload declared `checksum_sha256`: 409 `checksum_mismatch` if
|
|
5523
|
+
* the bytes hash differently, 409 `checksum_unverified` if the store
|
|
5524
|
+
* reports no checksum (the object stays pending either way). */
|
|
5120
5525
|
complete: (objectId: string) => Promise<{
|
|
5121
5526
|
object_id: string;
|
|
5122
5527
|
status: string;
|
|
@@ -5641,6 +6046,9 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
5641
6046
|
model?: string;
|
|
5642
6047
|
user_id?: string;
|
|
5643
6048
|
input?: Record<string, unknown>;
|
|
6049
|
+
/** Drop chunks whose cosine `similarity` to the query is below this
|
|
6050
|
+
* (-1..1) before grounding; overrides rag config `retrieval.minSimilarity`. */
|
|
6051
|
+
min_similarity?: number;
|
|
5644
6052
|
}) => Promise<RagAnswer>;
|
|
5645
6053
|
/** Streamed grounded answer: citations + the channel handle up front, tokens
|
|
5646
6054
|
* over the realtime channel. */
|
|
@@ -5655,13 +6063,18 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
5655
6063
|
model?: string;
|
|
5656
6064
|
user_id?: string;
|
|
5657
6065
|
input?: Record<string, unknown>;
|
|
6066
|
+
/** Drop chunks whose cosine `similarity` to the query is below this
|
|
6067
|
+
* (-1..1) before grounding; overrides rag config `retrieval.minSimilarity`. */
|
|
6068
|
+
min_similarity?: number;
|
|
5658
6069
|
}) => Promise<RagStreamHandle>;
|
|
5659
6070
|
/** Retrieval-only grounding preview (guide ch. 6, rag): the exact chunks `answer`
|
|
5660
6071
|
* would ground on, with rerank + metadata boosts applied — no generation,
|
|
5661
6072
|
* no token spend. `boosts`/`rerank`/`min_score` override the rag config.
|
|
5662
6073
|
* `min_score` floors the EFFECTIVE `score`, which is a RANK value (about
|
|
5663
|
-
* 0.016–0.033 at the top): a floor above ~0.033 drops every hit.
|
|
5664
|
-
* relevance
|
|
6074
|
+
* 0.016–0.033 at the top): a floor above ~0.033 drops every hit. For a
|
|
6075
|
+
* relevance threshold use `min_similarity`, which floors each hit's cosine
|
|
6076
|
+
* `similarity` (-1..1; overrides config `retrieval.minSimilarity`; a hit
|
|
6077
|
+
* with no measured similarity, e.g. keyword mode, is kept). */
|
|
5665
6078
|
search: (input: {
|
|
5666
6079
|
query: string;
|
|
5667
6080
|
collection?: string;
|
|
@@ -5671,6 +6084,7 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
5671
6084
|
rerank?: boolean;
|
|
5672
6085
|
boosts?: Record<string, unknown>;
|
|
5673
6086
|
min_score?: number;
|
|
6087
|
+
min_similarity?: number;
|
|
5674
6088
|
}) => Promise<RagSearchResult>;
|
|
5675
6089
|
/** Ingest into the backing vector-search collection (chunk → embed → index). */
|
|
5676
6090
|
ingest: (collection: string, input: SearchIngestInput) => Promise<SearchIngestResult>;
|
|
@@ -5832,7 +6246,9 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
5832
6246
|
* (no oversell). Pass `job_id` to make the debit PROVISIONAL (held, not yet
|
|
5833
6247
|
* committed): a linked jobs run that terminally fails auto-refunds the hold,
|
|
5834
6248
|
* a success settles it. Throws VxilError(402, 'INSUFFICIENT_CREDITS') when the
|
|
5835
|
-
* available balance can't cover `amount`.
|
|
6249
|
+
* available balance can't cover `amount`. Throws VxilError(409,
|
|
6250
|
+
* 'job_released') when `job_id` names a generation run that already ended
|
|
6251
|
+
* (cancelled or failed) before this hold landed: nothing is held.
|
|
5836
6252
|
*
|
|
5837
6253
|
* Ordered credits: pass `credit_types` (1–8, in spend order — e.g.
|
|
5838
6254
|
* `['free', 'subscription', 'topup']`) instead of `credit_type`; the WHOLE
|
|
@@ -6083,6 +6499,30 @@ export declare class Vxil<S extends VxilSchemaShape = VxilSchemaShape> {
|
|
|
6083
6499
|
user_id: string;
|
|
6084
6500
|
tier?: string;
|
|
6085
6501
|
}) => Promise<PaymentsSimulationResult>;
|
|
6502
|
+
/** SERVER-ONLY TEST CLOCK — move the end (`until`, past or future, within
|
|
6503
|
+
* 5 years of now) of a MANUAL grant or a purchase pass, to test expired /
|
|
6504
|
+
* export-window / renew-soon states on demand. Allowed only where no live
|
|
6505
|
+
* money can be involved: a `mock`-provider project, a project whose
|
|
6506
|
+
* provider runs in its sandbox (`paddle.sandbox`, `paypal.sandbox`, a
|
|
6507
|
+
* Stripe `sk_test_` key), or a dev/preview project — elsewhere 403
|
|
6508
|
+
* `test_clock_forbidden` (also for a pass linked to a non-sandbox charge).
|
|
6509
|
+
* 409 `provider_managed` for a provider subscription (use the provider's
|
|
6510
|
+
* own test clock); 409 `subscription_ended` for a revoked/refunded row.
|
|
6511
|
+
* The effect is a natural lapse's: the entitlements refold
|
|
6512
|
+
* (`payments.entitlement.changed`), a move into the past turns an active
|
|
6513
|
+
* row `lapsed` and emits `payments.subscription.lapsed` (`event_type:
|
|
6514
|
+
* 'test_clock'`, `environment: 'sandbox'`) once; a move back into the
|
|
6515
|
+
* future revives it (as `active` — a `trialing` row does not return to
|
|
6516
|
+
* `trialing`; a `past_due` row's status is left as it is). Only the end
|
|
6517
|
+
* moves: `since` (the period start) is never rewritten, so after a move
|
|
6518
|
+
* before it `since` > `until`. Every move emits
|
|
6519
|
+
* `payments.test_clock.moved`. Both events are emitted after the move
|
|
6520
|
+
* commits, best-effort (as the period-end sweep's are): if one fails to
|
|
6521
|
+
* record, the move still stands and is not re-announced on a retry, so
|
|
6522
|
+
* assert on the returned `status` / `lapsed` rather than only on the
|
|
6523
|
+
* event. Same-tier passes stacked behind the moved one are not
|
|
6524
|
+
* re-chained. No credits are granted or reversed. */
|
|
6525
|
+
moveSubscriptionUntil: (subscriptionId: string, until: string | Date) => Promise<PaymentsTestClockResult>;
|
|
6086
6526
|
/** The last report-only reconciliation sweep result for this project
|
|
6087
6527
|
* (`run: null` before the first daily tick). Finding kinds:
|
|
6088
6528
|
* `balance_drift`, `entitlement_lag`, `null_tier`, `refund_pending`,
|