@withandeo/cli 0.19.9 → 0.19.11
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 +18 -3
- package/dist/api.d.ts +0 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +0 -2
- package/dist/api.js.map +1 -1
- package/dist/contracts.d.ts +8 -0
- package/dist/contracts.d.ts.map +1 -1
- package/dist/documentation.d.ts +12 -2
- package/dist/documentation.d.ts.map +1 -1
- package/dist/documentation.js +107 -11
- package/dist/documentation.js.map +1 -1
- package/dist/flagship-browser.d.ts +18 -0
- package/dist/flagship-browser.d.ts.map +1 -0
- package/dist/flagship-browser.js +63 -0
- package/dist/flagship-browser.js.map +1 -0
- package/dist/flagship-contract.d.ts +4 -37
- package/dist/flagship-contract.d.ts.map +1 -1
- package/dist/flagship-contract.js +23 -65
- package/dist/flagship-contract.js.map +1 -1
- package/dist/flagship-definition.d.ts +67 -0
- package/dist/flagship-definition.d.ts.map +1 -0
- package/dist/flagship-definition.js +207 -0
- package/dist/flagship-definition.js.map +1 -0
- package/dist/flagship-runtime.d.ts +57 -0
- package/dist/flagship-runtime.d.ts.map +1 -0
- package/dist/flagship-runtime.js +79 -0
- package/dist/flagship-runtime.js.map +1 -0
- package/dist/main.js +79 -43
- package/dist/main.js.map +1 -1
- package/dist/public-skill-contract.d.ts +21 -0
- package/dist/public-skill-contract.d.ts.map +1 -0
- package/dist/public-skill-contract.js +47 -0
- package/dist/public-skill-contract.js.map +1 -0
- package/package.json +7 -2
- package/skill/publication.json +3 -0
- package/skill/tender-accounts/SKILL.md +3 -2
- package/skill/tender-accounts/references/feature-flags.md +140 -69
- package/skill/tender-accounts/references/managed-source.md +14 -2
- package/skill/tender-accounts/references/skills.md +7 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
export * from "./flagship-definition.js";
|
|
2
2
|
export type FlagEnvironment = "development" | "preview" | "production";
|
|
3
|
+
export declare const FLAG_DELETION_GUIDANCE = "Disable the flag, observe for unexpected behavior, remove its evaluations from application code, and deploy that change before deleting. Disabled status alone does not prove that no code still uses the flag.";
|
|
3
4
|
export interface FlagBinding {
|
|
4
5
|
binding: string;
|
|
5
6
|
app_id: string;
|
|
@@ -20,44 +21,10 @@ export declare function flagBindings(value: unknown): FlagBinding[];
|
|
|
20
21
|
export declare function parseFlagBindings(value: unknown): FlagBindings | undefined;
|
|
21
22
|
export declare function selectedFlagBindings(value: FlagBindings | undefined, environment: FlagEnvironment): FlagBinding[];
|
|
22
23
|
export declare function flagKey(value: unknown): string;
|
|
23
|
-
export
|
|
24
|
-
export declare function rolloutPercentage(value: unknown): number;
|
|
25
|
-
export interface BooleanFlag {
|
|
26
|
-
key: string;
|
|
27
|
-
description?: string;
|
|
28
|
-
enabled: boolean;
|
|
29
|
-
default_variation: "off";
|
|
30
|
-
variations: {
|
|
31
|
-
off: false;
|
|
32
|
-
on: true;
|
|
33
|
-
};
|
|
34
|
-
rules: Array<{
|
|
35
|
-
priority: number;
|
|
36
|
-
conditions: Array<{
|
|
37
|
-
attribute: "customerId";
|
|
38
|
-
operator: "in";
|
|
39
|
-
value: string[];
|
|
40
|
-
}>;
|
|
41
|
-
serve_variation: "on";
|
|
42
|
-
rollout?: {
|
|
43
|
-
percentage: number;
|
|
44
|
-
attribute: "customerId";
|
|
45
|
-
};
|
|
46
|
-
}>;
|
|
47
|
-
}
|
|
48
|
-
export declare function booleanFlag(key: string, enabled?: boolean, ids?: string[], percentage?: number, description?: string): BooleanFlag;
|
|
49
|
-
/** Reject unsupported dashboard edits instead of erasing them. Provider metadata is excluded. */
|
|
50
|
-
export declare function supportedFlag(value: unknown): {
|
|
51
|
-
definition: BooleanFlag;
|
|
52
|
-
ids: string[];
|
|
53
|
-
percentage: number;
|
|
54
|
-
};
|
|
55
|
-
export type FlagAction = "create" | "enable" | "disable" | "audience" | "rollout";
|
|
24
|
+
export type FlagAction = "create" | "enable" | "disable" | "apply";
|
|
56
25
|
export declare function changeFlag(current: unknown, action: FlagAction, input: {
|
|
57
26
|
key: string;
|
|
58
|
-
|
|
59
|
-
percentage?: unknown;
|
|
60
|
-
all?: boolean;
|
|
27
|
+
definition?: unknown;
|
|
61
28
|
}): Record<string, unknown>;
|
|
62
29
|
export declare function record(value: unknown): value is Record<string, unknown>;
|
|
63
30
|
//# sourceMappingURL=flagship-contract.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flagship-contract.d.ts","sourceRoot":"","sources":["../src/flagship-contract.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"flagship-contract.d.ts","sourceRoot":"","sources":["../src/flagship-contract.ts"],"names":[],"mappings":"AAEA,cAAc,0BAA0B,CAAC;AACzC,MAAM,MAAM,eAAe,GAAG,aAAa,GAAG,SAAS,GAAG,YAAY,CAAC;AACvE,eAAO,MAAM,sBAAsB,oNAAoN,CAAC;AACxP,MAAM,WAAW,WAAW;IAAG,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AAChE,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,GAAG,EAAE;QAAE,OAAO,EAAE;YAAE,QAAQ,EAAE,WAAW,EAAE,CAAA;SAAE,CAAC;QAAC,UAAU,EAAE;YAAE,QAAQ,EAAE,WAAW,EAAE,CAAA;SAAE,CAAA;KAAE,CAAC;CACxF;AACD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAG/D;AACD,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,EAAE,CAW1D;AACD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,GAAG,SAAS,CAe1E;AACD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,EAAE,WAAW,EAAE,eAAe,GAAG,WAAW,EAAE,CAEjH;AACD,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAG9C;AACD,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AACnE,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgBpI;AACD,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAA0E"}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/** Shared admission contract. No runtime rules engine: Cloudflare owns evaluation. */
|
|
2
|
+
import { validateFlagDefinition, observedFlagDefinition } from "./flagship-definition.js";
|
|
3
|
+
export * from "./flagship-definition.js";
|
|
4
|
+
export const FLAG_DELETION_GUIDANCE = "Disable the flag, observe for unexpected behavior, remove its evaluations from application code, and deploy that change before deleting. Disabled status alone does not prove that no code still uses the flag.";
|
|
1
5
|
export function flagEnvironment(value) {
|
|
2
6
|
if (value !== "development" && value !== "preview" && value !== "production")
|
|
3
7
|
throw new Error("flagship_environment_invalid");
|
|
@@ -42,76 +46,30 @@ export function selectedFlagBindings(value, environment) {
|
|
|
42
46
|
return value === undefined ? [] : environment === "development" ? value.flagship : value.env[environment].flagship;
|
|
43
47
|
}
|
|
44
48
|
export function flagKey(value) {
|
|
45
|
-
if (typeof value !== "string" || !/^[
|
|
49
|
+
if (typeof value !== "string" || !/^[A-Za-z0-9_-]{1,64}$/.test(value) || ["__proto__", "prototype", "constructor"].includes(value))
|
|
46
50
|
throw new Error("flagship_key_invalid");
|
|
47
51
|
return value;
|
|
48
52
|
}
|
|
49
|
-
export function customerIds(value) {
|
|
50
|
-
if (!Array.isArray(value) || value.length > 1000 || value.some(id => typeof id !== "string" || !id.trim() || id !== id.trim() || id.length > 128 || /[\x00-\x1f\x7f]/.test(id)))
|
|
51
|
-
throw new Error("flagship_audience_invalid");
|
|
52
|
-
return [...new Set(value)].sort();
|
|
53
|
-
}
|
|
54
|
-
export function rolloutPercentage(value) {
|
|
55
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > 100 || Number(value.toFixed(2)) !== value)
|
|
56
|
-
throw new Error("flagship_percentage_invalid");
|
|
57
|
-
return value;
|
|
58
|
-
}
|
|
59
|
-
export function booleanFlag(key, enabled = false, ids = [], percentage = 0, description) {
|
|
60
|
-
ids = customerIds(ids);
|
|
61
|
-
percentage = rolloutPercentage(percentage);
|
|
62
|
-
return { key: flagKey(key), ...(description === undefined ? {} : { description }), enabled, default_variation: "off", variations: { off: false, on: true }, rules: [
|
|
63
|
-
...(ids.length ? [{ priority: 1, conditions: [{ attribute: "customerId", operator: "in", value: ids }], serve_variation: "on" }] : []),
|
|
64
|
-
...(percentage > 0 ? [{ priority: 2, conditions: [], serve_variation: "on", rollout: { percentage, attribute: "customerId" } }] : []),
|
|
65
|
-
] };
|
|
66
|
-
}
|
|
67
|
-
/** Reject unsupported dashboard edits instead of erasing them. Provider metadata is excluded. */
|
|
68
|
-
export function supportedFlag(value) {
|
|
69
|
-
if (!record(value) || typeof value.enabled !== "boolean" || value.default_variation !== "off" || !record(value.variations)
|
|
70
|
-
|| value.variations.off !== false || value.variations.on !== true || Object.keys(value.variations).length !== 2
|
|
71
|
-
|| !Array.isArray(value.rules) || value.rules.length > 2 || (value.description !== undefined && typeof value.description !== "string"))
|
|
72
|
-
throw new Error("flagship_reconciliation_required");
|
|
73
|
-
let ids = [], percentage = 0;
|
|
74
|
-
for (const rule of value.rules) {
|
|
75
|
-
if (!record(rule) || Object.keys(rule).some(k => !["priority", "conditions", "serve_variation", "rollout"].includes(k)) || rule.serve_variation !== "on" || !Array.isArray(rule.conditions))
|
|
76
|
-
throw new Error("flagship_reconciliation_required");
|
|
77
|
-
if (rule.priority === 1 && rule.conditions.length === 1 && rule.rollout === undefined && !ids.length) {
|
|
78
|
-
const condition = rule.conditions[0];
|
|
79
|
-
if (!record(condition) || Object.keys(condition).some(k => !["attribute", "operator", "value"].includes(k)) || condition.attribute !== "customerId" || condition.operator !== "in")
|
|
80
|
-
throw new Error("flagship_reconciliation_required");
|
|
81
|
-
ids = customerIds(condition.value);
|
|
82
|
-
if (!ids.length)
|
|
83
|
-
throw new Error("flagship_reconciliation_required");
|
|
84
|
-
}
|
|
85
|
-
else if (rule.priority === 2 && rule.conditions.length === 0 && record(rule.rollout) && percentage === 0
|
|
86
|
-
&& Object.keys(rule.rollout).every(k => ["percentage", "attribute"].includes(k)) && rule.rollout.attribute === "customerId") {
|
|
87
|
-
percentage = rolloutPercentage(rule.rollout.percentage);
|
|
88
|
-
if (percentage === 0)
|
|
89
|
-
throw new Error("flagship_reconciliation_required");
|
|
90
|
-
}
|
|
91
|
-
else
|
|
92
|
-
throw new Error("flagship_reconciliation_required");
|
|
93
|
-
}
|
|
94
|
-
return { definition: booleanFlag(flagKey(value.key), value.enabled, ids, percentage, value.description), ids, percentage };
|
|
95
|
-
}
|
|
96
53
|
export function changeFlag(current, action, input) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
throw new Error("
|
|
104
|
-
|
|
105
|
-
|
|
54
|
+
flagKey(input.key);
|
|
55
|
+
if (action === "create" || action === "apply") {
|
|
56
|
+
const next = validateFlagDefinition(input.definition);
|
|
57
|
+
if (next.key !== input.key)
|
|
58
|
+
throw new Error("flagship_key_mismatch");
|
|
59
|
+
if (action === "create" && next.enabled)
|
|
60
|
+
throw new Error("flagship_create_disabled_required");
|
|
61
|
+
// Configuration editing cannot implicitly enable. Explicit enable remains separately reviewed.
|
|
62
|
+
if (action === "apply" && record(current) && next.enabled !== current.enabled)
|
|
63
|
+
throw new Error("flagship_enabled_change_requires_action");
|
|
64
|
+
return next;
|
|
65
|
+
}
|
|
66
|
+
if (action === "enable" || action === "disable") {
|
|
67
|
+
const definition = validateFlagDefinition(observedFlagDefinition(current));
|
|
68
|
+
if (definition.key !== input.key)
|
|
69
|
+
throw new Error("flagship_key_mismatch");
|
|
70
|
+
return { ...definition, enabled: action === "enable" };
|
|
106
71
|
}
|
|
107
|
-
|
|
108
|
-
if (definition.key !== input.key)
|
|
109
|
-
throw new Error("flagship_key_mismatch");
|
|
110
|
-
const nextIds = action === "audience" && !input.all ? customerIds(input.customerIds) : ids;
|
|
111
|
-
const nextPercentage = action === "rollout" ? rolloutPercentage(input.percentage) : action === "audience" && input.all ? 100 : percentage;
|
|
112
|
-
if (action === "enable" && !nextIds.length && nextPercentage === 0)
|
|
113
|
-
throw new Error("flagship_empty_audience");
|
|
114
|
-
return booleanFlag(input.key, action === "enable" ? true : definition.enabled, nextIds, nextPercentage, definition.description);
|
|
72
|
+
throw new Error("flagship_action_invalid");
|
|
115
73
|
}
|
|
116
74
|
export function record(value) { return !!value && typeof value === "object" && !Array.isArray(value); }
|
|
117
75
|
//# sourceMappingURL=flagship-contract.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flagship-contract.js","sourceRoot":"","sources":["../src/flagship-contract.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"flagship-contract.js","sourceRoot":"","sources":["../src/flagship-contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/** Admission and preset compilation only. Cloudflare owns evaluation and hashing.
|
|
2
|
+
* Wire contract pinned to wrangler 4.135.0 (src/flagship/client.ts, shared.ts).
|
|
3
|
+
*/
|
|
4
|
+
export declare const FLAGSHIP_SCHEMA = "cloudflare/wrangler@4.135.0";
|
|
5
|
+
export declare const FLAG_OPERATORS: readonly ["equals", "not_equals", "greater_than", "less_than", "greater_than_or_equals", "less_than_or_equals", "contains", "starts_with", "ends_with", "in", "not_in"];
|
|
6
|
+
export type FlagOperator = typeof FLAG_OPERATORS[number];
|
|
7
|
+
export type FlagValue = boolean | string | number | null | FlagValue[] | {
|
|
8
|
+
[key: string]: FlagValue;
|
|
9
|
+
};
|
|
10
|
+
export type FlagValueType = "boolean" | "string" | "number" | "json";
|
|
11
|
+
export type FlagContext = Record<string, string | number | boolean>;
|
|
12
|
+
export type FlagCondition = {
|
|
13
|
+
attribute: string;
|
|
14
|
+
operator: FlagOperator;
|
|
15
|
+
value: string | number | Array<string | number>;
|
|
16
|
+
} | {
|
|
17
|
+
logical_operator: "AND" | "OR";
|
|
18
|
+
clauses: FlagCondition[];
|
|
19
|
+
};
|
|
20
|
+
export interface FlagRule {
|
|
21
|
+
priority: number;
|
|
22
|
+
conditions: FlagCondition[];
|
|
23
|
+
serve_variation: string;
|
|
24
|
+
rollout?: {
|
|
25
|
+
percentage: number;
|
|
26
|
+
attribute?: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export interface FlagDefinition {
|
|
30
|
+
key: string;
|
|
31
|
+
description?: string;
|
|
32
|
+
enabled: boolean;
|
|
33
|
+
default_variation: string;
|
|
34
|
+
variations: Record<string, FlagValue>;
|
|
35
|
+
rules: FlagRule[];
|
|
36
|
+
}
|
|
37
|
+
export declare class FlagCompatibilityError extends Error {
|
|
38
|
+
readonly field: string;
|
|
39
|
+
readonly code = "flagship_definition_invalid";
|
|
40
|
+
constructor(field: string, detail: string);
|
|
41
|
+
}
|
|
42
|
+
export declare function flagValueType(value: unknown): FlagValueType;
|
|
43
|
+
/** Bound JSON before traversing or serializing. Do not coerce or change key/value case. */
|
|
44
|
+
export declare function safeFlagJson(value: unknown, path?: string, depth?: number): void;
|
|
45
|
+
export declare function flagContext(value?: unknown): FlagContext;
|
|
46
|
+
/** One pinned provider schema applies to every flag definition. */
|
|
47
|
+
export declare function validateFlagDefinition(value: unknown): FlagDefinition;
|
|
48
|
+
/** Known read-only metadata is stripped only for writes. Unknown fields survive inspection. */
|
|
49
|
+
export declare function observedFlagDefinition(value: unknown): Record<string, unknown>;
|
|
50
|
+
export declare function canonicalFlag(value: unknown): string;
|
|
51
|
+
export declare function flagDiff(before: unknown, after: unknown): Array<{
|
|
52
|
+
field: string;
|
|
53
|
+
before?: unknown;
|
|
54
|
+
after?: unknown;
|
|
55
|
+
}>;
|
|
56
|
+
export interface FlagSplit {
|
|
57
|
+
attribute: string;
|
|
58
|
+
conditions: FlagCondition[];
|
|
59
|
+
shares: Array<{
|
|
60
|
+
variant: string;
|
|
61
|
+
percentage: number;
|
|
62
|
+
}>;
|
|
63
|
+
}
|
|
64
|
+
export declare function compileFlagSplit(definition: FlagDefinition, split: FlagSplit): FlagDefinition;
|
|
65
|
+
export declare function parseFlagSplit(definition: FlagDefinition): FlagSplit | null;
|
|
66
|
+
export declare function globalBooleanFlag(key: string): FlagDefinition;
|
|
67
|
+
//# sourceMappingURL=flagship-definition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flagship-definition.d.ts","sourceRoot":"","sources":["../src/flagship-definition.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/** Admission and preset compilation only. Cloudflare owns evaluation and hashing.
|
|
2
|
+
* Wire contract pinned to wrangler 4.135.0 (src/flagship/client.ts, shared.ts).
|
|
3
|
+
*/
|
|
4
|
+
export const FLAGSHIP_SCHEMA = "cloudflare/wrangler@4.135.0";
|
|
5
|
+
export const FLAG_OPERATORS = ["equals", "not_equals", "greater_than", "less_than", "greater_than_or_equals", "less_than_or_equals", "contains", "starts_with", "ends_with", "in", "not_in"];
|
|
6
|
+
export class FlagCompatibilityError extends Error {
|
|
7
|
+
field;
|
|
8
|
+
code = "flagship_definition_invalid";
|
|
9
|
+
constructor(field, detail) {
|
|
10
|
+
super(`${field}: ${detail}`);
|
|
11
|
+
this.field = field;
|
|
12
|
+
this.name = "FlagCompatibilityError";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
const object = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
16
|
+
const badKeys = new Set(["__proto__", "prototype", "constructor"]);
|
|
17
|
+
function fail(path, message) { throw new FlagCompatibilityError(path, message); }
|
|
18
|
+
function fields(value, allowed, path) {
|
|
19
|
+
for (const key of Object.keys(value))
|
|
20
|
+
if (!allowed.includes(key))
|
|
21
|
+
fail(`${path}.${key}`, "Unsupported field for pinned provider schema; export and resolve compatibility before editing.");
|
|
22
|
+
}
|
|
23
|
+
function name(value, path, pattern = /^[A-Za-z0-9_-]{1,64}$/) {
|
|
24
|
+
if (typeof value !== "string" || !pattern.test(value) || badKeys.has(value))
|
|
25
|
+
fail(path, "Invalid name (maximum 64 characters).");
|
|
26
|
+
}
|
|
27
|
+
export function flagValueType(value) {
|
|
28
|
+
return typeof value === "boolean" ? "boolean" : typeof value === "string" ? "string" : typeof value === "number" ? "number" : "json";
|
|
29
|
+
}
|
|
30
|
+
/** Bound JSON before traversing or serializing. Do not coerce or change key/value case. */
|
|
31
|
+
export function safeFlagJson(value, path = "$", depth = 0) {
|
|
32
|
+
if (depth > 32)
|
|
33
|
+
fail(path, "JSON nesting exceeds 32 levels.");
|
|
34
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
35
|
+
return;
|
|
36
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
37
|
+
return;
|
|
38
|
+
if (Array.isArray(value)) {
|
|
39
|
+
value.forEach((v, i) => safeFlagJson(v, `${path}[${i}]`, depth + 1));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (object(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)) {
|
|
43
|
+
for (const [k, v] of Object.entries(value)) {
|
|
44
|
+
if (badKeys.has(k))
|
|
45
|
+
fail(`${path}.${k}`, "Unsafe object key.");
|
|
46
|
+
safeFlagJson(v, `${path}.${k}`, depth + 1);
|
|
47
|
+
}
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
fail(path, "Expected finite JSON data.");
|
|
51
|
+
}
|
|
52
|
+
export function flagContext(value = {}) {
|
|
53
|
+
if (!object(value) || Object.keys(value).length > 64)
|
|
54
|
+
fail("context", "Expected at most 64 scalar attributes.");
|
|
55
|
+
safeFlagJson(value, "context");
|
|
56
|
+
for (const [k, v] of Object.entries(value)) {
|
|
57
|
+
if (!k || k.length > 64 || /[\x00-\x1f\x7f]/.test(k))
|
|
58
|
+
fail(`context.${k}`, "Invalid attribute name.");
|
|
59
|
+
if (!["string", "boolean", "number"].includes(typeof v))
|
|
60
|
+
fail(`context.${k}`, "Context values must be string, number, or boolean.");
|
|
61
|
+
if (typeof v === "string" && v.length > 1024)
|
|
62
|
+
fail(`context.${k}`, "Context string exceeds 1024 characters.");
|
|
63
|
+
}
|
|
64
|
+
if (new TextEncoder().encode(JSON.stringify(value)).length > 16 * 1024)
|
|
65
|
+
fail("context", "Context exceeds 16 KB.");
|
|
66
|
+
return structuredClone(value);
|
|
67
|
+
}
|
|
68
|
+
function condition(value, path, depth) {
|
|
69
|
+
if (!object(value))
|
|
70
|
+
fail(path, "Expected condition object.");
|
|
71
|
+
if (depth > 5)
|
|
72
|
+
fail(path, "Provider condition nesting exceeds five levels.");
|
|
73
|
+
if ("logical_operator" in value || "clauses" in value) {
|
|
74
|
+
fields(value, ["logical_operator", "clauses"], path);
|
|
75
|
+
if (value.logical_operator !== "AND" && value.logical_operator !== "OR")
|
|
76
|
+
fail(`${path}.logical_operator`, "Expected AND or OR.");
|
|
77
|
+
if (!Array.isArray(value.clauses) || !value.clauses.length)
|
|
78
|
+
fail(`${path}.clauses`, "Expected nonempty clauses.");
|
|
79
|
+
value.clauses.forEach((v, i) => condition(v, `${path}.clauses[${i}]`, depth + 1));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
fields(value, ["attribute", "operator", "value"], path);
|
|
83
|
+
name(value.attribute, `${path}.attribute`, /^[^\x00-\x1f\x7f]{1,64}$/);
|
|
84
|
+
if (!FLAG_OPERATORS.includes(value.operator))
|
|
85
|
+
fail(`${path}.operator`, "Unknown provider operator.");
|
|
86
|
+
const operand = (v) => typeof v === "string" && v.length <= 256 || typeof v === "number" && Number.isFinite(v);
|
|
87
|
+
if (value.operator === "in" || value.operator === "not_in") {
|
|
88
|
+
if (!Array.isArray(value.value) || !value.value.every(operand))
|
|
89
|
+
fail(`${path}.value`, "Membership requires an array of strings or finite numbers.");
|
|
90
|
+
}
|
|
91
|
+
else if (["greater_than", "less_than", "greater_than_or_equals", "less_than_or_equals"].includes(value.operator)) {
|
|
92
|
+
if (!(typeof value.value === "number" && Number.isFinite(value.value)) && !(typeof value.value === "string" && value.value.length <= 256 && /^\d{4}-\d\d-\d\dT/.test(value.value) && Number.isFinite(Date.parse(value.value))))
|
|
93
|
+
fail(`${path}.value`, "Comparison requires a finite number or ISO 8601 datetime.");
|
|
94
|
+
}
|
|
95
|
+
else if (typeof value.value !== "string" || value.value.length > 256)
|
|
96
|
+
fail(`${path}.value`, "This provider operator requires a string of at most 256 characters.");
|
|
97
|
+
}
|
|
98
|
+
/** One pinned provider schema applies to every flag definition. */
|
|
99
|
+
export function validateFlagDefinition(value) {
|
|
100
|
+
safeFlagJson(value);
|
|
101
|
+
if (!object(value))
|
|
102
|
+
fail("$", "Expected a flag definition.");
|
|
103
|
+
fields(value, ["key", "description", "enabled", "default_variation", "variations", "rules"], "$");
|
|
104
|
+
name(value.key, "$.key");
|
|
105
|
+
if (value.description !== undefined && (typeof value.description !== "string" || value.description.length > 512))
|
|
106
|
+
fail("$.description", "Expected at most 512 characters.");
|
|
107
|
+
if (typeof value.enabled !== "boolean")
|
|
108
|
+
fail("$.enabled", "Expected boolean.");
|
|
109
|
+
if (!object(value.variations) || !Object.keys(value.variations).length)
|
|
110
|
+
fail("$.variations", "Expected named variants.");
|
|
111
|
+
let type;
|
|
112
|
+
for (const [k, v] of Object.entries(value.variations)) {
|
|
113
|
+
name(k, `$.variations.${k}`);
|
|
114
|
+
const actual = flagValueType(v);
|
|
115
|
+
if (type && actual !== type)
|
|
116
|
+
fail(`$.variations.${k}`, "All variants must share one value type.");
|
|
117
|
+
type = actual;
|
|
118
|
+
// Conservative decimal KB until provider byte-unit enforcement is hosted-verified.
|
|
119
|
+
if (new TextEncoder().encode(JSON.stringify(v)).length > 10000)
|
|
120
|
+
fail(`$.variations.${k}`, "Serialized variant exceeds 10 KB.");
|
|
121
|
+
}
|
|
122
|
+
if (typeof value.default_variation !== "string" || !Object.hasOwn(value.variations, value.default_variation))
|
|
123
|
+
fail("$.default_variation", "Default must reference a variant.");
|
|
124
|
+
if (!Array.isArray(value.rules))
|
|
125
|
+
fail("$.rules", "Expected ordered rules.");
|
|
126
|
+
const priorities = new Set();
|
|
127
|
+
value.rules.forEach((r, i) => {
|
|
128
|
+
const path = `$.rules[${i}]`;
|
|
129
|
+
if (!object(r))
|
|
130
|
+
fail(path, "Expected rule object.");
|
|
131
|
+
fields(r, ["priority", "conditions", "serve_variation", "rollout"], path);
|
|
132
|
+
if (typeof r.priority !== "number" || !Number.isSafeInteger(r.priority) || r.priority < 1 || priorities.has(r.priority))
|
|
133
|
+
fail(`${path}.priority`, "Expected unique positive integer priority.");
|
|
134
|
+
priorities.add(r.priority);
|
|
135
|
+
if (typeof r.serve_variation !== "string" || !Object.hasOwn(value.variations, r.serve_variation))
|
|
136
|
+
fail(`${path}.serve_variation`, "Rule must reference a variant.");
|
|
137
|
+
if (!Array.isArray(r.conditions))
|
|
138
|
+
fail(`${path}.conditions`, "Expected condition array.");
|
|
139
|
+
r.conditions.forEach((c, j) => condition(c, `${path}.conditions[${j}]`, 1));
|
|
140
|
+
if (r.rollout !== undefined) {
|
|
141
|
+
if (!object(r.rollout))
|
|
142
|
+
fail(`${path}.rollout`, "Expected rollout object.");
|
|
143
|
+
fields(r.rollout, ["percentage", "attribute"], `${path}.rollout`);
|
|
144
|
+
if (typeof r.rollout.percentage !== "number" || !Number.isFinite(r.rollout.percentage) || r.rollout.percentage < 0 || r.rollout.percentage > 100
|
|
145
|
+
|| Number(r.rollout.percentage.toFixed(2)) !== r.rollout.percentage)
|
|
146
|
+
fail(`${path}.rollout.percentage`, "Expected percentage from 0 through 100 with at most two decimal places.");
|
|
147
|
+
if (r.rollout.attribute !== undefined)
|
|
148
|
+
name(r.rollout.attribute, `${path}.rollout.attribute`, /^[^\x00-\x1f\x7f]{1,64}$/);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
if (new TextEncoder().encode(JSON.stringify(value)).length > 192 * 1024)
|
|
152
|
+
fail("$", "Andeo definition admission limit is 192 KB (separate from provider app quota).");
|
|
153
|
+
return structuredClone(value);
|
|
154
|
+
}
|
|
155
|
+
/** Known read-only metadata is stripped only for writes. Unknown fields survive inspection. */
|
|
156
|
+
export function observedFlagDefinition(value) {
|
|
157
|
+
if (!object(value))
|
|
158
|
+
fail("$", "Invalid provider response.");
|
|
159
|
+
const metadata = new Set(["id", "type", "created_at", "updated_at", "updated_by", "created_on", "modified_on", "app_id", "version"]);
|
|
160
|
+
return Object.fromEntries(Object.entries(value).filter(([k, v]) => !metadata.has(k) && v !== undefined && !(k === "description" && v === null)));
|
|
161
|
+
}
|
|
162
|
+
export function canonicalFlag(value) {
|
|
163
|
+
const sort = (v) => Array.isArray(v) ? v.map(sort) : object(v) ? Object.fromEntries(Object.keys(v).sort().map(k => [k, sort(v[k])])) : v;
|
|
164
|
+
return JSON.stringify(sort(value));
|
|
165
|
+
}
|
|
166
|
+
export function flagDiff(before, after) {
|
|
167
|
+
if (!object(before) || !object(after))
|
|
168
|
+
return canonicalFlag(before) === canonicalFlag(after) ? [] : [{ field: "$", before, after }];
|
|
169
|
+
return [...new Set([...Object.keys(before), ...Object.keys(after)])].filter(k => canonicalFlag(before[k]) !== canonicalFlag(after[k])).map(k => ({ field: k, before: before[k], after: after[k] }));
|
|
170
|
+
}
|
|
171
|
+
export function compileFlagSplit(definition, split) {
|
|
172
|
+
name(split.attribute, "split.attribute", /^[^\x00-\x1f\x7f]{1,64}$/);
|
|
173
|
+
if (split.shares.length < 2 || new Set(split.shares.map(s => s.variant)).size !== split.shares.length)
|
|
174
|
+
fail("split.shares", "Expected at least two distinct variants.");
|
|
175
|
+
let threshold = 0;
|
|
176
|
+
const rules = split.shares.map((s, i) => {
|
|
177
|
+
if (!Number.isFinite(s.percentage) || s.percentage <= 0 || s.percentage > 100 || Number(s.percentage.toFixed(2)) !== s.percentage)
|
|
178
|
+
fail(`split.shares[${i}].percentage`, "Shares must be positive percentages with at most two decimals.");
|
|
179
|
+
threshold = Math.round((threshold + s.percentage) * 100) / 100;
|
|
180
|
+
return { priority: i + 1, conditions: structuredClone(split.conditions), serve_variation: s.variant, rollout: { percentage: threshold, attribute: split.attribute } };
|
|
181
|
+
});
|
|
182
|
+
if (threshold !== 100)
|
|
183
|
+
fail("split.shares", "Shares must total 100% of eligible traffic. Partial enrollment requires advanced rules.");
|
|
184
|
+
return validateFlagDefinition({ ...definition, rules });
|
|
185
|
+
}
|
|
186
|
+
export function parseFlagSplit(definition) {
|
|
187
|
+
if (definition.rules.length < 2)
|
|
188
|
+
return null;
|
|
189
|
+
const first = definition.rules[0];
|
|
190
|
+
if (!first.rollout?.attribute)
|
|
191
|
+
return null;
|
|
192
|
+
let previous = 0;
|
|
193
|
+
const variants = new Set(), shares = [];
|
|
194
|
+
for (const [i, r] of definition.rules.entries()) {
|
|
195
|
+
if (r.priority !== i + 1 || !r.rollout || r.rollout.attribute !== first.rollout.attribute || canonicalFlag(r.conditions) !== canonicalFlag(first.conditions)
|
|
196
|
+
|| r.rollout.percentage <= previous || variants.has(r.serve_variation))
|
|
197
|
+
return null;
|
|
198
|
+
shares.push({ variant: r.serve_variation, percentage: Math.round((r.rollout.percentage - previous) * 100) / 100 });
|
|
199
|
+
previous = r.rollout.percentage;
|
|
200
|
+
variants.add(r.serve_variation);
|
|
201
|
+
}
|
|
202
|
+
return previous === 100 ? { attribute: first.rollout.attribute, conditions: structuredClone(first.conditions), shares } : null;
|
|
203
|
+
}
|
|
204
|
+
export function globalBooleanFlag(key) {
|
|
205
|
+
return validateFlagDefinition({ key, enabled: false, default_variation: "off", variations: { off: false, on: true }, rules: [{ priority: 1, conditions: [], serve_variation: "on" }] });
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=flagship-definition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flagship-definition.js","sourceRoot":"","sources":["../src/flagship-definition.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { type FlagContext, type FlagValue, type FlagValueType } from "./flagship-contract.js";
|
|
2
|
+
export interface NativeFlagDetails<T = FlagValue> {
|
|
3
|
+
flagKey: string;
|
|
4
|
+
value: T;
|
|
5
|
+
variant?: string;
|
|
6
|
+
reason?: string;
|
|
7
|
+
errorCode?: string;
|
|
8
|
+
}
|
|
9
|
+
/** Structural native binding contract; no rules, hashes or provider credentials. */
|
|
10
|
+
export interface NativeFlags {
|
|
11
|
+
getBooleanDetails(key: string, fallback: boolean, context?: FlagContext): Promise<NativeFlagDetails<boolean>>;
|
|
12
|
+
getStringDetails(key: string, fallback: string, context?: FlagContext): Promise<NativeFlagDetails<string>>;
|
|
13
|
+
getNumberDetails(key: string, fallback: number, context?: FlagContext): Promise<NativeFlagDetails<number>>;
|
|
14
|
+
getObjectDetails<T>(key: string, fallback: T, context?: FlagContext): Promise<NativeFlagDetails<T>>;
|
|
15
|
+
}
|
|
16
|
+
export interface ClientVisibleFlag {
|
|
17
|
+
key: string;
|
|
18
|
+
type: FlagValueType;
|
|
19
|
+
fallback: FlagValue;
|
|
20
|
+
}
|
|
21
|
+
export interface FlagBootstrap {
|
|
22
|
+
schema: "andeo.flag-bootstrap/v1";
|
|
23
|
+
environment: string;
|
|
24
|
+
refreshAfterMs: number;
|
|
25
|
+
values: Record<string, NativeFlagDetails>;
|
|
26
|
+
}
|
|
27
|
+
export declare function nativeFlagDetails(binding: NativeFlags, flag: ClientVisibleFlag, context: FlagContext): Promise<NativeFlagDetails>;
|
|
28
|
+
/** Application-owned GET endpoint/SSR bootstrap. The server chooses scope and keys;
|
|
29
|
+
* resolveContext must authenticate/enrich trusted properties and select only
|
|
30
|
+
* designated presentation attributes. No management credential or private rules.
|
|
31
|
+
*/
|
|
32
|
+
export declare function createFlagGateway(input: {
|
|
33
|
+
binding: NativeFlags;
|
|
34
|
+
environment: string;
|
|
35
|
+
flags: readonly ClientVisibleFlag[];
|
|
36
|
+
resolveContext: (request: Request) => FlagContext | Promise<FlagContext>;
|
|
37
|
+
refreshAfterMs?: number;
|
|
38
|
+
}): (request: Request) => Promise<Response>;
|
|
39
|
+
export interface FlagExposure {
|
|
40
|
+
flagKey: string;
|
|
41
|
+
variant: string;
|
|
42
|
+
reason?: string;
|
|
43
|
+
environment: string;
|
|
44
|
+
experimentVersion: string;
|
|
45
|
+
}
|
|
46
|
+
/** Call only when the application actually shows an experience. Caller chooses
|
|
47
|
+
* deduplication lifetime and measurement destination; no raw context is emitted.
|
|
48
|
+
*/
|
|
49
|
+
export declare function flagExposure(details: NativeFlagDetails, environment: string, experimentVersion: string): FlagExposure | null;
|
|
50
|
+
/** Optional server-owned one-year anonymous cookie. Reuse on browser and server
|
|
51
|
+
* actions; login does not change it. Explicit reset returns a new identity.
|
|
52
|
+
*/
|
|
53
|
+
export declare function flagVisitorIdentity(request: Request, reset?: boolean): {
|
|
54
|
+
targetingKey: string;
|
|
55
|
+
setCookie?: string;
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=flagship-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flagship-runtime.d.ts","sourceRoot":"","sources":["../src/flagship-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqD,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEjJ,MAAM,WAAW,iBAAiB,CAAC,CAAC,GAAG,SAAS;IAAI,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE;AACtI,oFAAoF;AACpF,MAAM,WAAW,WAAW;IAC1B,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC;IAC9G,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3G,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3G,gBAAgB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;CACrG;AACD,MAAM,WAAW,iBAAiB;IAAG,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAA;CAAE;AAC5F,MAAM,WAAW,aAAa;IAAG,MAAM,EAAE,yBAAyB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;CAAE;AAC5J,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,CASvI;AACD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IAAE,OAAO,EAAE,WAAW,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACxH,cAAc,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,aAO5E,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC,CAmBnD;AACD,MAAM,WAAW,YAAY;IAAG,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE;AACnI;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAG5H;AACD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,UAAQ,GAAG;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAOjH"}
|