@revturbine/cli 0.7.1 → 0.8.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/README.md +16 -4
- package/dist/cli.js +1173 -233
- package/package.json +22 -11
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
4
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
5
5
|
import path2 from "path";
|
|
6
6
|
import { createRequire } from "module";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
7
8
|
import { createInterface } from "readline/promises";
|
|
8
|
-
import { spawn as spawn2 } from "child_process";
|
|
9
|
+
import { spawn as spawn2, spawnSync } from "child_process";
|
|
9
10
|
import { Command, CommanderError, Option } from "commander";
|
|
10
11
|
import { z as z29 } from "zod";
|
|
11
12
|
|
|
@@ -196,6 +197,7 @@ var NameField = z2.string().min(1).max(200);
|
|
|
196
197
|
var HandleField = z2.string().min(1).max(100);
|
|
197
198
|
var DescriptionField = z2.string().max(500).optional();
|
|
198
199
|
var MetadataField = z2.record(z2.string(), z2.unknown()).default({});
|
|
200
|
+
var ThresholdPercentField = z2.number().int().min(10).max(100).multipleOf(10);
|
|
199
201
|
var NullableDatetimeField = z2.string().datetime().nullable().default(null);
|
|
200
202
|
var AnchorFields = z2.object({
|
|
201
203
|
environment_id: z2.string().min(1).default("production").meta({ ...Unrestricted, readOnly: true })
|
|
@@ -265,6 +267,52 @@ var CtaActionTypeSchema = z2.enum([
|
|
|
265
267
|
"snooze",
|
|
266
268
|
"custom"
|
|
267
269
|
]).meta({ id: "CtaActionType", "x-revturbine-schema-persistence": Transient, "x-revturbine-schema-exposure": External });
|
|
270
|
+
var SchemaContext = {
|
|
271
|
+
Playbook: "playbook",
|
|
272
|
+
Branding: "branding",
|
|
273
|
+
Billing: "billing",
|
|
274
|
+
Metering: "metering",
|
|
275
|
+
CustomerOperations: "customer_operations",
|
|
276
|
+
EventIngestion: "event_ingestion"
|
|
277
|
+
};
|
|
278
|
+
var SchemaSource = {
|
|
279
|
+
Customer: "customer",
|
|
280
|
+
Stripe: "stripe",
|
|
281
|
+
CodeConstant: "code-constant",
|
|
282
|
+
Runtime: "runtime"
|
|
283
|
+
};
|
|
284
|
+
var SCHEMA_CONTEXT_META_KEY = "x-revturbine-context";
|
|
285
|
+
var SCHEMA_IN_CONFIG_META_KEY = "x-revturbine-in-config";
|
|
286
|
+
var SCHEMA_SDK_INPUT_META_KEY = "x-revturbine-sdk-input";
|
|
287
|
+
var SCHEMA_SOURCE_META_KEY = "x-revturbine-source";
|
|
288
|
+
var SCHEMA_DEPRECATION_META_KEY = "x-revturbine-deprecation";
|
|
289
|
+
var DEFAULT_SOURCE_BY_CONTEXT = {
|
|
290
|
+
[SchemaContext.Playbook]: SchemaSource.Customer,
|
|
291
|
+
[SchemaContext.Branding]: SchemaSource.Customer,
|
|
292
|
+
[SchemaContext.Billing]: SchemaSource.Stripe,
|
|
293
|
+
[SchemaContext.Metering]: SchemaSource.Customer,
|
|
294
|
+
[SchemaContext.CustomerOperations]: SchemaSource.Runtime,
|
|
295
|
+
[SchemaContext.EventIngestion]: SchemaSource.Runtime
|
|
296
|
+
};
|
|
297
|
+
function schemaFacets(context, options) {
|
|
298
|
+
return {
|
|
299
|
+
[SCHEMA_CONTEXT_META_KEY]: context,
|
|
300
|
+
[SCHEMA_IN_CONFIG_META_KEY]: options.inConfig ?? context === SchemaContext.Playbook,
|
|
301
|
+
[SCHEMA_SDK_INPUT_META_KEY]: options.sdkInput,
|
|
302
|
+
[SCHEMA_SOURCE_META_KEY]: options.source ?? DEFAULT_SOURCE_BY_CONTEXT[context]
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
function schemaDeprecation(declaration) {
|
|
306
|
+
return {
|
|
307
|
+
deprecated: true,
|
|
308
|
+
[SCHEMA_DEPRECATION_META_KEY]: {
|
|
309
|
+
since: declaration.since,
|
|
310
|
+
replacement: declaration.replacement,
|
|
311
|
+
remove_after: declaration.removeAfter,
|
|
312
|
+
reason: declaration.reason
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
}
|
|
268
316
|
var IdentityKind = {
|
|
269
317
|
/** Author-given, human-meaningful handle (plans, entitlements, segments, …). */
|
|
270
318
|
Named: "named",
|
|
@@ -297,6 +345,9 @@ var ListQueryParamsSchema = z4.object({
|
|
|
297
345
|
var { Unrestricted: Unrestricted2, Financial } = DataClassification;
|
|
298
346
|
var { Persisted: Persisted2, Transient: Transient2 } = SchemaPersistence;
|
|
299
347
|
var { External: External2 } = SchemaExposure;
|
|
348
|
+
var PLAYBOOK_SDK_FACETS = schemaFacets(SchemaContext.Playbook, { sdkInput: true });
|
|
349
|
+
var PLAYBOOK_AUTHORING_FACETS = schemaFacets(SchemaContext.Playbook, { sdkInput: false });
|
|
350
|
+
var BILLING_FACETS = schemaFacets(SchemaContext.Billing, { sdkInput: false });
|
|
300
351
|
var PlanVisibilitySchema = z5.enum(["public", "unlisted", "legacy"]).meta(
|
|
301
352
|
{
|
|
302
353
|
id: "PlanVisibility",
|
|
@@ -330,6 +381,7 @@ var PlanSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(Ancho
|
|
|
330
381
|
id: "Plan",
|
|
331
382
|
"x-revturbine-schema-persistence": Persisted2,
|
|
332
383
|
"x-revturbine-schema-exposure": External2,
|
|
384
|
+
...PLAYBOOK_SDK_FACETS,
|
|
333
385
|
...namedIdentity()
|
|
334
386
|
}
|
|
335
387
|
);
|
|
@@ -343,6 +395,9 @@ var PlanVariationSchema = IdField.merge(TimestampFields).merge(TenantIdField).me
|
|
|
343
395
|
price_amount: z5.number().min(0).meta(Financial),
|
|
344
396
|
pricing_model: PricingModelSchema.meta(Unrestricted2),
|
|
345
397
|
visibility: PlanVisibilitySchema.default("public").meta(Unrestricted2),
|
|
398
|
+
// Soft reference → StripePrice.stripe_price_id (the backend Stripe-price mirror).
|
|
399
|
+
// No DB foreign key: stripe_price_id lives on the append-only version tables and
|
|
400
|
+
// a hard FK would block plan-122 price-deletion sync (plan 118 FK decision, devkit #472).
|
|
346
401
|
stripe_price_id: z5.string().optional().meta(Unrestricted2),
|
|
347
402
|
price_source: PriceSourceSchema.default("static").meta(Unrestricted2)
|
|
348
403
|
}).meta(
|
|
@@ -350,6 +405,7 @@ var PlanVariationSchema = IdField.merge(TimestampFields).merge(TenantIdField).me
|
|
|
350
405
|
id: "PlanVariation",
|
|
351
406
|
"x-revturbine-schema-persistence": Persisted2,
|
|
352
407
|
"x-revturbine-schema-exposure": External2,
|
|
408
|
+
...BILLING_FACETS,
|
|
353
409
|
...mintedIdentity()
|
|
354
410
|
}
|
|
355
411
|
);
|
|
@@ -365,6 +421,7 @@ var AddOnSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(Anch
|
|
|
365
421
|
id: "AddOn",
|
|
366
422
|
"x-revturbine-schema-persistence": Persisted2,
|
|
367
423
|
"x-revturbine-schema-exposure": External2,
|
|
424
|
+
...PLAYBOOK_AUTHORING_FACETS,
|
|
368
425
|
...namedIdentity()
|
|
369
426
|
}
|
|
370
427
|
);
|
|
@@ -380,6 +437,9 @@ var AddOnVariationSchema = IdField.merge(TimestampFields).merge(TenantIdField).m
|
|
|
380
437
|
price_amount: z5.number().min(0).meta(Financial),
|
|
381
438
|
pricing_model: PricingModelSchema.meta(Unrestricted2),
|
|
382
439
|
visibility: PlanVisibilitySchema.default("public").meta(Unrestricted2),
|
|
440
|
+
// Soft reference → StripePrice.stripe_price_id (the backend Stripe-price mirror).
|
|
441
|
+
// No DB foreign key: stripe_price_id lives on the append-only version tables and
|
|
442
|
+
// a hard FK would block plan-122 price-deletion sync (plan 118 FK decision, devkit #472).
|
|
383
443
|
stripe_price_id: z5.string().optional().meta(Unrestricted2),
|
|
384
444
|
price_source: PriceSourceSchema.default("static").meta(Unrestricted2)
|
|
385
445
|
}).meta(
|
|
@@ -387,33 +447,41 @@ var AddOnVariationSchema = IdField.merge(TimestampFields).merge(TenantIdField).m
|
|
|
387
447
|
id: "AddOnVariation",
|
|
388
448
|
"x-revturbine-schema-persistence": Persisted2,
|
|
389
449
|
"x-revturbine-schema-exposure": External2,
|
|
450
|
+
...BILLING_FACETS,
|
|
390
451
|
...mintedIdentity()
|
|
391
452
|
}
|
|
392
453
|
);
|
|
393
454
|
var AddOnVariationAnchorSchema = makeAnchor("AddOnVariationAnchor");
|
|
394
|
-
var
|
|
395
|
-
id: "
|
|
455
|
+
var StripePriceBillingPeriodSchema = z5.enum(["monthly", "annual", "one_time", "custom"]).meta({
|
|
456
|
+
id: "StripePriceBillingPeriod",
|
|
396
457
|
"x-revturbine-schema-persistence": Transient2,
|
|
397
458
|
"x-revturbine-schema-exposure": External2
|
|
398
459
|
});
|
|
399
|
-
var
|
|
460
|
+
var StripePriceSchema = IdField.merge(TimestampFields).merge(TenantIdField).extend({
|
|
400
461
|
stripe_price_id: z5.string().min(1).meta(Unrestricted2),
|
|
401
462
|
stripe_product_id: z5.string().min(1).meta(Unrestricted2),
|
|
402
|
-
billing_period:
|
|
463
|
+
billing_period: StripePriceBillingPeriodSchema.meta(Unrestricted2),
|
|
403
464
|
unit_amount_cents: z5.number().int().min(0).nullable().default(null).meta(Financial),
|
|
404
465
|
currency: CurrencySchema.meta(Financial),
|
|
405
466
|
pricing_model: PricingModelSchema.meta(Unrestricted2),
|
|
406
|
-
nickname: z5.string().nullable().default(null).meta(Unrestricted2)
|
|
467
|
+
nickname: z5.string().nullable().default(null).meta(Unrestricted2),
|
|
468
|
+
// Placeholder/seed price (demo or pre-integration tenants) vs a real
|
|
469
|
+
// Stripe-synced mirror row. Migration backfills existing seed rows to true.
|
|
470
|
+
is_mock: z5.boolean().default(false).meta(Unrestricted2),
|
|
471
|
+
// Timestamp of the last successful sync from Stripe; null for rows that were
|
|
472
|
+
// never sourced from a real Stripe Price (seeds/mocks).
|
|
473
|
+
last_updated_from_stripe: NullableDatetimeField.meta(Unrestricted2)
|
|
407
474
|
}).meta({
|
|
408
|
-
id: "
|
|
475
|
+
id: "StripePrice",
|
|
409
476
|
"x-revturbine-schema-persistence": Persisted2,
|
|
410
|
-
"x-revturbine-schema-exposure": External2
|
|
477
|
+
"x-revturbine-schema-exposure": External2,
|
|
478
|
+
...BILLING_FACETS
|
|
411
479
|
});
|
|
412
480
|
var PlanWriteSchema = toWritableSchema(PlanSchema);
|
|
413
481
|
var PlanVariationWriteSchema = toWritableSchema(PlanVariationSchema);
|
|
414
482
|
var AddOnWriteSchema = toWritableSchema(AddOnSchema);
|
|
415
483
|
var AddOnVariationWriteSchema = toWritableSchema(AddOnVariationSchema);
|
|
416
|
-
var
|
|
484
|
+
var StripePriceWriteSchema = toWritableSchema(StripePriceSchema);
|
|
417
485
|
var planPaths = {
|
|
418
486
|
"/api/plan-anchors": {
|
|
419
487
|
get: operation({
|
|
@@ -674,55 +742,60 @@ var planPaths = {
|
|
|
674
742
|
"x-revturbine-operation": { exposure: "external", resource: "addon-variations", persistence: { table: "addonVariationVersions", mode: "delete" } }
|
|
675
743
|
})
|
|
676
744
|
},
|
|
677
|
-
"/api/stripe-prices
|
|
745
|
+
"/api/stripe-prices": {
|
|
678
746
|
get: operation({
|
|
679
|
-
operationId: "
|
|
747
|
+
operationId: "listStripePrices",
|
|
680
748
|
requestParams: { query: ListQueryParamsSchema },
|
|
681
|
-
summary: "List Stripe
|
|
749
|
+
summary: "List Stripe prices",
|
|
682
750
|
tags: ["plans"],
|
|
683
|
-
responses: { "200": { description: "Stripe price
|
|
684
|
-
"x-revturbine-operation": { exposure: "external", resource: "stripe-prices
|
|
751
|
+
responses: { "200": { description: "Stripe price list", content: { "application/json": { schema: ListEnvelope(StripePriceSchema) } } } },
|
|
752
|
+
"x-revturbine-operation": { exposure: "external", resource: "stripe-prices", persistence: { table: "stripePrices", mode: "list" } }
|
|
685
753
|
}),
|
|
686
754
|
post: operation({
|
|
687
|
-
operationId: "
|
|
688
|
-
summary: "Create Stripe price
|
|
755
|
+
operationId: "createStripePrice",
|
|
756
|
+
summary: "Create Stripe price",
|
|
689
757
|
tags: ["plans"],
|
|
690
|
-
requestBody: { required: true, content: { "application/json": { schema: toCreateSchema(
|
|
691
|
-
responses: { "201": { description: "Created Stripe price
|
|
692
|
-
"x-revturbine-operation": { exposure: "external", resource: "stripe-prices
|
|
758
|
+
requestBody: { required: true, content: { "application/json": { schema: toCreateSchema(StripePriceSchema) } } },
|
|
759
|
+
responses: { "201": { description: "Created Stripe price", content: { "application/json": { schema: StripePriceSchema } } } },
|
|
760
|
+
"x-revturbine-operation": { exposure: "external", resource: "stripe-prices", persistence: { table: "stripePrices", mode: "create" } }
|
|
693
761
|
})
|
|
694
762
|
},
|
|
695
|
-
"/api/stripe-prices
|
|
763
|
+
"/api/stripe-prices/{id}": {
|
|
696
764
|
get: operation({
|
|
697
|
-
operationId: "
|
|
765
|
+
operationId: "getStripePrice",
|
|
698
766
|
requestParams: { path: z5.object({ id: z5.string() }) },
|
|
699
|
-
summary: "Get Stripe price
|
|
767
|
+
summary: "Get Stripe price by ID",
|
|
700
768
|
tags: ["plans"],
|
|
701
|
-
responses: { "200": { description: "Stripe price
|
|
702
|
-
"x-revturbine-operation": { exposure: "external", resource: "stripe-prices
|
|
769
|
+
responses: { "200": { description: "Stripe price detail", content: { "application/json": { schema: StripePriceSchema } } } },
|
|
770
|
+
"x-revturbine-operation": { exposure: "external", resource: "stripe-prices", persistence: { table: "stripePrices", mode: "get" } }
|
|
703
771
|
}),
|
|
704
772
|
patch: operation({
|
|
705
|
-
operationId: "
|
|
773
|
+
operationId: "updateStripePrice",
|
|
706
774
|
requestParams: { path: z5.object({ id: z5.string() }) },
|
|
707
|
-
summary: "Update Stripe price
|
|
775
|
+
summary: "Update Stripe price",
|
|
708
776
|
tags: ["plans"],
|
|
709
|
-
requestBody: { required: true, content: { "application/json": { schema:
|
|
710
|
-
responses: { "200": { description: "Updated Stripe price
|
|
711
|
-
"x-revturbine-operation": { exposure: "external", resource: "stripe-prices
|
|
777
|
+
requestBody: { required: true, content: { "application/json": { schema: StripePriceWriteSchema } } },
|
|
778
|
+
responses: { "200": { description: "Updated Stripe price", content: { "application/json": { schema: StripePriceSchema } } } },
|
|
779
|
+
"x-revturbine-operation": { exposure: "external", resource: "stripe-prices", persistence: { table: "stripePrices", mode: "update" } }
|
|
712
780
|
}),
|
|
713
781
|
delete: operation({
|
|
714
|
-
operationId: "
|
|
782
|
+
operationId: "deleteStripePrice",
|
|
715
783
|
requestParams: { path: z5.object({ id: z5.string() }) },
|
|
716
|
-
summary: "Delete Stripe price
|
|
784
|
+
summary: "Delete Stripe price",
|
|
717
785
|
tags: ["plans"],
|
|
718
|
-
responses: { "204": { description: "Stripe price
|
|
719
|
-
"x-revturbine-operation": { exposure: "external", resource: "stripe-prices
|
|
786
|
+
responses: { "204": { description: "Stripe price deleted" } },
|
|
787
|
+
"x-revturbine-operation": { exposure: "external", resource: "stripe-prices", persistence: { table: "stripePrices", mode: "delete" } }
|
|
720
788
|
})
|
|
721
789
|
}
|
|
722
790
|
};
|
|
723
791
|
var { Unrestricted: Unrestricted3 } = DataClassification;
|
|
724
792
|
var { Persisted: Persisted3, Transient: Transient3 } = SchemaPersistence;
|
|
725
793
|
var { Internal: Internal2, External: External3 } = SchemaExposure;
|
|
794
|
+
var PLAYBOOK_SDK_FACETS2 = schemaFacets(SchemaContext.Playbook, { sdkInput: true });
|
|
795
|
+
var PENDING_PLAYBOOK_FACETS = schemaFacets(SchemaContext.Playbook, {
|
|
796
|
+
inConfig: false,
|
|
797
|
+
sdkInput: false
|
|
798
|
+
});
|
|
726
799
|
var UsagePeriodScopeSchema = z6.enum(["per_month", "per_year", "per_billing_period", "lifetime", "concurrent", "per_instance", "per_second", "per_minute", "per_hour", "per_6_hours", "per_day", "per_week"]).meta(
|
|
727
800
|
{ id: "UsagePeriodScope", "x-revturbine-schema-persistence": Transient3, "x-revturbine-schema-exposure": External3 }
|
|
728
801
|
);
|
|
@@ -792,6 +865,94 @@ var EntitlementRuleTargetSchema = z6.object({
|
|
|
792
865
|
var EntitlementRulePeriodUnitSchema = z6.enum(["month", "day", "week", "quarter", "year", "billing_period", "on_purchase", "hour", "six_hours"]).meta(
|
|
793
866
|
{ id: "EntitlementRulePeriodUnit", "x-revturbine-schema-persistence": Transient3, "x-revturbine-schema-exposure": External3 }
|
|
794
867
|
);
|
|
868
|
+
var LimitValueField = z6.union([z6.number(), z6.literal("unlimited")]).nullable().optional();
|
|
869
|
+
var EntitlementTypeFieldsFeatureSchema = z6.looseObject({
|
|
870
|
+
kind: z6.literal("feature").meta(Unrestricted3),
|
|
871
|
+
enabled: z6.boolean().optional().meta(Unrestricted3)
|
|
872
|
+
}).meta(
|
|
873
|
+
{ id: "EntitlementTypeFieldsFeature", "x-revturbine-schema-persistence": Transient3, "x-revturbine-schema-exposure": External3 }
|
|
874
|
+
);
|
|
875
|
+
var EntitlementTypeFieldsCapabilityTierSchema = z6.looseObject({
|
|
876
|
+
kind: z6.literal("capability_tier").meta(Unrestricted3),
|
|
877
|
+
tier_name: z6.string().optional().meta(Unrestricted3),
|
|
878
|
+
tier_description: z6.string().optional().meta(Unrestricted3)
|
|
879
|
+
}).meta(
|
|
880
|
+
{ id: "EntitlementTypeFieldsCapabilityTier", "x-revturbine-schema-persistence": Transient3, "x-revturbine-schema-exposure": External3 }
|
|
881
|
+
);
|
|
882
|
+
var EntitlementTypeFieldsUsageLimitSchema = z6.looseObject({
|
|
883
|
+
kind: z6.literal("usage_limit").meta(Unrestricted3),
|
|
884
|
+
limit_value: LimitValueField.meta(Unrestricted3),
|
|
885
|
+
unit: z6.string().optional().meta(Unrestricted3),
|
|
886
|
+
period: UsagePeriodScopeSchema.optional().meta(Unrestricted3),
|
|
887
|
+
enforcement: EnforcementModeSchema.optional().meta(Unrestricted3)
|
|
888
|
+
}).meta(
|
|
889
|
+
{ id: "EntitlementTypeFieldsUsageLimit", "x-revturbine-schema-persistence": Transient3, "x-revturbine-schema-exposure": External3 }
|
|
890
|
+
);
|
|
891
|
+
var EntitlementTypeFieldsPricePerUnitSchema = z6.looseObject({
|
|
892
|
+
kind: z6.literal("price_per_unit").meta(Unrestricted3),
|
|
893
|
+
amount_cents: z6.number().optional().meta(Unrestricted3),
|
|
894
|
+
currency: z6.string().optional().meta(Unrestricted3),
|
|
895
|
+
unit: z6.string().optional().meta(Unrestricted3),
|
|
896
|
+
period: UsagePeriodScopeSchema.optional().meta(Unrestricted3)
|
|
897
|
+
}).meta(
|
|
898
|
+
{ id: "EntitlementTypeFieldsPricePerUnit", "x-revturbine-schema-persistence": Transient3, "x-revturbine-schema-exposure": External3 }
|
|
899
|
+
);
|
|
900
|
+
var EntitlementTypeFieldsRateLimitSchema = z6.looseObject({
|
|
901
|
+
kind: z6.literal("rate_limit").meta(Unrestricted3),
|
|
902
|
+
rate_value: z6.number().optional().meta(Unrestricted3),
|
|
903
|
+
period_scope: UsagePeriodScopeSchema.optional().meta(Unrestricted3),
|
|
904
|
+
enforcement: EnforcementModeSchema.optional().meta(Unrestricted3)
|
|
905
|
+
}).meta(
|
|
906
|
+
{ id: "EntitlementTypeFieldsRateLimit", "x-revturbine-schema-persistence": Transient3, "x-revturbine-schema-exposure": External3 }
|
|
907
|
+
);
|
|
908
|
+
var EntitlementTypeFieldsCreditsSchema = z6.looseObject({
|
|
909
|
+
kind: z6.literal("credits").meta(Unrestricted3),
|
|
910
|
+
allowance: LimitValueField.meta(Unrestricted3),
|
|
911
|
+
initial_grant: z6.number().optional().meta(Unrestricted3),
|
|
912
|
+
unit: z6.string().optional().meta(Unrestricted3),
|
|
913
|
+
// Wire cadence uses the `per_*` vocabulary; the persisted `reset_period`
|
|
914
|
+
// column uses the bare vocabulary (`month`). Both are declared so the
|
|
915
|
+
// translation gap is visible to the contract instead of silent (plan 109).
|
|
916
|
+
period: UsagePeriodScopeSchema.optional().meta(Unrestricted3),
|
|
917
|
+
reset_period: EntitlementRulePeriodUnitSchema.optional().meta(Unrestricted3),
|
|
918
|
+
rollover: z6.boolean().optional().meta(Unrestricted3),
|
|
919
|
+
// `max_balance` — the maximum balance allowed at any time — is the ONLY
|
|
920
|
+
// credits cap in the model (Kent, 2026-07-22). The older `max_rollover`
|
|
921
|
+
// (how much unused balance carried into the next period) was folded away
|
|
922
|
+
// when plan 28 REQ-13 renamed the column, and authored configs have since
|
|
923
|
+
// been migrated off it. Do not re-add it: it has no column, IR field, or
|
|
924
|
+
// bundle slot — plan 37 retired its FlatBuffer slot to a -1 sentinel — so
|
|
925
|
+
// declaring it would promise a round-trip the model cannot honour.
|
|
926
|
+
max_balance: LimitValueField.meta(Unrestricted3),
|
|
927
|
+
top_up_available: z6.boolean().optional().meta(Unrestricted3)
|
|
928
|
+
}).meta(
|
|
929
|
+
{ id: "EntitlementTypeFieldsCredits", "x-revturbine-schema-persistence": Transient3, "x-revturbine-schema-exposure": External3 }
|
|
930
|
+
);
|
|
931
|
+
var EntitlementTypeFieldsSeatSchema = z6.looseObject({
|
|
932
|
+
kind: z6.literal("seat").meta(Unrestricted3),
|
|
933
|
+
included_seats: z6.union([z6.number(), z6.literal("unlimited")]).optional().meta(Unrestricted3),
|
|
934
|
+
// Authored configs already carry `null` here; plan 72 treats null as the
|
|
935
|
+
// canonical "unlimited". The 999999 sentinel is an export-side artifact.
|
|
936
|
+
max_seats: z6.union([z6.number(), z6.literal("unlimited")]).nullable().optional().meta(Unrestricted3),
|
|
937
|
+
seat_type: z6.string().optional().meta(Unrestricted3)
|
|
938
|
+
}).meta(
|
|
939
|
+
{ id: "EntitlementTypeFieldsSeat", "x-revturbine-schema-persistence": Transient3, "x-revturbine-schema-exposure": External3 }
|
|
940
|
+
);
|
|
941
|
+
var EntitlementTypeFieldsUntypedSchema = z6.looseObject({}).meta(
|
|
942
|
+
{ id: "EntitlementTypeFieldsUntyped", "x-revturbine-schema-persistence": Transient3, "x-revturbine-schema-exposure": External3 }
|
|
943
|
+
);
|
|
944
|
+
var ENTITLEMENT_TYPE_FIELDS_VARIANTS = [
|
|
945
|
+
EntitlementTypeFieldsFeatureSchema,
|
|
946
|
+
EntitlementTypeFieldsCapabilityTierSchema,
|
|
947
|
+
EntitlementTypeFieldsUsageLimitSchema,
|
|
948
|
+
EntitlementTypeFieldsPricePerUnitSchema,
|
|
949
|
+
EntitlementTypeFieldsRateLimitSchema,
|
|
950
|
+
EntitlementTypeFieldsCreditsSchema,
|
|
951
|
+
EntitlementTypeFieldsSeatSchema
|
|
952
|
+
];
|
|
953
|
+
var EntitlementTypeFieldsSchema = z6.union([...ENTITLEMENT_TYPE_FIELDS_VARIANTS, EntitlementTypeFieldsUntypedSchema]).meta(
|
|
954
|
+
{ id: "EntitlementTypeFields", "x-revturbine-schema-persistence": Transient3, "x-revturbine-schema-exposure": External3 }
|
|
955
|
+
);
|
|
795
956
|
var EntitlementSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(AnchorFields).merge(VersionFields).extend({
|
|
796
957
|
anchor_id: z6.string().min(1).meta({ ...Unrestricted3, readOnly: true }),
|
|
797
958
|
name: NameField.meta(Unrestricted3),
|
|
@@ -813,25 +974,11 @@ var EntitlementSchema = IdField.merge(TimestampFields).merge(TenantIdField).merg
|
|
|
813
974
|
id: "Entitlement",
|
|
814
975
|
"x-revturbine-schema-persistence": Persisted3,
|
|
815
976
|
"x-revturbine-schema-exposure": External3,
|
|
977
|
+
...PLAYBOOK_SDK_FACETS2,
|
|
816
978
|
...namedIdentity()
|
|
817
979
|
}
|
|
818
980
|
);
|
|
819
981
|
var EntitlementAnchorSchema = makeAnchor("EntitlementAnchor");
|
|
820
|
-
var PlanEntitlementSchema = TenantIdField.merge(AnchorFields).merge(VersionFields).extend({
|
|
821
|
-
handle: HandleField.meta({ ...Unrestricted3, readOnly: true }),
|
|
822
|
-
id: z6.number().int().meta({ ...Unrestricted3, readOnly: true }),
|
|
823
|
-
plan_id: z6.string().min(1).meta(Unrestricted3),
|
|
824
|
-
entitlement_id: z6.string().min(1).meta(Unrestricted3),
|
|
825
|
-
value: z6.union([z6.boolean(), z6.number(), z6.string()]).meta(Unrestricted3),
|
|
826
|
-
override_label: z6.string().max(200).optional().meta(Unrestricted3)
|
|
827
|
-
}).meta(
|
|
828
|
-
{
|
|
829
|
-
id: "PlanEntitlement",
|
|
830
|
-
"x-revturbine-schema-persistence": Persisted3,
|
|
831
|
-
"x-revturbine-schema-exposure": Internal2,
|
|
832
|
-
...mintedIdentity()
|
|
833
|
-
}
|
|
834
|
-
);
|
|
835
982
|
var EntitlementRuleSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(AnchorFields).merge(VersionFields).extend({
|
|
836
983
|
anchor_id: z6.string().min(1).meta({ ...Unrestricted3, readOnly: true }),
|
|
837
984
|
handle: HandleField.meta({ ...Unrestricted3, readOnly: true }),
|
|
@@ -854,6 +1001,12 @@ var EntitlementRuleSchema = IdField.merge(TimestampFields).merge(TenantIdField).
|
|
|
854
1001
|
// Type-specific fields (populated based on entitlement type)
|
|
855
1002
|
limit_value: z6.union([z6.number(), z6.literal("unlimited")]).optional().meta(Unrestricted3),
|
|
856
1003
|
enforcement: EnforcementModeSchema.optional().meta(Unrestricted3),
|
|
1004
|
+
// Usage-warning emitter (plan 138 REQ-13): the percent at which this rule
|
|
1005
|
+
// emits a usage-warning crossing event. 10% increments so a placement's
|
|
1006
|
+
// `threshold_percent` (same field type) can align with — "should match one
|
|
1007
|
+
// of those global values" (placement-studio-ui.md §3.4). Optional; a rule
|
|
1008
|
+
// with no warning threshold emits none.
|
|
1009
|
+
warning_threshold_percent: ThresholdPercentField.optional().meta(Unrestricted3),
|
|
857
1010
|
overage_price_ref: z6.string().optional().meta(Unrestricted3),
|
|
858
1011
|
grace_period_hours: z6.number().int().min(0).optional().meta(Unrestricted3),
|
|
859
1012
|
tier_value: z6.string().optional().meta(Unrestricted3),
|
|
@@ -873,6 +1026,7 @@ var EntitlementRuleSchema = IdField.merge(TimestampFields).merge(TenantIdField).
|
|
|
873
1026
|
id: "EntitlementRule",
|
|
874
1027
|
"x-revturbine-schema-persistence": Persisted3,
|
|
875
1028
|
"x-revturbine-schema-exposure": Internal2,
|
|
1029
|
+
...PLAYBOOK_SDK_FACETS2,
|
|
876
1030
|
// Bucket 2: a rule IS its scope (entitlement + segments + targets); its
|
|
877
1031
|
// limit/enforcement is the mutable payload. Behaviour-only edits coalesce
|
|
878
1032
|
// as the same rule; a scope edit is a new rule identity (plan 121 REQ-3).
|
|
@@ -930,12 +1084,12 @@ var EntitlementRuleVariantSchema = IdField.merge(TimestampFields).merge(TenantId
|
|
|
930
1084
|
id: "EntitlementRuleVariant",
|
|
931
1085
|
"x-revturbine-schema-persistence": Persisted3,
|
|
932
1086
|
"x-revturbine-schema-exposure": Internal2,
|
|
1087
|
+
...PENDING_PLAYBOOK_FACETS,
|
|
933
1088
|
...mintedIdentity()
|
|
934
1089
|
}
|
|
935
1090
|
);
|
|
936
1091
|
var EntitlementWriteSchema = toWritableSchema(EntitlementSchema);
|
|
937
1092
|
var EntitlementRuleWriteSchema = toWritableSchema(EntitlementRuleSchema);
|
|
938
|
-
var PlanEntitlementWriteSchema = toWritableSchema(PlanEntitlementSchema);
|
|
939
1093
|
var entitlementPaths = {
|
|
940
1094
|
"/api/entitlement-anchors": {
|
|
941
1095
|
get: operation({
|
|
@@ -1074,56 +1228,26 @@ var entitlementPaths = {
|
|
|
1074
1228
|
responses: { "201": { description: "Created", content: { "application/json": { schema: EntitlementRuleVariantSchema } } } },
|
|
1075
1229
|
"x-revturbine-operation": { exposure: "external", resource: "entitlement-rule-variants", persistence: { table: "entitlementRuleVariants", mode: "create" } }
|
|
1076
1230
|
})
|
|
1077
|
-
},
|
|
1078
|
-
"/api/plan-entitlements": {
|
|
1079
|
-
get: operation({
|
|
1080
|
-
operationId: "listPlanEntitlements",
|
|
1081
|
-
requestParams: { query: ListQueryParamsSchema },
|
|
1082
|
-
summary: "List plan \u2194 entitlement mappings",
|
|
1083
|
-
tags: ["entitlements"],
|
|
1084
|
-
responses: { "200": { description: "Plan entitlement list", content: { "application/json": { schema: ListEnvelope(PlanEntitlementSchema) } } } },
|
|
1085
|
-
"x-revturbine-operation": { exposure: "internal", resource: "plan-entitlements", persistence: { table: "planEntitlements", mode: "list" } }
|
|
1086
|
-
}),
|
|
1087
|
-
post: operation({
|
|
1088
|
-
operationId: "createPlanEntitlement",
|
|
1089
|
-
summary: "Create plan \u2194 entitlement mapping",
|
|
1090
|
-
tags: ["entitlements"],
|
|
1091
|
-
requestBody: { required: true, content: { "application/json": { schema: toCreateSchema(PlanEntitlementSchema) } } },
|
|
1092
|
-
responses: { "201": { description: "Created", content: { "application/json": { schema: PlanEntitlementSchema } } } },
|
|
1093
|
-
"x-revturbine-operation": { exposure: "internal", resource: "plan-entitlements", persistence: { table: "planEntitlements", mode: "create" } }
|
|
1094
|
-
})
|
|
1095
|
-
},
|
|
1096
|
-
"/api/plan-entitlements/{id}": {
|
|
1097
|
-
get: operation({
|
|
1098
|
-
operationId: "getPlanEntitlement",
|
|
1099
|
-
requestParams: { path: z6.object({ id: z6.string() }) },
|
|
1100
|
-
summary: "Get plan \u2194 entitlement mapping",
|
|
1101
|
-
tags: ["entitlements"],
|
|
1102
|
-
responses: { "200": { description: "Plan entitlement detail", content: { "application/json": { schema: PlanEntitlementSchema } } } },
|
|
1103
|
-
"x-revturbine-operation": { exposure: "internal", resource: "plan-entitlements", persistence: { table: "planEntitlements", mode: "get" } }
|
|
1104
|
-
}),
|
|
1105
|
-
put: operation({
|
|
1106
|
-
operationId: "updatePlanEntitlement",
|
|
1107
|
-
requestParams: { path: z6.object({ id: z6.string() }) },
|
|
1108
|
-
summary: "Update plan \u2194 entitlement mapping",
|
|
1109
|
-
tags: ["entitlements"],
|
|
1110
|
-
requestBody: { required: true, content: { "application/json": { schema: PlanEntitlementWriteSchema } } },
|
|
1111
|
-
responses: { "200": { description: "Updated", content: { "application/json": { schema: PlanEntitlementSchema } } } },
|
|
1112
|
-
"x-revturbine-operation": { exposure: "internal", resource: "plan-entitlements", persistence: { table: "planEntitlements", mode: "update" } }
|
|
1113
|
-
}),
|
|
1114
|
-
delete: operation({
|
|
1115
|
-
operationId: "deletePlanEntitlement",
|
|
1116
|
-
requestParams: { path: z6.object({ id: z6.string() }) },
|
|
1117
|
-
summary: "Delete plan \u2194 entitlement mapping",
|
|
1118
|
-
tags: ["entitlements"],
|
|
1119
|
-
responses: { "204": { description: "Deleted" }, default: { description: "Error", content: { "application/json": { schema: ErrorEnvelope } } } },
|
|
1120
|
-
"x-revturbine-operation": { exposure: "internal", resource: "plan-entitlements", persistence: { table: "planEntitlements", mode: "delete" } }
|
|
1121
|
-
})
|
|
1122
1231
|
}
|
|
1123
1232
|
};
|
|
1124
1233
|
var { Unrestricted: Unrestricted4 } = DataClassification;
|
|
1125
1234
|
var { Persisted: Persisted4, Transient: Transient4 } = SchemaPersistence;
|
|
1126
1235
|
var { External: External4, Internal: Internal3 } = SchemaExposure;
|
|
1236
|
+
var PLAYBOOK_SDK_FACETS3 = schemaFacets(SchemaContext.Playbook, { sdkInput: true });
|
|
1237
|
+
var PENDING_PLAYBOOK_FACETS2 = schemaFacets(SchemaContext.Playbook, {
|
|
1238
|
+
inConfig: false,
|
|
1239
|
+
sdkInput: false
|
|
1240
|
+
});
|
|
1241
|
+
var EMBEDDED_PLAYBOOK_SDK_FACETS = schemaFacets(SchemaContext.Playbook, {
|
|
1242
|
+
inConfig: false,
|
|
1243
|
+
sdkInput: true
|
|
1244
|
+
});
|
|
1245
|
+
var DISCOVERED_PLAYBOOK_FACETS = schemaFacets(SchemaContext.Playbook, {
|
|
1246
|
+
inConfig: false,
|
|
1247
|
+
sdkInput: false,
|
|
1248
|
+
source: SchemaSource.Runtime
|
|
1249
|
+
});
|
|
1250
|
+
var PlacementQualifierSchema = z7.enum(["none_always_on", "overage_vs_upgrade", "time_bound", "payment_failed", "payment_at_risk"]);
|
|
1127
1251
|
var PlacementCategorySchema = z7.enum([
|
|
1128
1252
|
"fixed",
|
|
1129
1253
|
"gated_feature",
|
|
@@ -1152,7 +1276,8 @@ var SurfaceTypeCapRuleSchema = z7.object({
|
|
|
1152
1276
|
id: "SurfaceTypeCapRule",
|
|
1153
1277
|
"x-revturbine-schema-persistence": Persisted4,
|
|
1154
1278
|
"x-revturbine-schema-exposure": External4,
|
|
1155
|
-
"x-revturbine-data-classification": "operational"
|
|
1279
|
+
"x-revturbine-data-classification": "operational",
|
|
1280
|
+
...EMBEDDED_PLAYBOOK_SDK_FACETS
|
|
1156
1281
|
}
|
|
1157
1282
|
);
|
|
1158
1283
|
var CtaPathTypeSchema = z7.enum([
|
|
@@ -1187,12 +1312,12 @@ var PlacementSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(
|
|
|
1187
1312
|
surface_slot_id: z7.string().optional().meta(Unrestricted4),
|
|
1188
1313
|
entitlement_id: z7.string().optional().meta(Unrestricted4),
|
|
1189
1314
|
tier_threshold: z7.string().optional().meta(Unrestricted4),
|
|
1190
|
-
threshold_percent:
|
|
1315
|
+
threshold_percent: ThresholdPercentField.optional().meta(Unrestricted4),
|
|
1191
1316
|
trial_type: z7.enum(["free", "reverse"]).optional().meta(Unrestricted4),
|
|
1192
1317
|
trigger_type: z7.string().optional().meta(Unrestricted4),
|
|
1193
1318
|
trial_progress_percent: z7.number().min(0).max(100).optional().meta(Unrestricted4),
|
|
1194
1319
|
days_before_end: z7.number().int().min(0).optional().meta(Unrestricted4),
|
|
1195
|
-
qualifier:
|
|
1320
|
+
qualifier: PlacementQualifierSchema.optional().meta(Unrestricted4),
|
|
1196
1321
|
activation_window_start: z7.string().datetime().optional().meta(Unrestricted4),
|
|
1197
1322
|
activation_window_end: z7.string().datetime().optional().meta(Unrestricted4),
|
|
1198
1323
|
metadata: MetadataField.meta(Unrestricted4)
|
|
@@ -1201,10 +1326,31 @@ var PlacementSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(
|
|
|
1201
1326
|
id: "Placement",
|
|
1202
1327
|
"x-revturbine-schema-persistence": Persisted4,
|
|
1203
1328
|
"x-revturbine-schema-exposure": External4,
|
|
1329
|
+
...PLAYBOOK_SDK_FACETS3,
|
|
1204
1330
|
...namedIdentity()
|
|
1205
1331
|
}
|
|
1206
1332
|
);
|
|
1207
1333
|
var PlacementAnchorSchema = makeAnchor("PlacementAnchor");
|
|
1334
|
+
var PlacementWarningCodeSchema = z7.enum(["threshold_not_emitted"]).meta(
|
|
1335
|
+
{ id: "PlacementWarningCode", "x-revturbine-schema-persistence": Transient4, "x-revturbine-schema-exposure": External4 }
|
|
1336
|
+
);
|
|
1337
|
+
var PlacementWarningSchema = z7.object({
|
|
1338
|
+
code: PlacementWarningCodeSchema.meta(Unrestricted4),
|
|
1339
|
+
message: z7.string().min(1).meta(Unrestricted4),
|
|
1340
|
+
/** Optional field path the warning relates to (e.g. `['threshold_percent']`). */
|
|
1341
|
+
path: z7.array(z7.union([z7.string(), z7.number().int()])).optional().meta(Unrestricted4)
|
|
1342
|
+
}).meta(
|
|
1343
|
+
{ id: "PlacementWarning", "x-revturbine-schema-persistence": Transient4, "x-revturbine-schema-exposure": External4 }
|
|
1344
|
+
);
|
|
1345
|
+
var PlacementWriteResponseSchema = PlacementSchema.extend({
|
|
1346
|
+
warnings: z7.array(PlacementWarningSchema).optional().meta(Unrestricted4)
|
|
1347
|
+
}).meta(
|
|
1348
|
+
{
|
|
1349
|
+
id: "PlacementWriteResponse",
|
|
1350
|
+
"x-revturbine-schema-persistence": Transient4,
|
|
1351
|
+
"x-revturbine-schema-exposure": External4
|
|
1352
|
+
}
|
|
1353
|
+
);
|
|
1208
1354
|
var CtaObjectSchema = z7.object({
|
|
1209
1355
|
label: z7.string().min(1).max(200).meta(Unrestricted4),
|
|
1210
1356
|
cta_path_type: CtaPathTypeSchema.meta(Unrestricted4),
|
|
@@ -1239,6 +1385,7 @@ var PlacementPayloadSchema = IdField.merge(TimestampFields).merge(TenantIdField)
|
|
|
1239
1385
|
id: "PlacementPayload",
|
|
1240
1386
|
"x-revturbine-schema-persistence": Persisted4,
|
|
1241
1387
|
"x-revturbine-schema-exposure": External4,
|
|
1388
|
+
...PLAYBOOK_SDK_FACETS3,
|
|
1242
1389
|
// KENT-REVIEW (plan 121): defaulted to Bucket 2 on (placement_id, drag_order)
|
|
1243
1390
|
// — a payload's ordinal within its placement. This is the strongest Bucket-3
|
|
1244
1391
|
// candidate (reordering a key edit would fork history); if lineage must survive
|
|
@@ -1262,6 +1409,7 @@ var PlacementVariantSchema = IdField.merge(TimestampFields).merge(TenantIdField)
|
|
|
1262
1409
|
id: "PlacementVariant",
|
|
1263
1410
|
"x-revturbine-schema-persistence": Persisted4,
|
|
1264
1411
|
"x-revturbine-schema-exposure": Internal3,
|
|
1412
|
+
...PENDING_PLAYBOOK_FACETS2,
|
|
1265
1413
|
...mintedIdentity()
|
|
1266
1414
|
}
|
|
1267
1415
|
);
|
|
@@ -1279,6 +1427,7 @@ var SurfaceSlotSchema = IdField.merge(TimestampFields).merge(TenantIdField).merg
|
|
|
1279
1427
|
id: "SurfaceSlot",
|
|
1280
1428
|
"x-revturbine-schema-persistence": Persisted4,
|
|
1281
1429
|
"x-revturbine-schema-exposure": External4,
|
|
1430
|
+
...DISCOVERED_PLAYBOOK_FACETS,
|
|
1282
1431
|
...namedIdentity("surface_slot_handle")
|
|
1283
1432
|
}
|
|
1284
1433
|
);
|
|
@@ -1312,7 +1461,7 @@ var placementPaths = {
|
|
|
1312
1461
|
summary: "Create placement",
|
|
1313
1462
|
tags: ["placements"],
|
|
1314
1463
|
requestBody: { required: true, content: { "application/json": { schema: toCreateSchema(PlacementSchema) } } },
|
|
1315
|
-
responses: { "201": { description: "Created", content: { "application/json": { schema:
|
|
1464
|
+
responses: { "201": { description: "Created", content: { "application/json": { schema: PlacementWriteResponseSchema } } } },
|
|
1316
1465
|
"x-revturbine-operation": { exposure: "external", resource: "placements", persistence: { table: "placementVersions", mode: "create" } }
|
|
1317
1466
|
})
|
|
1318
1467
|
},
|
|
@@ -1331,7 +1480,7 @@ var placementPaths = {
|
|
|
1331
1480
|
summary: "Update placement",
|
|
1332
1481
|
tags: ["placements"],
|
|
1333
1482
|
requestBody: { required: true, content: { "application/json": { schema: PlacementWriteSchema } } },
|
|
1334
|
-
responses: { "200": { description: "Updated", content: { "application/json": { schema:
|
|
1483
|
+
responses: { "200": { description: "Updated", content: { "application/json": { schema: PlacementWriteResponseSchema } } } },
|
|
1335
1484
|
"x-revturbine-operation": { exposure: "external", resource: "placements", persistence: { table: "placementVersions", mode: "update" } }
|
|
1336
1485
|
}),
|
|
1337
1486
|
delete: operation({
|
|
@@ -1510,6 +1659,27 @@ var UserContextSchema = IdField.merge(TenantIdField).merge(TimestampFields).exte
|
|
|
1510
1659
|
/** Aggregate usage entries across all instances, keyed by handle. */
|
|
1511
1660
|
usage: z8.record(z8.string(), UserUsageEntrySchema).default({}).meta(Unrestricted5),
|
|
1512
1661
|
trial: UserTrialStatusSchema.optional().meta(Unrestricted5),
|
|
1662
|
+
/**
|
|
1663
|
+
* Billing-recovery signals (account-level). `payment_failed` reflects a
|
|
1664
|
+
* hard payment failure (e.g. Stripe `invoice.payment_failed`);
|
|
1665
|
+
* `payment_at_risk` an expiring / missing-backup payment method. They
|
|
1666
|
+
* drive the Retention `qualifier` placement triggers
|
|
1667
|
+
* (placement-studio-ui.md §3.7) — the SDK surfaces them onto the
|
|
1668
|
+
* PlanProvider state the placement resolver reads. Omitted for users in
|
|
1669
|
+
* good standing; a qualifier gate reads `=== true`, so an absent signal
|
|
1670
|
+
* never fires the recovery placement.
|
|
1671
|
+
*/
|
|
1672
|
+
payment_failed: z8.boolean().optional().meta(Unrestricted5),
|
|
1673
|
+
payment_at_risk: z8.boolean().optional().meta(Unrestricted5),
|
|
1674
|
+
/**
|
|
1675
|
+
* The user's current tier per `capability_tier` entitlement, keyed by
|
|
1676
|
+
* entitlement handle → tier handle (plan 138 TASK-4). Drives the
|
|
1677
|
+
* `entitlement_gate.tier_threshold` placement trigger: the SDK surfaces
|
|
1678
|
+
* this onto the EntitlementProvider state, and the resolver ranks the
|
|
1679
|
+
* current tier against the entitlement's ordered ladder. Omitted for a
|
|
1680
|
+
* user holding no tier (ranks below every threshold).
|
|
1681
|
+
*/
|
|
1682
|
+
tiers: z8.record(z8.string(), z8.string()).optional().meta(Unrestricted5),
|
|
1513
1683
|
/** Account-level entitlements, keyed by handle. */
|
|
1514
1684
|
entitlements: z8.record(z8.string(), z8.union([z8.boolean(), EntitlementGrantSchema])).default({}).meta(Unrestricted5),
|
|
1515
1685
|
/** Per-instance breakdowns when the account has multiple product instances. */
|
|
@@ -1594,6 +1764,9 @@ var userContextPaths = {
|
|
|
1594
1764
|
var { Unrestricted: Unrestricted6, Pii: Pii2 } = DataClassification;
|
|
1595
1765
|
var { Persisted: Persisted6, Transient: Transient6 } = SchemaPersistence;
|
|
1596
1766
|
var { Internal: Internal4 } = SchemaExposure;
|
|
1767
|
+
var CUSTOMER_OPERATIONS_FACETS = schemaFacets(SchemaContext.CustomerOperations, {
|
|
1768
|
+
sdkInput: false
|
|
1769
|
+
});
|
|
1597
1770
|
var IdentitySchema = z9.object({
|
|
1598
1771
|
external_id: z9.string().min(1).meta(Pii2),
|
|
1599
1772
|
traits: z9.record(z9.string(), z9.unknown()).default({}).meta(Pii2),
|
|
@@ -1654,6 +1827,7 @@ var CustomerOverrideSchema = IdField.merge(TimestampFields).merge(TenantIdField)
|
|
|
1654
1827
|
id: "CustomerOverride",
|
|
1655
1828
|
"x-revturbine-schema-persistence": Persisted6,
|
|
1656
1829
|
"x-revturbine-schema-exposure": Internal4,
|
|
1830
|
+
...CUSTOMER_OPERATIONS_FACETS,
|
|
1657
1831
|
// KENT-REVIEW (plan 121): defaulted to Bucket 2 on (customer_id, override_type,
|
|
1658
1832
|
// target_id) — one override per customer per target per type. Note the optional
|
|
1659
1833
|
// `customer_id_list` (multi-customer overrides) complicates the tuple; confirm
|
|
@@ -1752,6 +1926,11 @@ var customerPaths = {
|
|
|
1752
1926
|
var { Unrestricted: Unrestricted7 } = DataClassification;
|
|
1753
1927
|
var { Persisted: Persisted7, Transient: Transient7 } = SchemaPersistence;
|
|
1754
1928
|
var { Internal: Internal5 } = SchemaExposure;
|
|
1929
|
+
var PLAYBOOK_SDK_FACETS4 = schemaFacets(SchemaContext.Playbook, { sdkInput: true });
|
|
1930
|
+
var PENDING_PLAYBOOK_SDK_FACETS = schemaFacets(SchemaContext.Playbook, {
|
|
1931
|
+
inConfig: false,
|
|
1932
|
+
sdkInput: true
|
|
1933
|
+
});
|
|
1755
1934
|
var DimensionCategorySchema = z10.enum(["default", "custom"]).meta(
|
|
1756
1935
|
{ id: "DimensionCategory", "x-revturbine-schema-persistence": Transient7, "x-revturbine-schema-exposure": Internal5 }
|
|
1757
1936
|
);
|
|
@@ -1775,6 +1954,7 @@ var SegmentDimensionSchema = IdField.merge(TimestampFields).merge(TenantIdField)
|
|
|
1775
1954
|
id: "SegmentDimension",
|
|
1776
1955
|
"x-revturbine-schema-persistence": Persisted7,
|
|
1777
1956
|
"x-revturbine-schema-exposure": Internal5,
|
|
1957
|
+
...PENDING_PLAYBOOK_SDK_FACETS,
|
|
1778
1958
|
...namedIdentity()
|
|
1779
1959
|
}
|
|
1780
1960
|
);
|
|
@@ -1792,6 +1972,7 @@ var SegmentValueSchema = IdField.merge(TimestampFields).merge(TenantIdField).mer
|
|
|
1792
1972
|
id: "SegmentValue",
|
|
1793
1973
|
"x-revturbine-schema-persistence": Persisted7,
|
|
1794
1974
|
"x-revturbine-schema-exposure": Internal5,
|
|
1975
|
+
...PENDING_PLAYBOOK_SDK_FACETS,
|
|
1795
1976
|
...namedIdentity()
|
|
1796
1977
|
}
|
|
1797
1978
|
);
|
|
@@ -1810,6 +1991,7 @@ var SegmentSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(An
|
|
|
1810
1991
|
id: "Segment",
|
|
1811
1992
|
"x-revturbine-schema-persistence": Persisted7,
|
|
1812
1993
|
"x-revturbine-schema-exposure": Internal5,
|
|
1994
|
+
...PLAYBOOK_SDK_FACETS4,
|
|
1813
1995
|
...namedIdentity()
|
|
1814
1996
|
}
|
|
1815
1997
|
);
|
|
@@ -1923,6 +2105,20 @@ var segmentPaths = {
|
|
|
1923
2105
|
var { Unrestricted: Unrestricted8 } = DataClassification;
|
|
1924
2106
|
var { Persisted: Persisted8, Transient: Transient8 } = SchemaPersistence;
|
|
1925
2107
|
var { External: External6 } = SchemaExposure;
|
|
2108
|
+
var PLAYBOOK_SDK_FACETS5 = schemaFacets(SchemaContext.Playbook, { sdkInput: true });
|
|
2109
|
+
var PENDING_PLAYBOOK_FACETS3 = schemaFacets(SchemaContext.Playbook, {
|
|
2110
|
+
inConfig: false,
|
|
2111
|
+
sdkInput: false
|
|
2112
|
+
});
|
|
2113
|
+
var EMBEDDED_PLAYBOOK_SDK_FACETS2 = schemaFacets(SchemaContext.Playbook, {
|
|
2114
|
+
inConfig: false,
|
|
2115
|
+
sdkInput: true
|
|
2116
|
+
});
|
|
2117
|
+
var PLAYBOOK_VOCABULARY_FACETS = schemaFacets(SchemaContext.Playbook, {
|
|
2118
|
+
inConfig: false,
|
|
2119
|
+
sdkInput: true,
|
|
2120
|
+
source: SchemaSource.CodeConstant
|
|
2121
|
+
});
|
|
1926
2122
|
var MessageSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(AnchorFields).merge(VersionFields).extend({
|
|
1927
2123
|
anchor_id: z11.string().min(1).meta({ ...Unrestricted8, readOnly: true }),
|
|
1928
2124
|
handle: HandleField.meta({ ...Unrestricted8, readOnly: true }),
|
|
@@ -1933,7 +2129,7 @@ var MessageSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(An
|
|
|
1933
2129
|
template_variables: z11.array(z11.string()).default([]).meta(Unrestricted8),
|
|
1934
2130
|
metadata: MetadataField.meta(Unrestricted8)
|
|
1935
2131
|
}).meta(
|
|
1936
|
-
{ id: "Message", "x-revturbine-schema-persistence": Persisted8, "x-revturbine-schema-exposure": External6, ...mintedIdentity() }
|
|
2132
|
+
{ id: "Message", "x-revturbine-schema-persistence": Persisted8, "x-revturbine-schema-exposure": External6, ...PENDING_PLAYBOOK_FACETS3, ...mintedIdentity() }
|
|
1937
2133
|
);
|
|
1938
2134
|
var CtaPathSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(AnchorFields).merge(VersionFields).extend({
|
|
1939
2135
|
anchor_id: z11.string().min(1).meta({ ...Unrestricted8, readOnly: true }),
|
|
@@ -1945,7 +2141,7 @@ var CtaPathSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(An
|
|
|
1945
2141
|
config_fields: z11.record(z11.string(), z11.unknown()).default({}).meta(Unrestricted8),
|
|
1946
2142
|
metadata: MetadataField.meta(Unrestricted8)
|
|
1947
2143
|
}).meta(
|
|
1948
|
-
{ id: "CtaPath", "x-revturbine-schema-persistence": Persisted8, "x-revturbine-schema-exposure": External6, ...namedIdentity() }
|
|
2144
|
+
{ id: "CtaPath", "x-revturbine-schema-persistence": Persisted8, "x-revturbine-schema-exposure": External6, ...PLAYBOOK_SDK_FACETS5, ...namedIdentity() }
|
|
1949
2145
|
);
|
|
1950
2146
|
var CtaPathAnchorSchema = makeAnchor("CtaPathAnchor");
|
|
1951
2147
|
var TemplateFieldTypeSchema = z11.enum([
|
|
@@ -1964,7 +2160,7 @@ var TemplateFieldTypeSchema = z11.enum([
|
|
|
1964
2160
|
"dropdown",
|
|
1965
2161
|
"json"
|
|
1966
2162
|
]).meta(
|
|
1967
|
-
{ id: "TemplateFieldType", "x-revturbine-schema-persistence": Persisted8, "x-revturbine-schema-exposure": External6 }
|
|
2163
|
+
{ id: "TemplateFieldType", "x-revturbine-schema-persistence": Persisted8, "x-revturbine-schema-exposure": External6, ...PLAYBOOK_VOCABULARY_FACETS }
|
|
1968
2164
|
);
|
|
1969
2165
|
var FieldDefinitionSchema = z11.object({
|
|
1970
2166
|
name: z11.string().min(1),
|
|
@@ -1979,7 +2175,7 @@ var FieldDefinitionSchema = z11.object({
|
|
|
1979
2175
|
order: z11.number().int().min(0).optional(),
|
|
1980
2176
|
help_text: z11.string().max(500).optional()
|
|
1981
2177
|
}).meta(
|
|
1982
|
-
{ id: "FieldDefinition", "x-revturbine-schema-persistence": Persisted8, "x-revturbine-schema-exposure": External6 }
|
|
2178
|
+
{ id: "FieldDefinition", "x-revturbine-schema-persistence": Persisted8, "x-revturbine-schema-exposure": External6, ...EMBEDDED_PLAYBOOK_SDK_FACETS2 }
|
|
1983
2179
|
);
|
|
1984
2180
|
var SurfaceTemplateSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(AnchorFields).merge(VersionFields).extend({
|
|
1985
2181
|
anchor_id: z11.string().min(1).meta({ ...Unrestricted8, readOnly: true }),
|
|
@@ -1989,7 +2185,7 @@ var SurfaceTemplateSchema = IdField.merge(TimestampFields).merge(TenantIdField).
|
|
|
1989
2185
|
field_definitions: z11.array(FieldDefinitionSchema).default([]).meta(Unrestricted8),
|
|
1990
2186
|
description: DescriptionField.meta(Unrestricted8)
|
|
1991
2187
|
}).meta(
|
|
1992
|
-
{ id: "SurfaceTemplate", "x-revturbine-schema-persistence": Persisted8, "x-revturbine-schema-exposure": External6, ...namedIdentity() }
|
|
2188
|
+
{ id: "SurfaceTemplate", "x-revturbine-schema-persistence": Persisted8, "x-revturbine-schema-exposure": External6, ...PLAYBOOK_SDK_FACETS5, ...namedIdentity() }
|
|
1993
2189
|
);
|
|
1994
2190
|
var SurfaceTemplateAnchorSchema = makeAnchor("SurfaceTemplateAnchor");
|
|
1995
2191
|
var MessageBlockRecordSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(AnchorFields).merge(VersionFields).extend({
|
|
@@ -2005,7 +2201,7 @@ var MessageBlockRecordSchema = IdField.merge(TimestampFields).merge(TenantIdFiel
|
|
|
2005
2201
|
notes: z11.string().max(1e3).optional().meta(Unrestricted8),
|
|
2006
2202
|
used_in_count: z11.number().int().min(0).default(0).meta({ ...Unrestricted8, readOnly: true })
|
|
2007
2203
|
}).meta(
|
|
2008
|
-
{ id: "MessageBlockRecord", "x-revturbine-schema-persistence": Persisted8, "x-revturbine-schema-exposure": External6, ...namedIdentity() }
|
|
2204
|
+
{ id: "MessageBlockRecord", "x-revturbine-schema-persistence": Persisted8, "x-revturbine-schema-exposure": External6, ...PLAYBOOK_SDK_FACETS5, ...namedIdentity() }
|
|
2009
2205
|
);
|
|
2010
2206
|
var MessageBlockRecordAnchorSchema = makeAnchor("MessageBlockRecordAnchor");
|
|
2011
2207
|
var ContentPayloadSegmentEntrySchema = z11.object({
|
|
@@ -2129,6 +2325,7 @@ var contentPaths = {
|
|
|
2129
2325
|
var { Unrestricted: Unrestricted9, Pii: Pii3 } = DataClassification;
|
|
2130
2326
|
var { Persisted: Persisted9, Transient: Transient9 } = SchemaPersistence;
|
|
2131
2327
|
var { Internal: Internal6, External: External7 } = SchemaExposure;
|
|
2328
|
+
var BRANDING_FACETS = schemaFacets(SchemaContext.Branding, { sdkInput: false });
|
|
2132
2329
|
var ThemeSchema = z12.object({
|
|
2133
2330
|
id: z12.string().min(1).meta({ ...Unrestricted9, readOnly: true }),
|
|
2134
2331
|
name: z12.string().min(1).max(120).meta(Unrestricted9),
|
|
@@ -2138,7 +2335,8 @@ var ThemeSchema = z12.object({
|
|
|
2138
2335
|
{
|
|
2139
2336
|
id: "Theme",
|
|
2140
2337
|
"x-revturbine-schema-persistence": Persisted9,
|
|
2141
|
-
"x-revturbine-schema-exposure": External7
|
|
2338
|
+
"x-revturbine-schema-exposure": External7,
|
|
2339
|
+
...BRANDING_FACETS
|
|
2142
2340
|
}
|
|
2143
2341
|
);
|
|
2144
2342
|
var UiPreferenceSchema = IdField.merge(TimestampFields).extend({
|
|
@@ -2642,6 +2840,13 @@ var EventIngestResponseSchema = z14.object({
|
|
|
2642
2840
|
}
|
|
2643
2841
|
);
|
|
2644
2842
|
var MAX_TRACK_EVENTS_PER_BATCH = 500;
|
|
2843
|
+
var EventOriginSchema = z14.enum(["explicit", "automatic", "derived", "raw"]).meta(
|
|
2844
|
+
{
|
|
2845
|
+
id: "EventOrigin",
|
|
2846
|
+
"x-revturbine-schema-persistence": Transient11,
|
|
2847
|
+
"x-revturbine-schema-exposure": External9
|
|
2848
|
+
}
|
|
2849
|
+
);
|
|
2645
2850
|
var TrackEventSchema = z14.object({
|
|
2646
2851
|
environment_id: z14.string().min(1).meta(Unrestricted11),
|
|
2647
2852
|
user_id: z14.string().min(1).meta(Pii4),
|
|
@@ -2655,7 +2860,28 @@ var TrackEventSchema = z14.object({
|
|
|
2655
2860
|
request_id: z14.string().optional().meta(Unrestricted11),
|
|
2656
2861
|
experiment_id: z14.string().nullable().optional().meta(Unrestricted11),
|
|
2657
2862
|
variant_key: z14.string().nullable().optional().meta(Unrestricted11),
|
|
2658
|
-
tenant_id: z14.string().optional().meta(Unrestricted11)
|
|
2863
|
+
tenant_id: z14.string().optional().meta(Unrestricted11),
|
|
2864
|
+
// ── Lifted provenance ────────────────────────────────────────────────
|
|
2865
|
+
//
|
|
2866
|
+
// `properties` is a serialized JSON string, so anything left inside it is
|
|
2867
|
+
// readable via JSONExtract but unindexed and scan-costly — fine for a
|
|
2868
|
+
// forensic lookup, not for a dashboard that groups 90 days of events. The
|
|
2869
|
+
// four fields below are the ones analytics actually slices by, so they
|
|
2870
|
+
// get named columns.
|
|
2871
|
+
//
|
|
2872
|
+
// The asymmetry that decides this: an unused column costs bytes, while a
|
|
2873
|
+
// missing one costs a forward-only recreate of a populated datasource
|
|
2874
|
+
// (the Tinybird TS SDK cannot emit FORWARD_QUERY). Lift deliberately, and
|
|
2875
|
+
// route genuinely new high-volume event classes to their own datasource
|
|
2876
|
+
// rather than widening this one.
|
|
2877
|
+
/** Sortable unique id minted at capture. Carried now so historical rows have it if dedup ever moves off `request_id` — a destructive sorting-key change not worth paying for while storage-layer dedup already collapses re-delivery. */
|
|
2878
|
+
event_id: z14.string().nullable().optional().meta(Unrestricted11),
|
|
2879
|
+
/** See {@link EventOriginSchema}. Low cardinality; every scoring query filters on it. */
|
|
2880
|
+
origin: EventOriginSchema.nullable().optional().meta(Unrestricted11),
|
|
2881
|
+
/** Immutable Playbook version that produced the experience. The field that makes a past decision reproducible. */
|
|
2882
|
+
playbook_version: z14.string().nullable().optional().meta(Unrestricted11),
|
|
2883
|
+
/** Correlates every event caused by one decision — a join key, not a group-by. */
|
|
2884
|
+
decision_id: z14.string().nullable().optional().meta(Unrestricted11)
|
|
2659
2885
|
}).meta(
|
|
2660
2886
|
{
|
|
2661
2887
|
id: "TrackEvent",
|
|
@@ -2804,6 +3030,11 @@ var eventPaths = {
|
|
|
2804
3030
|
var { Unrestricted: Unrestricted12 } = DataClassification;
|
|
2805
3031
|
var { Persisted: Persisted12, Transient: Transient12 } = SchemaPersistence;
|
|
2806
3032
|
var { Internal: Internal9 } = SchemaExposure;
|
|
3033
|
+
var PLAYBOOK_SDK_FACETS6 = schemaFacets(SchemaContext.Playbook, { sdkInput: true });
|
|
3034
|
+
var PENDING_PLAYBOOK_SDK_FACETS2 = schemaFacets(SchemaContext.Playbook, {
|
|
3035
|
+
inConfig: false,
|
|
3036
|
+
sdkInput: true
|
|
3037
|
+
});
|
|
2807
3038
|
var TrialStatusSchema = z15.enum(["not_started", "active", "expired", "converted", "cancelled"]).meta(
|
|
2808
3039
|
{ id: "TrialStatus", "x-revturbine-schema-persistence": Transient12, "x-revturbine-schema-exposure": Internal9 }
|
|
2809
3040
|
);
|
|
@@ -2856,7 +3087,7 @@ var FreeTrialRuleCoreFieldsSchema = z15.object({
|
|
|
2856
3087
|
var FreeTrialRuleSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(AnchorFields).merge(VersionFields).extend({
|
|
2857
3088
|
anchor_id: z15.string().min(1).meta({ ...Unrestricted12, readOnly: true })
|
|
2858
3089
|
}).merge(FreeTrialRuleCoreFieldsSchema).meta(
|
|
2859
|
-
{ id: "FreeTrialRule", "x-revturbine-schema-persistence": Persisted12, "x-revturbine-schema-exposure": Internal9, ...namedIdentity() }
|
|
3090
|
+
{ id: "FreeTrialRule", "x-revturbine-schema-persistence": Persisted12, "x-revturbine-schema-exposure": Internal9, ...PLAYBOOK_SDK_FACETS6, ...namedIdentity() }
|
|
2860
3091
|
);
|
|
2861
3092
|
var FreeTrialRuleAnchorSchema = makeAnchor("FreeTrialRuleAnchor");
|
|
2862
3093
|
var ReverseTrialStartPolicySchema = z15.enum(["signup", "first_premium_access", "manual"]).meta(
|
|
@@ -2881,7 +3112,7 @@ var ReverseTrialRuleCoreFieldsSchema = z15.object({
|
|
|
2881
3112
|
var ReverseTrialRuleSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(AnchorFields).merge(VersionFields).extend({
|
|
2882
3113
|
anchor_id: z15.string().min(1).meta({ ...Unrestricted12, readOnly: true })
|
|
2883
3114
|
}).merge(ReverseTrialRuleCoreFieldsSchema).meta(
|
|
2884
|
-
{ id: "ReverseTrialRule", "x-revturbine-schema-persistence": Persisted12, "x-revturbine-schema-exposure": Internal9, ...namedIdentity() }
|
|
3115
|
+
{ id: "ReverseTrialRule", "x-revturbine-schema-persistence": Persisted12, "x-revturbine-schema-exposure": Internal9, ...PLAYBOOK_SDK_FACETS6, ...namedIdentity() }
|
|
2885
3116
|
);
|
|
2886
3117
|
var ReverseTrialRuleAnchorSchema = makeAnchor("ReverseTrialRuleAnchor");
|
|
2887
3118
|
var TrialLimitPolicySchema = z15.enum(["1_per_lifetime", "1_per_plan", "1_per_year", "unlimited"]).meta(
|
|
@@ -2894,13 +3125,13 @@ var FreeTrialSettingsSchema = IdField.merge(TimestampFields).merge(TenantIdField
|
|
|
2894
3125
|
trial_limit_policy: TrialLimitPolicySchema.default("1_per_lifetime").meta(Unrestricted12),
|
|
2895
3126
|
eligibility_scope: TrialEligibilityScopeSchema.default("per_customer").meta(Unrestricted12)
|
|
2896
3127
|
}).meta(
|
|
2897
|
-
{ id: "FreeTrialSettings", "x-revturbine-schema-persistence": Persisted12, "x-revturbine-schema-exposure": Internal9 }
|
|
3128
|
+
{ id: "FreeTrialSettings", "x-revturbine-schema-persistence": Persisted12, "x-revturbine-schema-exposure": Internal9, ...PENDING_PLAYBOOK_SDK_FACETS2 }
|
|
2898
3129
|
);
|
|
2899
3130
|
var ReverseTrialSettingsSchema = IdField.merge(TimestampFields).merge(TenantIdField).extend({
|
|
2900
3131
|
trial_limit_policy: TrialLimitPolicySchema.default("1_per_lifetime").meta(Unrestricted12),
|
|
2901
3132
|
eligibility_scope: TrialEligibilityScopeSchema.default("per_customer").meta(Unrestricted12)
|
|
2902
3133
|
}).meta(
|
|
2903
|
-
{ id: "ReverseTrialSettings", "x-revturbine-schema-persistence": Persisted12, "x-revturbine-schema-exposure": Internal9 }
|
|
3134
|
+
{ id: "ReverseTrialSettings", "x-revturbine-schema-persistence": Persisted12, "x-revturbine-schema-exposure": Internal9, ...PENDING_PLAYBOOK_SDK_FACETS2 }
|
|
2904
3135
|
);
|
|
2905
3136
|
var TrialInstanceSchema = IdField.merge(TimestampFields).merge(TenantIdField).extend({
|
|
2906
3137
|
customer_id: z15.string().min(1).meta(Unrestricted12),
|
|
@@ -3178,6 +3409,10 @@ var trialPaths = {
|
|
|
3178
3409
|
var { Unrestricted: Unrestricted13 } = DataClassification;
|
|
3179
3410
|
var { Persisted: Persisted13, Transient: Transient13 } = SchemaPersistence;
|
|
3180
3411
|
var { Internal: Internal10 } = SchemaExposure;
|
|
3412
|
+
var PENDING_PLAYBOOK_SDK_FACETS3 = schemaFacets(SchemaContext.Playbook, {
|
|
3413
|
+
inConfig: false,
|
|
3414
|
+
sdkInput: true
|
|
3415
|
+
});
|
|
3181
3416
|
var ExperimentStatusSchema = z16.enum(["draft", "ramping", "winning", "neutral", "needs_attention", "paused", "complete"]).meta(
|
|
3182
3417
|
{ id: "ExperimentStatus", "x-revturbine-schema-persistence": Transient13, "x-revturbine-schema-exposure": Internal10 }
|
|
3183
3418
|
);
|
|
@@ -3191,7 +3426,7 @@ var ExperimentVariantSchema = z16.object({
|
|
|
3191
3426
|
is_control: z16.boolean().default(false),
|
|
3192
3427
|
config: z16.record(z16.string(), z16.unknown()).default({})
|
|
3193
3428
|
}).meta(
|
|
3194
|
-
{ id: "ExperimentVariant", "x-revturbine-schema-persistence": Persisted13, "x-revturbine-schema-exposure": Internal10 }
|
|
3429
|
+
{ id: "ExperimentVariant", "x-revturbine-schema-persistence": Persisted13, "x-revturbine-schema-exposure": Internal10, ...PENDING_PLAYBOOK_SDK_FACETS3 }
|
|
3195
3430
|
);
|
|
3196
3431
|
var ExperimentSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(AnchorFields).merge(VersionFields).extend({
|
|
3197
3432
|
anchor_id: z16.string().min(1).meta({ ...Unrestricted13, readOnly: true }),
|
|
@@ -3215,7 +3450,7 @@ var ExperimentSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge
|
|
|
3215
3450
|
winning_variant_id: z16.string().nullable().default(null).meta(Unrestricted13),
|
|
3216
3451
|
metadata: MetadataField.meta(Unrestricted13)
|
|
3217
3452
|
}).meta(
|
|
3218
|
-
{ id: "Experiment", "x-revturbine-schema-persistence": Persisted13, "x-revturbine-schema-exposure": Internal10, ...namedIdentity() }
|
|
3453
|
+
{ id: "Experiment", "x-revturbine-schema-persistence": Persisted13, "x-revturbine-schema-exposure": Internal10, ...PENDING_PLAYBOOK_SDK_FACETS3, ...namedIdentity() }
|
|
3219
3454
|
);
|
|
3220
3455
|
var ExperimentAnchorSchema = makeAnchor("ExperimentAnchor");
|
|
3221
3456
|
var SuggestionSeveritySchema = SeveritySchema;
|
|
@@ -3347,6 +3582,7 @@ var experimentPaths = {
|
|
|
3347
3582
|
var { Unrestricted: Unrestricted14, Financial: Financial3 } = DataClassification;
|
|
3348
3583
|
var { Persisted: Persisted14, Transient: Transient14 } = SchemaPersistence;
|
|
3349
3584
|
var { Internal: Internal11 } = SchemaExposure;
|
|
3585
|
+
var PLAYBOOK_SDK_FACETS7 = schemaFacets(SchemaContext.Playbook, { sdkInput: true });
|
|
3350
3586
|
var PromotionStatusSchema = z17.enum(["draft", "scheduled", "live", "expired", "archived"]).meta(
|
|
3351
3587
|
{ id: "PromotionStatus", "x-revturbine-schema-persistence": Transient14, "x-revturbine-schema-exposure": Internal11 }
|
|
3352
3588
|
);
|
|
@@ -3376,7 +3612,7 @@ var PromotionSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(
|
|
|
3376
3612
|
auto_sync_stripe: z17.boolean().default(false).meta(Unrestricted14),
|
|
3377
3613
|
metadata: MetadataField.meta(Unrestricted14)
|
|
3378
3614
|
}).meta(
|
|
3379
|
-
{ id: "Promotion", "x-revturbine-schema-persistence": Persisted14, "x-revturbine-schema-exposure": Internal11, ...namedIdentity() }
|
|
3615
|
+
{ id: "Promotion", "x-revturbine-schema-persistence": Persisted14, "x-revturbine-schema-exposure": Internal11, ...PLAYBOOK_SDK_FACETS7, ...namedIdentity() }
|
|
3380
3616
|
);
|
|
3381
3617
|
var PromotionAnchorSchema = makeAnchor("PromotionAnchor");
|
|
3382
3618
|
var promotionPaths = {
|
|
@@ -3542,17 +3778,39 @@ var runtimePaths = {
|
|
|
3542
3778
|
var { Unrestricted: Unrestricted16 } = DataClassification;
|
|
3543
3779
|
var { Persisted: Persisted16, Transient: Transient16 } = SchemaPersistence;
|
|
3544
3780
|
var { Internal: Internal13, External: External11 } = SchemaExposure;
|
|
3545
|
-
var
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3781
|
+
var PLAYBOOK_SDK_FACETS8 = schemaFacets(SchemaContext.Playbook, { sdkInput: true });
|
|
3782
|
+
var PLAYBOOK_AUTHORING_FACETS2 = schemaFacets(SchemaContext.Playbook, { sdkInput: false });
|
|
3783
|
+
var PENDING_PLAYBOOK_FACETS4 = schemaFacets(SchemaContext.Playbook, {
|
|
3784
|
+
inConfig: false,
|
|
3785
|
+
sdkInput: false
|
|
3786
|
+
});
|
|
3787
|
+
var PENDING_PLAYBOOK_SDK_FACETS4 = schemaFacets(SchemaContext.Playbook, {
|
|
3788
|
+
inConfig: false,
|
|
3789
|
+
sdkInput: true
|
|
3790
|
+
});
|
|
3791
|
+
var PLAYBOOK_VERSION_HEADER_FACETS = schemaFacets(SchemaContext.Playbook, {
|
|
3792
|
+
inConfig: false,
|
|
3793
|
+
sdkInput: true,
|
|
3794
|
+
source: SchemaSource.CodeConstant
|
|
3795
|
+
});
|
|
3796
|
+
var PLAYBOOK_PROVENANCE_HEADER_FACETS = schemaFacets(SchemaContext.Playbook, {
|
|
3797
|
+
inConfig: false,
|
|
3798
|
+
sdkInput: true,
|
|
3799
|
+
source: SchemaSource.Runtime
|
|
3800
|
+
});
|
|
3801
|
+
var PLAYBOOK_TARGET_FACETS = schemaFacets(SchemaContext.Playbook, {
|
|
3802
|
+
inConfig: false,
|
|
3803
|
+
sdkInput: false,
|
|
3804
|
+
source: SchemaSource.Runtime
|
|
3805
|
+
});
|
|
3806
|
+
var BILLING_FACETS2 = schemaFacets(SchemaContext.Billing, { sdkInput: false });
|
|
3807
|
+
var METERING_FACETS = schemaFacets(SchemaContext.Metering, { sdkInput: false });
|
|
3808
|
+
var LEGACY_BRANDING_FACETS = schemaFacets(SchemaContext.Branding, {
|
|
3809
|
+
inConfig: true,
|
|
3810
|
+
sdkInput: true
|
|
3811
|
+
});
|
|
3812
|
+
var BRANDING_FACETS2 = schemaFacets(SchemaContext.Branding, { sdkInput: false });
|
|
3813
|
+
var PLAYBOOK_FORMAT_VERSION = "1.0.0";
|
|
3556
3814
|
var SeatTypeSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(AnchorFields).merge(VersionFields).extend({
|
|
3557
3815
|
anchor_id: z19.string().min(1).meta({ ...Unrestricted16, readOnly: true }),
|
|
3558
3816
|
name: NameField.meta(Unrestricted16),
|
|
@@ -3562,9 +3820,24 @@ var SeatTypeSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(A
|
|
|
3562
3820
|
entitlement_ids: z19.array(z19.string()).default([]).meta(Unrestricted16),
|
|
3563
3821
|
metadata: MetadataField.meta(Unrestricted16)
|
|
3564
3822
|
}).meta(
|
|
3565
|
-
{ id: "SeatType", "x-revturbine-schema-persistence": Persisted16, "x-revturbine-schema-exposure": Internal13, ...namedIdentity() }
|
|
3823
|
+
{ id: "SeatType", "x-revturbine-schema-persistence": Persisted16, "x-revturbine-schema-exposure": Internal13, ...PENDING_PLAYBOOK_FACETS4, ...namedIdentity() }
|
|
3566
3824
|
);
|
|
3567
3825
|
var SeatTypeAnchorSchema = makeAnchor("SeatTypeAnchor");
|
|
3826
|
+
var PersonalizationTokenSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(AnchorFields).merge(VersionFields).extend({
|
|
3827
|
+
anchor_id: z19.string().min(1).meta({ ...Unrestricted16, readOnly: true }),
|
|
3828
|
+
handle: HandleField.meta(Unrestricted16),
|
|
3829
|
+
label: z19.string().min(1).meta(Unrestricted16),
|
|
3830
|
+
description: z19.string().nullable().default(null).meta(Unrestricted16),
|
|
3831
|
+
category: z19.enum(["user", "plan", "usage", "trial", "billing", "promotion", "custom"]).meta(Unrestricted16),
|
|
3832
|
+
data_source: z19.string().nullable().default(null).meta(Unrestricted16),
|
|
3833
|
+
example_value: z19.string().nullable().default(null).meta(Unrestricted16),
|
|
3834
|
+
value_map: z19.record(z19.string(), z19.string()).default({}).meta(Unrestricted16),
|
|
3835
|
+
format: z19.enum(["string", "number", "currency", "percentage", "date"]).nullable().default(null).meta(Unrestricted16),
|
|
3836
|
+
metadata: MetadataField.meta(Unrestricted16)
|
|
3837
|
+
}).meta(
|
|
3838
|
+
{ id: "PersonalizationToken", "x-revturbine-schema-persistence": Persisted16, "x-revturbine-schema-exposure": Internal13, ...PENDING_PLAYBOOK_FACETS4, ...namedIdentity() }
|
|
3839
|
+
);
|
|
3840
|
+
var PersonalizationTokenAnchorSchema = makeAnchor("PersonalizationTokenAnchor");
|
|
3568
3841
|
var OnboardingStateSchema = z19.enum(["not_started", "started", "details_submitted", "charges_enabled", "activated", "deauthorized"]).meta({ id: "OnboardingState", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": Internal13 });
|
|
3569
3842
|
var StripeIntegrationConfigSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(AnchorFields).merge(VersionFields).extend({
|
|
3570
3843
|
handle: HandleField.meta({ ...Unrestricted16, readOnly: true }),
|
|
@@ -3591,7 +3864,20 @@ var StripeIntegrationConfigSchema = IdField.merge(TimestampFields).merge(TenantI
|
|
|
3591
3864
|
last_sync_at: z19.string().optional().meta({ ...Unrestricted16, readOnly: true }),
|
|
3592
3865
|
metadata: MetadataField.meta(Unrestricted16)
|
|
3593
3866
|
}).meta(
|
|
3594
|
-
{ id: "StripeIntegrationConfig", "x-revturbine-schema-persistence": Persisted16, "x-revturbine-schema-exposure": Internal13, ...mintedIdentity() }
|
|
3867
|
+
{ id: "StripeIntegrationConfig", "x-revturbine-schema-persistence": Persisted16, "x-revturbine-schema-exposure": Internal13, ...BILLING_FACETS2, ...mintedIdentity() }
|
|
3868
|
+
);
|
|
3869
|
+
var BrandingConfigSchema = z19.object({
|
|
3870
|
+
theme: z19.record(z19.string(), z19.unknown()).optional().meta(Unrestricted16),
|
|
3871
|
+
workspace_name: z19.string().optional().meta(Unrestricted16),
|
|
3872
|
+
logo_url: z19.string().optional().meta(Unrestricted16),
|
|
3873
|
+
support_email: z19.string().optional().meta(Unrestricted16)
|
|
3874
|
+
}).meta(
|
|
3875
|
+
{
|
|
3876
|
+
id: "BrandingConfig",
|
|
3877
|
+
"x-revturbine-schema-persistence": Transient16,
|
|
3878
|
+
"x-revturbine-schema-exposure": External11,
|
|
3879
|
+
...BRANDING_FACETS2
|
|
3880
|
+
}
|
|
3595
3881
|
);
|
|
3596
3882
|
var MeteringConfigSchema = IdField.merge(TimestampFields).merge(TenantIdField).merge(AnchorFields).merge(VersionFields).extend({
|
|
3597
3883
|
handle: HandleField.meta({ ...Unrestricted16, readOnly: true }),
|
|
@@ -3603,7 +3889,7 @@ var MeteringConfigSchema = IdField.merge(TimestampFields).merge(TenantIdField).m
|
|
|
3603
3889
|
is_active: z19.boolean().default(true).meta(Unrestricted16),
|
|
3604
3890
|
metadata: MetadataField.meta(Unrestricted16)
|
|
3605
3891
|
}).meta(
|
|
3606
|
-
{ id: "MeteringConfig", "x-revturbine-schema-persistence": Persisted16, "x-revturbine-schema-exposure": Internal13, ...mintedIdentity() }
|
|
3892
|
+
{ id: "MeteringConfig", "x-revturbine-schema-persistence": Persisted16, "x-revturbine-schema-exposure": Internal13, ...METERING_FACETS, ...mintedIdentity() }
|
|
3607
3893
|
);
|
|
3608
3894
|
var EnforcementActionSchema = z19.enum(["block", "warn", "downgrade", "throttle", "notify_admin", "custom"]).meta(
|
|
3609
3895
|
{ id: "EnforcementAction", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": Internal13 }
|
|
@@ -3620,7 +3906,7 @@ var UsageEnforcementSettingsSchema = IdField.merge(TimestampFields).merge(Tenant
|
|
|
3620
3906
|
notification_channels: z19.array(z19.enum(["email", "in_app", "webhook"])).default(["in_app"]).meta(Unrestricted16),
|
|
3621
3907
|
is_active: z19.boolean().default(true).meta(Unrestricted16)
|
|
3622
3908
|
}).meta(
|
|
3623
|
-
{ id: "UsageEnforcementSettings", "x-revturbine-schema-persistence": Persisted16, "x-revturbine-schema-exposure": Internal13, ...mintedIdentity() }
|
|
3909
|
+
{ id: "UsageEnforcementSettings", "x-revturbine-schema-persistence": Persisted16, "x-revturbine-schema-exposure": Internal13, ...PENDING_PLAYBOOK_SDK_FACETS4, ...mintedIdentity() }
|
|
3624
3910
|
);
|
|
3625
3911
|
var UsageEnforcementSettingsAnchorSchema = makeAnchor("UsageEnforcementSettingsAnchor");
|
|
3626
3912
|
var PlacementSettingsCapRuleGroupItemSchema = z19.object({
|
|
@@ -3664,7 +3950,7 @@ var PlacementSettingsSchema = IdField.merge(TimestampFields).merge(TenantIdField
|
|
|
3664
3950
|
allow_stacking: z19.boolean().default(false).meta(Unrestricted16),
|
|
3665
3951
|
priority_collision_strategy: z19.enum(["highest_priority", "most_recent", "random"]).default("highest_priority").meta(Unrestricted16)
|
|
3666
3952
|
}).meta(
|
|
3667
|
-
{ id: "PlacementSettings", "x-revturbine-schema-persistence": Persisted16, "x-revturbine-schema-exposure": Internal13, ...mintedIdentity() }
|
|
3953
|
+
{ id: "PlacementSettings", "x-revturbine-schema-persistence": Persisted16, "x-revturbine-schema-exposure": Internal13, ...PENDING_PLAYBOOK_SDK_FACETS4, ...mintedIdentity() }
|
|
3668
3954
|
);
|
|
3669
3955
|
var PlacementSettingsAnchorSchema = makeAnchor("PlacementSettingsAnchor");
|
|
3670
3956
|
var RevTurbineConfigSegmentsItemPredicatesItemSchema = z19.object({
|
|
@@ -3689,7 +3975,7 @@ var RevTurbineConfigSegmentsItemSchema = z19.object({
|
|
|
3689
3975
|
// back to flat-OR (legacy single-segment behaviour).
|
|
3690
3976
|
dimension_id: z19.string().optional().meta(Unrestricted16)
|
|
3691
3977
|
}).meta(
|
|
3692
|
-
{ id: "RevTurbineConfigSegmentsItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11 }
|
|
3978
|
+
{ id: "RevTurbineConfigSegmentsItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_SDK_FACETS8 }
|
|
3693
3979
|
);
|
|
3694
3980
|
var RevTurbineConfigPlansItemSchema = z19.object({
|
|
3695
3981
|
// Plan 120 TASK-4: `unique_handle` is the sole logical identifier; the
|
|
@@ -3704,7 +3990,7 @@ var RevTurbineConfigPlansItemSchema = z19.object({
|
|
|
3704
3990
|
// own visibility for per-price overrides; this is the plan's default.
|
|
3705
3991
|
visibility: PlanVisibilitySchema.default("public").meta(Unrestricted16)
|
|
3706
3992
|
}).meta(
|
|
3707
|
-
{ id: "RevTurbineConfigPlansItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11 }
|
|
3993
|
+
{ id: "RevTurbineConfigPlansItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_SDK_FACETS8 }
|
|
3708
3994
|
);
|
|
3709
3995
|
var RevTurbineConfigAddonsItemSchema = z19.object({
|
|
3710
3996
|
// Plan 120 TASK-4: `unique_handle` is the sole logical identifier; the
|
|
@@ -3716,7 +4002,85 @@ var RevTurbineConfigAddonsItemSchema = z19.object({
|
|
|
3716
4002
|
// not price, so it lives in the config independent of addon_variations.
|
|
3717
4003
|
visibility: PlanVisibilitySchema.default("public").meta(Unrestricted16)
|
|
3718
4004
|
}).meta(
|
|
3719
|
-
{ id: "RevTurbineConfigAddonsItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11 }
|
|
4005
|
+
{ id: "RevTurbineConfigAddonsItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_AUTHORING_FACETS2 }
|
|
4006
|
+
);
|
|
4007
|
+
var RevTurbineConfigPlanVariationsItemSchema = z19.object({
|
|
4008
|
+
handle: z19.string().min(1).meta(Unrestricted16),
|
|
4009
|
+
plan_handle: z19.string().min(1).meta(Unrestricted16),
|
|
4010
|
+
billing_period: z19.enum(["monthly", "annual", "one_time", "custom"]).meta(Unrestricted16),
|
|
4011
|
+
segment_handle: z19.string().nullable().default(null).meta(Unrestricted16),
|
|
4012
|
+
price_amount: z19.number().min(0).meta(Unrestricted16),
|
|
4013
|
+
pricing_model: PricingModelSchema.meta(Unrestricted16),
|
|
4014
|
+
visibility: PlanVisibilitySchema.default("public").meta(Unrestricted16),
|
|
4015
|
+
stripe_price_id: z19.string().nullable().default(null).meta(Unrestricted16),
|
|
4016
|
+
price_source: PriceSourceSchema.meta(Unrestricted16)
|
|
4017
|
+
}).meta(
|
|
4018
|
+
{ id: "RevTurbineConfigPlanVariationsItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PENDING_PLAYBOOK_FACETS4 }
|
|
4019
|
+
);
|
|
4020
|
+
var RevTurbineConfigAddonVariationsItemSchema = z19.object({
|
|
4021
|
+
handle: z19.string().min(1).meta(Unrestricted16),
|
|
4022
|
+
addon_handle: z19.string().min(1).meta(Unrestricted16),
|
|
4023
|
+
billing_period: z19.enum(["monthly", "annual", "one_time", "custom"]).meta(Unrestricted16),
|
|
4024
|
+
segment_handle: z19.string().nullable().default(null).meta(Unrestricted16),
|
|
4025
|
+
price_amount: z19.number().min(0).meta(Unrestricted16),
|
|
4026
|
+
pricing_model: PricingModelSchema.meta(Unrestricted16),
|
|
4027
|
+
visibility: PlanVisibilitySchema.default("public").meta(Unrestricted16),
|
|
4028
|
+
stripe_price_id: z19.string().nullable().default(null).meta(Unrestricted16),
|
|
4029
|
+
price_source: PriceSourceSchema.meta(Unrestricted16)
|
|
4030
|
+
}).meta(
|
|
4031
|
+
{ id: "RevTurbineConfigAddonVariationsItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PENDING_PLAYBOOK_FACETS4 }
|
|
4032
|
+
);
|
|
4033
|
+
var RevTurbineConfigSeatTypesItemSchema = z19.object({
|
|
4034
|
+
handle: z19.string().min(1).meta(Unrestricted16),
|
|
4035
|
+
name: z19.string().min(1).meta(Unrestricted16),
|
|
4036
|
+
description: z19.string().nullable().default(null).meta(Unrestricted16),
|
|
4037
|
+
is_default: z19.boolean().default(false).meta(Unrestricted16),
|
|
4038
|
+
entitlement_handles: z19.array(z19.string()).default([]).meta(Unrestricted16)
|
|
4039
|
+
}).meta(
|
|
4040
|
+
{ id: "RevTurbineConfigSeatTypesItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_SDK_FACETS8 }
|
|
4041
|
+
);
|
|
4042
|
+
var RevTurbineConfigEnforcementDefaultsItemSchema = z19.object({
|
|
4043
|
+
handle: z19.string().min(1).meta(Unrestricted16),
|
|
4044
|
+
entitlement_handle: z19.string().nullable().default(null).meta(Unrestricted16),
|
|
4045
|
+
soft_limit_percent: z19.number().int().min(0).nullable().default(null).meta(Unrestricted16),
|
|
4046
|
+
hard_limit_percent: z19.number().int().min(0).nullable().default(null).meta(Unrestricted16),
|
|
4047
|
+
soft_limit_action: z19.string().meta(Unrestricted16),
|
|
4048
|
+
hard_limit_action: z19.string().meta(Unrestricted16),
|
|
4049
|
+
grace_period_hours: z19.number().int().min(0).nullable().default(null).meta(Unrestricted16),
|
|
4050
|
+
notification_channels: z19.array(z19.string()).default([]).meta(Unrestricted16),
|
|
4051
|
+
is_active: z19.boolean().default(true).meta(Unrestricted16)
|
|
4052
|
+
}).meta(
|
|
4053
|
+
{ id: "RevTurbineConfigEnforcementDefaultsItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_SDK_FACETS8 }
|
|
4054
|
+
);
|
|
4055
|
+
var RevTurbineConfigPlacementSettingsItemSchema = z19.object({
|
|
4056
|
+
handle: z19.string().min(1).meta(Unrestricted16),
|
|
4057
|
+
global_frequency_cap: PlacementSettingsCapStateSchema.nullable().default(null).meta(Unrestricted16),
|
|
4058
|
+
global_frequency_cap_period: z19.enum(["hour", "day", "week", "month", "session"]).nullable().default(null).meta(Unrestricted16),
|
|
4059
|
+
suppress_for_paid: z19.boolean().default(false).meta(Unrestricted16),
|
|
4060
|
+
suppress_for_trial: z19.boolean().default(false).meta(Unrestricted16),
|
|
4061
|
+
default_dismiss_cooldown_hours: z19.number().int().min(0).nullable().default(null).meta(Unrestricted16),
|
|
4062
|
+
allow_stacking: z19.boolean().default(false).meta(Unrestricted16),
|
|
4063
|
+
priority_collision_strategy: z19.string().nullable().default(null).meta(Unrestricted16)
|
|
4064
|
+
}).meta(
|
|
4065
|
+
{ id: "RevTurbineConfigPlacementSettingsItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_SDK_FACETS8 }
|
|
4066
|
+
);
|
|
4067
|
+
var RevTurbineConfigSegmentDimensionsItemSchema = z19.object({
|
|
4068
|
+
handle: z19.string().min(1).meta(Unrestricted16),
|
|
4069
|
+
name: z19.string().min(1).meta(Unrestricted16),
|
|
4070
|
+
category: z19.string().nullable().default(null).meta(Unrestricted16),
|
|
4071
|
+
visibility_toggle: z19.boolean().default(true).meta(Unrestricted16),
|
|
4072
|
+
source_type: z19.string().nullable().default(null).meta(Unrestricted16)
|
|
4073
|
+
}).meta(
|
|
4074
|
+
{ id: "RevTurbineConfigSegmentDimensionsItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_SDK_FACETS8 }
|
|
4075
|
+
);
|
|
4076
|
+
var RevTurbineConfigMeterBindingsItemSchema = z19.object({
|
|
4077
|
+
handle: z19.string().min(1).meta(Unrestricted16),
|
|
4078
|
+
entitlement_handle: z19.string().min(1).meta(Unrestricted16),
|
|
4079
|
+
meter_handle: z19.string().min(1).meta(Unrestricted16),
|
|
4080
|
+
limit: z19.number().int().min(0).nullable().default(null).meta(Unrestricted16),
|
|
4081
|
+
reset_period: z19.string().nullable().default(null).meta(Unrestricted16)
|
|
4082
|
+
}).meta(
|
|
4083
|
+
{ id: "RevTurbineConfigMeterBindingsItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_SDK_FACETS8 }
|
|
3720
4084
|
);
|
|
3721
4085
|
var RevTurbineConfigEntitlementsItemSchema = z19.object({
|
|
3722
4086
|
// Plan 120 TASK-4: `unique_handle` is the sole logical identifier; the
|
|
@@ -3724,9 +4088,20 @@ var RevTurbineConfigEntitlementsItemSchema = z19.object({
|
|
|
3724
4088
|
unique_handle: z19.string().min(1).meta(Unrestricted16),
|
|
3725
4089
|
name: z19.string().min(1).meta(Unrestricted16),
|
|
3726
4090
|
type: EntitlementTypeSchema.meta(Unrestricted16),
|
|
3727
|
-
unit: z19.string().optional().meta(Unrestricted16)
|
|
4091
|
+
unit: z19.string().optional().meta(Unrestricted16),
|
|
4092
|
+
// Ordered tier ladder for a `capability_tier` entitlement — projection of
|
|
4093
|
+
// the authored `EntitlementSchema.tier_definitions` (plan 138 TASK-4).
|
|
4094
|
+
// ARRAY ORDER IS THE RANK: the `entitlement_gate.tier_threshold` placement
|
|
4095
|
+
// trigger fires when the user's current tier ranks below the threshold tier
|
|
4096
|
+
// on this ladder. `name`/`description` are UI-helper denormalizations (plan
|
|
4097
|
+
// 118); the runtime gate reads only the ordered `handle`s.
|
|
4098
|
+
tier_definitions: z19.array(z19.object({
|
|
4099
|
+
name: z19.string(),
|
|
4100
|
+
handle: z19.string(),
|
|
4101
|
+
description: z19.string().optional()
|
|
4102
|
+
})).optional().meta(Unrestricted16)
|
|
3728
4103
|
}).meta(
|
|
3729
|
-
{ id: "RevTurbineConfigEntitlementsItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11 }
|
|
4104
|
+
{ id: "RevTurbineConfigEntitlementsItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_SDK_FACETS8 }
|
|
3730
4105
|
);
|
|
3731
4106
|
var RevTurbineConfigEntitlementRulesItemSchema = z19.object({
|
|
3732
4107
|
id: z19.string().min(1).meta(Unrestricted16),
|
|
@@ -3736,19 +4111,22 @@ var RevTurbineConfigEntitlementRulesItemSchema = z19.object({
|
|
|
3736
4111
|
// means "match all users" (replaces the singular `segment_id` field
|
|
3737
4112
|
// and its 'all'/null sentinels).
|
|
3738
4113
|
segment_ids: z19.array(z19.string()).default([]).meta(Unrestricted16),
|
|
3739
|
-
|
|
4114
|
+
// Typed per-kind wire shape (plan 141). Loose variants + an untyped tail,
|
|
4115
|
+
// so every input that parsed as the former opaque record still parses and
|
|
4116
|
+
// unmodelled keys survive; see EntitlementTypeFieldsSchema.
|
|
4117
|
+
type_fields: EntitlementTypeFieldsSchema.default({}).meta(Unrestricted16),
|
|
3740
4118
|
current_usage: z19.number().default(0).meta(Unrestricted16),
|
|
3741
4119
|
/** How usage is partitioned across the identity hierarchy. */
|
|
3742
4120
|
allocation: UsageAllocationSchema.optional().meta(Unrestricted16)
|
|
3743
4121
|
}).meta(
|
|
3744
|
-
{ id: "RevTurbineConfigEntitlementRulesItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11 }
|
|
4122
|
+
{ id: "RevTurbineConfigEntitlementRulesItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_SDK_FACETS8 }
|
|
3745
4123
|
);
|
|
3746
4124
|
var RevTurbineConfigSlotConfigsItemSchema = z19.object({
|
|
3747
4125
|
slot_id: z19.string().min(1).meta(Unrestricted16),
|
|
3748
4126
|
active: z19.boolean().meta(Unrestricted16),
|
|
3749
4127
|
triggers: z19.array(z19.string()).meta(Unrestricted16)
|
|
3750
4128
|
}).meta(
|
|
3751
|
-
{ id: "RevTurbineConfigSlotConfigsItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11 }
|
|
4129
|
+
{ id: "RevTurbineConfigSlotConfigsItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_SDK_FACETS8 }
|
|
3752
4130
|
);
|
|
3753
4131
|
var RevTurbineConfigPlacementSlotsItemSchema = z19.object({
|
|
3754
4132
|
id: z19.string().min(1).meta(Unrestricted16),
|
|
@@ -3758,7 +4136,7 @@ var RevTurbineConfigPlacementSlotsItemSchema = z19.object({
|
|
|
3758
4136
|
placement_handle: z19.string().min(1).meta(Unrestricted16),
|
|
3759
4137
|
template: z19.string().optional().meta(Unrestricted16)
|
|
3760
4138
|
}).meta(
|
|
3761
|
-
{ id: "RevTurbineConfigPlacementSlotsItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11 }
|
|
4139
|
+
{ id: "RevTurbineConfigPlacementSlotsItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_SDK_FACETS8 }
|
|
3762
4140
|
);
|
|
3763
4141
|
var RevTurbineConfigSurfaceTemplatesItemFieldsItemSchema = z19.object({
|
|
3764
4142
|
name: z19.string().min(1).meta(Unrestricted16),
|
|
@@ -3772,7 +4150,7 @@ var RevTurbineConfigSurfaceTemplatesItemSchema = z19.object({
|
|
|
3772
4150
|
surface_type: z19.string().meta(Unrestricted16),
|
|
3773
4151
|
fields: z19.array(RevTurbineConfigSurfaceTemplatesItemFieldsItemSchema).optional().meta(Unrestricted16)
|
|
3774
4152
|
}).meta(
|
|
3775
|
-
{ id: "RevTurbineConfigSurfaceTemplatesItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11 }
|
|
4153
|
+
{ id: "RevTurbineConfigSurfaceTemplatesItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_SDK_FACETS8 }
|
|
3776
4154
|
);
|
|
3777
4155
|
var RevTurbineConfigUiPathActionTypeSchema = z19.enum([
|
|
3778
4156
|
"open_checkout_modal",
|
|
@@ -3808,7 +4186,7 @@ var ContentUiPathSchema = z19.object({
|
|
|
3808
4186
|
target_billing_period: z19.enum(["monthly", "annual"]).optional().meta(Unrestricted16),
|
|
3809
4187
|
description: z19.string().optional().meta(Unrestricted16)
|
|
3810
4188
|
}).meta(
|
|
3811
|
-
{ id: "ContentUiPath", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11 }
|
|
4189
|
+
{ id: "ContentUiPath", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_SDK_FACETS8 }
|
|
3812
4190
|
);
|
|
3813
4191
|
var ContentPromotionSchema = z19.object({
|
|
3814
4192
|
id: z19.string().meta(Unrestricted16),
|
|
@@ -3817,9 +4195,9 @@ var ContentPromotionSchema = z19.object({
|
|
|
3817
4195
|
type: z19.string().meta(Unrestricted16),
|
|
3818
4196
|
status: z19.string().meta(Unrestricted16)
|
|
3819
4197
|
}).meta(
|
|
3820
|
-
{ id: "ContentPromotion", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11 }
|
|
4198
|
+
{ id: "ContentPromotion", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_SDK_FACETS8 }
|
|
3821
4199
|
);
|
|
3822
|
-
var
|
|
4200
|
+
var RevTurbineConfigPersonalizationTokensItemSchema = z19.object({
|
|
3823
4201
|
token: z19.string().regex(/^[a-z][a-z0-9_]*$/).meta(Unrestricted16),
|
|
3824
4202
|
label: z19.string().min(1).meta(Unrestricted16),
|
|
3825
4203
|
description: z19.string().optional().meta(Unrestricted16),
|
|
@@ -3829,7 +4207,7 @@ var PersonalizationTokenSchema = z19.object({
|
|
|
3829
4207
|
value_map: z19.record(z19.string(), z19.string()).optional().meta(Unrestricted16),
|
|
3830
4208
|
format: z19.enum(["string", "number", "currency", "percentage", "date"]).optional().meta(Unrestricted16)
|
|
3831
4209
|
}).meta(
|
|
3832
|
-
{ id: "
|
|
4210
|
+
{ id: "RevTurbineConfigPersonalizationTokensItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_SDK_FACETS8 }
|
|
3833
4211
|
);
|
|
3834
4212
|
var MessageBlockContentSchema = z19.object({
|
|
3835
4213
|
header: z19.string().optional().meta(Unrestricted16),
|
|
@@ -3858,7 +4236,7 @@ var MessageBlockSchema = z19.object({
|
|
|
3858
4236
|
created_at: z19.string().datetime().meta({ ...Unrestricted16, readOnly: true }),
|
|
3859
4237
|
updated_at: z19.string().datetime().meta({ ...Unrestricted16, readOnly: true })
|
|
3860
4238
|
}).meta(
|
|
3861
|
-
{ id: "MessageBlock", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11 }
|
|
4239
|
+
{ id: "MessageBlock", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_SDK_FACETS8 }
|
|
3862
4240
|
);
|
|
3863
4241
|
var RevTurbineConfigStudioCtaConfigSchema = z19.object({
|
|
3864
4242
|
label: z19.string().meta(Unrestricted16),
|
|
@@ -3911,9 +4289,9 @@ var RevTurbineConfigStudioPayloadSchema = z19.object({
|
|
|
3911
4289
|
var RevTurbineConfigPlacementTriggerSchema = z19.discriminatedUnion("type", [
|
|
3912
4290
|
z19.object({ type: z19.literal("surface_render"), slot_id: z19.string().min(1) }),
|
|
3913
4291
|
z19.object({ type: z19.literal("entitlement_gate"), entitlement_handle: z19.string().min(1), tier_threshold: z19.string().optional() }),
|
|
3914
|
-
z19.object({ type: z19.literal("usage_threshold"), entitlement_handle: z19.string().min(1), threshold_percent:
|
|
3915
|
-
z19.object({ type: z19.literal("credit_threshold"), entitlement_handle: z19.string().min(1), threshold_percent:
|
|
3916
|
-
z19.object({ type: z19.literal("seat_threshold"), entitlement_handle: z19.string().min(1), threshold_percent:
|
|
4292
|
+
z19.object({ type: z19.literal("usage_threshold"), entitlement_handle: z19.string().min(1), threshold_percent: ThresholdPercentField }),
|
|
4293
|
+
z19.object({ type: z19.literal("credit_threshold"), entitlement_handle: z19.string().min(1), threshold_percent: ThresholdPercentField }),
|
|
4294
|
+
z19.object({ type: z19.literal("seat_threshold"), entitlement_handle: z19.string().min(1), threshold_percent: ThresholdPercentField }),
|
|
3917
4295
|
z19.object({ type: z19.literal("trial_started"), trial_type: z19.enum(["free", "reverse"]).optional() }),
|
|
3918
4296
|
z19.object({ type: z19.literal("trial_progress"), progress_percent: z19.number().min(1).max(100) }),
|
|
3919
4297
|
z19.object({ type: z19.literal("trial_ending"), days_before_end: z19.number().int().min(0) }),
|
|
@@ -3934,7 +4312,7 @@ var RevTurbineConfigPlacementItemSchema = z19.object({
|
|
|
3934
4312
|
payloads: z19.array(RevTurbineConfigStudioPayloadSchema).meta(Unrestricted16),
|
|
3935
4313
|
order: z19.number().int().min(0).meta(Unrestricted16)
|
|
3936
4314
|
}).meta(
|
|
3937
|
-
{ id: "RevTurbineConfigPlacementItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11 }
|
|
4315
|
+
{ id: "RevTurbineConfigPlacementItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_SDK_FACETS8 }
|
|
3938
4316
|
);
|
|
3939
4317
|
var RevTurbineConfigPlacementPayloadItemSchema = z19.object({
|
|
3940
4318
|
payload_id: z19.string().min(1).meta(Unrestricted16),
|
|
@@ -3954,121 +4332,244 @@ var RevTurbineConfigPlacementPayloadItemSchema = z19.object({
|
|
|
3954
4332
|
content_payload_id: z19.string().optional()
|
|
3955
4333
|
}).optional().meta(Unrestricted16)
|
|
3956
4334
|
}).meta(
|
|
3957
|
-
{ id: "RevTurbineConfigPlacementPayloadItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11 }
|
|
4335
|
+
{ id: "RevTurbineConfigPlacementPayloadItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_SDK_FACETS8 }
|
|
3958
4336
|
);
|
|
3959
4337
|
var RevTurbineConfigExtensionRulesItemSchema = z19.object({
|
|
3960
4338
|
kind: z19.string().min(1).meta(Unrestricted16),
|
|
3961
4339
|
schema_version: z19.number().int().nonnegative().meta(Unrestricted16),
|
|
3962
4340
|
config: z19.unknown().meta(Unrestricted16)
|
|
3963
4341
|
}).meta(
|
|
3964
|
-
{ id: "RevTurbineConfigExtensionRulesItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11 }
|
|
4342
|
+
{ id: "RevTurbineConfigExtensionRulesItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PLAYBOOK_SDK_FACETS8 }
|
|
3965
4343
|
);
|
|
3966
4344
|
var RevTurbineConfigFreeTrialRuleItemSchema = IdField.merge(FreeTrialRuleCoreFieldsSchema).meta(
|
|
3967
|
-
{ id: "RevTurbineConfigFreeTrialRuleItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11 }
|
|
4345
|
+
{ id: "RevTurbineConfigFreeTrialRuleItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PENDING_PLAYBOOK_FACETS4 }
|
|
3968
4346
|
);
|
|
3969
4347
|
var RevTurbineConfigReverseTrialRuleItemSchema = IdField.merge(ReverseTrialRuleCoreFieldsSchema).meta(
|
|
3970
|
-
{ id: "RevTurbineConfigReverseTrialRuleItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11 }
|
|
4348
|
+
{ id: "RevTurbineConfigReverseTrialRuleItem", "x-revturbine-schema-persistence": Transient16, "x-revturbine-schema-exposure": External11, ...PENDING_PLAYBOOK_FACETS4 }
|
|
3971
4349
|
);
|
|
3972
|
-
var
|
|
3973
|
-
version: z19.string().meta(Unrestricted16),
|
|
3974
|
-
exported_at: z19.string().datetime().optional().meta({ ...Unrestricted16, readOnly: true }),
|
|
4350
|
+
var LegacyRevTurbineConfigSchema = z19.object({
|
|
4351
|
+
version: z19.string().meta({ ...Unrestricted16, ...PLAYBOOK_VERSION_HEADER_FACETS }),
|
|
4352
|
+
exported_at: z19.string().datetime().optional().meta({ ...Unrestricted16, ...PLAYBOOK_PROVENANCE_HEADER_FACETS, readOnly: true }),
|
|
3975
4353
|
// The @revt-eng/schema package version this config was generated with.
|
|
3976
|
-
schema_version: z19.string().optional().meta({ ...Unrestricted16, readOnly: true }),
|
|
4354
|
+
schema_version: z19.string().optional().meta({ ...Unrestricted16, ...PLAYBOOK_VERSION_HEADER_FACETS, readOnly: true }),
|
|
3977
4355
|
// The compiled-bundle wire-format SCHEMA_VERSION (core/bundle/ir.ts).
|
|
3978
|
-
bundle_schema_version: z19.number().int().optional().meta({ ...Unrestricted16, readOnly: true }),
|
|
4356
|
+
bundle_schema_version: z19.number().int().optional().meta({ ...Unrestricted16, ...PLAYBOOK_VERSION_HEADER_FACETS, readOnly: true }),
|
|
3979
4357
|
// The change set this export represents: the active change set by default,
|
|
3980
4358
|
// or a specific change set when one is requested. Null for an unscoped export.
|
|
3981
|
-
change_set_id: z19.string().nullable().default(null).meta({ ...Unrestricted16, readOnly: true }),
|
|
4359
|
+
change_set_id: z19.string().nullable().default(null).meta({ ...Unrestricted16, ...PLAYBOOK_PROVENANCE_HEADER_FACETS, readOnly: true }),
|
|
3982
4360
|
// Origin target identity (plan 131 TASK-10, cli.md "Target-aware, portable"):
|
|
3983
4361
|
// stamped by the server on export so a downloaded Config File records where
|
|
3984
4362
|
// it came from; upload tooling targets these by default and flags a tenant
|
|
3985
4363
|
// mismatch against the session before sending. Optional — hand-authored and
|
|
3986
4364
|
// pre-existing configs carry no target.
|
|
3987
|
-
tenant_id: z19.string().optional().meta({ ...Unrestricted16, readOnly: true }),
|
|
3988
|
-
environment_id: z19.string().optional().meta({ ...Unrestricted16, readOnly: true }),
|
|
3989
|
-
plans: z19.array(RevTurbineConfigPlansItemSchema).meta(Unrestricted16),
|
|
4365
|
+
tenant_id: z19.string().optional().meta({ ...Unrestricted16, ...PLAYBOOK_TARGET_FACETS, readOnly: true }),
|
|
4366
|
+
environment_id: z19.string().optional().meta({ ...Unrestricted16, ...PLAYBOOK_TARGET_FACETS, readOnly: true }),
|
|
4367
|
+
plans: z19.array(RevTurbineConfigPlansItemSchema).meta({ ...Unrestricted16, ...PLAYBOOK_SDK_FACETS8 }),
|
|
3990
4368
|
// Optional for back-compat: pre-plan-88 configs (and the live export until web
|
|
3991
4369
|
// adopts the new @revt-eng/schema) omit it. Add-on definitions only; pricing
|
|
3992
4370
|
// (addon_variations) stays in the Stripe layer, like plan_variations.
|
|
3993
|
-
addons: z19.array(RevTurbineConfigAddonsItemSchema).optional().meta(Unrestricted16),
|
|
3994
|
-
entitlements: z19.array(RevTurbineConfigEntitlementsItemSchema).meta(Unrestricted16),
|
|
3995
|
-
entitlement_rules: z19.array(RevTurbineConfigEntitlementRulesItemSchema).meta(Unrestricted16),
|
|
3996
|
-
segments: z19.array(RevTurbineConfigSegmentsItemSchema).meta(Unrestricted16),
|
|
3997
|
-
content_ui_paths: z19.array(ContentUiPathSchema).meta(Unrestricted16),
|
|
3998
|
-
slot_configs: z19.array(RevTurbineConfigSlotConfigsItemSchema).optional().meta(
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4371
|
+
addons: z19.array(RevTurbineConfigAddonsItemSchema).optional().meta({ ...Unrestricted16, ...PLAYBOOK_AUTHORING_FACETS2 }),
|
|
4372
|
+
entitlements: z19.array(RevTurbineConfigEntitlementsItemSchema).meta({ ...Unrestricted16, ...PLAYBOOK_SDK_FACETS8 }),
|
|
4373
|
+
entitlement_rules: z19.array(RevTurbineConfigEntitlementRulesItemSchema).meta({ ...Unrestricted16, ...PLAYBOOK_SDK_FACETS8 }),
|
|
4374
|
+
segments: z19.array(RevTurbineConfigSegmentsItemSchema).meta({ ...Unrestricted16, ...PLAYBOOK_SDK_FACETS8 }),
|
|
4375
|
+
content_ui_paths: z19.array(ContentUiPathSchema).meta({ ...Unrestricted16, ...PLAYBOOK_SDK_FACETS8 }),
|
|
4376
|
+
slot_configs: z19.array(RevTurbineConfigSlotConfigsItemSchema).optional().meta({
|
|
4377
|
+
...Unrestricted16,
|
|
4378
|
+
...PLAYBOOK_SDK_FACETS8,
|
|
4379
|
+
...schemaDeprecation({
|
|
4380
|
+
since: "0.1.117",
|
|
4381
|
+
replacement: "SDK-local activation/trigger state",
|
|
4382
|
+
removeAfter: "one compatibility window",
|
|
4383
|
+
reason: "Slot activation moved to SDK-local state (plan 118 TASK-6); no longer a Playbook authoring input."
|
|
4384
|
+
})
|
|
4385
|
+
}),
|
|
4386
|
+
content_overrides: z19.record(z19.string(), z19.record(z19.string(), z19.string())).optional().meta({
|
|
4387
|
+
...Unrestricted16,
|
|
4388
|
+
...PLAYBOOK_SDK_FACETS8,
|
|
4389
|
+
...schemaDeprecation({
|
|
4390
|
+
since: "0.1.117",
|
|
4391
|
+
replacement: "Message Block / Placement Payload content",
|
|
4392
|
+
removeAfter: "one compatibility window",
|
|
4393
|
+
reason: "Content overrides moved to Message Block / Payload content (plan 118 TASK-6); no longer a Playbook authoring input."
|
|
4394
|
+
})
|
|
4395
|
+
}),
|
|
4396
|
+
theme: z19.record(z19.string(), z19.unknown()).optional().meta({
|
|
4397
|
+
...Unrestricted16,
|
|
4398
|
+
...LEGACY_BRANDING_FACETS,
|
|
4399
|
+
...schemaDeprecation({
|
|
4400
|
+
since: "0.1.111",
|
|
4401
|
+
replacement: "SDK branding argument",
|
|
4402
|
+
removeAfter: "one compatibility window",
|
|
4403
|
+
reason: "Branding is independently owned and is not Playbook strategy."
|
|
4404
|
+
})
|
|
4405
|
+
}),
|
|
4406
|
+
placement_slots: z19.array(RevTurbineConfigPlacementSlotsItemSchema).optional().meta({ ...Unrestricted16, ...PLAYBOOK_SDK_FACETS8 }),
|
|
4407
|
+
message_blocks: z19.array(MessageBlockSchema).optional().meta({ ...Unrestricted16, ...PLAYBOOK_SDK_FACETS8 }),
|
|
4408
|
+
placement_payloads: z19.array(RevTurbineConfigPlacementPayloadItemSchema).optional().meta({ ...Unrestricted16, ...PLAYBOOK_SDK_FACETS8 }),
|
|
4409
|
+
placements: z19.array(RevTurbineConfigPlacementItemSchema).optional().meta({ ...Unrestricted16, ...PLAYBOOK_SDK_FACETS8 }),
|
|
4410
|
+
content_promotions: z19.array(ContentPromotionSchema).optional().meta({ ...Unrestricted16, ...PLAYBOOK_SDK_FACETS8 }),
|
|
4411
|
+
personalization_tokens: z19.array(RevTurbineConfigPersonalizationTokensItemSchema).optional().meta({ ...Unrestricted16, ...PLAYBOOK_SDK_FACETS8 }),
|
|
4412
|
+
surface_templates: z19.array(RevTurbineConfigSurfaceTemplatesItemSchema).optional().meta({ ...Unrestricted16, ...PLAYBOOK_SDK_FACETS8 }),
|
|
4008
4413
|
/**
|
|
4009
4414
|
* Free + reverse trial rule configurations (plan 43). Optional so
|
|
4010
4415
|
* pre-trial-runtime configs continue to parse. /api/config/import
|
|
4011
4416
|
* applies these to the tenant's free_trial_rules / reverse_trial_rules
|
|
4012
4417
|
* tables; /api/config/export reads them out for round-trip.
|
|
4013
4418
|
*/
|
|
4014
|
-
free_trial_rules: z19.array(RevTurbineConfigFreeTrialRuleItemSchema).optional().meta(Unrestricted16),
|
|
4015
|
-
reverse_trial_rules: z19.array(RevTurbineConfigReverseTrialRuleItemSchema).optional().meta(Unrestricted16),
|
|
4419
|
+
free_trial_rules: z19.array(RevTurbineConfigFreeTrialRuleItemSchema).optional().meta({ ...Unrestricted16, ...PLAYBOOK_AUTHORING_FACETS2 }),
|
|
4420
|
+
reverse_trial_rules: z19.array(RevTurbineConfigReverseTrialRuleItemSchema).optional().meta({ ...Unrestricted16, ...PLAYBOOK_AUTHORING_FACETS2 }),
|
|
4421
|
+
// Plan / add-on variation prices carried by handle (plan 118 TASK-16). These
|
|
4422
|
+
// live on the legacy schema (not just the canonical Playbook body) so that a
|
|
4423
|
+
// legacy `version`-shaped config — the shape the demo-data configs and the
|
|
4424
|
+
// pre-sales/CLI upload flow still use — can carry variation prices through
|
|
4425
|
+
// normalization instead of having them stripped. Pending until web
|
|
4426
|
+
// import/export activates them (TASK-21).
|
|
4427
|
+
plan_variations: z19.array(RevTurbineConfigPlanVariationsItemSchema).optional().meta({ ...Unrestricted16, ...PLAYBOOK_AUTHORING_FACETS2 }),
|
|
4428
|
+
addon_variations: z19.array(RevTurbineConfigAddonVariationsItemSchema).optional().meta({ ...Unrestricted16, ...PLAYBOOK_AUTHORING_FACETS2 }),
|
|
4016
4429
|
/**
|
|
4017
4430
|
* Tagged-opaque rule entries (Phase 3 / strategy 2). Each entry is
|
|
4018
4431
|
* dispatched to the corresponding `RuleAuthoringModule.kind` at
|
|
4019
4432
|
* compile time; unknown kinds are skipped silently so authoring can
|
|
4020
4433
|
* stage new kinds before the runtime catches up.
|
|
4021
4434
|
*/
|
|
4022
|
-
extension_rules: z19.array(RevTurbineConfigExtensionRulesItemSchema).optional().meta(Unrestricted16)
|
|
4435
|
+
extension_rules: z19.array(RevTurbineConfigExtensionRulesItemSchema).optional().meta({ ...Unrestricted16, ...PLAYBOOK_SDK_FACETS8 }),
|
|
4436
|
+
// Authored-config projections carried as active SDK inputs (plan 118
|
|
4437
|
+
// TASK-13/18). Declared here (not only on PlaybookBody) so the Bundle
|
|
4438
|
+
// compiler — which lowers the legacy `RevTurbineConfig` view — reads them
|
|
4439
|
+
// with proper types. Projected into the RuleBundle; see core/bundle.
|
|
4440
|
+
seat_types: z19.array(RevTurbineConfigSeatTypesItemSchema).optional().meta({ ...Unrestricted16, ...PLAYBOOK_SDK_FACETS8 }),
|
|
4441
|
+
enforcement_defaults: z19.array(RevTurbineConfigEnforcementDefaultsItemSchema).optional().meta({ ...Unrestricted16, ...PLAYBOOK_SDK_FACETS8 }),
|
|
4442
|
+
placement_settings: z19.array(RevTurbineConfigPlacementSettingsItemSchema).optional().meta({ ...Unrestricted16, ...PLAYBOOK_SDK_FACETS8 }),
|
|
4443
|
+
segment_dimensions: z19.array(RevTurbineConfigSegmentDimensionsItemSchema).optional().meta({ ...Unrestricted16, ...PLAYBOOK_SDK_FACETS8 }),
|
|
4444
|
+
meter_bindings: z19.array(RevTurbineConfigMeterBindingsItemSchema).optional().meta({ ...Unrestricted16, ...PLAYBOOK_SDK_FACETS8 })
|
|
4445
|
+
}).meta(
|
|
4446
|
+
{
|
|
4447
|
+
id: "RevTurbineConfig",
|
|
4448
|
+
"x-revturbine-schema-persistence": Transient16,
|
|
4449
|
+
"x-revturbine-schema-exposure": External11,
|
|
4450
|
+
...PLAYBOOK_SDK_FACETS8,
|
|
4451
|
+
...schemaDeprecation({
|
|
4452
|
+
since: "0.1.111",
|
|
4453
|
+
replacement: "PlaybookSchema",
|
|
4454
|
+
removeAfter: "one compatibility window",
|
|
4455
|
+
reason: "The legacy wire conflates format and provenance under version and change_set_id."
|
|
4456
|
+
})
|
|
4457
|
+
}
|
|
4458
|
+
);
|
|
4459
|
+
var PlaybookHeaderSchema = z19.object({
|
|
4460
|
+
artifact_type: z19.literal("playbook").meta({
|
|
4461
|
+
...Unrestricted16,
|
|
4462
|
+
...PLAYBOOK_VERSION_HEADER_FACETS,
|
|
4463
|
+
readOnly: true
|
|
4464
|
+
}),
|
|
4465
|
+
format_version: z19.literal(PLAYBOOK_FORMAT_VERSION).meta({
|
|
4466
|
+
...Unrestricted16,
|
|
4467
|
+
...PLAYBOOK_VERSION_HEADER_FACETS,
|
|
4468
|
+
readOnly: true
|
|
4469
|
+
}),
|
|
4470
|
+
playbook_handle: z19.string().min(1).default("default").meta({
|
|
4471
|
+
...Unrestricted16,
|
|
4472
|
+
...PLAYBOOK_VERSION_HEADER_FACETS
|
|
4473
|
+
}),
|
|
4474
|
+
playbook_version_id: z19.string().nullable().default(null).meta({
|
|
4475
|
+
...Unrestricted16,
|
|
4476
|
+
...PLAYBOOK_PROVENANCE_HEADER_FACETS,
|
|
4477
|
+
readOnly: true
|
|
4478
|
+
}),
|
|
4479
|
+
tenant_id: z19.string().min(1).meta({
|
|
4480
|
+
...Unrestricted16,
|
|
4481
|
+
...PLAYBOOK_TARGET_FACETS,
|
|
4482
|
+
readOnly: true
|
|
4483
|
+
}),
|
|
4484
|
+
environment_id: z19.string().min(1).meta({
|
|
4485
|
+
...Unrestricted16,
|
|
4486
|
+
...PLAYBOOK_TARGET_FACETS,
|
|
4487
|
+
readOnly: true
|
|
4488
|
+
}),
|
|
4489
|
+
project_id: z19.string().min(1).optional().meta({
|
|
4490
|
+
...Unrestricted16,
|
|
4491
|
+
...PLAYBOOK_TARGET_FACETS,
|
|
4492
|
+
readOnly: true
|
|
4493
|
+
}),
|
|
4494
|
+
exported_at: z19.string().datetime().optional().meta({
|
|
4495
|
+
...Unrestricted16,
|
|
4496
|
+
...PLAYBOOK_PROVENANCE_HEADER_FACETS,
|
|
4497
|
+
readOnly: true
|
|
4498
|
+
}),
|
|
4499
|
+
schema_version: z19.string().min(1).optional().meta({
|
|
4500
|
+
...Unrestricted16,
|
|
4501
|
+
...PLAYBOOK_VERSION_HEADER_FACETS,
|
|
4502
|
+
readOnly: true
|
|
4503
|
+
}),
|
|
4504
|
+
bundle_schema_version: z19.number().int().nonnegative().optional().meta({
|
|
4505
|
+
...Unrestricted16,
|
|
4506
|
+
...PLAYBOOK_VERSION_HEADER_FACETS,
|
|
4507
|
+
readOnly: true
|
|
4508
|
+
})
|
|
4509
|
+
}).meta(
|
|
4510
|
+
{
|
|
4511
|
+
id: "PlaybookHeader",
|
|
4512
|
+
"x-revturbine-schema-persistence": Transient16,
|
|
4513
|
+
"x-revturbine-schema-exposure": External11,
|
|
4514
|
+
...PLAYBOOK_PROVENANCE_HEADER_FACETS
|
|
4515
|
+
}
|
|
4516
|
+
);
|
|
4517
|
+
var LEGACY_HEADER_KEYS = {
|
|
4518
|
+
version: true,
|
|
4519
|
+
exported_at: true,
|
|
4520
|
+
schema_version: true,
|
|
4521
|
+
bundle_schema_version: true,
|
|
4522
|
+
change_set_id: true,
|
|
4523
|
+
tenant_id: true,
|
|
4524
|
+
environment_id: true
|
|
4525
|
+
};
|
|
4526
|
+
var PlaybookBodySchema = LegacyRevTurbineConfigSchema.omit(LEGACY_HEADER_KEYS).extend({
|
|
4527
|
+
experiments: z19.array(z19.unknown()).max(0).optional().meta({
|
|
4528
|
+
...Unrestricted16,
|
|
4529
|
+
...PENDING_PLAYBOOK_FACETS4
|
|
4530
|
+
}),
|
|
4531
|
+
// Reserved like `experiments` above: claim the key now, ship the
|
|
4532
|
+
// semantics later. A Playbook will eventually pin the Signal Catalog
|
|
4533
|
+
// version its targeting was interpreted under, so a decision stays
|
|
4534
|
+
// reproducible after the event taxonomy moves on. Reserving costs one
|
|
4535
|
+
// schema change; adding a top-level Playbook key after the fact costs a
|
|
4536
|
+
// second breaking cascade through the IR, the CLI, demo data, and every
|
|
4537
|
+
// SDK port.
|
|
4538
|
+
//
|
|
4539
|
+
// Empty-object-only until a consumer exists — `.strict()` rejects a
|
|
4540
|
+
// populated `{ id, version }` rather than letting it round-trip as
|
|
4541
|
+
// config nothing reads. Catalog *definitions* stay server-side and must
|
|
4542
|
+
// never reach the browser Playbook; only the reference will live here.
|
|
4543
|
+
signal_catalog: z19.object({}).strict().optional().meta({
|
|
4544
|
+
...Unrestricted16,
|
|
4545
|
+
...PENDING_PLAYBOOK_FACETS4
|
|
4546
|
+
})
|
|
4547
|
+
// NOTE: plan_variations / addon_variations are NOT re-declared here — they
|
|
4548
|
+
// now live on LegacyRevTurbineConfigSchema (plan 118) and flow through the
|
|
4549
|
+
// `.omit(LEGACY_HEADER_KEYS)` above, so both the legacy and canonical shapes
|
|
4550
|
+
// carry them from a single definition.
|
|
4551
|
+
// NOTE: the authored-config projections (seat_types, enforcement_defaults,
|
|
4552
|
+
// placement_settings, segment_dimensions, meter_bindings) are active SDK
|
|
4553
|
+
// inputs and flow through from LegacyRevTurbineConfigSchema (they are not
|
|
4554
|
+
// LEGACY_HEADER_KEYS, so `.omit` retains them). See plan 118 TASK-18.
|
|
4023
4555
|
}).meta(
|
|
4024
|
-
{
|
|
4556
|
+
{
|
|
4557
|
+
id: "PlaybookBody",
|
|
4558
|
+
"x-revturbine-schema-persistence": Transient16,
|
|
4559
|
+
"x-revturbine-schema-exposure": External11,
|
|
4560
|
+
...PLAYBOOK_SDK_FACETS8
|
|
4561
|
+
}
|
|
4025
4562
|
);
|
|
4563
|
+
var PlaybookSchema = PlaybookHeaderSchema.extend(PlaybookBodySchema.shape).meta(
|
|
4564
|
+
{
|
|
4565
|
+
id: "Playbook",
|
|
4566
|
+
"x-revturbine-schema-persistence": Transient16,
|
|
4567
|
+
"x-revturbine-schema-exposure": External11,
|
|
4568
|
+
...PLAYBOOK_SDK_FACETS8
|
|
4569
|
+
}
|
|
4570
|
+
);
|
|
4571
|
+
var RevTurbineConfigSchema = LegacyRevTurbineConfigSchema;
|
|
4026
4572
|
var configPaths = {
|
|
4027
|
-
"/api/config/application-surfaces": {
|
|
4028
|
-
get: operation({
|
|
4029
|
-
operationId: "listApplicationSurfaces",
|
|
4030
|
-
requestParams: { query: ListQueryParamsSchema },
|
|
4031
|
-
summary: "List application surfaces",
|
|
4032
|
-
tags: ["config"],
|
|
4033
|
-
responses: { "200": { description: "Surface list", content: { "application/json": { schema: ListEnvelope(ApplicationSurfaceSchema) } } } },
|
|
4034
|
-
"x-revturbine-operation": { exposure: "internal", resource: "application-surfaces", persistence: { table: "applicationSurfaces", mode: "list" } }
|
|
4035
|
-
}),
|
|
4036
|
-
post: operation({
|
|
4037
|
-
operationId: "createApplicationSurface",
|
|
4038
|
-
summary: "Create application surface",
|
|
4039
|
-
tags: ["config"],
|
|
4040
|
-
requestBody: { required: true, content: { "application/json": { schema: toCreateSchema(ApplicationSurfaceSchema) } } },
|
|
4041
|
-
responses: { "201": { description: "Created", content: { "application/json": { schema: ApplicationSurfaceSchema } } } },
|
|
4042
|
-
"x-revturbine-operation": { exposure: "internal", resource: "application-surfaces", persistence: { table: "applicationSurfaces", mode: "create" } }
|
|
4043
|
-
})
|
|
4044
|
-
},
|
|
4045
|
-
"/api/config/application-surfaces/{id}": {
|
|
4046
|
-
get: operation({
|
|
4047
|
-
operationId: "getApplicationSurface",
|
|
4048
|
-
requestParams: { path: z19.object({ id: z19.string() }) },
|
|
4049
|
-
summary: "Get application surface by ID",
|
|
4050
|
-
tags: ["config"],
|
|
4051
|
-
responses: { "200": { description: "Application surface detail", content: { "application/json": { schema: ApplicationSurfaceSchema } } } },
|
|
4052
|
-
"x-revturbine-operation": { exposure: "internal", resource: "application-surfaces", persistence: { table: "applicationSurfaces", mode: "get" } }
|
|
4053
|
-
}),
|
|
4054
|
-
patch: operation({
|
|
4055
|
-
operationId: "updateApplicationSurface",
|
|
4056
|
-
requestParams: { path: z19.object({ id: z19.string() }) },
|
|
4057
|
-
summary: "Update application surface",
|
|
4058
|
-
tags: ["config"],
|
|
4059
|
-
requestBody: { required: true, content: { "application/json": { schema: ApplicationSurfaceSchema.partial() } } },
|
|
4060
|
-
responses: { "200": { description: "Updated", content: { "application/json": { schema: ApplicationSurfaceSchema } } } },
|
|
4061
|
-
"x-revturbine-operation": { exposure: "internal", resource: "application-surfaces", persistence: { table: "applicationSurfaces", mode: "update" } }
|
|
4062
|
-
}),
|
|
4063
|
-
delete: operation({
|
|
4064
|
-
operationId: "deleteApplicationSurface",
|
|
4065
|
-
requestParams: { path: z19.object({ id: z19.string() }) },
|
|
4066
|
-
summary: "Delete application surface",
|
|
4067
|
-
tags: ["config"],
|
|
4068
|
-
responses: { "204": { description: "Deleted" } },
|
|
4069
|
-
"x-revturbine-operation": { exposure: "internal", resource: "application-surfaces", persistence: { table: "applicationSurfaces", mode: "delete" } }
|
|
4070
|
-
})
|
|
4071
|
-
},
|
|
4072
4573
|
"/api/seat-type-anchors": {
|
|
4073
4574
|
get: operation({
|
|
4074
4575
|
operationId: "listSeatTypeAnchors",
|
|
@@ -4119,6 +4620,56 @@ var configPaths = {
|
|
|
4119
4620
|
"x-revturbine-operation": { exposure: "internal", resource: "seat-types", persistence: { table: "seatTypeVersions", mode: "delete" } }
|
|
4120
4621
|
})
|
|
4121
4622
|
},
|
|
4623
|
+
"/api/personalization-token-anchors": {
|
|
4624
|
+
get: operation({
|
|
4625
|
+
operationId: "listPersonalizationTokenAnchors",
|
|
4626
|
+
requestParams: { query: ListQueryParamsSchema },
|
|
4627
|
+
summary: "List personalization token anchors (identity registry)",
|
|
4628
|
+
tags: ["config"],
|
|
4629
|
+
responses: {
|
|
4630
|
+
"200": { description: "Personalization token anchor list", content: { "application/json": { schema: ListEnvelope(PersonalizationTokenAnchorSchema) } } },
|
|
4631
|
+
default: { description: "Error response", content: { "application/json": { schema: ErrorEnvelope } } }
|
|
4632
|
+
},
|
|
4633
|
+
"x-revturbine-operation": { exposure: "internal", resource: "personalization-token-anchors", persistence: { table: "personalizationTokens", mode: "list" } }
|
|
4634
|
+
})
|
|
4635
|
+
},
|
|
4636
|
+
"/api/config/personalization-tokens": {
|
|
4637
|
+
get: operation({
|
|
4638
|
+
operationId: "listPersonalizationTokens",
|
|
4639
|
+
requestParams: { query: ListQueryParamsSchema },
|
|
4640
|
+
summary: "List personalization tokens",
|
|
4641
|
+
tags: ["config"],
|
|
4642
|
+
responses: { "200": { description: "Personalization token list", content: { "application/json": { schema: ListEnvelope(PersonalizationTokenSchema) } } } },
|
|
4643
|
+
"x-revturbine-operation": { exposure: "internal", resource: "personalization-tokens", persistence: { table: "personalizationTokenVersions", mode: "list" } }
|
|
4644
|
+
}),
|
|
4645
|
+
post: operation({
|
|
4646
|
+
operationId: "createPersonalizationToken",
|
|
4647
|
+
summary: "Create personalization token",
|
|
4648
|
+
tags: ["config"],
|
|
4649
|
+
requestBody: { required: true, content: { "application/json": { schema: toCreateSchema(PersonalizationTokenSchema) } } },
|
|
4650
|
+
responses: { "201": { description: "Created", content: { "application/json": { schema: PersonalizationTokenSchema } } } },
|
|
4651
|
+
"x-revturbine-operation": { exposure: "internal", resource: "personalization-tokens", persistence: { table: "personalizationTokenVersions", mode: "create" } }
|
|
4652
|
+
})
|
|
4653
|
+
},
|
|
4654
|
+
"/api/config/personalization-tokens/{id}": {
|
|
4655
|
+
patch: operation({
|
|
4656
|
+
operationId: "updatePersonalizationToken",
|
|
4657
|
+
requestParams: { path: z19.object({ id: z19.string() }) },
|
|
4658
|
+
summary: "Update personalization token",
|
|
4659
|
+
tags: ["config"],
|
|
4660
|
+
requestBody: { required: true, content: { "application/json": { schema: PersonalizationTokenSchema.partial() } } },
|
|
4661
|
+
responses: { "200": { description: "Updated", content: { "application/json": { schema: PersonalizationTokenSchema } } } },
|
|
4662
|
+
"x-revturbine-operation": { exposure: "internal", resource: "personalization-tokens", persistence: { table: "personalizationTokenVersions", mode: "update" } }
|
|
4663
|
+
}),
|
|
4664
|
+
delete: operation({
|
|
4665
|
+
operationId: "deletePersonalizationToken",
|
|
4666
|
+
requestParams: { path: z19.object({ id: z19.string() }) },
|
|
4667
|
+
summary: "Delete personalization token",
|
|
4668
|
+
tags: ["config"],
|
|
4669
|
+
responses: { "204": { description: "Deleted" } },
|
|
4670
|
+
"x-revturbine-operation": { exposure: "internal", resource: "personalization-tokens", persistence: { table: "personalizationTokenVersions", mode: "delete" } }
|
|
4671
|
+
})
|
|
4672
|
+
},
|
|
4122
4673
|
"/api/config/stripe": {
|
|
4123
4674
|
get: operation({
|
|
4124
4675
|
operationId: "getStripeIntegrationConfig",
|
|
@@ -4528,6 +5079,16 @@ var EntitlementCheckResultSchema = z23.object({
|
|
|
4528
5079
|
allowed: z23.boolean().meta(Unrestricted20),
|
|
4529
5080
|
reason: z23.string().optional().meta(Unrestricted20),
|
|
4530
5081
|
current_tier: z23.string().optional().meta(Unrestricted20),
|
|
5082
|
+
/**
|
|
5083
|
+
* Effective numeric limit from the matched entitlement rule (or usage
|
|
5084
|
+
* snapshot) — plan 133. Present only on limit-bearing outcomes
|
|
5085
|
+
* (usage_limit / credits); absence means limit-agnostic, not unlimited.
|
|
5086
|
+
*/
|
|
5087
|
+
limit: z23.number().optional().meta(Unrestricted20),
|
|
5088
|
+
/** Consumed amount the evaluation applied against `limit`. */
|
|
5089
|
+
used: z23.number().optional().meta(Unrestricted20),
|
|
5090
|
+
/** `max(0, limit - used)`. */
|
|
5091
|
+
remaining: z23.number().optional().meta(Unrestricted20),
|
|
4531
5092
|
/** Upsell placement to render when entitlement is denied. */
|
|
4532
5093
|
placement: PlacementDecisionOutputSchema.optional().meta(Unrestricted20)
|
|
4533
5094
|
}).meta({ id: "EntitlementCheckResult", "x-revturbine-schema-persistence": Transient19, "x-revturbine-schema-exposure": External12 });
|
|
@@ -5569,7 +6130,7 @@ function evaluate(graph, opts = {}) {
|
|
|
5569
6130
|
}
|
|
5570
6131
|
|
|
5571
6132
|
// src/schema/version.ts
|
|
5572
|
-
var SCHEMA_VERSION = "0.1.
|
|
6133
|
+
var SCHEMA_VERSION = "0.1.138";
|
|
5573
6134
|
|
|
5574
6135
|
// src/lib/credentials.ts
|
|
5575
6136
|
import { chmodSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "fs";
|
|
@@ -5926,6 +6487,75 @@ async function fetchValidation(baseUrl, playbookVersionId, headers, fetchImpl =
|
|
|
5926
6487
|
};
|
|
5927
6488
|
}
|
|
5928
6489
|
|
|
6490
|
+
// src/lib/playbook-header.ts
|
|
6491
|
+
var SUPPORTED_FORMAT_VERSIONS = /* @__PURE__ */ new Set(["1.0.0"]);
|
|
6492
|
+
var UnsupportedFormatError = class extends Error {
|
|
6493
|
+
constructor(message) {
|
|
6494
|
+
super(message);
|
|
6495
|
+
this.name = "UnsupportedFormatError";
|
|
6496
|
+
}
|
|
6497
|
+
};
|
|
6498
|
+
function str(value) {
|
|
6499
|
+
return typeof value === "string" ? value : void 0;
|
|
6500
|
+
}
|
|
6501
|
+
function readPlaybookHeader(config) {
|
|
6502
|
+
const c = config && typeof config === "object" ? config : {};
|
|
6503
|
+
const artifactType = str(c.artifact_type);
|
|
6504
|
+
const tenantId = str(c.tenant_id);
|
|
6505
|
+
const environmentId = str(c.environment_id);
|
|
6506
|
+
if (artifactType === "playbook") {
|
|
6507
|
+
return {
|
|
6508
|
+
shape: "canonical",
|
|
6509
|
+
artifactType,
|
|
6510
|
+
formatVersion: str(c.format_version),
|
|
6511
|
+
playbookHandle: str(c.playbook_handle),
|
|
6512
|
+
playbookVersionId: c.playbook_version_id ?? null,
|
|
6513
|
+
tenantId,
|
|
6514
|
+
environmentId
|
|
6515
|
+
};
|
|
6516
|
+
}
|
|
6517
|
+
if (artifactType === void 0 && typeof c.version === "string") {
|
|
6518
|
+
return {
|
|
6519
|
+
shape: "legacy",
|
|
6520
|
+
formatVersion: c.version,
|
|
6521
|
+
playbookVersionId: c.change_set_id ?? null,
|
|
6522
|
+
tenantId,
|
|
6523
|
+
environmentId
|
|
6524
|
+
};
|
|
6525
|
+
}
|
|
6526
|
+
return { shape: "unknown", artifactType, tenantId, environmentId };
|
|
6527
|
+
}
|
|
6528
|
+
function assertSupportedFormat(config) {
|
|
6529
|
+
const header = readPlaybookHeader(config);
|
|
6530
|
+
if (header.shape === "canonical") {
|
|
6531
|
+
const version = header.formatVersion;
|
|
6532
|
+
if (!version || !SUPPORTED_FORMAT_VERSIONS.has(version)) {
|
|
6533
|
+
throw new UnsupportedFormatError(
|
|
6534
|
+
`Unsupported Playbook format_version ${version ? `"${version}"` : "(missing)"}. This CLI supports: ${[...SUPPORTED_FORMAT_VERSIONS].join(", ")}. Update the CLI pinned in this repo (\`npm install -D @revturbine/cli@latest\`, or your package manager's equivalent).`
|
|
6535
|
+
);
|
|
6536
|
+
}
|
|
6537
|
+
return header;
|
|
6538
|
+
}
|
|
6539
|
+
if (header.shape === "unknown") {
|
|
6540
|
+
throw new UnsupportedFormatError(
|
|
6541
|
+
header.artifactType ? `Unrecognized artifact_type "${header.artifactType}" \u2014 expected "playbook" or a legacy Config File.` : 'File is neither a canonical Playbook (artifact_type: "playbook") nor a legacy Config File (missing "version").'
|
|
6542
|
+
);
|
|
6543
|
+
}
|
|
6544
|
+
return header;
|
|
6545
|
+
}
|
|
6546
|
+
function describePlaybookHeader(header) {
|
|
6547
|
+
if (header.shape === "legacy") {
|
|
6548
|
+
return `legacy Config File (version ${header.formatVersion ?? "?"})`;
|
|
6549
|
+
}
|
|
6550
|
+
if (header.shape === "canonical") {
|
|
6551
|
+
const parts = [`Playbook format_version ${header.formatVersion ?? "?"}`];
|
|
6552
|
+
if (header.playbookHandle) parts.push(`handle ${header.playbookHandle}`);
|
|
6553
|
+
if (header.playbookVersionId) parts.push(`playbook_version_id ${header.playbookVersionId}`);
|
|
6554
|
+
return parts.join(", ");
|
|
6555
|
+
}
|
|
6556
|
+
return "unrecognized artifact";
|
|
6557
|
+
}
|
|
6558
|
+
|
|
5929
6559
|
// src/lib/drafts.ts
|
|
5930
6560
|
async function resolveActiveDraft(baseUrl, headers, fetchImpl = fetch) {
|
|
5931
6561
|
const res = await fetchImpl(`${baseUrl}/api/optimization/drafts`, { headers });
|
|
@@ -5933,6 +6563,159 @@ async function resolveActiveDraft(baseUrl, headers, fetchImpl = fetch) {
|
|
|
5933
6563
|
return { ok: res.ok, status: res.status, draft: res.ok ? json.active ?? null : null };
|
|
5934
6564
|
}
|
|
5935
6565
|
|
|
6566
|
+
// src/lib/delegate.ts
|
|
6567
|
+
var DELEGATION_ENV = "REVTURBINE_DELEGATED";
|
|
6568
|
+
var NO_LOCAL_FLAG = "--no-local";
|
|
6569
|
+
function planDelegation(params) {
|
|
6570
|
+
if (params.env[DELEGATION_ENV]) {
|
|
6571
|
+
return { delegate: false, reason: "already delegated" };
|
|
6572
|
+
}
|
|
6573
|
+
if (params.argv.includes(NO_LOCAL_FLAG)) {
|
|
6574
|
+
return { delegate: false, reason: `${NO_LOCAL_FLAG} requested` };
|
|
6575
|
+
}
|
|
6576
|
+
if (!params.local) {
|
|
6577
|
+
return { delegate: false, reason: "no repo-pinned CLI found" };
|
|
6578
|
+
}
|
|
6579
|
+
if (samePath(params.local.entry, params.ownEntry)) {
|
|
6580
|
+
return { delegate: false, reason: "already running the repo-pinned CLI" };
|
|
6581
|
+
}
|
|
6582
|
+
return {
|
|
6583
|
+
delegate: true,
|
|
6584
|
+
target: params.local.entry,
|
|
6585
|
+
// Only surface skew when it exists: a diagnostic on every invocation is
|
|
6586
|
+
// noise, and noise gets filtered out along with the signal.
|
|
6587
|
+
skew: params.local.version === params.ownVersion ? void 0 : { local: params.local.version, global: params.ownVersion }
|
|
6588
|
+
};
|
|
6589
|
+
}
|
|
6590
|
+
function samePath(a, b) {
|
|
6591
|
+
const norm = (p) => {
|
|
6592
|
+
const unified = p.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
6593
|
+
return process.platform === "win32" ? unified.toLowerCase() : unified;
|
|
6594
|
+
};
|
|
6595
|
+
return norm(a) === norm(b);
|
|
6596
|
+
}
|
|
6597
|
+
function skewNotice(skew) {
|
|
6598
|
+
return `using the repo-pinned CLI ${skew.local} (this global is ${skew.global}) \u2014 the repo's pin wins because the schema snapshot is pinned with it. Run with ${NO_LOCAL_FLAG} to use the global instead.`;
|
|
6599
|
+
}
|
|
6600
|
+
|
|
6601
|
+
// src/lib/offline-schema.ts
|
|
6602
|
+
function schemaForConfig(raw) {
|
|
6603
|
+
const header = readPlaybookHeader(raw);
|
|
6604
|
+
return header.shape === "canonical" ? { schema: PlaybookSchema, shape: "canonical" } : { schema: RevTurbineConfigSchema, shape: "legacy" };
|
|
6605
|
+
}
|
|
6606
|
+
|
|
6607
|
+
// src/lib/init.ts
|
|
6608
|
+
var LOCKFILES = [
|
|
6609
|
+
["pnpm-lock.yaml", "pnpm"],
|
|
6610
|
+
["yarn.lock", "yarn"],
|
|
6611
|
+
["package-lock.json", "npm"]
|
|
6612
|
+
];
|
|
6613
|
+
function detectPackageManager(signals) {
|
|
6614
|
+
const field = signals.packageManagerField?.trim();
|
|
6615
|
+
if (field) {
|
|
6616
|
+
const name = field.split("@")[0]?.trim();
|
|
6617
|
+
if (name === "pnpm" || name === "npm" || name === "yarn") {
|
|
6618
|
+
return { name, reason: `packageManager field (${field})` };
|
|
6619
|
+
}
|
|
6620
|
+
}
|
|
6621
|
+
const files = new Set(signals.files ?? []);
|
|
6622
|
+
for (const [lockfile, name] of LOCKFILES) {
|
|
6623
|
+
if (files.has(lockfile)) return { name, reason: lockfile };
|
|
6624
|
+
}
|
|
6625
|
+
const agent = signals.userAgent ?? "";
|
|
6626
|
+
for (const name of ["pnpm", "yarn", "npm"]) {
|
|
6627
|
+
if (agent.startsWith(`${name}/`)) return { name, reason: `npm_config_user_agent (${name})` };
|
|
6628
|
+
}
|
|
6629
|
+
return { name: "npm", reason: "default" };
|
|
6630
|
+
}
|
|
6631
|
+
function detectStack(signals) {
|
|
6632
|
+
const deps = { ...signals.dependencies, ...signals.devDependencies };
|
|
6633
|
+
if (deps["next"]) return "next";
|
|
6634
|
+
if (deps["@remix-run/react"] || deps["@react-router/dev"]) return "remix";
|
|
6635
|
+
if (deps["astro"]) return "astro";
|
|
6636
|
+
if (deps["vite"]) return "vite";
|
|
6637
|
+
if (deps["react"]) return "react";
|
|
6638
|
+
return "unknown";
|
|
6639
|
+
}
|
|
6640
|
+
var SDK_PACKAGE = "@revturbine/sdk";
|
|
6641
|
+
var CLI_PACKAGE = "@revturbine/cli";
|
|
6642
|
+
function planInstall(params) {
|
|
6643
|
+
const deps = params.dependencies ?? {};
|
|
6644
|
+
const devDeps = params.devDependencies ?? {};
|
|
6645
|
+
const install = [];
|
|
6646
|
+
const skipped = [];
|
|
6647
|
+
const existingSdk = deps[SDK_PACKAGE] ?? devDeps[SDK_PACKAGE];
|
|
6648
|
+
if (existingSdk) {
|
|
6649
|
+
skipped.push(`${SDK_PACKAGE} already declared (${existingSdk})`);
|
|
6650
|
+
} else {
|
|
6651
|
+
install.push({ spec: SDK_PACKAGE, dev: false, exact: false });
|
|
6652
|
+
}
|
|
6653
|
+
const existingCli = devDeps[CLI_PACKAGE] ?? deps[CLI_PACKAGE];
|
|
6654
|
+
if (existingCli) {
|
|
6655
|
+
skipped.push(
|
|
6656
|
+
existingCli === params.cliVersion ? `${CLI_PACKAGE} already pinned (${existingCli})` : `${CLI_PACKAGE} already declared (${existingCli}) \u2014 left as-is; this CLI is ${params.cliVersion}`
|
|
6657
|
+
);
|
|
6658
|
+
} else {
|
|
6659
|
+
install.push({ spec: `${CLI_PACKAGE}@${params.cliVersion}`, dev: true, exact: true });
|
|
6660
|
+
}
|
|
6661
|
+
return { install, skipped };
|
|
6662
|
+
}
|
|
6663
|
+
function installArgs(manager, plan) {
|
|
6664
|
+
const exact = plan.exact ? [manager === "yarn" ? "--exact" : "--save-exact"] : [];
|
|
6665
|
+
const dev = plan.dev ? ["-D"] : [];
|
|
6666
|
+
const verb = manager === "npm" ? "install" : "add";
|
|
6667
|
+
return [verb, ...dev, ...exact, plan.spec];
|
|
6668
|
+
}
|
|
6669
|
+
|
|
6670
|
+
// src/lib/starter-playbook.ts
|
|
6671
|
+
var STARTER_PLAYBOOK_FILENAME = "revturbine.playbook.json";
|
|
6672
|
+
var STARTER_PLAYBOOK = {
|
|
6673
|
+
artifact_type: "playbook",
|
|
6674
|
+
format_version: "1.0.0",
|
|
6675
|
+
playbook_handle: "default",
|
|
6676
|
+
playbook_version_id: null,
|
|
6677
|
+
tenant_id: "local",
|
|
6678
|
+
environment_id: "local",
|
|
6679
|
+
plans: [
|
|
6680
|
+
{ id: "plan_free", unique_handle: "free", name: "Free", tier_position: 0, sort_order: 0 },
|
|
6681
|
+
{ id: "plan_pro", unique_handle: "pro", name: "Pro", tier_position: 1, sort_order: 1 }
|
|
6682
|
+
],
|
|
6683
|
+
entitlements: [
|
|
6684
|
+
{ id: "ent_advanced_export", unique_handle: "advanced_export", name: "Advanced Export", type: "feature" }
|
|
6685
|
+
],
|
|
6686
|
+
entitlement_rules: [
|
|
6687
|
+
{
|
|
6688
|
+
id: "er_advanced_export_free",
|
|
6689
|
+
entitlement_id: "ent_advanced_export",
|
|
6690
|
+
targets: [{ kind: "plan", id: "plan_free" }],
|
|
6691
|
+
segment_ids: [],
|
|
6692
|
+
type_fields: { kind: "feature", enabled: false },
|
|
6693
|
+
current_usage: 0
|
|
6694
|
+
},
|
|
6695
|
+
{
|
|
6696
|
+
id: "er_advanced_export_pro",
|
|
6697
|
+
entitlement_id: "ent_advanced_export",
|
|
6698
|
+
targets: [{ kind: "plan", id: "plan_pro" }],
|
|
6699
|
+
segment_ids: [],
|
|
6700
|
+
type_fields: { kind: "feature", enabled: true },
|
|
6701
|
+
current_usage: 0
|
|
6702
|
+
}
|
|
6703
|
+
],
|
|
6704
|
+
segments: [],
|
|
6705
|
+
content_ui_paths: [],
|
|
6706
|
+
surface_templates: [],
|
|
6707
|
+
placements: []
|
|
6708
|
+
};
|
|
6709
|
+
function validatePlaybook(config) {
|
|
6710
|
+
const parsed = PlaybookSchema.safeParse(config);
|
|
6711
|
+
if (!parsed.success) {
|
|
6712
|
+
return { ok: false, problems: parsed.error.issues ?? [parsed.error] };
|
|
6713
|
+
}
|
|
6714
|
+
const findings = evaluate(parsed.data, {});
|
|
6715
|
+
const blocking = findings.filter((f) => f.severity === "error_draft" || f.severity === "error_launch");
|
|
6716
|
+
return { ok: blocking.length === 0, problems: blocking };
|
|
6717
|
+
}
|
|
6718
|
+
|
|
5936
6719
|
// src/lib/output.ts
|
|
5937
6720
|
var EXIT = {
|
|
5938
6721
|
OK: 0,
|
|
@@ -6076,9 +6859,23 @@ function loadConfig(file) {
|
|
|
6076
6859
|
}
|
|
6077
6860
|
function verifyConfig(file) {
|
|
6078
6861
|
const parsed = loadConfig(file);
|
|
6862
|
+
const header = readPlaybookHeader(parsed);
|
|
6863
|
+
try {
|
|
6864
|
+
assertSupportedFormat(parsed);
|
|
6865
|
+
} catch (err) {
|
|
6866
|
+
if (err instanceof UnsupportedFormatError) {
|
|
6867
|
+
diag(`\u2717 ${file}: ${err.message}`);
|
|
6868
|
+
return null;
|
|
6869
|
+
}
|
|
6870
|
+
throw err;
|
|
6871
|
+
}
|
|
6872
|
+
if (header.shape === "canonical") {
|
|
6873
|
+
diag(`\u2713 ${file}: ${describePlaybookHeader(header)} \u2014 body validated server-side on import`);
|
|
6874
|
+
return parsed;
|
|
6875
|
+
}
|
|
6079
6876
|
const result = schema.safeParse(parsed);
|
|
6080
6877
|
if (result.success) {
|
|
6081
|
-
diag(`\u2713 ${file}: schema validation passed`);
|
|
6878
|
+
diag(`\u2713 ${file}: schema validation passed \u2014 ${describePlaybookHeader(header)}`);
|
|
6082
6879
|
return result.data;
|
|
6083
6880
|
}
|
|
6084
6881
|
diag(`\u2717 ${file}: schema validation FAILED:`);
|
|
@@ -6156,7 +6953,7 @@ function warnIfSchemaBehind(config) {
|
|
|
6156
6953
|
const server = serverSchemaIsNewer(config, SCHEMA_VERSION);
|
|
6157
6954
|
if (server) {
|
|
6158
6955
|
diag(
|
|
6159
|
-
`WARNING: the server's schema (${server}) is newer than this CLI's bundled snapshot (${SCHEMA_VERSION}) \u2014 offline validation may be missing rules. Update: npm
|
|
6956
|
+
`WARNING: the server's schema (${server}) is newer than this CLI's bundled snapshot (${SCHEMA_VERSION}) \u2014 offline validation may be missing rules. Update the CLI pinned in this repo: npm install -D @revturbine/cli@latest (or your package manager's equivalent).`
|
|
6160
6957
|
);
|
|
6161
6958
|
}
|
|
6162
6959
|
}
|
|
@@ -6283,6 +7080,7 @@ function renderShow(kind, config) {
|
|
|
6283
7080
|
var pkgVersion = createRequire(import.meta.url)("../package.json").version ?? "0.0.0";
|
|
6284
7081
|
var HELP_AFTER = `
|
|
6285
7082
|
Command groups:
|
|
7083
|
+
Set up init
|
|
6286
7084
|
Auth & meta login, logout, signup, whoami, schema, docs
|
|
6287
7085
|
Download download
|
|
6288
7086
|
Check validate, diff, show
|
|
@@ -6296,6 +7094,9 @@ Version selectors (no defaults \u2014 a command that reads a config requires one
|
|
|
6296
7094
|
--release <id> a specific playbook version / Release
|
|
6297
7095
|
|
|
6298
7096
|
Common workflows:
|
|
7097
|
+
# Add RevTurbine to an app (same routine as \`npm create revturbine@latest\`)
|
|
7098
|
+
revturbine init
|
|
7099
|
+
|
|
6299
7100
|
# Author, validate, and ship against the default instance (revturbine.com/app)
|
|
6300
7101
|
revturbine login
|
|
6301
7102
|
revturbine download --live --save ./config.json
|
|
@@ -6334,7 +7135,92 @@ program.hook("postAction", async (_thisCommand, actionCommand) => {
|
|
|
6334
7135
|
command: actionCommand.name()
|
|
6335
7136
|
});
|
|
6336
7137
|
});
|
|
6337
|
-
program.name("revturbine").description("Validate RevTurbine Config Files and ship them through the playbook-version lifecycle (draft \u2192 Release).").version(`${pkgVersion} (schema ${SCHEMA_VERSION})`, "-V, --version", "Print the revturbine and bundled schema versions").showHelpAfterError().addHelpText("after", HELP_AFTER);
|
|
7138
|
+
program.name("revturbine").description("Validate RevTurbine Config Files and ship them through the playbook-version lifecycle (draft \u2192 Release).").version(`${pkgVersion} (schema ${SCHEMA_VERSION})`, "-V, --version", "Print the revturbine and bundled schema versions").option(NO_LOCAL_FLAG, "Ignore the repo-pinned CLI and run this installation").showHelpAfterError().addHelpText("after", HELP_AFTER);
|
|
7139
|
+
function runInstall(manager, args, cwd) {
|
|
7140
|
+
return new Promise((resolve, reject) => {
|
|
7141
|
+
const child = spawn2(manager, args, { cwd, stdio: "inherit", shell: true });
|
|
7142
|
+
child.on("error", reject);
|
|
7143
|
+
child.on("close", (code) => resolve(code ?? 1));
|
|
7144
|
+
});
|
|
7145
|
+
}
|
|
7146
|
+
program.command("init").description("Scaffold RevTurbine into this app: detect the stack, install the SDK, and pin the CLI to the repo.").option("-d, --dir <path>", "Target directory (defaults to the current directory)").option("--dry-run", "Report what would be installed without running the package manager").option("--json", "Emit the scaffold plan as JSON").action(async (opts) => {
|
|
7147
|
+
const dir = path2.resolve(opts.dir ?? process.cwd());
|
|
7148
|
+
const manifestPath = path2.join(dir, "package.json");
|
|
7149
|
+
if (!existsSync2(manifestPath)) {
|
|
7150
|
+
fail(EXIT.USAGE, `No package.json in ${dir} \u2014 run init inside a JavaScript project (or pass --dir).`);
|
|
7151
|
+
}
|
|
7152
|
+
let manifest;
|
|
7153
|
+
try {
|
|
7154
|
+
manifest = JSON.parse(readFileSync2(manifestPath, "utf8"));
|
|
7155
|
+
} catch (err) {
|
|
7156
|
+
fail(EXIT.VALIDATION, `invalid JSON in ${manifestPath}: ${err.message}`);
|
|
7157
|
+
}
|
|
7158
|
+
const manager = detectPackageManager({
|
|
7159
|
+
files: readdirSync(dir),
|
|
7160
|
+
packageManagerField: manifest.packageManager,
|
|
7161
|
+
userAgent: process.env["npm_config_user_agent"]
|
|
7162
|
+
});
|
|
7163
|
+
const stack = detectStack(manifest);
|
|
7164
|
+
const plan = planInstall({
|
|
7165
|
+
dependencies: manifest.dependencies,
|
|
7166
|
+
devDependencies: manifest.devDependencies,
|
|
7167
|
+
cliVersion: pkgVersion
|
|
7168
|
+
});
|
|
7169
|
+
diag(`\u2713 Detected ${manager.name} (${manager.reason})`);
|
|
7170
|
+
if (stack !== "unknown") diag(`\u2713 Detected ${stack}`);
|
|
7171
|
+
for (const note of plan.skipped) diag(`\u2022 ${note}`);
|
|
7172
|
+
const playbookPath = path2.join(dir, STARTER_PLAYBOOK_FILENAME);
|
|
7173
|
+
const playbookExists = existsSync2(playbookPath);
|
|
7174
|
+
if (playbookExists) diag(`\u2022 ${STARTER_PLAYBOOK_FILENAME} already present \u2014 left as-is`);
|
|
7175
|
+
if (opts.json) {
|
|
7176
|
+
emit(
|
|
7177
|
+
{
|
|
7178
|
+
dir,
|
|
7179
|
+
manager: manager.name,
|
|
7180
|
+
stack,
|
|
7181
|
+
install: plan.install,
|
|
7182
|
+
skipped: plan.skipped,
|
|
7183
|
+
playbook: playbookExists ? "present" : STARTER_PLAYBOOK_FILENAME
|
|
7184
|
+
},
|
|
7185
|
+
true
|
|
7186
|
+
);
|
|
7187
|
+
}
|
|
7188
|
+
if (opts.dryRun) {
|
|
7189
|
+
for (const step of plan.install) {
|
|
7190
|
+
diag(`would run: ${manager.name} ${installArgs(manager.name, step).join(" ")}`);
|
|
7191
|
+
}
|
|
7192
|
+
if (!playbookExists) diag(`would write: ${STARTER_PLAYBOOK_FILENAME}`);
|
|
7193
|
+
if (plan.install.length === 0 && playbookExists) diag("\u2713 Already set up \u2014 nothing to do.");
|
|
7194
|
+
return;
|
|
7195
|
+
}
|
|
7196
|
+
for (const step of plan.install) {
|
|
7197
|
+
const args = installArgs(manager.name, step);
|
|
7198
|
+
diag(`${manager.name} ${args.join(" ")}`);
|
|
7199
|
+
let code;
|
|
7200
|
+
try {
|
|
7201
|
+
code = await runInstall(manager.name, args, dir);
|
|
7202
|
+
} catch (err) {
|
|
7203
|
+
fail(EXIT.UNEXPECTED, `could not run ${manager.name}: ${err.message}`);
|
|
7204
|
+
}
|
|
7205
|
+
if (code !== 0) fail(EXIT.UNEXPECTED, `${manager.name} ${args.join(" ")} failed (exit ${code}).`);
|
|
7206
|
+
}
|
|
7207
|
+
if (plan.install.length > 0) {
|
|
7208
|
+
diag(`\u2713 Installed the RevTurbine SDK and CLI (CLI pinned to ${pkgVersion})`);
|
|
7209
|
+
}
|
|
7210
|
+
if (!playbookExists) {
|
|
7211
|
+
const check = validatePlaybook(STARTER_PLAYBOOK);
|
|
7212
|
+
if (!check.ok) {
|
|
7213
|
+
fail(
|
|
7214
|
+
EXIT.VALIDATION,
|
|
7215
|
+
`the bundled starter Playbook failed validation against schema ${SCHEMA_VERSION} \u2014 this is a CLI bug, please report it.`
|
|
7216
|
+
);
|
|
7217
|
+
}
|
|
7218
|
+
writeFileSync2(playbookPath, `${JSON.stringify(STARTER_PLAYBOOK, null, 2)}
|
|
7219
|
+
`, "utf8");
|
|
7220
|
+
diag(`\u2713 Added a starter playbook (${STARTER_PLAYBOOK_FILENAME} \u2014 local mode, no account needed)`);
|
|
7221
|
+
}
|
|
7222
|
+
if (plan.install.length === 0 && playbookExists) diag("\u2713 Already set up \u2014 nothing to do.");
|
|
7223
|
+
});
|
|
6338
7224
|
program.command("login").description("Authorize this machine via the browser (device flow) and store a token for the instance (default: the production instance).").argument("[url]", `RevTurbine instance URL (default: ${DEFAULT_URL})`).action(async (url) => {
|
|
6339
7225
|
try {
|
|
6340
7226
|
const base = normalizeBaseUrl(url ?? DEFAULT_URL);
|
|
@@ -6490,6 +7376,7 @@ program.command("download").description("Fetch a config version from the server.
|
|
|
6490
7376
|
return;
|
|
6491
7377
|
}
|
|
6492
7378
|
const config = await downloadConfig(conn, playbookVersionId);
|
|
7379
|
+
diag(`Downloaded: ${describePlaybookHeader(readPlaybookHeader(config))}`);
|
|
6493
7380
|
const out = `${JSON.stringify(config, null, 2)}
|
|
6494
7381
|
`;
|
|
6495
7382
|
if (opts.save) {
|
|
@@ -6511,11 +7398,12 @@ program.command("validate").description("Validate a Config File offline (schema)
|
|
|
6511
7398
|
let blockedFiles = 0;
|
|
6512
7399
|
for (const file of files) {
|
|
6513
7400
|
const raw = loadConfig(file);
|
|
6514
|
-
const
|
|
7401
|
+
const { schema: fileSchema, shape } = schemaForConfig(raw);
|
|
7402
|
+
const parsed = fileSchema.safeParse(raw);
|
|
6515
7403
|
const findings = evaluate(parsed.success ? parsed.data : raw, {
|
|
6516
7404
|
structuralErrors: parsed.success ? void 0 : parsed.error
|
|
6517
7405
|
});
|
|
6518
|
-
diag(`Validation for ${file} (offline, schema ${SCHEMA_VERSION}):`);
|
|
7406
|
+
diag(`Validation for ${file} (offline, ${shape} shape, schema ${SCHEMA_VERSION}):`);
|
|
6519
7407
|
process.stdout.write(`${formatFindings(findings)}
|
|
6520
7408
|
`);
|
|
6521
7409
|
if (hasBlockingFindings(findings)) blockedFiles += 1;
|
|
@@ -6757,6 +7645,58 @@ var COMMAND_EXAMPLES = {
|
|
|
6757
7645
|
for (const [name, text] of Object.entries(COMMAND_EXAMPLES)) {
|
|
6758
7646
|
program.commands.find((c) => c.name() === name)?.addHelpText("after", text);
|
|
6759
7647
|
}
|
|
7648
|
+
function findRepoPinnedCli(from) {
|
|
7649
|
+
const start = path2.resolve(from);
|
|
7650
|
+
const stopAt = gitRootOf(start) ?? start;
|
|
7651
|
+
let dir = start;
|
|
7652
|
+
for (; ; ) {
|
|
7653
|
+
const pkgDir = path2.join(dir, "node_modules", "@revturbine", "cli");
|
|
7654
|
+
const pkgJson = path2.join(pkgDir, "package.json");
|
|
7655
|
+
if (existsSync2(pkgJson)) {
|
|
7656
|
+
try {
|
|
7657
|
+
const pkg = JSON.parse(readFileSync2(pkgJson, "utf8"));
|
|
7658
|
+
const rel = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.revturbine;
|
|
7659
|
+
if (rel) {
|
|
7660
|
+
const entry = path2.resolve(pkgDir, rel);
|
|
7661
|
+
if (existsSync2(entry)) return { entry, version: pkg.version ?? "0.0.0" };
|
|
7662
|
+
}
|
|
7663
|
+
} catch {
|
|
7664
|
+
}
|
|
7665
|
+
return null;
|
|
7666
|
+
}
|
|
7667
|
+
if (dir === stopAt) return null;
|
|
7668
|
+
const parent = path2.dirname(dir);
|
|
7669
|
+
if (parent === dir) return null;
|
|
7670
|
+
dir = parent;
|
|
7671
|
+
}
|
|
7672
|
+
}
|
|
7673
|
+
function gitRootOf(from) {
|
|
7674
|
+
let dir = path2.resolve(from);
|
|
7675
|
+
for (; ; ) {
|
|
7676
|
+
if (existsSync2(path2.join(dir, ".git"))) return dir;
|
|
7677
|
+
const parent = path2.dirname(dir);
|
|
7678
|
+
if (parent === dir) return null;
|
|
7679
|
+
dir = parent;
|
|
7680
|
+
}
|
|
7681
|
+
}
|
|
7682
|
+
{
|
|
7683
|
+
const ownEntry = fileURLToPath(import.meta.url);
|
|
7684
|
+
const decision = planDelegation({
|
|
7685
|
+
ownEntry,
|
|
7686
|
+
ownVersion: pkgVersion,
|
|
7687
|
+
local: findRepoPinnedCli(process.cwd()),
|
|
7688
|
+
env: process.env,
|
|
7689
|
+
argv: process.argv
|
|
7690
|
+
});
|
|
7691
|
+
if (decision.delegate) {
|
|
7692
|
+
if (decision.skew) diag(skewNotice(decision.skew));
|
|
7693
|
+
const child = spawnSync(process.execPath, [decision.target, ...process.argv.slice(2)], {
|
|
7694
|
+
stdio: "inherit",
|
|
7695
|
+
env: { ...process.env, [DELEGATION_ENV]: "1" }
|
|
7696
|
+
});
|
|
7697
|
+
process.exit(child.status ?? EXIT.UNEXPECTED);
|
|
7698
|
+
}
|
|
7699
|
+
}
|
|
6760
7700
|
program.exitOverride();
|
|
6761
7701
|
try {
|
|
6762
7702
|
await program.parseAsync(process.argv);
|