@orchestraworks/cli 0.5.7 → 0.6.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.
Files changed (94) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/api/approval.js +3 -3
  3. package/dist/cli/commands/outpost/local.js +3 -3
  4. package/dist/cli/commands/outpost/machine-names.d.ts +17 -0
  5. package/dist/cli/commands/outpost/machine-names.js +22 -0
  6. package/dist/cli/commands/outpost/up.js +7 -5
  7. package/dist/cli/commands/worker/enroll.d.ts +4 -3
  8. package/dist/cli/commands/worker/enroll.js +4 -3
  9. package/dist/cli/core/auth.d.ts +22 -2
  10. package/dist/cli/core/auth.js +69 -8
  11. package/dist/cli/core/errors.js +4 -0
  12. package/dist/cli/core/platform-client.d.ts +3 -2
  13. package/dist/cli/core/session-body.d.ts +1 -1
  14. package/dist/cli/core/session-body.js +1 -1
  15. package/dist/cli/firstRun.d.ts +3 -3
  16. package/dist/cli/firstRun.js +7 -5
  17. package/dist/cli/main.js +4 -3
  18. package/dist/constructs/environment.d.ts +24 -11
  19. package/dist/constructs/environment.js +76 -12
  20. package/dist/constructs/secret.d.ts +17 -7
  21. package/dist/constructs/secret.js +24 -16
  22. package/dist/core/labels.d.ts +32 -6
  23. package/dist/core/labels.js +70 -8
  24. package/dist/engine/diff.js +38 -11
  25. package/dist/engine/gateway-key-reconcile.d.ts +1 -2
  26. package/dist/engine/gateway-key-reconcile.js +19 -15
  27. package/dist/engine/pipeline-reconcile.js +2 -2
  28. package/dist/engine/pipeline-workflow-reconcile.js +15 -9
  29. package/dist/engine/reconcile.js +48 -15
  30. package/dist/engine/refusals.d.ts +0 -5
  31. package/dist/engine/refusals.js +1 -5
  32. package/dist/engine/secrets-apply.d.ts +10 -14
  33. package/dist/engine/secrets-apply.js +12 -17
  34. package/dist/engine/workflow-reconcile.d.ts +1 -1
  35. package/dist/generated/cli-commands.json +170 -34
  36. package/dist/generated/providers.d.ts +40 -0
  37. package/dist/generated/providers.js +30 -0
  38. package/docs/REFERENCE.md +26 -12
  39. package/node_modules/@orchestraworks/client/dist/esm/models/ApiErrorDetail.d.ts +1 -1
  40. package/node_modules/@orchestraworks/client/dist/esm/models/CreateEnvironmentRequest.d.ts +7 -0
  41. package/node_modules/@orchestraworks/client/dist/esm/models/CreateEnvironmentRequest.js +3 -0
  42. package/node_modules/@orchestraworks/client/dist/esm/models/CreateSecretRequest.d.ts +4 -3
  43. package/node_modules/@orchestraworks/client/dist/esm/models/Environment.d.ts +7 -0
  44. package/node_modules/@orchestraworks/client/dist/esm/models/Environment.js +3 -0
  45. package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentCredential.d.ts +38 -0
  46. package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentCredential.js +45 -0
  47. package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentProvisionSpec.d.ts +1 -1
  48. package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentProvisionSpecRequest.d.ts +1 -1
  49. package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentSnapshot.d.ts +1 -1
  50. package/node_modules/@orchestraworks/client/dist/esm/models/InjectionRecipe.d.ts +6 -0
  51. package/node_modules/@orchestraworks/client/dist/esm/models/InjectionRecipe.js +2 -0
  52. package/node_modules/@orchestraworks/client/dist/esm/models/OAuthTokenRequest.d.ts +1 -1
  53. package/node_modules/@orchestraworks/client/dist/esm/models/Secret.d.ts +1 -7
  54. package/node_modules/@orchestraworks/client/dist/esm/models/Secret.js +0 -4
  55. package/node_modules/@orchestraworks/client/dist/esm/models/UpdateEnvironmentRequest.d.ts +7 -0
  56. package/node_modules/@orchestraworks/client/dist/esm/models/UpdateEnvironmentRequest.js +3 -0
  57. package/node_modules/@orchestraworks/client/dist/esm/models/UpdateSecretRequest.d.ts +4 -3
  58. package/node_modules/@orchestraworks/client/dist/esm/models/index.d.ts +1 -0
  59. package/node_modules/@orchestraworks/client/dist/esm/models/index.js +1 -0
  60. package/node_modules/@orchestraworks/client/dist/models/ApiErrorDetail.d.ts +1 -1
  61. package/node_modules/@orchestraworks/client/dist/models/CreateEnvironmentRequest.d.ts +7 -0
  62. package/node_modules/@orchestraworks/client/dist/models/CreateEnvironmentRequest.js +3 -0
  63. package/node_modules/@orchestraworks/client/dist/models/CreateSecretRequest.d.ts +4 -3
  64. package/node_modules/@orchestraworks/client/dist/models/Environment.d.ts +7 -0
  65. package/node_modules/@orchestraworks/client/dist/models/Environment.js +3 -0
  66. package/node_modules/@orchestraworks/client/dist/models/EnvironmentCredential.d.ts +38 -0
  67. package/node_modules/@orchestraworks/client/dist/models/EnvironmentCredential.js +52 -0
  68. package/node_modules/@orchestraworks/client/dist/models/EnvironmentProvisionSpec.d.ts +1 -1
  69. package/node_modules/@orchestraworks/client/dist/models/EnvironmentProvisionSpecRequest.d.ts +1 -1
  70. package/node_modules/@orchestraworks/client/dist/models/EnvironmentSnapshot.d.ts +1 -1
  71. package/node_modules/@orchestraworks/client/dist/models/InjectionRecipe.d.ts +6 -0
  72. package/node_modules/@orchestraworks/client/dist/models/InjectionRecipe.js +2 -0
  73. package/node_modules/@orchestraworks/client/dist/models/OAuthTokenRequest.d.ts +1 -1
  74. package/node_modules/@orchestraworks/client/dist/models/Secret.d.ts +1 -7
  75. package/node_modules/@orchestraworks/client/dist/models/Secret.js +0 -4
  76. package/node_modules/@orchestraworks/client/dist/models/UpdateEnvironmentRequest.d.ts +7 -0
  77. package/node_modules/@orchestraworks/client/dist/models/UpdateEnvironmentRequest.js +3 -0
  78. package/node_modules/@orchestraworks/client/dist/models/UpdateSecretRequest.d.ts +4 -3
  79. package/node_modules/@orchestraworks/client/dist/models/index.d.ts +1 -0
  80. package/node_modules/@orchestraworks/client/dist/models/index.js +1 -0
  81. package/node_modules/@orchestraworks/client/package.json +1 -1
  82. package/package.json +4 -4
  83. package/skills/orchestra/SKILL.md +38 -17
  84. package/skills/orchestra-fdk/references/authoring.md +34 -26
  85. package/skills/orchestra-fdk/references/environment.md +49 -12
  86. package/skills/orchestra-fdk/references/integrations/code-repo.md +26 -5
  87. package/skills/orchestra-fdk/references/phases/1-discover.md +1 -1
  88. package/skills/orchestra-fdk/references/phases/2-plan.md +1 -1
  89. package/skills/orchestra-fdk/references/troubleshooting.md +5 -3
  90. package/templates/bug-fix/main.ts +7 -4
  91. package/templates/engineering-team/lib/environment.ts +6 -3
  92. package/templates/engineering-team/package.json +1 -1
  93. package/templates/todo-factory/main.ts +7 -4
  94. package/templates/todo-factory/package.json +1 -1
@@ -107,7 +107,7 @@ export interface EnvironmentSnapshot {
107
107
  */
108
108
  setup?: string;
109
109
  /**
110
- * Environment variables set on every machine created from this environment, and forwarded into the agent process itself. NOT A SECRET STORE: values are stored unencrypted on the environment row and returned verbatim by every read of it, so anyone who can read the environment can read them. Put credentials in a Secret referenced by an egress allow rule instead - the broker injects those into the outbound request at the egress edge and the agent process never holds them. Names beginning SFDK_ or ORCHESTRA_ are platform-owned and rejected, and the platform writes its own reserved variables last, overriding anything you declare. Names beginning ORCHESTRA_FDK_, the inputs of an agent-as-code kit, are accepted in exactly that spelling as ordinary variables of your own. The other exception is six worker settings, accepted in exactly this spelling: SFDK_WORKER_RESTART_AFTER_IDLE, SFDK_WORKER_RELEASE_FETCH_TIMEOUT and SFDK_WORKER_RELEASE_CHECK_INTERVAL, each a positive duration such as 30s or 5m; SFDK_WORKER_RELEASE_REGISTRY_URL, an http or https URL; and SFDK_WORKER_AUTO_UPGRADE and SFDK_WORKER_AUTO_RESTART, each exactly true or false, which turn the worker's move to a newer release and its restart into that release on or off. They reach the machine's worker, where each one set wins over the platform's release settings, and never an agent process. HOME and USERPROFILE are not among them: the platform sets neither, the account inside the image decides where the home directory is, and a HOME you declare here is passed to the harness to conform to or complain about. Declare a volume mount at /home if you want that home directory to be durable. On a Windows environment names are matched case-insensitively, the way Windows itself matches them - sfdk_x and orchestra_fdk_x are rejected reserved names there, and Home and HOME are one variable - while a POSIX environment matches names exactly. At most 64 entries; a key matches [A-Za-z_][A-Za-z0-9_]* and is at most 128 characters; a value is at most 4096 characters.
110
+ * Environment variables set on every machine created from this environment, and forwarded into the agent process itself. NOT A SECRET STORE: values are stored unencrypted on the environment row and returned verbatim by every read of it, so anyone who can read the environment can read them. Put credentials in a Secret referenced by an egress allow rule instead - the broker injects those into the outbound request at the egress edge and the agent process never holds them. Names beginning SFDK_ or ORCHESTRA_ are platform-owned and rejected, and the platform writes its own reserved variables last, overriding anything you declare. Names beginning ORCHESTRA_FDK_, the inputs of an agent-as-code kit, are accepted in exactly that spelling as ordinary variables of your own. The other exception is six worker settings, accepted in exactly this spelling: ORCHESTRA_WORKER_RESTART_AFTER_IDLE, ORCHESTRA_WORKER_RELEASE_FETCH_TIMEOUT and ORCHESTRA_WORKER_RELEASE_CHECK_INTERVAL, each a positive duration such as 30s or 5m; ORCHESTRA_WORKER_RELEASE_REGISTRY_URL, an http or https URL; and ORCHESTRA_WORKER_AUTO_UPGRADE and ORCHESTRA_WORKER_AUTO_RESTART, each exactly true or false, which turn the worker's move to a newer release and its restart into that release on or off. Their former spellings beginning SFDK_WORKER_ are refused. They reach the machine's worker, where each one set wins over the platform's release settings, and never an agent process. HOME and USERPROFILE are not among them: the platform sets neither, the account inside the image decides where the home directory is, and a HOME you declare here is passed to the harness to conform to or complain about. Declare a volume mount at /home if you want that home directory to be durable. On a Windows environment names are matched case-insensitively, the way Windows itself matches them - sfdk_x and orchestra_fdk_x are rejected reserved names there, and Home and HOME are one variable - while a POSIX environment matches names exactly. At most 64 entries; a key matches [A-Za-z_][A-Za-z0-9_]* and is at most 128 characters; a value is at most 4096 characters.
111
111
  * @type {{ [key: string]: string; }}
112
112
  * @memberof EnvironmentSnapshot
113
113
  */
@@ -28,6 +28,12 @@ export interface InjectionRecipe {
28
28
  * @memberof InjectionRecipe
29
29
  */
30
30
  removeHeaders: Array<string>;
31
+ /**
32
+ * Host patterns this secret is presented on, in egress rule host syntax (exact host, *.suffix, or *); empty or omitted covers no host. A non-empty list needs at least one header, and no pattern may name the platform API host or the object store host.
33
+ * @type {Array<string>}
34
+ * @memberof InjectionRecipe
35
+ */
36
+ hosts?: Array<string>;
31
37
  }
32
38
  /**
33
39
  * Check if a given object implements the InjectionRecipe interface.
@@ -37,6 +37,7 @@ function InjectionRecipeFromJSONTyped(json, ignoreDiscriminator) {
37
37
  return {
38
38
  'headers': json['headers'] == null ? undefined : (json['headers'].map(InjectionHeader_1.InjectionHeaderFromJSON)),
39
39
  'removeHeaders': json['removeHeaders'],
40
+ 'hosts': json['hosts'] == null ? undefined : json['hosts'],
40
41
  };
41
42
  }
42
43
  function InjectionRecipeToJSON(json) {
@@ -49,5 +50,6 @@ function InjectionRecipeToJSONTyped(value, ignoreDiscriminator = false) {
49
50
  return {
50
51
  'headers': value['headers'] == null ? undefined : (value['headers'].map(InjectionHeader_1.InjectionHeaderToJSON)),
51
52
  'removeHeaders': value['removeHeaders'],
53
+ 'hosts': value['hosts'],
52
54
  };
53
55
  }
@@ -46,7 +46,7 @@ export interface OAuthTokenRequest {
46
46
  */
47
47
  refreshToken?: string;
48
48
  /**
49
- * Public client identifier; omit it or send sfdk-public
49
+ * Public client identifier; omit it or send orchestra-public
50
50
  * @type {string}
51
51
  * @memberof OAuthTokenRequest
52
52
  */
@@ -80,17 +80,11 @@ export interface Secret {
80
80
  */
81
81
  expiresAt?: Date;
82
82
  /**
83
- * Optional injection recipe describing the request mutations the broker applies from this secret
83
+ * Optional injection recipe: the request mutations the broker applies from this secret, and the hosts it applies them on. A secret without one is stored only: the broker presents it on no request. For git over HTTPS, store base64 of <user>:<token> as the value, such as the output of printf 'x-access-token:%s' "$TOKEN" | base64 | tr -d '\n' for a GitHub token, and present it as Authorization: Basic ${secret}.
84
84
  * @type {InjectionRecipe}
85
85
  * @memberof Secret
86
86
  */
87
87
  injection?: InjectionRecipe;
88
- /**
89
- * Host patterns this secret is presented on, in egress rule host syntax (exact host, *.suffix, or *); empty covers no host
90
- * @type {Array<string>}
91
- * @memberof Secret
92
- */
93
- hosts: Array<string>;
94
88
  /**
95
89
  * The agents you can see that may use this secret, as IAM decides at this read. Present on the singular read only; a list row leaves it out.
96
90
  * @type {Array<Agent>}
@@ -40,8 +40,6 @@ function instanceOfSecret(value) {
40
40
  return false;
41
41
  if (!('updatedAt' in value) || value['updatedAt'] === undefined)
42
42
  return false;
43
- if (!('hosts' in value) || value['hosts'] === undefined)
44
- return false;
45
43
  return true;
46
44
  }
47
45
  function SecretFromJSON(json) {
@@ -63,7 +61,6 @@ function SecretFromJSONTyped(json, ignoreDiscriminator) {
63
61
  'updatedAt': (new Date(json['updatedAt'])),
64
62
  'expiresAt': json['expiresAt'] == null ? undefined : (new Date(json['expiresAt'])),
65
63
  'injection': json['injection'] == null ? undefined : (0, InjectionRecipe_1.InjectionRecipeFromJSON)(json['injection']),
66
- 'hosts': json['hosts'],
67
64
  'usableBy': json['usableBy'] == null ? undefined : (json['usableBy'].map(Agent_1.AgentFromJSON)),
68
65
  };
69
66
  }
@@ -86,6 +83,5 @@ function SecretToJSONTyped(value, ignoreDiscriminator = false) {
86
83
  'updatedAt': value['updatedAt'].toISOString(),
87
84
  'expiresAt': value['expiresAt'] == null ? value['expiresAt'] : value['expiresAt'].toISOString(),
88
85
  'injection': (0, InjectionRecipe_1.InjectionRecipeToJSON)(value['injection']),
89
- 'hosts': value['hosts'],
90
86
  };
91
87
  }
@@ -10,6 +10,7 @@
10
10
  * Do not edit the class manually.
11
11
  */
12
12
  import type { EnvironmentIngressPolicy } from './EnvironmentIngressPolicy';
13
+ import type { EnvironmentCredential } from './EnvironmentCredential';
13
14
  import type { EnvironmentPlatformRequest } from './EnvironmentPlatformRequest';
14
15
  import type { EnvironmentEgressPolicy } from './EnvironmentEgressPolicy';
15
16
  import type { EnvironmentProvisionSpecRequest } from './EnvironmentProvisionSpecRequest';
@@ -44,6 +45,12 @@ export interface UpdateEnvironmentRequest {
44
45
  * @memberof UpdateEnvironmentRequest
45
46
  */
46
47
  ingressPolicy?: EnvironmentIngressPolicy | null;
48
+ /**
49
+ * The credentials this environment's machines get on a request that names none, in order: the first one covering the request's host is added, whatever the agent. Each entry is a Secret or Connection of this organization by id, and adding one needs the caller's own use of it. A request naming a credential gets that one instead. A provided list replaces the stored one, and absent leaves it.
50
+ * @type {Array<EnvironmentCredential>}
51
+ * @memberof UpdateEnvironmentRequest
52
+ */
53
+ credentials?: Array<EnvironmentCredential>;
47
54
  /**
48
55
  * The launch spec — every fact that applies only when the platform controls the machine. Rejected on an enrolled environment, whose machine the platform never launches.
49
56
  * @type {EnvironmentProvisionSpecRequest}
@@ -19,6 +19,7 @@ exports.UpdateEnvironmentRequestFromJSONTyped = UpdateEnvironmentRequestFromJSON
19
19
  exports.UpdateEnvironmentRequestToJSON = UpdateEnvironmentRequestToJSON;
20
20
  exports.UpdateEnvironmentRequestToJSONTyped = UpdateEnvironmentRequestToJSONTyped;
21
21
  const EnvironmentIngressPolicy_1 = require("./EnvironmentIngressPolicy");
22
+ const EnvironmentCredential_1 = require("./EnvironmentCredential");
22
23
  const EnvironmentPlatformRequest_1 = require("./EnvironmentPlatformRequest");
23
24
  const EnvironmentEgressPolicy_1 = require("./EnvironmentEgressPolicy");
24
25
  const EnvironmentProvisionSpecRequest_1 = require("./EnvironmentProvisionSpecRequest");
@@ -41,6 +42,7 @@ function UpdateEnvironmentRequestFromJSONTyped(json, ignoreDiscriminator) {
41
42
  'platform': json['platform'] == null ? undefined : (0, EnvironmentPlatformRequest_1.EnvironmentPlatformRequestFromJSON)(json['platform']),
42
43
  'egressPolicy': json['egressPolicy'] == null ? undefined : (0, EnvironmentEgressPolicy_1.EnvironmentEgressPolicyFromJSON)(json['egressPolicy']),
43
44
  'ingressPolicy': json['ingressPolicy'] == null ? undefined : (0, EnvironmentIngressPolicy_1.EnvironmentIngressPolicyFromJSON)(json['ingressPolicy']),
45
+ 'credentials': json['credentials'] == null ? undefined : (json['credentials'].map(EnvironmentCredential_1.EnvironmentCredentialFromJSON)),
44
46
  'provisionSpec': json['provisionSpec'] == null ? undefined : (0, EnvironmentProvisionSpecRequest_1.EnvironmentProvisionSpecRequestFromJSON)(json['provisionSpec']),
45
47
  'workingDirectory': json['workingDirectory'] == null ? undefined : json['workingDirectory'],
46
48
  'hooks': json['hooks'] == null ? undefined : (0, EnvironmentHooksRequest_1.EnvironmentHooksRequestFromJSON)(json['hooks']),
@@ -59,6 +61,7 @@ function UpdateEnvironmentRequestToJSONTyped(value, ignoreDiscriminator = false)
59
61
  'platform': (0, EnvironmentPlatformRequest_1.EnvironmentPlatformRequestToJSON)(value['platform']),
60
62
  'egressPolicy': (0, EnvironmentEgressPolicy_1.EnvironmentEgressPolicyToJSON)(value['egressPolicy']),
61
63
  'ingressPolicy': (0, EnvironmentIngressPolicy_1.EnvironmentIngressPolicyToJSON)(value['ingressPolicy']),
64
+ 'credentials': value['credentials'] == null ? undefined : (value['credentials'].map(EnvironmentCredential_1.EnvironmentCredentialToJSON)),
62
65
  'provisionSpec': (0, EnvironmentProvisionSpecRequest_1.EnvironmentProvisionSpecRequestToJSON)(value['provisionSpec']),
63
66
  'workingDirectory': value['workingDirectory'],
64
67
  'hooks': (0, EnvironmentHooksRequest_1.EnvironmentHooksRequestToJSON)(value['hooks']),
@@ -29,7 +29,7 @@ export interface UpdateSecretRequest {
29
29
  */
30
30
  description?: string;
31
31
  /**
32
- * Secret value. This is write-only and is never returned by management APIs.
32
+ * Secret value. This is write-only and is never returned by management APIs. For git over HTTPS, store base64 of <user>:<token> as the value, such as the output of printf 'x-access-token:%s' "$TOKEN" | base64 | tr -d '\n' for a GitHub token, and present it as Authorization: Basic ${secret}.
33
33
  * @type {string}
34
34
  * @memberof UpdateSecretRequest
35
35
  */
@@ -41,7 +41,7 @@ export interface UpdateSecretRequest {
41
41
  */
42
42
  expiresAt?: Date;
43
43
  /**
44
- * Injection recipe update: absent = unchanged, null = clear the recipe, value = replace it
44
+ * Injection recipe update: absent = unchanged, null = clear the recipe and its hosts, leaving the secret stored only, value = replace the recipe and its hosts. Optional injection recipe: the request mutations the broker applies from this secret, and the hosts it applies them on. A secret without one is stored only: the broker presents it on no request. For git over HTTPS, store base64 of <user>:<token> as the value, such as the output of printf 'x-access-token:%s' "$TOKEN" | base64 | tr -d '\n' for a GitHub token, and present it as Authorization: Basic ${secret}.
45
45
  * @type {InjectionRecipe}
46
46
  * @memberof UpdateSecretRequest
47
47
  */
@@ -55,9 +55,10 @@ export interface UpdateSecretRequest {
55
55
  [key: string]: string | null;
56
56
  };
57
57
  /**
58
- * Whole-list replacement of the host patterns this secret is presented on; absent = unchanged, [] covers no host. A non-empty list needs an injection recipe with a header, and no pattern may name the platform API host or the object store host.
58
+ * Deprecated: write injection.hosts instead. Accepted for one release and moved into the recipe's hosts; a request whose recipe names other hosts is refused. Absent leaves the recipe's hosts unchanged; a list replaces them.
59
59
  * @type {Array<string>}
60
60
  * @memberof UpdateSecretRequest
61
+ * @deprecated
61
62
  */
62
63
  hosts?: Array<string>;
63
64
  }
@@ -120,6 +120,7 @@ export * from './EmbeddedResourceResource';
120
120
  export * from './EntitlementPeriodUsage';
121
121
  export * from './EntitlementTeamUsage';
122
122
  export * from './Environment';
123
+ export * from './EnvironmentCredential';
123
124
  export * from './EnvironmentDisk';
124
125
  export * from './EnvironmentDiskMount';
125
126
  export * from './EnvironmentEgressPolicy';
@@ -138,6 +138,7 @@ __exportStar(require("./EmbeddedResourceResource"), exports);
138
138
  __exportStar(require("./EntitlementPeriodUsage"), exports);
139
139
  __exportStar(require("./EntitlementTeamUsage"), exports);
140
140
  __exportStar(require("./Environment"), exports);
141
+ __exportStar(require("./EnvironmentCredential"), exports);
141
142
  __exportStar(require("./EnvironmentDisk"), exports);
142
143
  __exportStar(require("./EnvironmentDiskMount"), exports);
143
144
  __exportStar(require("./EnvironmentEgressPolicy"), exports);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchestraworks/client",
3
- "version": "0.5.7",
3
+ "version": "0.6.0",
4
4
  "description": "Orchestra public API TypeScript client",
5
5
  "author": "Living Computers",
6
6
  "repository": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchestraworks/cli",
3
- "version": "0.5.7",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "description": "The Orchestra command line.",
6
6
  "license": "Apache-2.0",
@@ -109,13 +109,13 @@
109
109
  },
110
110
  "dependencies": {
111
111
  "@agentclientprotocol/sdk": "1.3.0",
112
- "@orchestraworks/client": "0.5.7",
113
- "@orchestraworks/worker": "0.0.140",
112
+ "@orchestraworks/client": "0.6.0",
113
+ "@orchestraworks/worker": "0.0.142",
114
114
  "commander": "^14.0.0",
115
115
  "liquidjs": "^10.28.0"
116
116
  },
117
117
  "optionalDependencies": {
118
- "@orchestraworks/local": "0.0.140"
118
+ "@orchestraworks/local": "0.0.142"
119
119
  },
120
120
  "bundleDependencies": [
121
121
  "@orchestraworks/client"
@@ -265,8 +265,8 @@ unless you set one, so it wins over the open default and over the usual allow ru
265
265
  **Live effect.** The edge reads the environment's rules on each request. So an apply that changes the rules
266
266
  reaches every machine at once, machines already running included, from their next request.
267
267
 
268
- **How it relates.** On a request a rule allows, the edge adds the secret or connection whose `hosts` cover the
269
- host, and only on `https` (section 6). Calls to the Orchestra platform itself skip these rules: the agent's
268
+ **How it relates.** On a request a rule allows, the edge adds a secret or connection whose `hosts` cover the
269
+ host, only on `https`, and only when the request names it or an environment default covers it (section 6). Calls to the Orchestra platform itself skip these rules: the agent's
270
270
  role decides them (section 1). So a machine blocked from the code host still downloads a file through
271
271
  `orchestra files get-content`. The worker points each harness's tools at the edge through proxy variables, so
272
272
  a service the agent runs in a container needs its name in `NO_PROXY` in the environment's settings.
@@ -291,10 +291,19 @@ resolved at the edge on an allow); AGENTS.md "Egress And Credentials". Kit: cli/
291
291
  **What it's for.** It lets agents use a key without seeing it. No agent, no person and no apply output ever shows
292
292
  the value.
293
293
 
294
- **What it is.** A *secret* is a stored value that can be written and never read back. It declares its `hosts`
295
- and an `injection` recipe, the headers it sets, and the network edge adds it to each allowed `https` request
296
- to one of those hosts. This is *credential injection at the network edge*. When two credentials cover one
297
- host, the request names one with a reference, `orchestra:secret/<id>`, in place of its key.
294
+ **What it is.** A *secret* is a stored value that can be written and never read back. It declares an
295
+ `injection` recipe, the headers it sets and the `hosts` it sets them on, and the network edge adds it to an
296
+ allowed `https` request to one of those hosts. A secret with no recipe is stored only, and the edge never adds it. This is *credential injection at the network edge*. The edge adds it only in two cases:
297
+
298
+ - The request names it with a reference, `orchestra:secret/<id>` or `orchestra:connection/<id>`, in place
299
+ of its key. A `Secret` or `Connection` set as an environment `env` value is written as that reference:
300
+ `ANTHROPIC_API_KEY` for claude, `GH_TOKEN` for `gh`, `GITLAB_TOKEN` for `glab`, `ORCHESTRA_GIT_CREDENTIAL`
301
+ for git. `routeModelsViaGateway({ key })` names the gateway key this way for claude and codex. The
302
+ `linear`, `slack` and `teams` commands take `--connection-id <id>`.
303
+ - The environment's `credentials` list covers the host, for a request that names nothing. The first
304
+ covering entry serves; with `replace: false`, a request carrying its own value keeps it.
305
+
306
+ A request that names nothing and that no default covers leaves as it was sent.
298
307
 
299
308
  **How it relates.** A secret is added only where a network rule lets the request leave (section 5). Never put
300
309
  a key in an environment's settings or in instructions: the machine's processes read every setting.
@@ -325,8 +334,9 @@ network rules carry the option (sections 2 and 5).
325
334
  **A Claude or Codex subscription.**
326
335
 
327
336
  - *Claude.* `claude setup-token` prints a long-lived token. It is stored as a secret, and the network edge
328
- adds it to each call to `api.anthropic.com`. The machine holds only a placeholder token and an empty API
329
- key, so no agent and no person sees the real one. Never put the token in an environment's settings: they
337
+ adds it to each call to `api.anthropic.com` that names it. The environment's `env` names the secret in
338
+ `CLAUDE_CODE_OAUTH_TOKEN` by reference, `orchestra:secret/<id>`, beside an empty API key, so no agent
339
+ and no person sees the real one. Never put the token in an environment's settings: they
330
340
  are plain text.
331
341
  - *Codex.* A personal access token, made by a ChatGPT Business or Enterprise member, or a separate ChatGPT
332
342
  sign-in kept on a `/home` volume that every machine using it shares. A Codex sign-in stays off the model
@@ -337,7 +347,8 @@ network rules carry the option (sections 2 and 5).
337
347
 
338
348
  **An Orchestra account, through the model gateway.** The model gateway is a hosted service at
339
349
  `models.orchestraworks.ai`. One endpoint reaches OpenAI, Anthropic and open models. A *gateway key* is a key
340
- to it, stored as a secret. The network edge adds it to each model call, so no agent and no person sees it.
350
+ to it, stored as a secret. `routeModelsViaGateway({ key })` names it to each harness, and the network edge
351
+ adds it to each model call, so no agent and no person sees it.
341
352
  Without it, an agent's first message fails with "Invalid API key".
342
353
 
343
354
  - *Routing.* `orchestra model-configs` sets which providers serve a model, and in which order, so a call
@@ -348,10 +359,11 @@ Without it, an agent's first message fails with "Invalid API key".
348
359
  - *A cap.* Each gateway key can carry a monthly cap, set in the console at **Settings › Gateway keys**.
349
360
 
350
361
  **Their own provider API key.** The team's Anthropic or OpenAI API key is a secret that the network edge adds
351
- to calls straight to the provider, with no gateway in between.
362
+ to calls straight to the provider, with no gateway in between. The environment names it in `ANTHROPIC_API_KEY`
363
+ or `ORCHESTRA_WORKER_OPENAI_API_KEY`, or lists it in `credentials`.
352
364
 
353
365
  **How it relates.** Each option reaches the model through an ordinary allow rule on the model's host, and a
354
- secret whose `hosts` name that host (sections 5 and 6). An agent on the model gateway turns it on in its model settings (section 2). An agent on a
366
+ secret whose recipe's `hosts` name that host (sections 5 and 6). An agent on the model gateway turns it on in its model settings (section 2). An agent on a
355
367
  subscription or its own key turns it off. For plan questions, send the person to **Settings › Plan & usage**
356
368
  in the console.
357
369
 
@@ -549,7 +561,8 @@ names its team, and a row with none sits in Shared.
549
561
 
550
562
  <!-- Sources, on the kit's own branch: cli/src/cli/main.ts:60-160 (two jobs; nouns match API paths; standard
551
563
  verbs; --output json; --body @file.json; approval defaults; orchestra api), cli/src/cli/core/auth.ts:1-45
552
- (ORCHESTRA_API_TOKEN, then the login profile, then the machine's edge; ORCHESTRA_BASE_URL),
564
+ (ORCHESTRA_API_TOKEN, then the file ORCHESTRA_API_TOKEN_FILE names, then the login profile, then the machine's
565
+ edge; ORCHESTRA_BASE_URL),
553
566
  cli/src/cli/core/profile.ts:39-52 (profiles in ~/.config/orchestra/config.json), cli/src/generated/cli-commands.json
554
567
  (each command's answer), cli/src/cli/core/output.ts:94-113 and :143-145 (json prints the answer as it is),
555
568
  cli/src/cli/core/errors.ts:287-296 and :366-370 (the json error, on stderr), cli/src/cli/core/login.ts:361-363 (a
@@ -581,8 +594,12 @@ each part at length. What follows is only what a reader needs to run a command s
581
594
  `~/.config/orchestra/config.json`. It selects the person's organization when they have one; with several,
582
595
  name it: `orchestra auth login --org <organization>`. The browser sign-in renews itself. A token typed at the
583
596
  `--no-browser` prompt cannot renew itself, so it suits a short run only.
584
- - **Scripts.** `ORCHESTRA_API_TOKEN` and `ORCHESTRA_BASE_URL` in the shell are used before the profile. On an
585
- Orchestra machine, the network edge signs the agent's calls, so it needs no token.
597
+ - **Scripts.** `ORCHESTRA_API_TOKEN` and `ORCHESTRA_BASE_URL` in the shell are used before the profile.
598
+ - **On an Orchestra machine.** The worker writes the agent's own token to a file, renews it, and names the
599
+ file in `ORCHESTRA_API_TOKEN_FILE`. `orchestra` reads that file before each request, so the agent needs no
600
+ sign-in. Where a network edge stands in front of the machine, the edge replaces that token with one for the
601
+ same agent. A 401 here is not fixed by `orchestra auth login`: the token expired before the worker renewed
602
+ it, or the agent is no longer placed on the machine.
586
603
  - **Fallback.** `orchestra api <METHOD> </path>` makes a raw call when a typed command is missing.
587
604
 
588
605
  A first look at an organization, in the order a new reader runs it:
@@ -642,7 +659,7 @@ local/launch/modelkey.go (model key carriers per harness, the gateway address va
642
659
  worker/facts/families.json (how each harness takes the gateway address); on develop at f62fad1481,
643
660
  agents/runtime/assembly/common/placeholder-env (the images' placeholder ANTHROPIC_API_KEY),
644
661
  LauncherProperties.kt (the gallery images at Versions/latest), launcher/config/config.go (Dsv5 default);
645
- worker/facts/families.json (the ORCHESTRA_WORKER_ names), worker/service/manager_windows.go (SfdkWorker),
662
+ worker/facts/families.json (the ORCHESTRA_WORKER_ names), worker/service/service.go (OrchestraWorker, and the previous SfdkWorker),
646
663
  infra/packer/azure-windows-runtime.pkr.hcl (the startup task), launcher/cloud/cloud.go (the VM tags);
647
664
  the proven list is the test run of 2026-10-05. -->
648
665
 
@@ -672,8 +689,8 @@ the proven list is the test run of 2026-10-05. -->
672
689
  1. The environment's `env` (`provisionSpec.env`). A declared value replaces our image's placeholder,
673
690
  never a real value. The platform stores `env` values in plain text, an environment read returns
674
691
  them, and the machine's startup data carries them.
675
- 2. Baked into the team's image at machine scope: on Windows the `SfdkWorker` service's `Environment`
676
- registry value, on Linux a drop-in on `sfdk-worker.service`.
692
+ 2. Baked into the team's image at machine scope: on Windows the `OrchestraWorker` service's
693
+ `Environment` registry value, on Linux a drop-in on `orchestra-worker.service`.
677
694
  3. The `onStartAgent` hook writes the harness's own key file: `.claude/.credentials.json` for a Claude
678
695
  sign-in, `.codex/auth.json` for `codex`, `.pi/agent/auth.json` for `pi`. A raw Claude API key has
679
696
  no file.
@@ -681,6 +698,10 @@ the proven list is the test run of 2026-10-05. -->
681
698
  `ORCHESTRA_WORKER_CLAUDE_OAUTH_TOKEN` for a Claude subscription token; `ORCHESTRA_WORKER_OPENAI_API_KEY`
682
699
  or `ORCHESTRA_WORKER_CODEX_PERSONAL_ACCESS_TOKEN` for `codex`. With a gateway key, keep the agent's
683
700
  model gateway on. The platform sets the gateway address.
701
+ - An install replaces the service an earlier release registered as `SfdkWorker` on Windows,
702
+ `sfdk-worker.service` on Linux or `ai.livingcomputers.sfdk.worker` on macOS. The new ones are
703
+ `OrchestraWorker`, `orchestra-worker.service` and `ai.livingcomputers.orchestra.worker`. Change your own
704
+ scripts that name the old ones.
684
705
  - Never restart the worker service to load a key. A restart after the worker registered stops the
685
706
  machine's work, and the platform parks the VM.
686
707
  - The details: the orchestra-fdk skill's `references/environment.md`, "Tokens on a compute provider's
@@ -68,8 +68,10 @@ const factory = new Factory({ name: "acme-support" });
68
68
  new Secret(factory, "openai-api-key", {
69
69
  name: "OpenAI API key",
70
70
  value: SecretValue.fromEnv("OPENAI_API_KEY_VALUE"), // read from env at apply — never in the plan
71
- hosts: ["api.openai.com"], // where the edge presents it
72
- injection: { headers: [{ name: "Authorization", value: "Bearer ${secret}" }] }, // how
71
+ injection: {
72
+ headers: [{ name: "Authorization", value: "Bearer ${secret}" }], // how the edge presents it
73
+ hosts: ["api.openai.com"], // where
74
+ },
73
75
  });
74
76
 
75
77
  const runtime = new Environment(factory, "runtime", {
@@ -554,26 +556,29 @@ token the platform mints. The **Claude sign-in recipe** is the one to copy when
554
556
  on a person's Claude subscription token rather than an API key:
555
557
 
556
558
  ```ts
557
- new Secret(factory, "claude-sign-in", {
559
+ const claudeSignIn = new Secret(factory, "claude-sign-in", {
558
560
  value: SecretValue.fromEnv("ORCHESTRA_FDK_CLAUDE_CODE_OAUTH_TOKEN"),
559
- hosts: ["api.anthropic.com"],
560
561
  injection: {
561
562
  headers: [{ name: "authorization", value: "Bearer ${secret}" }],
562
563
  removeHeaders: ["x-api-key"], // stripped before injection
564
+ hosts: ["api.anthropic.com"],
563
565
  },
564
566
  });
565
567
 
566
568
  // …in the Environment's props:
567
- env: { CLAUDE_CODE_OAUTH_TOKEN: "software-factory-egress-placeholder", ANTHROPIC_API_KEY: "" },
569
+ env: { CLAUDE_CODE_OAUTH_TOKEN: claudeSignIn, ANTHROPIC_API_KEY: "" },
568
570
  egress: EgressPolicy.allowAll()
569
571
  .allow("claude-sign-in", { hosts: ["api.anthropic.com"], priority: 300 }),
570
572
  ```
571
573
 
572
574
  It injects `authorization` and nothing else. **Never inject an `anthropic-beta` header**: an injected
573
- one replaces the harness's own list of beta flags, and every call then answers 400. The placeholder
574
- `CLAUDE_CODE_OAUTH_TOKEN` makes the harness sign in the subscription way and send its own list, and the
575
- edge swaps the real token in. The empty `ANTHROPIC_API_KEY` covers the runtime image's placeholder key,
576
- which the harness would otherwise send instead.
575
+ one replaces the harness's own list of beta flags, and every call then answers 400. A Secret as an `env`
576
+ value is written as its reference, `orchestra:secret/<id>`, with the id resolved at apply. In
577
+ `CLAUDE_CODE_OAUTH_TOKEN` it makes the harness sign in the subscription way and send its own list, and the
578
+ edge reads the reference where the token goes and swaps the real token in. The edge adds a credential only
579
+ to a request that names one, or that an environment default covers (`references/environment.md`, "Naming a
580
+ credential"). The empty `ANTHROPIC_API_KEY` covers the runtime image's placeholder key, which the harness
581
+ would otherwise send instead.
577
582
 
578
583
  - Sources: `SecretValue.fromEnv(NAME)`, `SecretValue.fromCommandLine(label?)` and
579
584
  `SecretValue.fromGatewayKey(key)`, plus the derived recipes `basicAuth`, `registryCredential` and
@@ -613,7 +618,7 @@ which the harness would otherwise send instead.
613
618
  `GatewayKey` you declare in the same factory — `new GatewayKey(factory, "model-gateway-key", props)`,
614
619
  whose only props are `slug`, `displayName`, `monthlyCreditCap` and `labels` — so apply mints the
615
620
  key and writes the token it shows *exactly once* straight into this Secret, which the edge then
616
- adds on its `hosts` like any other. It is legal only as the whole top-level value of exactly one Secret:
621
+ adds on its recipe's `hosts` like any other. It is legal only as the whole top-level value of exactly one Secret:
617
622
  nesting it inside another recipe, or a key with zero or two Secrets, is a synth error, and there
618
623
  is no importer because an existing key's token is unrecoverable. Rotation is new-slug-only.
619
624
  - A **`ModelProviderKey`** is the other credential you can declare: your organization's own key for
@@ -648,11 +653,12 @@ which the harness would otherwise send instead.
648
653
  suppresses it and none can supply it either, so a headless apply of a `fromCommandLine`
649
654
  declaration refuses at *every* level and tells you to run from a terminal or change the source —
650
655
  it never recommends a policy lever that could not clear it.
651
- - Presenting a secret on the network: the `Secret` itself declares `hosts` (where: an exact host,
652
- `*.suffix`, or `*`) and an `injection` recipe (how: the headers it sets, reading `${secret}`, or
653
- `${secret.<field>}` for a `SecretValue.fields` value). Egress rules carry no credential, so a rule
654
- that passes `credential` or `credentials` is a synth error; a Secret with no `hosts` is presented
655
- nowhere.
656
+ - Presenting a secret on the network: the `Secret` itself declares an `injection` recipe — how: the
657
+ headers it sets, reading `${secret}`, or `${secret.<field>}` for a `SecretValue.fields` value; and
658
+ where: its `hosts`, each an exact host, `*.suffix`, or `*`. Egress rules carry no credential, so a rule
659
+ that passes `credential` or `credentials` is a synth error. A Secret with no `injection` is stored
660
+ only, and one whose recipe has no `hosts` is presented nowhere. The top-level `hosts` prop is
661
+ deprecated: it is moved into the recipe for one release.
656
662
 
657
663
  ## How the agents reach a model
658
664
 
@@ -668,9 +674,9 @@ on their own computer; run from your shell, its browser step hangs. Never read o
668
674
  At apply, the shell exports it from that file into the variable the Secret reads. Declare the Claude
669
675
  sign-in recipe (§ Secrets are recipes, never values): a `Secret`, an egress rule that allows
670
676
  `api.anthropic.com` and sets `Authorization: Bearer ${secret}` with `x-api-key` removed, and, in the
671
- environment's `env`, `CLAUDE_CODE_OAUTH_TOKEN: "software-factory-egress-placeholder"` and an empty
672
- `ANTHROPIC_API_KEY`. Turn `enableModelGateway` off for the agent. The machine holds only the
673
- placeholder; the edge adds the token. Copying the renewing credentials file instead is the fallback,
677
+ environment's `env`, `CLAUDE_CODE_OAUTH_TOKEN` set to that Secret and an empty `ANTHROPIC_API_KEY`.
678
+ Turn `enableModelGateway` off for the agent. The machine holds only the Secret's reference; the edge
679
+ adds the token. Copying the renewing credentials file instead is the fallback,
674
680
  and follows the ChatGPT sign-in steps below.
675
681
  - **Codex: a personal access token, where the workspace allows one.** A ChatGPT Business or Enterprise
676
682
  member creates it at chatgpt.com/admin/access-tokens, once the workspace owner allows access tokens,
@@ -762,7 +768,7 @@ An environment's `egress` is a policy you build up from one of **two starting po
762
768
  - **`EgressPolicy.allowAll()`** allows every host no rule refuses.
763
769
 
764
770
  Rules fold onto either one the same way: a rule only opens or closes the network, a credential still goes
765
- only to the hosts its own `hosts` cover, and a deny still refuses.
771
+ only to the hosts its own recipe's `hosts` cover, and a deny still refuses.
766
772
 
767
773
  Most of what an agent needs to reach arrives ready-made as a **bundle** — a list of rules folded onto
768
774
  the policy by one `applyPreset(...)` call — so **reach for the bundles first** and hand-write allow/deny
@@ -1079,7 +1085,7 @@ orchestra gateway-keys create --slug ci-smoke --output-file key.json
1079
1085
  export, a CI secret) suppresses the only prompt you would have seen, the command says so in one
1080
1086
  line on **stderr**, naming the lever — stdout stays the response document.
1081
1087
  - **Writing to a factory-managed resource warns.** `apply` stamps what it manages with an
1082
- `sfdk.managedBy` labels key naming the owning factory, and a write to a stamped resource says so:
1088
+ `orchestra.managedBy` labels key naming the owning factory, and a write to a stamped resource says so:
1083
1089
  the next `apply` reverts it. It is a warning, not a refusal — the fallback has to stay usable in an
1084
1090
  emergency — and it is the CLI telling you this belongs in `main.ts`.
1085
1091
 
@@ -1106,17 +1112,19 @@ itself a credential.
1106
1112
  An agent running inside a machine types the **same commands** as an operator at a workstation. There
1107
1113
  is no separate agent CLI, no agent-only spelling, and nothing for you to author differently:
1108
1114
 
1109
- - **The agent holds no token.** Its machine is declared as edge-injected, so the CLI sends the request
1110
- *bare* to the platform's public HTTPS name (`PLATFORM_BASE_URL`), and the egress edge stamps the
1111
- authorization onto it on the way out. Credential material never enters the machine. Setting
1112
- `ORCHESTRA_API_TOKEN` deliberately still wins — the edge leaves an `Authorization` header the client
1113
- supplied alone.
1115
+ - **The agent sets no token.** The worker writes the agent's own short-lived platform token to a file,
1116
+ renews it before it expires, and sets `ORCHESTRA_API_TOKEN_FILE` to that file's path on each agent
1117
+ process. The CLI reads the file before each request and sends its token to the platform's public HTTPS
1118
+ name (`PLATFORM_BASE_URL`), with no organization header, because the token names its organization.
1119
+ The token works only while the agent is placed on that machine. A token set in `ORCHESTRA_API_TOKEN`
1120
+ comes before the file. On a machine behind the platform's network edge, the edge replaces the
1121
+ `Authorization` header of each call with a token for the same agent, whatever token the call carried.
1114
1122
  - **IAM is the only difference between principals.** The same command run by an agent and by a human
1115
1123
  differs only in what their grants allow; a refusal is a permission error naming the action, never
1116
1124
  an instruction to log in (there is nothing in a machine to log into).
1117
1125
  - **The factory loop works there too.** `synth`, `diff` and `apply` (and `grant`) are ordinary
1118
1126
  platform callers, so an agent can preview and apply a factory from inside its machine with no token
1119
- and no organization set — the same bare send, judged by the same IAM.
1127
+ and no organization set — the same token file, judged by the same IAM.
1120
1128
  - **Triggers are runtime wiring: agents observe it, they do not author it.** Declare them in code
1121
1129
  (`new Trigger(factory, …)`) or have an explicitly granted principal create them. The managed
1122
1130
  worker role deliberately carries **no** trigger-authoring capability, so `triggers create`