@shipeasy/openapi 1.2.0 → 1.5.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.js +40 -9
- package/dist/resources/alert-rules.d.ts +3 -1
- package/dist/resources/alert-rules.js +11 -2
- package/dist/resources/experiments.d.ts +6 -30
- package/dist/resources/experiments.js +6 -1
- package/dist/resources/gates.d.ts +95 -0
- package/dist/resources/gates.js +23 -6
- package/dist/resources/index.d.ts +101 -30
- package/dist/resources/index.js +40 -9
- package/dist/schemas/alert-rules.d.ts +23 -1
- package/dist/schemas/alert-rules.js +13 -3
- package/dist/schemas/experiments.d.ts +4 -20
- package/dist/schemas/experiments.js +6 -1
- package/dist/schemas/gates.d.ts +83 -1
- package/dist/schemas/gates.js +24 -6
- package/dist/schemas/index.d.ts +2 -2
- package/dist/schemas/index.js +42 -9
- package/openapi.json +319 -51
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -108,12 +108,14 @@ var gateRuleSchema = z3.object({
|
|
|
108
108
|
"semver_gt",
|
|
109
109
|
"semver_gte",
|
|
110
110
|
"semver_lt",
|
|
111
|
-
"semver_lte"
|
|
111
|
+
"semver_lte",
|
|
112
|
+
"gate_pass",
|
|
113
|
+
"exp_in"
|
|
112
114
|
]).describe(
|
|
113
|
-
|
|
115
|
+
'Comparison operator. Equality: `eq`/`neq`. Set membership: `in`/`not_in` (value is an array). Numeric order: `gt`/`gte`/`lt`/`lte`. Semver order: `semver_gt`/`semver_gte`/`semver_lt`/`semver_lte` (value is a dotted version like `4.2.0`). String: `contains` (substring), `regex` (JS-flavour pattern, value is the pattern string). Cross-resource references (evaluated only on the worker hot path, where both KV blobs load): `gate_pass` (`value` is another gate\'s name \u2014 true when that gate passes for the same caller); `exp_in` (`attr` is a running experiment\'s name, `value` is a group name, `"$holdout"`, or `"$any"` \u2014 true when the caller is in that variant / the universe holdout / any variant).'
|
|
114
116
|
),
|
|
115
117
|
value: z3.unknown().describe(
|
|
116
|
-
|
|
118
|
+
'Operand. Shape depends on `op`: scalar for `eq/neq/gt/gte/lt/lte/contains/semver_*`; array of scalars for `in/not_in`; string pattern for `regex`; referenced gate name for `gate_pass`; group name / `"$holdout"` / `"$any"` for `exp_in`.'
|
|
117
119
|
)
|
|
118
120
|
}).describe(
|
|
119
121
|
"Single targeting predicate. A gate's `rules` array is evaluated with AND semantics; use the gatekeeper `stack` for OR / fall-through logic."
|
|
@@ -124,9 +126,17 @@ var gateNameSchema = z3.string().regex(
|
|
|
124
126
|
).max(128).describe(
|
|
125
127
|
"Stable gate key used by SDKs (`Shipeasy.checkGate(user, '<name>')`). Single segment or `folder.name`. Lowercase letters, digits, `_` or `-`; max 128 chars. Immutable after create \u2014 rename = delete + recreate."
|
|
126
128
|
);
|
|
129
|
+
var rampSchema = z3.object({
|
|
130
|
+
from: z3.number().int().min(0).max(1e4).describe("Start of the ramp in basis points (0\u201310000)."),
|
|
131
|
+
to: z3.number().int().min(0).max(1e4).describe("End of the ramp in basis points (0\u201310000)."),
|
|
132
|
+
startAt: z3.number().int().nonnegative().describe("Ramp start, epoch milliseconds (UTC)."),
|
|
133
|
+
durationMs: z3.number().int().positive().describe("Ramp length in milliseconds.")
|
|
134
|
+
}).describe(
|
|
135
|
+
"Linear rollout ramp. The effective rollout % interpolates `from`\u2192`to` over `[startAt, startAt+durationMs]`, clamped outside that window, evaluated against the wall-clock at eval time. Overrides the entry's static `rolloutPct` while present."
|
|
136
|
+
);
|
|
127
137
|
var stackedConditionSchema = z3.object({
|
|
128
138
|
id: z3.string().min(1).describe(
|
|
129
|
-
"Client-supplied stable id for the stack entry (used for React keys, audit diffs)."
|
|
139
|
+
"Client-supplied stable id for the stack entry (used for React keys, audit diffs, and as the default per-condition rollout salt)."
|
|
130
140
|
),
|
|
131
141
|
type: z3.literal("condition").describe("Discriminator. `condition` = rule-based predicate sub-gate."),
|
|
132
142
|
name: z3.string().optional().describe("Human label shown in the dashboard."),
|
|
@@ -135,9 +145,15 @@ var stackedConditionSchema = z3.object({
|
|
|
135
145
|
),
|
|
136
146
|
pass: z3.enum(["all", "any"]).optional().describe("Combinator across `rules`. `all` = AND (default), `any` = OR."),
|
|
137
147
|
rules: z3.array(gateRuleSchema).default([]).describe("Predicates evaluated under `pass`. Empty array = match nothing."),
|
|
148
|
+
rolloutPct: z3.number().int().min(0).max(1e4).optional().describe(
|
|
149
|
+
"Per-condition rollout in basis points. After the rules match, the caller is bucketed at this %; in-bucket \u2192 gate `true`, otherwise fall through to the next entry. Absent \u21D2 10000 (100%, every matching caller passes)."
|
|
150
|
+
),
|
|
151
|
+
bucketBy: z3.string().optional().describe("Attribute used to hash the caller into the per-condition bucket. Default `userID`."),
|
|
152
|
+
salt: z3.string().optional().describe("Per-condition hash salt. Defaults to the entry `id`, then the gate salt."),
|
|
153
|
+
ramp: rampSchema.optional(),
|
|
138
154
|
locked: z3.boolean().optional().describe("If `true`, dashboard hides edit controls (e.g. the trailing public-floor entry).")
|
|
139
155
|
}).describe(
|
|
140
|
-
"Rule-based sub-gate. When
|
|
156
|
+
"Rule-based sub-gate. When the rules match and the caller falls in the per-condition rollout bucket, evaluation short-circuits and the gate returns `true`; otherwise it falls through to the next entry."
|
|
141
157
|
);
|
|
142
158
|
var stackedRolloutSchema = z3.object({
|
|
143
159
|
id: z3.string().min(1).describe("Client-supplied stable id for the stack entry."),
|
|
@@ -153,9 +169,10 @@ var stackedRolloutSchema = z3.object({
|
|
|
153
169
|
salt: z3.string().optional().describe(
|
|
154
170
|
"Per-entry hash salt. Defaults to the gate's salt. Set explicitly to keep two rollouts independent or correlated across gates."
|
|
155
171
|
),
|
|
172
|
+
ramp: rampSchema.optional(),
|
|
156
173
|
locked: z3.boolean().optional().describe("If `true`, dashboard hides edit controls.")
|
|
157
174
|
}).describe(
|
|
158
|
-
"Percentage-rollout sub-gate. Hashes `bucketBy` (default `userID`) with `salt` and returns `true` for `rolloutPct/10000` fraction of callers."
|
|
175
|
+
"Percentage-rollout sub-gate. Hashes `bucketBy` (default `userID`) with `salt` and returns `true` for `rolloutPct/10000` fraction of callers (or the ramp's effective % when `ramp` is set)."
|
|
159
176
|
);
|
|
160
177
|
var stackedGateEntrySchema = z3.discriminatedUnion("type", [stackedConditionSchema, stackedRolloutSchema]).describe(
|
|
161
178
|
"One entry in the ordered gatekeeper stack. Evaluated top-to-bottom; first matching entry decides. Mix `condition` and `rollout` entries to express `internal-only` + `1% beta` + `50% public` in a single gate."
|
|
@@ -599,7 +616,12 @@ var experimentGroupSchema = z6.object({
|
|
|
599
616
|
var paramSchemaSchema = z6.record(z6.string(), z6.enum(["string", "bool", "number"])).describe(
|
|
600
617
|
"Map of param-name \u2192 scalar type. Defines the shape of `groups[].params`. Example: `{ headline: 'string', show_cta: 'bool' }`."
|
|
601
618
|
);
|
|
602
|
-
var bucketBySchema = z6.
|
|
619
|
+
var bucketBySchema = z6.string().min(1).max(128).regex(
|
|
620
|
+
/^[a-zA-Z_][a-zA-Z0-9_]*$/,
|
|
621
|
+
"Must be a user-attribute name (letters, digits, underscore; not starting with a digit)."
|
|
622
|
+
).describe(
|
|
623
|
+
"User-attribute name used as the bucketing key \u2014 e.g. `user_id` (default), `session_id`, `device_id`, or a custom attribute like `company_id` to keep a whole org on one variant. Defaults to `user_id` when omitted."
|
|
624
|
+
);
|
|
603
625
|
var experimentCreateSchema = z6.object({
|
|
604
626
|
name: experimentNameSchema,
|
|
605
627
|
description: z6.string().max(2e3).nullable().default(null).describe("Free-form description. Max 2000 chars, markdown rendered in the dashboard."),
|
|
@@ -2343,6 +2365,13 @@ var killswitchesResource = {
|
|
|
2343
2365
|
import { z as z14 } from "zod";
|
|
2344
2366
|
var ALERT_COMPARATORS = ["gt", "gte", "lt", "lte"];
|
|
2345
2367
|
var ALERT_SEVERITIES = ["danger", "warn", "info"];
|
|
2368
|
+
var notificationTargetSchema = z14.object({
|
|
2369
|
+
slackChannel: z14.object({
|
|
2370
|
+
id: z14.string().min(1).describe("Slack channel id (e.g. C0123ABCD)."),
|
|
2371
|
+
name: z14.string().min(1).describe("Slack channel name (without the leading #).")
|
|
2372
|
+
}).nullish().describe("Slack channel to post this rule's alert to. Requires a Slack connector."),
|
|
2373
|
+
email: z14.string().email().nullish().describe("Email address to notify for this rule (overrides the default recipient).")
|
|
2374
|
+
}).strict();
|
|
2346
2375
|
var alertRuleCreateSchema = z14.object({
|
|
2347
2376
|
name: z14.string().min(1).max(120).describe("Human label for the rule, shown on the alert and the rules list."),
|
|
2348
2377
|
metricId: z14.string().min(1).describe("Id of the metric to evaluate."),
|
|
@@ -2350,7 +2379,8 @@ var alertRuleCreateSchema = z14.object({
|
|
|
2350
2379
|
threshold: z14.number().finite().describe("Threshold the metric value is compared against."),
|
|
2351
2380
|
windowHours: z14.number().int().min(1).max(720).default(24).describe("Lookback window (hours) the metric is aggregated over. 1\u2013720."),
|
|
2352
2381
|
severity: z14.enum(ALERT_SEVERITIES).default("warn").describe("Severity of the raised alert."),
|
|
2353
|
-
enabled: z14.boolean().default(true).describe("Whether the rule is evaluated by the cron.")
|
|
2382
|
+
enabled: z14.boolean().default(true).describe("Whether the rule is evaluated by the cron."),
|
|
2383
|
+
notify: notificationTargetSchema.nullish().describe("Where to deliver this rule's alert (Slack channel and/or email target).")
|
|
2354
2384
|
}).strict();
|
|
2355
2385
|
var alertRuleUpdateSchema = z14.object({
|
|
2356
2386
|
name: z14.string().min(1).max(120),
|
|
@@ -2358,7 +2388,8 @@ var alertRuleUpdateSchema = z14.object({
|
|
|
2358
2388
|
threshold: z14.number().finite(),
|
|
2359
2389
|
windowHours: z14.number().int().min(1).max(720),
|
|
2360
2390
|
severity: z14.enum(ALERT_SEVERITIES),
|
|
2361
|
-
enabled: z14.boolean()
|
|
2391
|
+
enabled: z14.boolean(),
|
|
2392
|
+
notify: notificationTargetSchema.nullish()
|
|
2362
2393
|
}).partial().strict();
|
|
2363
2394
|
|
|
2364
2395
|
// src/resources/alert-rules.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { alertRuleCreateSchema, alertRuleUpdateSchema } from '../schemas/alert-rules.js';
|
|
2
|
+
import { NotificationTarget, alertRuleCreateSchema, alertRuleUpdateSchema } from '../schemas/alert-rules.js';
|
|
3
3
|
import { Transport } from '../transport.js';
|
|
4
4
|
|
|
5
5
|
type AlertRuleCreateInput = z.input<typeof alertRuleCreateSchema>;
|
|
@@ -24,6 +24,8 @@ interface AlertRule {
|
|
|
24
24
|
windowHours: number;
|
|
25
25
|
severity: "danger" | "warn" | "info";
|
|
26
26
|
enabled: boolean;
|
|
27
|
+
/** Delivery target for this rule's alert; null = use project default. */
|
|
28
|
+
notify: NotificationTarget | null;
|
|
27
29
|
createdAt: string;
|
|
28
30
|
updatedAt: string;
|
|
29
31
|
}
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
var ALERT_COMPARATORS = ["gt", "gte", "lt", "lte"];
|
|
4
4
|
var ALERT_SEVERITIES = ["danger", "warn", "info"];
|
|
5
|
+
var notificationTargetSchema = z.object({
|
|
6
|
+
slackChannel: z.object({
|
|
7
|
+
id: z.string().min(1).describe("Slack channel id (e.g. C0123ABCD)."),
|
|
8
|
+
name: z.string().min(1).describe("Slack channel name (without the leading #).")
|
|
9
|
+
}).nullish().describe("Slack channel to post this rule's alert to. Requires a Slack connector."),
|
|
10
|
+
email: z.string().email().nullish().describe("Email address to notify for this rule (overrides the default recipient).")
|
|
11
|
+
}).strict();
|
|
5
12
|
var alertRuleCreateSchema = z.object({
|
|
6
13
|
name: z.string().min(1).max(120).describe("Human label for the rule, shown on the alert and the rules list."),
|
|
7
14
|
metricId: z.string().min(1).describe("Id of the metric to evaluate."),
|
|
@@ -9,7 +16,8 @@ var alertRuleCreateSchema = z.object({
|
|
|
9
16
|
threshold: z.number().finite().describe("Threshold the metric value is compared against."),
|
|
10
17
|
windowHours: z.number().int().min(1).max(720).default(24).describe("Lookback window (hours) the metric is aggregated over. 1\u2013720."),
|
|
11
18
|
severity: z.enum(ALERT_SEVERITIES).default("warn").describe("Severity of the raised alert."),
|
|
12
|
-
enabled: z.boolean().default(true).describe("Whether the rule is evaluated by the cron.")
|
|
19
|
+
enabled: z.boolean().default(true).describe("Whether the rule is evaluated by the cron."),
|
|
20
|
+
notify: notificationTargetSchema.nullish().describe("Where to deliver this rule's alert (Slack channel and/or email target).")
|
|
13
21
|
}).strict();
|
|
14
22
|
var alertRuleUpdateSchema = z.object({
|
|
15
23
|
name: z.string().min(1).max(120),
|
|
@@ -17,7 +25,8 @@ var alertRuleUpdateSchema = z.object({
|
|
|
17
25
|
threshold: z.number().finite(),
|
|
18
26
|
windowHours: z.number().int().min(1).max(720),
|
|
19
27
|
severity: z.enum(ALERT_SEVERITIES),
|
|
20
|
-
enabled: z.boolean()
|
|
28
|
+
enabled: z.boolean(),
|
|
29
|
+
notify: notificationTargetSchema.nullish()
|
|
21
30
|
}).partial().strict();
|
|
22
31
|
|
|
23
32
|
// src/transport.ts
|
|
@@ -86,11 +86,7 @@ declare const experimentsResource: {
|
|
|
86
86
|
tag: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
87
87
|
owner_email: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
88
88
|
audience: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
89
|
-
bucket_by: z.ZodDefault<z.ZodNullable<z.
|
|
90
|
-
user_id: "user_id";
|
|
91
|
-
session_id: "session_id";
|
|
92
|
-
device_id: "device_id";
|
|
93
|
-
}>>>;
|
|
89
|
+
bucket_by: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
94
90
|
folder: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
95
91
|
universe: z.ZodString;
|
|
96
92
|
targeting_gate: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
@@ -126,11 +122,7 @@ declare const experimentsResource: {
|
|
|
126
122
|
tag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
127
123
|
owner_email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
128
124
|
audience: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
129
|
-
bucket_by: z.ZodOptional<z.ZodNullable<z.
|
|
130
|
-
user_id: "user_id";
|
|
131
|
-
session_id: "session_id";
|
|
132
|
-
device_id: "device_id";
|
|
133
|
-
}>>>;
|
|
125
|
+
bucket_by: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
134
126
|
folder: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
135
127
|
targeting_gate: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
136
128
|
allocation_pct: z.ZodOptional<z.ZodNumber>;
|
|
@@ -191,11 +183,7 @@ declare const experimentsResource: {
|
|
|
191
183
|
tag: z.ZodNullable<z.ZodString>;
|
|
192
184
|
ownerEmail: z.ZodNullable<z.ZodString>;
|
|
193
185
|
audience: z.ZodNullable<z.ZodString>;
|
|
194
|
-
bucketBy: z.ZodNullable<z.
|
|
195
|
-
user_id: "user_id";
|
|
196
|
-
session_id: "session_id";
|
|
197
|
-
device_id: "device_id";
|
|
198
|
-
}>>;
|
|
186
|
+
bucketBy: z.ZodNullable<z.ZodString>;
|
|
199
187
|
folder: z.ZodNullable<z.ZodString>;
|
|
200
188
|
status: z.ZodEnum<{
|
|
201
189
|
draft: "draft";
|
|
@@ -278,11 +266,7 @@ declare const experimentsResource: {
|
|
|
278
266
|
tag: z.ZodNullable<z.ZodString>;
|
|
279
267
|
ownerEmail: z.ZodNullable<z.ZodString>;
|
|
280
268
|
audience: z.ZodNullable<z.ZodString>;
|
|
281
|
-
bucketBy: z.ZodNullable<z.
|
|
282
|
-
user_id: "user_id";
|
|
283
|
-
session_id: "session_id";
|
|
284
|
-
device_id: "device_id";
|
|
285
|
-
}>>;
|
|
269
|
+
bucketBy: z.ZodNullable<z.ZodString>;
|
|
286
270
|
folder: z.ZodNullable<z.ZodString>;
|
|
287
271
|
status: z.ZodEnum<{
|
|
288
272
|
draft: "draft";
|
|
@@ -357,11 +341,7 @@ declare const experimentsResource: {
|
|
|
357
341
|
tag: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
358
342
|
owner_email: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
359
343
|
audience: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
360
|
-
bucket_by: z.ZodDefault<z.ZodNullable<z.
|
|
361
|
-
user_id: "user_id";
|
|
362
|
-
session_id: "session_id";
|
|
363
|
-
device_id: "device_id";
|
|
364
|
-
}>>>;
|
|
344
|
+
bucket_by: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
365
345
|
folder: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
366
346
|
universe: z.ZodString;
|
|
367
347
|
targeting_gate: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
@@ -496,11 +476,7 @@ declare const experimentsResource: {
|
|
|
496
476
|
tag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
497
477
|
owner_email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
498
478
|
audience: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
499
|
-
bucket_by: z.ZodOptional<z.ZodNullable<z.
|
|
500
|
-
user_id: "user_id";
|
|
501
|
-
session_id: "session_id";
|
|
502
|
-
device_id: "device_id";
|
|
503
|
-
}>>>;
|
|
479
|
+
bucket_by: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
504
480
|
folder: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
505
481
|
targeting_gate: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
506
482
|
allocation_pct: z.ZodOptional<z.ZodNumber>;
|
|
@@ -34,7 +34,12 @@ var experimentGroupSchema = z3.object({
|
|
|
34
34
|
var paramSchemaSchema = z3.record(z3.string(), z3.enum(["string", "bool", "number"])).describe(
|
|
35
35
|
"Map of param-name \u2192 scalar type. Defines the shape of `groups[].params`. Example: `{ headline: 'string', show_cta: 'bool' }`."
|
|
36
36
|
);
|
|
37
|
-
var bucketBySchema = z3.
|
|
37
|
+
var bucketBySchema = z3.string().min(1).max(128).regex(
|
|
38
|
+
/^[a-zA-Z_][a-zA-Z0-9_]*$/,
|
|
39
|
+
"Must be a user-attribute name (letters, digits, underscore; not starting with a digit)."
|
|
40
|
+
).describe(
|
|
41
|
+
"User-attribute name used as the bucketing key \u2014 e.g. `user_id` (default), `session_id`, `device_id`, or a custom attribute like `company_id` to keep a whole org on one variant. Defaults to `user_id` when omitted."
|
|
42
|
+
);
|
|
38
43
|
var experimentCreateSchema = z3.object({
|
|
39
44
|
name: experimentNameSchema,
|
|
40
45
|
description: z3.string().max(2e3).nullable().default(null).describe("Free-form description. Max 2000 chars, markdown rendered in the dashboard."),
|
|
@@ -90,6 +90,8 @@ declare const gatesResource: {
|
|
|
90
90
|
semver_gte: "semver_gte";
|
|
91
91
|
semver_lt: "semver_lt";
|
|
92
92
|
semver_lte: "semver_lte";
|
|
93
|
+
gate_pass: "gate_pass";
|
|
94
|
+
exp_in: "exp_in";
|
|
93
95
|
}>;
|
|
94
96
|
value: z.ZodUnknown;
|
|
95
97
|
}, z.core.$strip>>>;
|
|
@@ -120,9 +122,20 @@ declare const gatesResource: {
|
|
|
120
122
|
semver_gte: "semver_gte";
|
|
121
123
|
semver_lt: "semver_lt";
|
|
122
124
|
semver_lte: "semver_lte";
|
|
125
|
+
gate_pass: "gate_pass";
|
|
126
|
+
exp_in: "exp_in";
|
|
123
127
|
}>;
|
|
124
128
|
value: z.ZodUnknown;
|
|
125
129
|
}, z.core.$strip>>>;
|
|
130
|
+
rolloutPct: z.ZodOptional<z.ZodNumber>;
|
|
131
|
+
bucketBy: z.ZodOptional<z.ZodString>;
|
|
132
|
+
salt: z.ZodOptional<z.ZodString>;
|
|
133
|
+
ramp: z.ZodOptional<z.ZodObject<{
|
|
134
|
+
from: z.ZodNumber;
|
|
135
|
+
to: z.ZodNumber;
|
|
136
|
+
startAt: z.ZodNumber;
|
|
137
|
+
durationMs: z.ZodNumber;
|
|
138
|
+
}, z.core.$strip>>;
|
|
126
139
|
locked: z.ZodOptional<z.ZodBoolean>;
|
|
127
140
|
}, z.core.$strip>, z.ZodObject<{
|
|
128
141
|
id: z.ZodString;
|
|
@@ -132,6 +145,12 @@ declare const gatesResource: {
|
|
|
132
145
|
rolloutPct: z.ZodNumber;
|
|
133
146
|
bucketBy: z.ZodOptional<z.ZodString>;
|
|
134
147
|
salt: z.ZodOptional<z.ZodString>;
|
|
148
|
+
ramp: z.ZodOptional<z.ZodObject<{
|
|
149
|
+
from: z.ZodNumber;
|
|
150
|
+
to: z.ZodNumber;
|
|
151
|
+
startAt: z.ZodNumber;
|
|
152
|
+
durationMs: z.ZodNumber;
|
|
153
|
+
}, z.core.$strip>>;
|
|
135
154
|
locked: z.ZodOptional<z.ZodBoolean>;
|
|
136
155
|
}, z.core.$strip>], "type">>>>;
|
|
137
156
|
}, z.core.$strip>;
|
|
@@ -160,6 +179,8 @@ declare const gatesResource: {
|
|
|
160
179
|
semver_gte: "semver_gte";
|
|
161
180
|
semver_lt: "semver_lt";
|
|
162
181
|
semver_lte: "semver_lte";
|
|
182
|
+
gate_pass: "gate_pass";
|
|
183
|
+
exp_in: "exp_in";
|
|
163
184
|
}>;
|
|
164
185
|
value: z.ZodUnknown;
|
|
165
186
|
}, z.core.$strip>>>;
|
|
@@ -190,9 +211,20 @@ declare const gatesResource: {
|
|
|
190
211
|
semver_gte: "semver_gte";
|
|
191
212
|
semver_lt: "semver_lt";
|
|
192
213
|
semver_lte: "semver_lte";
|
|
214
|
+
gate_pass: "gate_pass";
|
|
215
|
+
exp_in: "exp_in";
|
|
193
216
|
}>;
|
|
194
217
|
value: z.ZodUnknown;
|
|
195
218
|
}, z.core.$strip>>>;
|
|
219
|
+
rolloutPct: z.ZodOptional<z.ZodNumber>;
|
|
220
|
+
bucketBy: z.ZodOptional<z.ZodString>;
|
|
221
|
+
salt: z.ZodOptional<z.ZodString>;
|
|
222
|
+
ramp: z.ZodOptional<z.ZodObject<{
|
|
223
|
+
from: z.ZodNumber;
|
|
224
|
+
to: z.ZodNumber;
|
|
225
|
+
startAt: z.ZodNumber;
|
|
226
|
+
durationMs: z.ZodNumber;
|
|
227
|
+
}, z.core.$strip>>;
|
|
196
228
|
locked: z.ZodOptional<z.ZodBoolean>;
|
|
197
229
|
}, z.core.$strip>, z.ZodObject<{
|
|
198
230
|
id: z.ZodString;
|
|
@@ -202,6 +234,12 @@ declare const gatesResource: {
|
|
|
202
234
|
rolloutPct: z.ZodNumber;
|
|
203
235
|
bucketBy: z.ZodOptional<z.ZodString>;
|
|
204
236
|
salt: z.ZodOptional<z.ZodString>;
|
|
237
|
+
ramp: z.ZodOptional<z.ZodObject<{
|
|
238
|
+
from: z.ZodNumber;
|
|
239
|
+
to: z.ZodNumber;
|
|
240
|
+
startAt: z.ZodNumber;
|
|
241
|
+
durationMs: z.ZodNumber;
|
|
242
|
+
}, z.core.$strip>>;
|
|
205
243
|
locked: z.ZodOptional<z.ZodBoolean>;
|
|
206
244
|
}, z.core.$strip>], "type">>>>;
|
|
207
245
|
}, z.core.$strip>;
|
|
@@ -248,6 +286,8 @@ declare const gatesResource: {
|
|
|
248
286
|
semver_gte: "semver_gte";
|
|
249
287
|
semver_lt: "semver_lt";
|
|
250
288
|
semver_lte: "semver_lte";
|
|
289
|
+
gate_pass: "gate_pass";
|
|
290
|
+
exp_in: "exp_in";
|
|
251
291
|
}>;
|
|
252
292
|
value: z.ZodUnknown;
|
|
253
293
|
}, z.core.$strip>>>;
|
|
@@ -283,9 +323,20 @@ declare const gatesResource: {
|
|
|
283
323
|
semver_gte: "semver_gte";
|
|
284
324
|
semver_lt: "semver_lt";
|
|
285
325
|
semver_lte: "semver_lte";
|
|
326
|
+
gate_pass: "gate_pass";
|
|
327
|
+
exp_in: "exp_in";
|
|
286
328
|
}>;
|
|
287
329
|
value: z.ZodUnknown;
|
|
288
330
|
}, z.core.$strip>>>;
|
|
331
|
+
rolloutPct: z.ZodOptional<z.ZodNumber>;
|
|
332
|
+
bucketBy: z.ZodOptional<z.ZodString>;
|
|
333
|
+
salt: z.ZodOptional<z.ZodString>;
|
|
334
|
+
ramp: z.ZodOptional<z.ZodObject<{
|
|
335
|
+
from: z.ZodNumber;
|
|
336
|
+
to: z.ZodNumber;
|
|
337
|
+
startAt: z.ZodNumber;
|
|
338
|
+
durationMs: z.ZodNumber;
|
|
339
|
+
}, z.core.$strip>>;
|
|
289
340
|
locked: z.ZodOptional<z.ZodBoolean>;
|
|
290
341
|
}, z.core.$strip>, z.ZodObject<{
|
|
291
342
|
id: z.ZodString;
|
|
@@ -295,6 +346,12 @@ declare const gatesResource: {
|
|
|
295
346
|
rolloutPct: z.ZodNumber;
|
|
296
347
|
bucketBy: z.ZodOptional<z.ZodString>;
|
|
297
348
|
salt: z.ZodOptional<z.ZodString>;
|
|
349
|
+
ramp: z.ZodOptional<z.ZodObject<{
|
|
350
|
+
from: z.ZodNumber;
|
|
351
|
+
to: z.ZodNumber;
|
|
352
|
+
startAt: z.ZodNumber;
|
|
353
|
+
durationMs: z.ZodNumber;
|
|
354
|
+
}, z.core.$strip>>;
|
|
298
355
|
locked: z.ZodOptional<z.ZodBoolean>;
|
|
299
356
|
}, z.core.$strip>], "type">>>>;
|
|
300
357
|
updatedAt: z.ZodString;
|
|
@@ -364,6 +421,8 @@ declare const gatesResource: {
|
|
|
364
421
|
semver_gte: "semver_gte";
|
|
365
422
|
semver_lt: "semver_lt";
|
|
366
423
|
semver_lte: "semver_lte";
|
|
424
|
+
gate_pass: "gate_pass";
|
|
425
|
+
exp_in: "exp_in";
|
|
367
426
|
}>;
|
|
368
427
|
value: z.ZodUnknown;
|
|
369
428
|
}, z.core.$strip>>>;
|
|
@@ -394,9 +453,20 @@ declare const gatesResource: {
|
|
|
394
453
|
semver_gte: "semver_gte";
|
|
395
454
|
semver_lt: "semver_lt";
|
|
396
455
|
semver_lte: "semver_lte";
|
|
456
|
+
gate_pass: "gate_pass";
|
|
457
|
+
exp_in: "exp_in";
|
|
397
458
|
}>;
|
|
398
459
|
value: z.ZodUnknown;
|
|
399
460
|
}, z.core.$strip>>>;
|
|
461
|
+
rolloutPct: z.ZodOptional<z.ZodNumber>;
|
|
462
|
+
bucketBy: z.ZodOptional<z.ZodString>;
|
|
463
|
+
salt: z.ZodOptional<z.ZodString>;
|
|
464
|
+
ramp: z.ZodOptional<z.ZodObject<{
|
|
465
|
+
from: z.ZodNumber;
|
|
466
|
+
to: z.ZodNumber;
|
|
467
|
+
startAt: z.ZodNumber;
|
|
468
|
+
durationMs: z.ZodNumber;
|
|
469
|
+
}, z.core.$strip>>;
|
|
400
470
|
locked: z.ZodOptional<z.ZodBoolean>;
|
|
401
471
|
}, z.core.$strip>, z.ZodObject<{
|
|
402
472
|
id: z.ZodString;
|
|
@@ -406,6 +476,12 @@ declare const gatesResource: {
|
|
|
406
476
|
rolloutPct: z.ZodNumber;
|
|
407
477
|
bucketBy: z.ZodOptional<z.ZodString>;
|
|
408
478
|
salt: z.ZodOptional<z.ZodString>;
|
|
479
|
+
ramp: z.ZodOptional<z.ZodObject<{
|
|
480
|
+
from: z.ZodNumber;
|
|
481
|
+
to: z.ZodNumber;
|
|
482
|
+
startAt: z.ZodNumber;
|
|
483
|
+
durationMs: z.ZodNumber;
|
|
484
|
+
}, z.core.$strip>>;
|
|
409
485
|
locked: z.ZodOptional<z.ZodBoolean>;
|
|
410
486
|
}, z.core.$strip>], "type">>>>;
|
|
411
487
|
}, z.core.$strip>;
|
|
@@ -531,6 +607,8 @@ declare const gatesResource: {
|
|
|
531
607
|
semver_gte: "semver_gte";
|
|
532
608
|
semver_lt: "semver_lt";
|
|
533
609
|
semver_lte: "semver_lte";
|
|
610
|
+
gate_pass: "gate_pass";
|
|
611
|
+
exp_in: "exp_in";
|
|
534
612
|
}>;
|
|
535
613
|
value: z.ZodUnknown;
|
|
536
614
|
}, z.core.$strip>>>;
|
|
@@ -561,9 +639,20 @@ declare const gatesResource: {
|
|
|
561
639
|
semver_gte: "semver_gte";
|
|
562
640
|
semver_lt: "semver_lt";
|
|
563
641
|
semver_lte: "semver_lte";
|
|
642
|
+
gate_pass: "gate_pass";
|
|
643
|
+
exp_in: "exp_in";
|
|
564
644
|
}>;
|
|
565
645
|
value: z.ZodUnknown;
|
|
566
646
|
}, z.core.$strip>>>;
|
|
647
|
+
rolloutPct: z.ZodOptional<z.ZodNumber>;
|
|
648
|
+
bucketBy: z.ZodOptional<z.ZodString>;
|
|
649
|
+
salt: z.ZodOptional<z.ZodString>;
|
|
650
|
+
ramp: z.ZodOptional<z.ZodObject<{
|
|
651
|
+
from: z.ZodNumber;
|
|
652
|
+
to: z.ZodNumber;
|
|
653
|
+
startAt: z.ZodNumber;
|
|
654
|
+
durationMs: z.ZodNumber;
|
|
655
|
+
}, z.core.$strip>>;
|
|
567
656
|
locked: z.ZodOptional<z.ZodBoolean>;
|
|
568
657
|
}, z.core.$strip>, z.ZodObject<{
|
|
569
658
|
id: z.ZodString;
|
|
@@ -573,6 +662,12 @@ declare const gatesResource: {
|
|
|
573
662
|
rolloutPct: z.ZodNumber;
|
|
574
663
|
bucketBy: z.ZodOptional<z.ZodString>;
|
|
575
664
|
salt: z.ZodOptional<z.ZodString>;
|
|
665
|
+
ramp: z.ZodOptional<z.ZodObject<{
|
|
666
|
+
from: z.ZodNumber;
|
|
667
|
+
to: z.ZodNumber;
|
|
668
|
+
startAt: z.ZodNumber;
|
|
669
|
+
durationMs: z.ZodNumber;
|
|
670
|
+
}, z.core.$strip>>;
|
|
576
671
|
locked: z.ZodOptional<z.ZodBoolean>;
|
|
577
672
|
}, z.core.$strip>], "type">>>>;
|
|
578
673
|
}, z.core.$strip>;
|
package/dist/resources/gates.js
CHANGED
|
@@ -29,12 +29,14 @@ var gateRuleSchema = z2.object({
|
|
|
29
29
|
"semver_gt",
|
|
30
30
|
"semver_gte",
|
|
31
31
|
"semver_lt",
|
|
32
|
-
"semver_lte"
|
|
32
|
+
"semver_lte",
|
|
33
|
+
"gate_pass",
|
|
34
|
+
"exp_in"
|
|
33
35
|
]).describe(
|
|
34
|
-
|
|
36
|
+
'Comparison operator. Equality: `eq`/`neq`. Set membership: `in`/`not_in` (value is an array). Numeric order: `gt`/`gte`/`lt`/`lte`. Semver order: `semver_gt`/`semver_gte`/`semver_lt`/`semver_lte` (value is a dotted version like `4.2.0`). String: `contains` (substring), `regex` (JS-flavour pattern, value is the pattern string). Cross-resource references (evaluated only on the worker hot path, where both KV blobs load): `gate_pass` (`value` is another gate\'s name \u2014 true when that gate passes for the same caller); `exp_in` (`attr` is a running experiment\'s name, `value` is a group name, `"$holdout"`, or `"$any"` \u2014 true when the caller is in that variant / the universe holdout / any variant).'
|
|
35
37
|
),
|
|
36
38
|
value: z2.unknown().describe(
|
|
37
|
-
|
|
39
|
+
'Operand. Shape depends on `op`: scalar for `eq/neq/gt/gte/lt/lte/contains/semver_*`; array of scalars for `in/not_in`; string pattern for `regex`; referenced gate name for `gate_pass`; group name / `"$holdout"` / `"$any"` for `exp_in`.'
|
|
38
40
|
)
|
|
39
41
|
}).describe(
|
|
40
42
|
"Single targeting predicate. A gate's `rules` array is evaluated with AND semantics; use the gatekeeper `stack` for OR / fall-through logic."
|
|
@@ -45,9 +47,17 @@ var gateNameSchema = z2.string().regex(
|
|
|
45
47
|
).max(128).describe(
|
|
46
48
|
"Stable gate key used by SDKs (`Shipeasy.checkGate(user, '<name>')`). Single segment or `folder.name`. Lowercase letters, digits, `_` or `-`; max 128 chars. Immutable after create \u2014 rename = delete + recreate."
|
|
47
49
|
);
|
|
50
|
+
var rampSchema = z2.object({
|
|
51
|
+
from: z2.number().int().min(0).max(1e4).describe("Start of the ramp in basis points (0\u201310000)."),
|
|
52
|
+
to: z2.number().int().min(0).max(1e4).describe("End of the ramp in basis points (0\u201310000)."),
|
|
53
|
+
startAt: z2.number().int().nonnegative().describe("Ramp start, epoch milliseconds (UTC)."),
|
|
54
|
+
durationMs: z2.number().int().positive().describe("Ramp length in milliseconds.")
|
|
55
|
+
}).describe(
|
|
56
|
+
"Linear rollout ramp. The effective rollout % interpolates `from`\u2192`to` over `[startAt, startAt+durationMs]`, clamped outside that window, evaluated against the wall-clock at eval time. Overrides the entry's static `rolloutPct` while present."
|
|
57
|
+
);
|
|
48
58
|
var stackedConditionSchema = z2.object({
|
|
49
59
|
id: z2.string().min(1).describe(
|
|
50
|
-
"Client-supplied stable id for the stack entry (used for React keys, audit diffs)."
|
|
60
|
+
"Client-supplied stable id for the stack entry (used for React keys, audit diffs, and as the default per-condition rollout salt)."
|
|
51
61
|
),
|
|
52
62
|
type: z2.literal("condition").describe("Discriminator. `condition` = rule-based predicate sub-gate."),
|
|
53
63
|
name: z2.string().optional().describe("Human label shown in the dashboard."),
|
|
@@ -56,9 +66,15 @@ var stackedConditionSchema = z2.object({
|
|
|
56
66
|
),
|
|
57
67
|
pass: z2.enum(["all", "any"]).optional().describe("Combinator across `rules`. `all` = AND (default), `any` = OR."),
|
|
58
68
|
rules: z2.array(gateRuleSchema).default([]).describe("Predicates evaluated under `pass`. Empty array = match nothing."),
|
|
69
|
+
rolloutPct: z2.number().int().min(0).max(1e4).optional().describe(
|
|
70
|
+
"Per-condition rollout in basis points. After the rules match, the caller is bucketed at this %; in-bucket \u2192 gate `true`, otherwise fall through to the next entry. Absent \u21D2 10000 (100%, every matching caller passes)."
|
|
71
|
+
),
|
|
72
|
+
bucketBy: z2.string().optional().describe("Attribute used to hash the caller into the per-condition bucket. Default `userID`."),
|
|
73
|
+
salt: z2.string().optional().describe("Per-condition hash salt. Defaults to the entry `id`, then the gate salt."),
|
|
74
|
+
ramp: rampSchema.optional(),
|
|
59
75
|
locked: z2.boolean().optional().describe("If `true`, dashboard hides edit controls (e.g. the trailing public-floor entry).")
|
|
60
76
|
}).describe(
|
|
61
|
-
"Rule-based sub-gate. When
|
|
77
|
+
"Rule-based sub-gate. When the rules match and the caller falls in the per-condition rollout bucket, evaluation short-circuits and the gate returns `true`; otherwise it falls through to the next entry."
|
|
62
78
|
);
|
|
63
79
|
var stackedRolloutSchema = z2.object({
|
|
64
80
|
id: z2.string().min(1).describe("Client-supplied stable id for the stack entry."),
|
|
@@ -74,9 +90,10 @@ var stackedRolloutSchema = z2.object({
|
|
|
74
90
|
salt: z2.string().optional().describe(
|
|
75
91
|
"Per-entry hash salt. Defaults to the gate's salt. Set explicitly to keep two rollouts independent or correlated across gates."
|
|
76
92
|
),
|
|
93
|
+
ramp: rampSchema.optional(),
|
|
77
94
|
locked: z2.boolean().optional().describe("If `true`, dashboard hides edit controls.")
|
|
78
95
|
}).describe(
|
|
79
|
-
"Percentage-rollout sub-gate. Hashes `bucketBy` (default `userID`) with `salt` and returns `true` for `rolloutPct/10000` fraction of callers."
|
|
96
|
+
"Percentage-rollout sub-gate. Hashes `bucketBy` (default `userID`) with `salt` and returns `true` for `rolloutPct/10000` fraction of callers (or the ramp's effective % when `ramp` is set)."
|
|
80
97
|
);
|
|
81
98
|
var stackedGateEntrySchema = z2.discriminatedUnion("type", [stackedConditionSchema, stackedRolloutSchema]).describe(
|
|
82
99
|
"One entry in the ordered gatekeeper stack. Evaluated top-to-bottom; first matching entry decides. Mix `condition` and `rollout` entries to express `internal-only` + `1% beta` + `50% public` in a single gate."
|