@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
@@ -22819,6 +22819,26 @@
22819
22819
  }
22820
22820
  }
22821
22821
  },
22822
+ "credentials": {
22823
+ "schema": {
22824
+ "kind": "array",
22825
+ "items": {
22826
+ "kind": "object",
22827
+ "fields": {
22828
+ "credential": {
22829
+ "schema": {
22830
+ "kind": "scalar"
22831
+ }
22832
+ },
22833
+ "replace": {
22834
+ "schema": {
22835
+ "kind": "scalar"
22836
+ }
22837
+ }
22838
+ }
22839
+ }
22840
+ }
22841
+ },
22822
22842
  "kind": {
22823
22843
  "schema": {
22824
22844
  "kind": "scalar"
@@ -23188,6 +23208,26 @@
23188
23208
  }
23189
23209
  }
23190
23210
  },
23211
+ "credentials": {
23212
+ "schema": {
23213
+ "kind": "array",
23214
+ "items": {
23215
+ "kind": "object",
23216
+ "fields": {
23217
+ "credential": {
23218
+ "schema": {
23219
+ "kind": "scalar"
23220
+ }
23221
+ },
23222
+ "replace": {
23223
+ "schema": {
23224
+ "kind": "scalar"
23225
+ }
23226
+ }
23227
+ }
23228
+ }
23229
+ }
23230
+ },
23191
23231
  "kind": {
23192
23232
  "schema": {
23193
23233
  "kind": "scalar"
@@ -23614,6 +23654,26 @@
23614
23654
  }
23615
23655
  }
23616
23656
  },
23657
+ "credentials": {
23658
+ "schema": {
23659
+ "kind": "array",
23660
+ "items": {
23661
+ "kind": "object",
23662
+ "fields": {
23663
+ "credential": {
23664
+ "schema": {
23665
+ "kind": "scalar"
23666
+ }
23667
+ },
23668
+ "replace": {
23669
+ "schema": {
23670
+ "kind": "scalar"
23671
+ }
23672
+ }
23673
+ }
23674
+ }
23675
+ }
23676
+ },
23617
23677
  "kind": {
23618
23678
  "schema": {
23619
23679
  "kind": "scalar"
@@ -24075,6 +24135,26 @@
24075
24135
  }
24076
24136
  }
24077
24137
  },
24138
+ "credentials": {
24139
+ "schema": {
24140
+ "kind": "array",
24141
+ "items": {
24142
+ "kind": "object",
24143
+ "fields": {
24144
+ "credential": {
24145
+ "schema": {
24146
+ "kind": "scalar"
24147
+ }
24148
+ },
24149
+ "replace": {
24150
+ "schema": {
24151
+ "kind": "scalar"
24152
+ }
24153
+ }
24154
+ }
24155
+ }
24156
+ }
24157
+ },
24078
24158
  "kind": {
24079
24159
  "schema": {
24080
24160
  "kind": "scalar"
@@ -24503,6 +24583,26 @@
24503
24583
  }
24504
24584
  }
24505
24585
  },
24586
+ "credentials": {
24587
+ "schema": {
24588
+ "kind": "array",
24589
+ "items": {
24590
+ "kind": "object",
24591
+ "fields": {
24592
+ "credential": {
24593
+ "schema": {
24594
+ "kind": "scalar"
24595
+ }
24596
+ },
24597
+ "replace": {
24598
+ "schema": {
24599
+ "kind": "scalar"
24600
+ }
24601
+ }
24602
+ }
24603
+ }
24604
+ }
24605
+ },
24506
24606
  "provisionSpec": {
24507
24607
  "schema": {
24508
24608
  "kind": "object",
@@ -24862,6 +24962,26 @@
24862
24962
  }
24863
24963
  }
24864
24964
  },
24965
+ "credentials": {
24966
+ "schema": {
24967
+ "kind": "array",
24968
+ "items": {
24969
+ "kind": "object",
24970
+ "fields": {
24971
+ "credential": {
24972
+ "schema": {
24973
+ "kind": "scalar"
24974
+ }
24975
+ },
24976
+ "replace": {
24977
+ "schema": {
24978
+ "kind": "scalar"
24979
+ }
24980
+ }
24981
+ }
24982
+ }
24983
+ }
24984
+ },
24865
24985
  "kind": {
24866
24986
  "schema": {
24867
24987
  "kind": "scalar"
@@ -46431,7 +46551,7 @@
46431
46551
  "required": true,
46432
46552
  "repeatable": false,
46433
46553
  "credential": true,
46434
- "description": "Secret value. This is write-only and is never returned by management APIs."
46554
+ "description": "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}."
46435
46555
  },
46436
46556
  {
46437
46557
  "name": "expires-at",
@@ -46531,6 +46651,14 @@
46531
46651
  "kind": "scalar"
46532
46652
  }
46533
46653
  }
46654
+ },
46655
+ "hosts": {
46656
+ "schema": {
46657
+ "kind": "array",
46658
+ "items": {
46659
+ "kind": "scalar"
46660
+ }
46661
+ }
46534
46662
  }
46535
46663
  }
46536
46664
  }
@@ -46640,18 +46768,18 @@
46640
46768
  "kind": "scalar"
46641
46769
  }
46642
46770
  }
46771
+ },
46772
+ "hosts": {
46773
+ "schema": {
46774
+ "kind": "array",
46775
+ "items": {
46776
+ "kind": "scalar"
46777
+ }
46778
+ }
46643
46779
  }
46644
46780
  }
46645
46781
  }
46646
46782
  },
46647
- "hosts": {
46648
- "schema": {
46649
- "kind": "array",
46650
- "items": {
46651
- "kind": "scalar"
46652
- }
46653
- }
46654
- },
46655
46783
  "usableBy": {
46656
46784
  "schema": {
46657
46785
  "kind": "array",
@@ -47095,18 +47223,18 @@
47095
47223
  "kind": "scalar"
47096
47224
  }
47097
47225
  }
47226
+ },
47227
+ "hosts": {
47228
+ "schema": {
47229
+ "kind": "array",
47230
+ "items": {
47231
+ "kind": "scalar"
47232
+ }
47233
+ }
47098
47234
  }
47099
47235
  }
47100
47236
  }
47101
47237
  },
47102
- "hosts": {
47103
- "schema": {
47104
- "kind": "array",
47105
- "items": {
47106
- "kind": "scalar"
47107
- }
47108
- }
47109
- },
47110
47238
  "usableBy": {
47111
47239
  "schema": {
47112
47240
  "kind": "array",
@@ -47571,18 +47699,18 @@
47571
47699
  "kind": "scalar"
47572
47700
  }
47573
47701
  }
47702
+ },
47703
+ "hosts": {
47704
+ "schema": {
47705
+ "kind": "array",
47706
+ "items": {
47707
+ "kind": "scalar"
47708
+ }
47709
+ }
47574
47710
  }
47575
47711
  }
47576
47712
  }
47577
47713
  },
47578
- "hosts": {
47579
- "schema": {
47580
- "kind": "array",
47581
- "items": {
47582
- "kind": "scalar"
47583
- }
47584
- }
47585
- },
47586
47714
  "usableBy": {
47587
47715
  "schema": {
47588
47716
  "kind": "array",
@@ -47968,7 +48096,7 @@
47968
48096
  "required": false,
47969
48097
  "repeatable": false,
47970
48098
  "credential": true,
47971
- "description": "Secret value. This is write-only and is never returned by management APIs."
48099
+ "description": "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}."
47972
48100
  },
47973
48101
  {
47974
48102
  "name": "expires-at",
@@ -48045,6 +48173,14 @@
48045
48173
  "kind": "scalar"
48046
48174
  }
48047
48175
  }
48176
+ },
48177
+ "hosts": {
48178
+ "schema": {
48179
+ "kind": "array",
48180
+ "items": {
48181
+ "kind": "scalar"
48182
+ }
48183
+ }
48048
48184
  }
48049
48185
  }
48050
48186
  }
@@ -48154,18 +48290,18 @@
48154
48290
  "kind": "scalar"
48155
48291
  }
48156
48292
  }
48293
+ },
48294
+ "hosts": {
48295
+ "schema": {
48296
+ "kind": "array",
48297
+ "items": {
48298
+ "kind": "scalar"
48299
+ }
48300
+ }
48157
48301
  }
48158
48302
  }
48159
48303
  }
48160
48304
  },
48161
- "hosts": {
48162
- "schema": {
48163
- "kind": "array",
48164
- "items": {
48165
- "kind": "scalar"
48166
- }
48167
- }
48168
- },
48169
48305
  "usableBy": {
48170
48306
  "schema": {
48171
48307
  "kind": "array",
@@ -547,6 +547,16 @@ export declare const Slack: {
547
547
  readonly SessionPerConversation: import("../constructs/provider-types.js").Binding<"slack::app_mention" | "slack::message" | "slack::message.im" | "slack::message.mpim">;
548
548
  readonly SessionPerThread: import("../constructs/provider-types.js").Binding<"slack::app_mention" | "slack::message" | "slack::message.im" | "slack::message.mpim">;
549
549
  };
550
+ readonly skill: {
551
+ /**
552
+ * Accepts a platform id or a slug interchangeably — one rule for every reference property, stated
553
+ * once on `IResource` (`constructs/interfaces.ts`). A catalog row is seeded with slug = id, so this
554
+ * one key is both at once.
555
+ */
556
+ readonly skillId: "skill_slack";
557
+ /** @internal — the reference this catalog skill contributes when passed (its `org_global` key). */
558
+ readonly _resourceId: () => string;
559
+ };
550
560
  readonly conversation: {
551
561
  readonly mention: import("../constructs/provider-types.js").ProviderEventHandle<"slack::app_mention">;
552
562
  readonly dm: import("../constructs/provider-types.js").ProviderEventHandle<"slack::message.im">;
@@ -605,6 +615,16 @@ export declare const Teams: {
605
615
  readonly SessionPerConversation: import("../constructs/provider-types.js").Binding<"teams::message">;
606
616
  readonly SessionPerThread: import("../constructs/provider-types.js").Binding<"teams::message">;
607
617
  };
618
+ readonly skill: {
619
+ /**
620
+ * Accepts a platform id or a slug interchangeably — one rule for every reference property, stated
621
+ * once on `IResource` (`constructs/interfaces.ts`). A catalog row is seeded with slug = id, so this
622
+ * one key is both at once.
623
+ */
624
+ readonly skillId: "skill_teams";
625
+ /** @internal — the reference this catalog skill contributes when passed (its `org_global` key). */
626
+ readonly _resourceId: () => string;
627
+ };
608
628
  readonly conversation: {
609
629
  readonly message: import("../constructs/provider-types.js").ProviderEventHandle<"teams::message">;
610
630
  readonly inChannel: () => ScopedCondition<"teams::message">;
@@ -1140,6 +1160,16 @@ export declare const Providers: {
1140
1160
  readonly SessionPerConversation: import("../constructs/provider-types.js").Binding<"slack::app_mention" | "slack::message" | "slack::message.im" | "slack::message.mpim">;
1141
1161
  readonly SessionPerThread: import("../constructs/provider-types.js").Binding<"slack::app_mention" | "slack::message" | "slack::message.im" | "slack::message.mpim">;
1142
1162
  };
1163
+ readonly skill: {
1164
+ /**
1165
+ * Accepts a platform id or a slug interchangeably — one rule for every reference property, stated
1166
+ * once on `IResource` (`constructs/interfaces.ts`). A catalog row is seeded with slug = id, so this
1167
+ * one key is both at once.
1168
+ */
1169
+ readonly skillId: "skill_slack";
1170
+ /** @internal — the reference this catalog skill contributes when passed (its `org_global` key). */
1171
+ readonly _resourceId: () => string;
1172
+ };
1143
1173
  readonly conversation: {
1144
1174
  readonly mention: import("../constructs/provider-types.js").ProviderEventHandle<"slack::app_mention">;
1145
1175
  readonly dm: import("../constructs/provider-types.js").ProviderEventHandle<"slack::message.im">;
@@ -1191,6 +1221,16 @@ export declare const Providers: {
1191
1221
  readonly SessionPerConversation: import("../constructs/provider-types.js").Binding<"teams::message">;
1192
1222
  readonly SessionPerThread: import("../constructs/provider-types.js").Binding<"teams::message">;
1193
1223
  };
1224
+ readonly skill: {
1225
+ /**
1226
+ * Accepts a platform id or a slug interchangeably — one rule for every reference property, stated
1227
+ * once on `IResource` (`constructs/interfaces.ts`). A catalog row is seeded with slug = id, so this
1228
+ * one key is both at once.
1229
+ */
1230
+ readonly skillId: "skill_teams";
1231
+ /** @internal — the reference this catalog skill contributes when passed (its `org_global` key). */
1232
+ readonly _resourceId: () => string;
1233
+ };
1194
1234
  readonly conversation: {
1195
1235
  readonly message: import("../constructs/provider-types.js").ProviderEventHandle<"teams::message">;
1196
1236
  readonly inChannel: () => ScopedCondition<"teams::message">;
@@ -538,6 +538,20 @@ export const Slack = {
538
538
  conversational: true,
539
539
  events: slackEvents,
540
540
  bindings: slackBindings,
541
+ // The provider's catalog skill — attach it with `skills: [Slack.skill]`. A plain catalog literal
542
+ // satisfying `ISkill` rather than a registered plan import: a module-level constant has no construct
543
+ // scope to register one in. It skips synth-time plan-import registration only — at apply the ref still
544
+ // resolves through one idempotent getSkill, and boot validation guarantees the catalog row exists.
545
+ skill: {
546
+ /**
547
+ * Accepts a platform id or a slug interchangeably — one rule for every reference property, stated
548
+ * once on `IResource` (`constructs/interfaces.ts`). A catalog row is seeded with slug = id, so this
549
+ * one key is both at once.
550
+ */
551
+ skillId: "skill_slack",
552
+ /** @internal — the reference this catalog skill contributes when passed (its `org_global` key). */
553
+ _resourceId: () => "skill_slack",
554
+ },
541
555
  // The conversation authoring sugar, generated from the catalog conversation block.
542
556
  conversation: {
543
557
  mention: slackEvents.AppMention,
@@ -589,6 +603,20 @@ export const Teams = {
589
603
  conversational: true,
590
604
  events: teamsEvents,
591
605
  bindings: teamsBindings,
606
+ // The provider's catalog skill — attach it with `skills: [Teams.skill]`. A plain catalog literal
607
+ // satisfying `ISkill` rather than a registered plan import: a module-level constant has no construct
608
+ // scope to register one in. It skips synth-time plan-import registration only — at apply the ref still
609
+ // resolves through one idempotent getSkill, and boot validation guarantees the catalog row exists.
610
+ skill: {
611
+ /**
612
+ * Accepts a platform id or a slug interchangeably — one rule for every reference property, stated
613
+ * once on `IResource` (`constructs/interfaces.ts`). A catalog row is seeded with slug = id, so this
614
+ * one key is both at once.
615
+ */
616
+ skillId: "skill_teams",
617
+ /** @internal — the reference this catalog skill contributes when passed (its `org_global` key). */
618
+ _resourceId: () => "skill_teams",
619
+ },
592
620
  // The conversation authoring sugar, generated from the catalog conversation block.
593
621
  conversation: {
594
622
  message: teamsEvents.Message,
@@ -673,6 +701,8 @@ export const PROVIDER_SKILL_IDS = {
673
701
  "jira-classic": "skill_jira-classic",
674
702
  "linear": "skill_linear",
675
703
  "notion": "skill_notion",
704
+ "slack": "skill_slack",
705
+ "teams": "skill_teams",
676
706
  "zendesk": "skill_zendesk",
677
707
  };
678
708
  /**
package/docs/REFERENCE.md CHANGED
@@ -131,29 +131,43 @@ export ORCHESTRA_API_TOKEN="…" # any principal's bearer; the CLI ne
131
131
  export ORCHESTRA_ORGANIZATION_ID="org_…"
132
132
  ```
133
133
 
134
+ Each `ORCHESTRA_` machine variable this page names also has a former `SFDK_` spelling. Until the rename's compatibility period ends ([D50](../../docs/specs/2026-10-03_2446_orchestra_rename_spec.md)), the platform and the worker still write the former spelling beside the new one, and every reader takes the new name first and the former one when the new one is absent.
135
+
134
136
  **The auth-provider chain** (one ordered chain for every command, presence is selection):
135
- `ORCHESTRA_API_TOKEN` → the `login` profile → the platform-injected machine edge flag
136
- (`SFDK_AUTH_EDGE_INJECTED`, which makes the CLI send the request **bare** so the egress edge
137
- stamps the agent's authorization — no credential ever enters the machine) → a named
138
- missing-credentials error. There is **no `--token` flag**: a token never appears in argv.
137
+ `ORCHESTRA_API_TOKEN` → the file `ORCHESTRA_API_TOKEN_FILE` names → the `login` profile → the
138
+ platform-injected machine edge flag (`ORCHESTRA_AUTH_EDGE_INJECTED`) → a named missing-credentials error.
139
+ There is **no `--token` flag**: a token never appears in argv.
140
+
141
+ - **The token file.** On an Orchestra machine, the worker writes the agent's own platform token to a
142
+ file and renews it before it expires. It sets `ORCHESTRA_API_TOKEN_FILE` to that file's path on each
143
+ agent process. The CLI reads the file again before each request, so a long `orchestra sessions wait`
144
+ always sends the current token. A missing, empty or unreadable file counts as absent. The worker sets
145
+ the path before it writes the file, so right after the agent starts, a command may report that the
146
+ file is not written yet.
147
+ - **The edge flag.** On a machine behind the platform's network edge, the edge adds the agent's
148
+ authorization to each call to the platform. It replaces any token the request carried with a token for
149
+ the same agent. With the edge flag and no token, the CLI sends the request **bare**.
150
+ - **A 401 under the token file.** The agent has nothing to renew. The token expired before the worker
151
+ renewed it, or the agent is no longer placed on the machine, the machine stopped, or the agent is not
152
+ active.
139
153
 
140
154
  **Resolved alongside the chain, per field:** the base URL (`--base-url` → `ORCHESTRA_BASE_URL`, then `PLATFORM_BASE_URL` → profile;
141
155
  `login` alone adds the built-in default as a fourth tier, because it is the command that has no profile
142
156
  to read yet — every other command needs one of the three, and says so if it has none)
143
- and the organization (`--org` → `ORCHESTRA_ORGANIZATION_ID` → profile; under the edge provider the organization
144
- rides the stamped identity server-side). Every authenticated request requires HTTPS or loopback — the
157
+ and the organization (`--org` → `ORCHESTRA_ORGANIZATION_ID` → profile; under the token file and the edge flag
158
+ the organization rides the agent's token server-side). Every authenticated request requires HTTPS or loopback — the
145
159
  bearer is itself a credential — with the unauthenticated `health` ping the one exemption. `diff`/`apply`
146
160
  print the resolved target org as a banner before any read/write, and warn when an exported
147
161
  `ORCHESTRA_ORGANIZATION_ID` diverges from the profile's org (so a stale export can't silently redirect writes).
148
162
 
149
- The conversation (`SFDK_SESSION_ID`, under every provider). The worker sets it on each harness process
163
+ The conversation (`ORCHESTRA_SESSION_ID`, under every provider). The worker sets it on each harness process
150
164
  it starts, so a command an agent runs knows which conversation it is in. When it is set, `orchestra` adds
151
165
  `sessionId` to every JSON request body that has none: typed commands, `orchestra api`, `apply`, and the
152
166
  `login` and refresh token requests. A body that already names a `sessionId` is sent unchanged, so
153
167
  `artifacts create --session-id <id>` wins. Query strings, uploads and other non-JSON bodies are never
154
168
  changed, and an empty or whitespace-only value counts as unset. The platform checks a supplied session as
155
169
  usual. An artifact takes its project from the session, so a command that must publish into another project
156
- than its conversation's runs without the variable: `env -u SFDK_SESSION_ID orchestra artifacts create …`. A
170
+ than its conversation's runs without the variable: `env -u ORCHESTRA_SESSION_ID orchestra artifacts create …`. A
157
171
  value you export by hand in your own shell applies the same way.
158
172
 
159
173
  ## 4. Author your first factory
@@ -807,7 +821,7 @@ subscription token rather than an API key:
807
821
  import { EgressPolicy, Secret, SecretValue } from "@orchestraworks/cli";
808
822
 
809
823
  new Secret(factory, "claude-sign-in", {
810
- value: SecretValue.fromEnv("SFDK_CLAUDE_CODE_OAUTH_TOKEN"),
824
+ value: SecretValue.fromEnv("ORCHESTRA_FDK_CLAUDE_CODE_OAUTH_TOKEN"),
811
825
  hosts: ["api.anthropic.com"],
812
826
  injection: {
813
827
  headers: [{ name: "authorization", value: "Bearer ${secret}" }],
@@ -851,7 +865,7 @@ Agent.fromSlug(factory, "existing-agent");
851
865
  Environment.fromSlug(factory, "shared-runtime");
852
866
  Volume.fromSlug(factory, "cache-vol");
853
867
  Volume.fromId(factory, "volume_…");
854
- Connection.fromEnv(factory, "SFDK_ZENDESK_CONNECTION_ID", { provider: Providers.Zendesk });
868
+ Connection.fromEnv(factory, "ORCHESTRA_FDK_ZENDESK_CONNECTION_ID", { provider: Providers.Zendesk });
855
869
  ```
856
870
 
857
871
  `Connection.fromEnv` resolves the connection id from `process.env` at apply, so **no tenant id
@@ -1057,8 +1071,8 @@ const ourSlackApp = new Connector(factory, "our-slack-app", {
1057
1071
  provider: Providers.Slack,
1058
1072
  clientId: "1234.5678",
1059
1073
  appId: "A0ACME",
1060
- clientSecret: new Secret(factory, "slack-client-secret", { value: SecretValue.fromEnv("SFDK_SLACK_CLIENT_SECRET") }),
1061
- signingSecret: new Secret(factory, "slack-signing-secret", { value: SecretValue.fromEnv("SFDK_SLACK_SIGNING_SECRET") }),
1074
+ clientSecret: new Secret(factory, "slack-client-secret", { value: SecretValue.fromEnv("ORCHESTRA_FDK_SLACK_CLIENT_SECRET") }),
1075
+ signingSecret: new Secret(factory, "slack-signing-secret", { value: SecretValue.fromEnv("ORCHESTRA_FDK_SLACK_SIGNING_SECRET") }),
1062
1076
  });
1063
1077
 
1064
1078
  const workspace = new Connection(factory, "workspace", {
@@ -16,7 +16,7 @@
16
16
  */
17
17
  export interface ApiErrorDetail {
18
18
  /**
19
- * Present only when `code` is CREDENTIAL_UNAVAILABLE, ORGANIZATION_AUTH_POLICY_UNSATISFIED or SSO_CALLER_SESSION_REQUIRED. Published as a plain value rather than a closed enum because the shapes that carry `reason` do not agree on one value set. When `code` is CREDENTIAL_UNAVAILABLE: Closed denial-reason class explaining why the credential chain refused — one of secret_missing, secret_expired, refresh_failed, recipe_field_missing, policy_denied, ambiguous_match, connection_needs_attention, user_subject_required, user_grant_unavailable, conversation_not_attested, path_not_permitted, forge_credential_stale, install_declaration_invalid, provider_unavailable, internal_error, credential_not_found, use_denied, host_not_covered, machine_in_setup, credential_needs_https, plan_feature_disabled. When `code` is ORGANIZATION_AUTH_POLICY_UNSATISFIED or SSO_CALLER_SESSION_REQUIRED: Closed reason class naming the first policy check the session failed — one of ORGANIZATION_NOT_ACTIVE, SSO_ENFORCED_WITHOUT_BINDING, WRONG_IDENTITY_PROVIDER, AUTHENTICATION_METHOD_NOT_ALLOWED, MFA_REQUIRED.
19
+ * Present only when `code` is CREDENTIAL_UNAVAILABLE, ORGANIZATION_AUTH_POLICY_UNSATISFIED or SSO_CALLER_SESSION_REQUIRED. Published as a plain value rather than a closed enum because the shapes that carry `reason` do not agree on one value set. When `code` is CREDENTIAL_UNAVAILABLE: Closed denial-reason class explaining why the credential chain refused — one of secret_missing, secret_expired, refresh_failed, recipe_field_missing, policy_denied, connection_needs_attention, user_subject_required, user_grant_unavailable, conversation_not_attested, path_not_permitted, forge_credential_stale, install_declaration_invalid, provider_unavailable, internal_error, credential_not_found, use_denied, host_not_covered, machine_in_setup, credential_needs_https, plan_feature_disabled. When `code` is ORGANIZATION_AUTH_POLICY_UNSATISFIED or SSO_CALLER_SESSION_REQUIRED: Closed reason class naming the first policy check the session failed — one of ORGANIZATION_NOT_ACTIVE, SSO_ENFORCED_WITHOUT_BINDING, WRONG_IDENTITY_PROVIDER, AUTHENTICATION_METHOD_NOT_ALLOWED, MFA_REQUIRED.
20
20
  * @type {string}
21
21
  * @memberof ApiErrorDetail
22
22
  */
@@ -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 { EnvironmentHooks } from './EnvironmentHooks';
14
15
  import type { EnvironmentPlatformRequest } from './EnvironmentPlatformRequest';
15
16
  import type { EnvironmentEgressPolicy } from './EnvironmentEgressPolicy';
@@ -50,6 +51,12 @@ export interface CreateEnvironmentRequest {
50
51
  * @memberof CreateEnvironmentRequest
51
52
  */
52
53
  ingressPolicy?: EnvironmentIngressPolicy | null;
54
+ /**
55
+ * 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. Absent declares none.
56
+ * @type {Array<EnvironmentCredential>}
57
+ * @memberof CreateEnvironmentRequest
58
+ */
59
+ credentials?: Array<EnvironmentCredential>;
53
60
  /**
54
61
  * Whether the platform provisions this environment's machines (provisioned, the default) or a customer's own machine enrols into it (enrolled). Fixed at create.
55
62
  * @type {CreateEnvironmentRequestKindEnum}
@@ -12,6 +12,7 @@
12
12
  * Do not edit the class manually.
13
13
  */
14
14
  import { EnvironmentIngressPolicyFromJSON, EnvironmentIngressPolicyToJSON, } from './EnvironmentIngressPolicy';
15
+ import { EnvironmentCredentialFromJSON, EnvironmentCredentialToJSON, } from './EnvironmentCredential';
15
16
  import { EnvironmentHooksFromJSON, EnvironmentHooksToJSON, } from './EnvironmentHooks';
16
17
  import { EnvironmentPlatformRequestFromJSON, EnvironmentPlatformRequestToJSON, } from './EnvironmentPlatformRequest';
17
18
  import { EnvironmentEgressPolicyFromJSON, EnvironmentEgressPolicyToJSON, } from './EnvironmentEgressPolicy';
@@ -44,6 +45,7 @@ export function CreateEnvironmentRequestFromJSONTyped(json, ignoreDiscriminator)
44
45
  'platform': json['platform'] == null ? undefined : EnvironmentPlatformRequestFromJSON(json['platform']),
45
46
  'egressPolicy': json['egressPolicy'] == null ? undefined : EnvironmentEgressPolicyFromJSON(json['egressPolicy']),
46
47
  'ingressPolicy': json['ingressPolicy'] == null ? undefined : EnvironmentIngressPolicyFromJSON(json['ingressPolicy']),
48
+ 'credentials': json['credentials'] == null ? undefined : (json['credentials'].map(EnvironmentCredentialFromJSON)),
47
49
  'kind': json['kind'] == null ? undefined : json['kind'],
48
50
  'provisionSpec': json['provisionSpec'] == null ? undefined : EnvironmentProvisionSpecRequestFromJSON(json['provisionSpec']),
49
51
  'teamId': json['teamId'] == null ? undefined : json['teamId'],
@@ -65,6 +67,7 @@ export function CreateEnvironmentRequestToJSONTyped(value, ignoreDiscriminator =
65
67
  'platform': EnvironmentPlatformRequestToJSON(value['platform']),
66
68
  'egressPolicy': EnvironmentEgressPolicyToJSON(value['egressPolicy']),
67
69
  'ingressPolicy': EnvironmentIngressPolicyToJSON(value['ingressPolicy']),
70
+ 'credentials': value['credentials'] == null ? undefined : (value['credentials'].map(EnvironmentCredentialToJSON)),
68
71
  'kind': value['kind'],
69
72
  'provisionSpec': EnvironmentProvisionSpecRequestToJSON(value['provisionSpec']),
70
73
  'teamId': value['teamId'],
@@ -35,7 +35,7 @@ export interface CreateSecretRequest {
35
35
  */
36
36
  description?: string;
37
37
  /**
38
- * Secret value. This is write-only and is never returned by management APIs.
38
+ * 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}.
39
39
  * @type {string}
40
40
  * @memberof CreateSecretRequest
41
41
  */
@@ -53,7 +53,7 @@ export interface CreateSecretRequest {
53
53
  */
54
54
  teamId?: string;
55
55
  /**
56
- * Optional injection recipe describing the request mutations the broker applies from this secret
56
+ * 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}.
57
57
  * @type {InjectionRecipe}
58
58
  * @memberof CreateSecretRequest
59
59
  */
@@ -67,9 +67,10 @@ export interface CreateSecretRequest {
67
67
  [key: string]: string;
68
68
  };
69
69
  /**
70
- * 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 an injection recipe with a header, and no pattern may name the platform API host or the object store host.
70
+ * 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.
71
71
  * @type {Array<string>}
72
72
  * @memberof CreateSecretRequest
73
+ * @deprecated
73
74
  */
74
75
  hosts?: Array<string>;
75
76
  }
@@ -11,6 +11,7 @@
11
11
  */
12
12
  import type { EnvironmentIngressPolicy } from './EnvironmentIngressPolicy';
13
13
  import type { EnvironmentPlatformWithRuntime } from './EnvironmentPlatformWithRuntime';
14
+ import type { EnvironmentCredential } from './EnvironmentCredential';
14
15
  import type { EnvironmentHooks } from './EnvironmentHooks';
15
16
  import type { EnvironmentEgressPolicy } from './EnvironmentEgressPolicy';
16
17
  import type { EnvironmentProvisionSpec } from './EnvironmentProvisionSpec';
@@ -68,6 +69,12 @@ export interface Environment {
68
69
  * @memberof Environment
69
70
  */
70
71
  ingressPolicy?: EnvironmentIngressPolicy;
72
+ /**
73
+ * 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.
74
+ * @type {Array<EnvironmentCredential>}
75
+ * @memberof Environment
76
+ */
77
+ credentials?: Array<EnvironmentCredential>;
71
78
  /**
72
79
  * Whether the platform provisions this environment's machines (provisioned) or a customer's own machine enrols into it (enrolled). Fixed when the environment is created.
73
80
  * @type {EnvironmentKindEnum}