@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.
Files changed (39) hide show
  1. package/README.md +18 -3
  2. package/dist/api.d.ts +0 -1
  3. package/dist/api.d.ts.map +1 -1
  4. package/dist/api.js +0 -2
  5. package/dist/api.js.map +1 -1
  6. package/dist/contracts.d.ts +8 -0
  7. package/dist/contracts.d.ts.map +1 -1
  8. package/dist/documentation.d.ts +12 -2
  9. package/dist/documentation.d.ts.map +1 -1
  10. package/dist/documentation.js +107 -11
  11. package/dist/documentation.js.map +1 -1
  12. package/dist/flagship-browser.d.ts +18 -0
  13. package/dist/flagship-browser.d.ts.map +1 -0
  14. package/dist/flagship-browser.js +63 -0
  15. package/dist/flagship-browser.js.map +1 -0
  16. package/dist/flagship-contract.d.ts +4 -37
  17. package/dist/flagship-contract.d.ts.map +1 -1
  18. package/dist/flagship-contract.js +23 -65
  19. package/dist/flagship-contract.js.map +1 -1
  20. package/dist/flagship-definition.d.ts +67 -0
  21. package/dist/flagship-definition.d.ts.map +1 -0
  22. package/dist/flagship-definition.js +207 -0
  23. package/dist/flagship-definition.js.map +1 -0
  24. package/dist/flagship-runtime.d.ts +57 -0
  25. package/dist/flagship-runtime.d.ts.map +1 -0
  26. package/dist/flagship-runtime.js +79 -0
  27. package/dist/flagship-runtime.js.map +1 -0
  28. package/dist/main.js +79 -43
  29. package/dist/main.js.map +1 -1
  30. package/dist/public-skill-contract.d.ts +21 -0
  31. package/dist/public-skill-contract.d.ts.map +1 -0
  32. package/dist/public-skill-contract.js +47 -0
  33. package/dist/public-skill-contract.js.map +1 -0
  34. package/package.json +7 -2
  35. package/skill/publication.json +3 -0
  36. package/skill/tender-accounts/SKILL.md +3 -2
  37. package/skill/tender-accounts/references/feature-flags.md +140 -69
  38. package/skill/tender-accounts/references/managed-source.md +14 -2
  39. package/skill/tender-accounts/references/skills.md +7 -0
@@ -0,0 +1,21 @@
1
+ export declare const PUBLIC_SKILL_URL = "https://agents.withandeo.com/public/skills/andeo";
2
+ export declare const PUBLIC_SKILL_KEY = "public/andeo/v1/latest.json";
3
+ export declare const MAX_PUBLIC_SKILL_BYTES: number;
4
+ export interface PublicSkillFile {
5
+ path: string;
6
+ content: string;
7
+ sha256: string;
8
+ bytes: number;
9
+ }
10
+ export interface PublicSkillBundle {
11
+ schema: "andeo.public-skill/v1";
12
+ name: "andeo";
13
+ revision: string;
14
+ minimumCliVersion: string;
15
+ files: PublicSkillFile[];
16
+ }
17
+ export declare function publicSkillPath(path: string): boolean;
18
+ export declare function parsePublicSkillBundle(value: unknown): PublicSkillBundle;
19
+ export declare function publicSkillRevisionInput(bundle: Pick<PublicSkillBundle, "minimumCliVersion" | "files">): string;
20
+ export declare function verifyPublicSkillBundle(bundle: PublicSkillBundle, sha256: (bytes: Uint8Array<ArrayBuffer>) => Promise<string>): Promise<void>;
21
+ //# sourceMappingURL=public-skill-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"public-skill-contract.d.ts","sourceRoot":"","sources":["../src/public-skill-contract.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,qDAAqD,CAAC;AACnF,eAAO,MAAM,gBAAgB,gCAAgC,CAAC;AAC9D,eAAO,MAAM,sBAAsB,QAAc,CAAC;AAElD,MAAM,WAAW,eAAe;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AACjG,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,uBAAuB,CAAC;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,eAAe,EAAE,CAAC;CAC1B;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB,CAkBxE;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,IAAI,CAAC,iBAAiB,EAAE,mBAAmB,GAAG,OAAO,CAAC,GAAG,MAAM,CAG/G;AAED,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,EACrE,MAAM,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,WAAW,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAO5E"}
@@ -0,0 +1,47 @@
1
+ export const PUBLIC_SKILL_URL = "https://agents.withandeo.com/public/skills/andeo";
2
+ export const PUBLIC_SKILL_KEY = "public/andeo/v1/latest.json";
3
+ export const MAX_PUBLIC_SKILL_BYTES = 1024 * 1024;
4
+ export function publicSkillPath(path) {
5
+ return path === "SKILL.md" || /^references\/[A-Za-z0-9][A-Za-z0-9._-]*\.md$/u.test(path);
6
+ }
7
+ export function parsePublicSkillBundle(value) {
8
+ const hash = /^[a-f0-9]{64}$/u;
9
+ if (!record(value) || value.schema !== "andeo.public-skill/v1" || value.name !== "andeo"
10
+ || typeof value.revision !== "string" || !hash.test(value.revision)
11
+ || typeof value.minimumCliVersion !== "string" || !/^\d{1,6}\.\d{1,6}\.\d{1,6}$/u.test(value.minimumCliVersion)
12
+ || !Array.isArray(value.files) || value.files.length < 1 || value.files.length > 100)
13
+ throw invalid();
14
+ const paths = new Set();
15
+ const files = value.files.map(file => {
16
+ if (!record(file) || typeof file.path !== "string" || file.path.length > 240 || !publicSkillPath(file.path)
17
+ || paths.has(file.path) || typeof file.content !== "string" || file.content.length > MAX_PUBLIC_SKILL_BYTES
18
+ || typeof file.sha256 !== "string" || !hash.test(file.sha256) || !Number.isSafeInteger(file.bytes)
19
+ || file.bytes < 1 || file.bytes > 512 * 1024)
20
+ throw invalid();
21
+ paths.add(file.path);
22
+ return { path: file.path, content: file.content, sha256: file.sha256, bytes: file.bytes };
23
+ });
24
+ if (!paths.has("SKILL.md"))
25
+ throw invalid();
26
+ return { schema: "andeo.public-skill/v1", name: "andeo", revision: value.revision,
27
+ minimumCliVersion: value.minimumCliVersion, files };
28
+ }
29
+ export function publicSkillRevisionInput(bundle) {
30
+ return JSON.stringify({ minimumCliVersion: bundle.minimumCliVersion,
31
+ files: bundle.files.map(({ path, sha256, bytes }) => ({ path, sha256, bytes })) });
32
+ }
33
+ export async function verifyPublicSkillBundle(bundle, sha256) {
34
+ const encoder = new TextEncoder();
35
+ for (const file of bundle.files) {
36
+ const bytes = encoder.encode(file.content);
37
+ if (bytes.byteLength !== file.bytes || await sha256(bytes) !== file.sha256)
38
+ throw invalid();
39
+ }
40
+ if (await sha256(encoder.encode(publicSkillRevisionInput(bundle))) !== bundle.revision)
41
+ throw invalid();
42
+ }
43
+ function record(value) {
44
+ return typeof value === "object" && value !== null && !Array.isArray(value);
45
+ }
46
+ function invalid() { return new Error("The public Andeo skill bundle is invalid."); }
47
+ //# sourceMappingURL=public-skill-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"public-skill-contract.js","sourceRoot":"","sources":["../src/public-skill-contract.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@withandeo/cli",
3
- "version": "0.19.9",
3
+ "version": "0.19.11",
4
4
  "description": "Developer CLI for Andeo applications",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -27,6 +27,8 @@
27
27
  "prepack": "npm run sync:starter && npm run check"
28
28
  },
29
29
  "devDependencies": {
30
+ "@cloudflare/flagship": "0.5.0",
31
+ "@openfeature/server-sdk": "1.23.0",
30
32
  "@types/node": "^26.2.0",
31
33
  "typescript": "^7.0.2",
32
34
  "vitest": "^4.1.11"
@@ -39,7 +41,10 @@
39
41
  "smol-toml": "1.8.0"
40
42
  },
41
43
  "exports": {
42
- "./cli": "./dist/main.js"
44
+ "./cli": "./dist/main.js",
45
+ "./flagship-runtime": "./dist/flagship-runtime.js",
46
+ "./flagship-browser": "./dist/flagship-browser.js",
47
+ "./package": "./dist/workflow-package.js"
43
48
  },
44
49
  "publishConfig": {
45
50
  "access": "public"
@@ -0,0 +1,3 @@
1
+ {
2
+ "minimumCliVersion": "0.19.11"
3
+ }
@@ -23,7 +23,7 @@ Use `npx @withandeo/cli` as the merchant platform interface. Keep merchant behav
23
23
  | Define or operate background work | [Workflows](references/workflows.md) |
24
24
  | Public configuration or private tokens | [Configuration and secrets](references/configuration-secrets.md) |
25
25
  | Declare resources or evolve app-owned state | [Storage](references/storage.md) |
26
- | Guard operations with selected customers or percentage rollouts | [Feature flags](references/feature-flags.md); authenticated `feature-flags` skill |
26
+ | Manage typed feature flags, experiments, collections and runtime guards | [Feature flags](references/feature-flags.md); authenticated `feature-flags` skill |
27
27
  | Connect private apps or workflow services | [Services](references/services.md) |
28
28
  | Custom domains and customer sign-in | [Domains and authentication](references/domains-auth.md) |
29
29
  | Diagnose requests or workflow execution | [Observability](references/observability.md) |
@@ -75,7 +75,8 @@ The source defaults to HEAD; the destination remains independent. Confirm the
75
75
  returned `sourceRevision` and `sourceDiffersFromHead`. Dirty files are excluded,
76
76
  and reviewed repositories still protect their default branch.
77
77
 
78
- For a protected managed repository, read the managed-source reference and use
78
+ For a managed repository with source protection or an explicit native-preview
79
+ agent merge grant, verify the exact branch preview, read the managed-source reference and use
79
80
  `andeo source merge --head BRANCH --title TITLE --expected-head PUSHED_SHA --idempotency-key KEY --wait --json`
80
81
  to request hosted landing and follow the saved publication policy. Inspect required
81
82
  human review, deployment and cleanup outcomes separately; do not push main to bypass them.
@@ -1,90 +1,161 @@
1
- # Tenant feature flags
1
+ # Flexible feature flags
2
2
 
3
- This CLI implements boolean flag management and native Cloudflare Flagship declarations.
4
- Availability requires tenant enablement, a project grant, provisioned environment apps,
5
- and configured trusted management. Run `andeo capabilities --json` and `andeo doctor`;
6
- `implemented_pending_hosted_proof` does not certify a deployed binding. Read the
7
- authenticated `feature-flags` skill with `andeo skills get feature-flags --json`.
3
+ Andeo wraps native Cloudflare Flagship: boolean/string/number/JSON variants,
4
+ configured defaults, ordered rules, nested targeting and weighted experiments.
5
+ Use `andeo capabilities --json`, `andeo doctor` and the authenticated
6
+ `andeo skills get feature-flags --json`. Local implementation is not hosted proof.
7
+ Use `andeo flagship --help` for this installed version's exact commands.
8
8
 
9
- Use an explicit environment on every command. Administrators connect projects with
10
- `andeo flagship apps ensure --env preview --json`. That grants only this project to
11
- the tenant's shared preview app. Developers manage granted nonproduction apps;
12
- production writes require the credential owner's current merchant-admin role.
13
- Viewers cannot mutate. A Cloudflare app ID alone gives no permission.
9
+ Every remote command requires explicit `--env development|preview|production`,
10
+ tenant enablement and a project grant. Current administrators connect collections
11
+ and perform lifecycle changes; developers edit granted nonproduction flags;
12
+ production writes require current administrator authority; viewers read only.
13
+ An app ID alone is not authorization. Tenant quota remains at most three apps
14
+ across environments/collections, separate from Cloudflare limits.
14
15
 
15
16
  ```sh
17
+ andeo flagship apps ensure --collection checkout --env preview --json
16
18
  andeo flagship apps list --env preview --json
17
- andeo flagship flags create APP_ID example-feature --env preview --json
18
- andeo flagship flags audience APP_ID example-feature --env preview --customer-ids-file ./synthetic-ids.json --json
19
- andeo flagship flags evaluate APP_ID example-feature --env preview --context customerId=synthetic-customer-a --json
20
- andeo flagship flags enable APP_ID example-feature --env preview --json
21
- andeo flagship flags rollout APP_ID example-feature --env preview --to on --percentage 5 --by customerId --json
22
- andeo flagship flags disable APP_ID example-feature --env preview --json
23
- andeo flagship flags get APP_ID example-feature --env preview --json
24
- andeo flagship flags reconcile APP_ID example-feature --env preview --json
25
- andeo flagship flags changelog APP_ID example-feature --env preview --json
19
+ andeo flagship flags validate --file ./definition.json --json
20
+ andeo flagship flags create APP_ID checkout-layout --file ./definition.json --env preview --json
21
+ andeo flagship flags export APP_ID checkout-layout --env preview --json
22
+ andeo flagship flags diff APP_ID checkout-layout --file ./edited.json --env preview --json
23
+ andeo flagship flags apply APP_ID checkout-layout --file ./edited.json --expected-revision 3 --expected-digest OBSERVED_DIGEST --env preview --json
24
+ andeo flagship flags evaluate APP_ID checkout-layout --context-file ./synthetic-context.json --type string --fallback-file ./fallback.json --env preview --json
25
+ andeo flagship flags enable APP_ID checkout-layout --env preview --json
26
+ andeo flagship flags disable APP_ID checkout-layout --env preview --json
27
+ andeo flagship flags reconcile APP_ID checkout-layout --env preview --json
28
+ andeo flagship flags changelog APP_ID checkout-layout --env preview --json
26
29
  ```
27
30
 
28
- Create defaults to disabled, no selected customers, 0%, and false fallback.
29
- Customer files contain bounded JSON arrays of strings, for example
30
- `["synthetic-customer-a"]`. Do not commit real customer inventories. 0% still
31
- admits selected customers when enabled. `audience --all` selects 100% without
32
- discarding the list. Audience and percentage edits preserve each other and never
33
- enable a disabled flag. Enable rejects an empty list with 0%.
31
+ Offline validate needs no auth or environment. Definitions use the pinned
32
+ Wrangler 4.135.0 schema: key, description?, enabled, default_variation, variations,
33
+ rules. A rule has priority, conditions, serve_variation and optional rollout
34
+ {percentage, attribute?}; a nested condition has logical_operator and clauses.
35
+ All variants share one type. Create requires `--file` and starts disabled. Apply preserves
36
+ enabled state, requires the observed revision/digest and cannot enable implicitly.
37
+ Export returns an envelope: extract `definition` for editing, retain `observed`
38
+ and compatibility diagnostics for unknown fields. Inspect the complete diff first.
34
39
 
35
- Ordinary edits read a revision first; pass `--expected-revision N` to use a
36
- previous observation. The service checks it inside durable serialization.
37
- A stale edit cannot overwrite a newer Disable. Unknown provider outcomes block
38
- conflicting changes until `reconcile` reads the requested definition back.
39
- External unsupported rules require operator reconciliation; emergency Disable
40
- preserves them only when the observed default variation is false.
40
+ Native disabled evaluation returns the configured default, which can be true or
41
+ non-boolean. Choose false defaults/fallbacks for business guards. Caller fallback
42
+ is distinct from default and type mismatch. The official OpenFeature provider
43
+ 0.5.0 returns caller fallback on DISABLED; native details return configured default.
41
44
 
42
- In `tender-app.config.json`, preserve the rest of your app contract and add:
45
+ Context files are bounded JSON objects of string/number/boolean properties, including
46
+ {}. Native evaluation supports these types. Current management REST transport only
47
+ verifies strings and rejects numbers/booleans with
48
+ flagship_typed_management_context_unverified; no implicit string coercion occurs.
49
+ Use synthetic fixtures, never commit customer inventories.
50
+
51
+ Experiments use positive shares totaling 100% of eligible traffic, compiled into
52
+ cumulative thresholds with identical eligibility and bucketing attribute. A 50/50
53
+ split is thresholds 50 then 100, not independent 50/50 rules. Variant names differ
54
+ from returned values. Default control is not enrolled control: inspect reason and
55
+ variant. Missing targetingKey can assign randomly. Use stable server-owned IDs for
56
+ sticky assignment; request IDs deliberately sample requests. Changing app, weights,
57
+ eligibility or attribute can change assignment. Exposure occurs when the experience
58
+ is actually shown. Assignment is not conversion analysis/statistical significance.
59
+
60
+ All flags use the general definition model. Targeting and rollouts are configured
61
+ through rules in the full definition. Evaluation accepts `--context-file` or empty
62
+ context; customerId is an ordinary attribute. There are no customer-specific
63
+ commands, automatic definitions or old-key validation exceptions.
64
+
65
+ External changes require explicit reconciliation. Unknown outcomes retain pending
66
+ intent and block conflicting writes; never blindly replay. Disable keeps
67
+ the full compatible typed definition and requires external edits to be reconciled.
68
+ Unknown writable fields block all edits, including Disable. Save/readback means changes are propagating,
69
+ not globally cut over; runtime propagation and browser refresh add delay.
70
+
71
+ ```sh
72
+ andeo flagship apps get APP_ID --env preview --json
73
+ andeo flagship apps rename APP_ID --name reviewed-provider-name --expected-revision 0 --env preview --json
74
+ andeo flagship apps disconnect APP_ID --confirm PROJECT_ID --expected-revision 1 --env preview --json
75
+ andeo flagship flags delete APP_ID KEY --confirm KEY --expected-revision 4 --expected-digest OBSERVED_DIGEST --env preview --json
76
+ andeo flagship apps delete APP_ID --confirm APP_ID --expected-revision 2 --env preview --json
77
+ ```
78
+
79
+ Inspect affected projects and receipts. Retained builds block disconnect; grants
80
+ and flags block app deletion. Deletion has no restore guarantee. Tombstones retain
81
+ revisions; ensure never recreates deleted or pending collections. App reconcile
82
+ requires expected revision. Promotion/history reapplication use an exported exact
83
+ definition, current destination enabled state, current revision/digest and reviewed
84
+ diff/apply, followed by separate Enable. Deployment/rollback never copies flags.
85
+
86
+ Flag deletion requires a disabled saved provider definition. Disable, observe,
87
+ remove its evaluations from application code, and deploy before using `--confirm
88
+ KEY`. Disabled status alone does not prove that no code still uses the flag;
89
+ Andeo does not detect remaining evaluations automatically. Refresh the revision
90
+ and digest after Disable. Final readback rejects re-enabling or definition changes
91
+ during review; it cannot atomically prevent external provider edits after the read.
92
+
93
+ Declare the native binding separately for every environment in tender-app.config.json:
43
94
 
44
95
  ```json
45
96
  {
46
- "flagship": [{"binding":"FLAGS","app_id":"DEVELOPMENT_APP_ID"}],
47
- "env": {
48
- "preview": {"flagship":[{"binding":"FLAGS","app_id":"PREVIEW_APP_ID"}]},
49
- "production": {"flagship":[{"binding":"FLAGS","app_id":"PRODUCTION_APP_ID"}]}
97
+ "flagship":[{"binding":"FLAGS","app_id":"DEVELOPMENT_APP_ID"}],
98
+ "env":{
99
+ "preview":{"flagship":[{"binding":"FLAGS","app_id":"PREVIEW_APP_ID"}]},
100
+ "production":{"flagship":[{"binding":"FLAGS","app_id":"PRODUCTION_APP_ID"}]}
50
101
  }
51
102
  }
52
103
  ```
53
104
 
54
- The CLI's artifact packaging retains all three environments under `manifest.flags`.
55
- The trusted deployer chooses the environment and verifies registry ownership,
56
- tenant enablement, account and project grants. No environment inherits another ID.
57
- Binding names cannot conflict with resources, services, workflows, secrets or vars.
58
- Deploy/rollback never changes flag definitions. Concurrent previews share their app.
105
+ Packaging retains all environments in manifest.flags. Trusted delivery verifies
106
+ registry/account/environment/tenant/project grants. No environment inherits IDs.
107
+ Previews share live definitions. GitHub workflows must run installed
108
+ `andeo artifact finalize --artifact-directory .tender/artifacts/current --json`
109
+ after pack:tender, before OIDC delivery; use a released CLI containing this command.
110
+ Finalization retains workflows, flags and attested source revision without relabeling.
59
111
 
60
- Native Worker usage, immediately before each external write attempt:
112
+ Worker code evaluates env.FLAGS details methods. Optional official OpenFeature:
61
113
 
62
114
  ```ts
63
- async function allowed(env: { FLAGS?: Flagship }, customerId: string) {
64
- if (!customerId?.trim() || !env.FLAGS) return false;
65
- try { return (await env.FLAGS.getBooleanDetails("example-feature", false, { customerId })).value === true; }
66
- catch { return false; }
67
- }
115
+ import {OpenFeature} from "@openfeature/server-sdk";
116
+ import {FlagshipServerProvider} from "@cloudflare/flagship/server";
117
+ await OpenFeature.setProviderAndWait("checkout",new FlagshipServerProvider({binding:env.FLAGS}));
118
+ const result=await OpenFeature.getClient("checkout","1").getStringDetails(
119
+ "checkout-layout","caller-fallback",{targetingKey:serverOwnedKey,plan:trustedPlan});
68
120
  ```
69
121
 
70
- Use the same canonical customer ID in callers and private provider services.
71
- Recheck on each batch/retry in the credential-holding service; do not cache an
72
- allow decision in a durable workflow step. Direct workflow evaluation is not
73
- supported: call a granted private service. Keep business eligibility and
74
- authorization checks. Flags do not grant permission to use live write credentials.
75
-
76
- Changes can take up to 30 seconds to propagate. Disable cannot recall an issued
77
- request. Record partial effects as `blocked_by_feature_flag`; retain evidence,
78
- do not mark completion, blindly replay events, or undo provider changes. Authorized
79
- recovery and readback remain available when ordinary operations are disabled.
80
-
81
- Wrangler 4.135.0 supports a local simulator: use development bindings with
82
- `remote:false`, explicit synthetic definitions, and test credentials. The Andeo
83
- workflow-local host rejects Flagship declarations until native evaluation is
84
- supported there; use the application's Wrangler simulator and mock private
85
- service calls. Never silently substitute production apps or credentials.
86
- Optional OpenFeature integration is application-owned; no SDK install is required.
87
-
88
- References: https://developers.cloudflare.com/flagship/configuration/,
89
- https://developers.cloudflare.com/flagship/binding/methods/,
90
- https://developers.cloudflare.com/flagship/reference/wrangler-commands/.
122
+ Pass request-local context, never mutate global client context across requests.
123
+ External Node/Go/Python official providers require a separately approved scoped
124
+ credential path and revocation proof; Andeo does not issue these credentials here
125
+ or share its management token. Direct Workflow binding is unsupported: call an
126
+ explicitly granted private service and recheck each external write/retry there.
127
+ Keep business eligibility, authorization and recovery independent of feature flags.
128
+
129
+ Browser helpers: import @withandeo/cli/flagship-runtime for createFlagGateway,
130
+ flagVisitorIdentity and optional flagExposure; import @withandeo/cli/flagship-browser
131
+ for createFlagBrowserClient after release. The application authenticates its own
132
+ gateway, selects client-visible keys/environment/binding and enriches trusted
133
+ context server-side. Return bounded values and refresh hints, never private rules,
134
+ raw context or provider tokens. Initial loading uses caller fallbacks; SSR can
135
+ hydrate matching bootstrap. Each client instance isolates caches; invalidate on
136
+ login/logout/tenant/context changes before refresh. The app schedules refreshes.
137
+ Server actions independently guard operations. Optional one-year HttpOnly visitor
138
+ cookie survives login/actions; explicit reset changes identity. Consent, exposure
139
+ deduplication/retention and outcome measurement remain application-owned.
140
+
141
+ Local simulator uses remote:false and synthetic definitions/test credentials.
142
+ Andeo's Workflow dev host rejects native flags; use app Wrangler simulation plus
143
+ mock private services. Do not swap production IDs into development. New names
144
+ use the pinned syntax and a maximum of 64 characters for every operation. Values are
145
+ finite bounded JSON with safe keys; provider/Andeo limits are separately documented.
146
+ No local check establishes hosted lifecycle, propagation or external SDK readiness.
147
+
148
+ See repository docs/runbooks/FLEXIBLE_FEATURE_FLAGS.md for the parity matrix,
149
+ migration 0092, exact boundaries and remaining hosted acceptance evidence.
150
+ Official documentation: https://developers.cloudflare.com/flagship/.
151
+
152
+ External access design: Specified Flagship apps + Flagship App Evaluate, limited
153
+ to the exact approved collection/environment, server-side secret storage, no Read,
154
+ Write or Entire Account permissions. Provisioning/revocation proof is pending.
155
+ Node uses the official appId/accountId/authToken provider; Go uses
156
+ github.com/cloudflare/flagship/sdks/go; Python uses cloudflare-flagship. Go/Python
157
+ evaluate HTTP only and offer sync/details (Python also async), request-local scalar
158
+ context and optional TTL caches; leave caches off for guards until verified.
159
+ See https://developers.cloudflare.com/flagship/sdk/go/,
160
+ https://developers.cloudflare.com/flagship/sdk/python/ and
161
+ https://developers.cloudflare.com/flagship/api-tokens/.
@@ -2,8 +2,10 @@
2
2
 
3
3
  ## Request merge and deployment
4
4
 
5
- On a protected repository, push the committed feature branch, then request one
6
- exact hosted merge. Read `capabilities` and `source merge-policy show` first.
5
+ On a managed repository, push the committed feature branch and verify its exact
6
+ native preview, then request one hosted merge. Read `capabilities`,
7
+ `source merge-policy show` and `source policy show` first. Exercise the changed
8
+ behavior on the preview; a successful build alone is not behavioral verification.
7
9
 
8
10
  ```sh
9
11
  andeo source push --branch feat/account-copy --json
@@ -23,6 +25,16 @@ review; `--expected-snapshot N` pins the inspected snapshot.
23
25
  Human review remains the default. A merchant administrator may explicitly grant
24
26
  stable principal IDs with `source merge-policy set --mode agent --principals IDS
25
27
  --expected-revision N --idempotency-key KEY [--execution-seconds 300..86400]`.
28
+ This native-preview grant works with source protection enabled or disabled;
29
+ enabling protection is not required. With protection disabled, a saved grant for
30
+ the CLI credential's owner is required before merge admission. Ordinary developer
31
+ access is insufficient. The grant, owner access, exact refs and preview evidence
32
+ are rechecked before landing and publication. An administrator can configure the
33
+ grant through the CLI once; eligible merges need no console intervention.
34
+ Source protection independently blocks direct writes that bypass Andeo. Leaving
35
+ it disabled does not guarantee that every push to main followed preview review.
36
+ Do not push main directly as a substitute for this merge operation. Post-landing
37
+ branch cleanup retains the branch while source protection is disabled.
26
38
  Changed validation/dependency inputs and artifact capabilities still require
27
39
  review. Merge policy and default-branch publication policy are separate grants.
28
40
  Preview-only publication returns `publication_not_enabled` after successful landing.
@@ -1,5 +1,12 @@
1
1
  # Authenticated skills
2
2
 
3
+ The global Andeo guide is public and updates independently of CLI releases.
4
+ Run `andeo skill install --agent codex --force --json` to refresh its latest
5
+ compatible revision, without login. Check the returned source and revision;
6
+ `--bundled` selects the CLI's offline snapshot. `andeo doctor` checks global
7
+ guidance against the public revision. The private practice skills below still
8
+ require authentication and do not use this public endpoint.
9
+
3
10
  Andeo distributes rolling implementation guidance through the authenticated CLI. The CLI is the access boundary: catalog and file reads use the current Andeo credential against the agent API, and the API reads private objects without returning an R2 URL.
4
11
 
5
12
  ## Discover and read