@orchestraworks/cli 0.5.2 → 0.5.4

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 (128) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/api/compute-provider-check.d.ts +29 -0
  3. package/dist/cli/api/compute-provider-check.js +207 -0
  4. package/dist/cli/api/tail.d.ts +66 -0
  5. package/dist/cli/api/tail.js +564 -0
  6. package/dist/cli/main.d.ts +5 -1
  7. package/dist/cli/main.js +22 -0
  8. package/dist/constructs/agent.d.ts +10 -0
  9. package/dist/constructs/agent.js +39 -4
  10. package/dist/constructs/environment.d.ts +29 -1
  11. package/dist/constructs/environment.js +28 -1
  12. package/dist/constructs/skill.d.ts +6 -1
  13. package/dist/constructs/skill.js +21 -2
  14. package/dist/engine/reconcile.js +15 -1
  15. package/dist/generated/cli-commands.json +1646 -198
  16. package/dist/generated/cli-dispatch.js +9 -0
  17. package/dist/generated/managed-skills.d.ts +2 -0
  18. package/dist/generated/managed-skills.js +18 -0
  19. package/dist/index.d.ts +1 -1
  20. package/docs/REFERENCE.md +21 -1
  21. package/node_modules/@orchestraworks/client/dist/apis/OrganizationInvitationsApi.d.ts +29 -0
  22. package/node_modules/@orchestraworks/client/dist/apis/OrganizationInvitationsApi.js +96 -0
  23. package/node_modules/@orchestraworks/client/dist/esm/apis/OrganizationInvitationsApi.d.ts +29 -0
  24. package/node_modules/@orchestraworks/client/dist/esm/apis/OrganizationInvitationsApi.js +96 -0
  25. package/node_modules/@orchestraworks/client/dist/esm/models/ComputeProvider.d.ts +3 -3
  26. package/node_modules/@orchestraworks/client/dist/esm/models/CreateEnvironmentRequest.d.ts +13 -0
  27. package/node_modules/@orchestraworks/client/dist/esm/models/CreateEnvironmentRequest.js +5 -0
  28. package/node_modules/@orchestraworks/client/dist/esm/models/CreateOrganizationInvitationRequest.d.ts +2 -2
  29. package/node_modules/@orchestraworks/client/dist/esm/models/Environment.d.ts +13 -0
  30. package/node_modules/@orchestraworks/client/dist/esm/models/Environment.js +5 -0
  31. package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentHook.d.ts +38 -0
  32. package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentHook.js +45 -0
  33. package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentHooks.d.ts +39 -0
  34. package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentHooks.js +44 -0
  35. package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentHooksRequest.d.ts +39 -0
  36. package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentHooksRequest.js +44 -0
  37. package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentProvisionSpec.d.ts +2 -1
  38. package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentProvisionSpecRequest.d.ts +2 -1
  39. package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentSnapshot.d.ts +19 -0
  40. package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentSnapshot.js +7 -0
  41. package/node_modules/@orchestraworks/client/dist/esm/models/Machine.d.ts +7 -1
  42. package/node_modules/@orchestraworks/client/dist/esm/models/Machine.js +2 -0
  43. package/node_modules/@orchestraworks/client/dist/esm/models/OrganizationAuthPolicy.d.ts +1 -1
  44. package/node_modules/@orchestraworks/client/dist/esm/models/OrganizationInvitation.d.ts +14 -1
  45. package/node_modules/@orchestraworks/client/dist/esm/models/OrganizationInvitation.js +8 -1
  46. package/node_modules/@orchestraworks/client/dist/esm/models/Principal.d.ts +6 -0
  47. package/node_modules/@orchestraworks/client/dist/esm/models/Principal.js +2 -0
  48. package/node_modules/@orchestraworks/client/dist/esm/models/UpdateEnvironmentRequest.d.ts +13 -0
  49. package/node_modules/@orchestraworks/client/dist/esm/models/UpdateEnvironmentRequest.js +5 -0
  50. package/node_modules/@orchestraworks/client/dist/esm/models/UpdateOrganizationInvitationRequest.d.ts +2 -1
  51. package/node_modules/@orchestraworks/client/dist/esm/models/UpdateOrganizationInvitationRequest.js +2 -1
  52. package/node_modules/@orchestraworks/client/dist/esm/models/User.d.ts +6 -0
  53. package/node_modules/@orchestraworks/client/dist/esm/models/User.js +4 -0
  54. package/node_modules/@orchestraworks/client/dist/esm/models/index.d.ts +3 -0
  55. package/node_modules/@orchestraworks/client/dist/esm/models/index.js +3 -0
  56. package/node_modules/@orchestraworks/client/dist/models/ComputeProvider.d.ts +3 -3
  57. package/node_modules/@orchestraworks/client/dist/models/CreateEnvironmentRequest.d.ts +13 -0
  58. package/node_modules/@orchestraworks/client/dist/models/CreateEnvironmentRequest.js +5 -0
  59. package/node_modules/@orchestraworks/client/dist/models/CreateOrganizationInvitationRequest.d.ts +2 -2
  60. package/node_modules/@orchestraworks/client/dist/models/Environment.d.ts +13 -0
  61. package/node_modules/@orchestraworks/client/dist/models/Environment.js +5 -0
  62. package/node_modules/@orchestraworks/client/dist/models/EnvironmentHook.d.ts +38 -0
  63. package/node_modules/@orchestraworks/client/dist/models/EnvironmentHook.js +52 -0
  64. package/node_modules/@orchestraworks/client/dist/models/EnvironmentHooks.d.ts +39 -0
  65. package/node_modules/@orchestraworks/client/dist/models/EnvironmentHooks.js +51 -0
  66. package/node_modules/@orchestraworks/client/dist/models/EnvironmentHooksRequest.d.ts +39 -0
  67. package/node_modules/@orchestraworks/client/dist/models/EnvironmentHooksRequest.js +51 -0
  68. package/node_modules/@orchestraworks/client/dist/models/EnvironmentProvisionSpec.d.ts +2 -1
  69. package/node_modules/@orchestraworks/client/dist/models/EnvironmentProvisionSpecRequest.d.ts +2 -1
  70. package/node_modules/@orchestraworks/client/dist/models/EnvironmentSnapshot.d.ts +19 -0
  71. package/node_modules/@orchestraworks/client/dist/models/EnvironmentSnapshot.js +7 -0
  72. package/node_modules/@orchestraworks/client/dist/models/Machine.d.ts +7 -1
  73. package/node_modules/@orchestraworks/client/dist/models/Machine.js +2 -0
  74. package/node_modules/@orchestraworks/client/dist/models/OrganizationAuthPolicy.d.ts +1 -1
  75. package/node_modules/@orchestraworks/client/dist/models/OrganizationInvitation.d.ts +14 -1
  76. package/node_modules/@orchestraworks/client/dist/models/OrganizationInvitation.js +8 -1
  77. package/node_modules/@orchestraworks/client/dist/models/Principal.d.ts +6 -0
  78. package/node_modules/@orchestraworks/client/dist/models/Principal.js +2 -0
  79. package/node_modules/@orchestraworks/client/dist/models/UpdateEnvironmentRequest.d.ts +13 -0
  80. package/node_modules/@orchestraworks/client/dist/models/UpdateEnvironmentRequest.js +5 -0
  81. package/node_modules/@orchestraworks/client/dist/models/UpdateOrganizationInvitationRequest.d.ts +2 -1
  82. package/node_modules/@orchestraworks/client/dist/models/UpdateOrganizationInvitationRequest.js +2 -1
  83. package/node_modules/@orchestraworks/client/dist/models/User.d.ts +6 -0
  84. package/node_modules/@orchestraworks/client/dist/models/User.js +4 -0
  85. package/node_modules/@orchestraworks/client/dist/models/index.d.ts +3 -0
  86. package/node_modules/@orchestraworks/client/dist/models/index.js +3 -0
  87. package/node_modules/@orchestraworks/client/package.json +1 -1
  88. package/package.json +4 -4
  89. package/skills/orchestra/SKILL.md +167 -42
  90. package/skills/orchestra-fdk/SKILL.md +112 -545
  91. package/skills/orchestra-fdk/references/authoring.md +29 -2
  92. package/skills/orchestra-fdk/references/environment.md +295 -41
  93. package/skills/orchestra-fdk/references/integrations/analytics.md +18 -0
  94. package/skills/orchestra-fdk/references/integrations/ci-cd.md +20 -0
  95. package/skills/orchestra-fdk/references/integrations/cloud.md +19 -0
  96. package/skills/orchestra-fdk/references/integrations/code-repo.md +76 -0
  97. package/skills/orchestra-fdk/references/integrations/databases.md +22 -0
  98. package/skills/orchestra-fdk/references/integrations/dependencies.md +29 -0
  99. package/skills/orchestra-fdk/references/integrations/design.md +18 -0
  100. package/skills/orchestra-fdk/references/integrations/feature-flags.md +19 -0
  101. package/skills/orchestra-fdk/references/integrations/incident.md +29 -0
  102. package/skills/orchestra-fdk/references/integrations/issue-tracker.md +65 -0
  103. package/skills/orchestra-fdk/references/integrations/knowledge-base.md +43 -0
  104. package/skills/orchestra-fdk/references/integrations/messaging.md +38 -0
  105. package/skills/orchestra-fdk/references/integrations/observability.md +36 -0
  106. package/skills/orchestra-fdk/references/integrations/secrets-managers.md +25 -0
  107. package/skills/orchestra-fdk/references/integrations/support-desk.md +31 -0
  108. package/skills/orchestra-fdk/references/phases/0-start.md +62 -0
  109. package/skills/orchestra-fdk/references/phases/1-discover.md +111 -0
  110. package/skills/orchestra-fdk/references/phases/2-plan.md +157 -0
  111. package/skills/orchestra-fdk/references/phases/3-connect.md +99 -0
  112. package/skills/orchestra-fdk/references/phases/4-build.md +159 -0
  113. package/skills/orchestra-fdk/references/phases/5-prove.md +107 -0
  114. package/skills/orchestra-fdk/references/phases/6-handover.md +42 -0
  115. package/skills/orchestra-fdk/references/troubleshooting.md +128 -0
  116. package/templates/bug-fix/agents/bugfix.md +1 -1
  117. package/templates/bug-fix/main.ts +1 -1
  118. package/templates/engineering-team/README.md +45 -181
  119. package/templates/engineering-team/agents/engineer-agent.md +10 -7
  120. package/templates/engineering-team/agents/manager-agent.md +23 -120
  121. package/templates/engineering-team/inputs.json +1 -3
  122. package/templates/engineering-team/lib/environment.ts +10 -90
  123. package/templates/engineering-team/lib/inputs.ts +5 -97
  124. package/templates/engineering-team/main.ts +22 -69
  125. package/templates/todo-factory/agents/bugfix.md +1 -1
  126. package/templates/todo-factory/main.ts +1 -1
  127. package/templates/engineering-team/agents/engineer-bare.md +0 -22
  128. package/templates/engineering-team/onboarding/create-score-metrics.sh +0 -33
@@ -103,6 +103,21 @@ entrypoint decides what answers. Omit `harness`, or misspell it, and synth fails
103
103
  a message naming the five; there is no default, because guessing which one an author meant would pick a
104
104
  different program than the one they wanted.
105
105
 
106
+ ### Every agent's instructions start with an Attribution section
107
+
108
+ The starter's agents start their instructions with it. When you write an agent of your own, start its
109
+ instructions with the same section, with the agent's display name and slug filled in:
110
+
111
+ ```
112
+ ## Attribution
113
+ You are <agent display name>. Mark the work you produce as yours:
114
+ - every commit message and pull request description ends with
115
+ Co-Authored-By: <agent display name> <<agent-slug>@agents.orchestraworks.ai>
116
+ - every comment and tracker edit ends with one line: — <agent display name>, Orchestra
117
+ ```
118
+
119
+ A person who reads a commit, a pull request, a comment or a tracker edit then sees which agent made it.
120
+
106
121
  ### Platform skills are attached by id
107
122
 
108
123
  An agent uses a platform skill only when its `skills` list names it: `Skill.fromId(factory, "skill_<key>")`
@@ -1077,9 +1092,9 @@ cookie your app sets must carry `SameSite=None; Secure; Partitioned`, or the bro
1077
1092
  frame and your app's own sign-in or session state is lost on each load. The platform's own access
1078
1093
  cookie is already set this way, and your app never sees it.
1079
1094
 
1080
- ### Typed flows: `user-grants grant` and `sessions wait`
1095
+ ### Typed flows: `user-grants grant`, `sessions wait` and `sessions tail`
1081
1096
 
1082
- Two commands stay hand-shaped, because the orchestration is the value a bare generated call would
1097
+ Three commands stay hand-shaped, because the orchestration is the value a bare generated call would
1083
1098
  drop. Both are platform commands — they read and write the live factory, not your code.
1084
1099
 
1085
1100
  ```bash
@@ -1104,6 +1119,18 @@ taking no more messages), which settles too. `--interval` and `--timeout` are yo
1104
1119
  any settlement (the printed state
1105
1120
  carries the outcome) and non-zero only on a timeout or a failed call.
1106
1121
 
1122
+ ```bash
1123
+ orchestra sessions tail session_01abc --until-settled
1124
+ ```
1125
+
1126
+ Prints each item of the session as it is saved: a reply line by line as it grows, a tool call as one
1127
+ line, printed again when its status changes. With `--output json` it prints each item once, as one
1128
+ JSON line, when the item can no longer change. It starts with the items that
1129
+ already exist; `--after <item id>` starts after that item instead. While a turn runs, each read waits
1130
+ on the platform for the next saved output, so the command does not poll on a timer. `--until-settled`
1131
+ exits once the turn has ended and prints the session's status, with exit 0 whatever the status, as
1132
+ `sessions wait` does. Without it, the command follows the session until Ctrl-C.
1133
+
1107
1134
  ### The backup: `orchestra api`
1108
1135
 
1109
1136
  `orchestra api GET "/sessions?limit=5"` makes a raw authenticated call — exactly `gh api`'s role — through
@@ -1,7 +1,7 @@
1
1
  # Port a codebase's setup to Orchestra machines
2
2
 
3
- Step 8 of the orchestra-fdk skill, "Set up the machines", sends you here, and so does its step 3 for a new
4
- environment in an existing factory. When you finish, go back to the step that sent you.
3
+ Phase 4 of the orchestra-fdk skill, "Build", sends you here, for a new factory and for a new environment in
4
+ an existing factory. When you finish section 6, go back to phase 4 for the apply.
5
5
 
6
6
  An agent can fix, test or show a codebase only if its machine can install and run it. You find out how
7
7
  this team sets up their code, prove it on this computer first, write it into the factory, and apply it.
@@ -319,7 +319,7 @@ Orchestra Secret, and our network edge adds it to each model call, so no machine
319
319
 
320
320
  - For the gateway, `apply` creates the gateway key and its secret. The starter already declares them.
321
321
  - For a subscription token or a provider key, declare a Secret and a rule that adds it on the provider's
322
- host, as step 6 of the orchestra-fdk skill says (orchestra skill, sections 6 and 7).
322
+ host, as phase 2 of the orchestra-fdk skill, "The model route", says (orchestra skill, sections 6 and 7).
323
323
 
324
324
  Ask the developer to revoke the `local-dev` gateway key, at **Settings › Gateway keys**, when local work is
325
325
  done.
@@ -332,6 +332,116 @@ fails and why. Report which tests ran and which could not. Then run `orchestra l
332
332
  Ask the developer to confirm the path you recommend, with your question tool. The mode you proved points
333
333
  to the path, as the table in section 2 says: a container machine to A, the host outpost to B.
334
334
 
335
+ ### The machine's runtime, by operating system
336
+
337
+ An environment's `platform` is `{ os, arch, runtime }`, set when the environment is created. `runtime` never
338
+ changes. On a provisioned environment it is `microvm` (the default) or `vm`. An enrolled environment is
339
+ `host`: the team's own machine, as it is, with no network rules of ours.
340
+
341
+ The setup script runs once, as root or as the machine's service account, on each new machine, before the
342
+ agent arrives and before any code is cloned. It is at most 64 KiB. It has 10 minutes. The limit is fixed for
343
+ now, and an environment cannot raise it. A worker that starts again on the same
344
+ machine reuses the result it kept, and does not run the script again.
345
+
346
+ #### Linux
347
+
348
+ Most code: web, backend, mobile build tools, anything that runs in Docker.
349
+
350
+ | Runtime and where it runs | Base image: what's in it | Sizes | Disks and shared volumes | Setup script | Home and continuity | Requirements and limits |
351
+ |---|---|---|---|---|---|---|
352
+ | `microvm`: a Kata micro VM on Kubernetes, amd64. `vm`: an EC2 Ubuntu VM, amd64 or arm64 | `microvm`: Debian with Node 24, Java 21 and 25, Python 3, a C and C++ build toolchain, git, the GitHub CLI `gh`, and Docker with Compose and Buildx (not started until the setup script starts it). `vm`: Ubuntu 24.04 with Node 24, git, and rootless Docker with Buildx, which runs from boot as the agent's user. The VM has no Java and no Compose plugin: install the ones the code needs in the setup script. Both carry the worker and the `claude`, `codex`, `pi` and `script` harnesses | `microvm`: 0.5, 1, 2, 4, 8, 16 or 32 CPU. `vm`: 2, 4 or 8 CPU. 2 GB of memory per CPU | `vm`: a 40 GiB root disk. Up to four extra disks (`disks`), such as `/var/lib/docker` and `/work`. Shared volumes (`volumeMounts`) on EFS, which every machine of an environment can mount together | Bash, run with `bash -e`. One exit code per step | A volume at `/home` keeps the agent's home across machines. Without it, nothing in `/home` outlives the machine | No Windows or macOS programs. A kernel of its own, an Android device or nested virtualization needs `vm` |
353
+
354
+ #### Windows
355
+
356
+ Code that builds or runs only on Windows: .NET Framework, WinForms, WPF, IIS, Windows-only tools.
357
+
358
+ | Runtime and where it runs | Base image: what's in it | Sizes | Disks and shared volumes | Setup script | Home and continuity | Requirements and limits |
359
+ |---|---|---|---|---|---|---|
360
+ | `vm`: an EC2 Windows Server VM, amd64. Set `platform: { os: "windows", arch: "amd64", runtime: "vm" }` | Our image only: Windows Server 2025 Core, Node 24, Docker for Windows containers with the Containers feature, the worker, the `orchestra` command, and the `claude`, `codex`, `pi` and `script` harnesses. No git: install it in the setup script. A hosted Windows machine cannot start from another image | 4 or 8 CPU, 2 GB of memory per CPU | The image's 100 GiB root disk. No extra disks: remove `disks`. Shared volumes: not stated | PowerShell 5.1, run as the machine's service account. One exit code per step. Template: "A Windows setup script" below | The machine is parked when idle and keeps its disk, so the home (`C:\sf\home`) and `C:\work` stay. The setup script runs once per machine | Docker runs Windows containers only, for administrators only. A machine takes up to 15 minutes to start the first time |
361
+
362
+ **Windows in three stages.** Guide a Windows team through these stages, in order. Write the stage you plan
363
+ into `orchestra-factory-notes.md`.
364
+
365
+ 1. **Start on hosted Windows, with our image.** This proves the factory works, with nothing to run in the
366
+ team's own cloud. The setup script installs what fits in its 10 minutes: Git, and the small tools. A
367
+ larger toolchain, such as Visual Studio Build Tools or an old SDK, goes in the agent's first turn. The
368
+ machine is parked when idle and keeps its disk, so the next turn finds the toolchain installed. The agent
369
+ runs the install in the turn and waits for it: a park stops the VM and kills an install still running.
370
+ The machine is deleted after `ttl`, 2 hours by default, and a new one starts without the toolchain.
371
+ 2. **Then move to the team's own Windows image, through a compute provider in their cloud.** The benefit:
372
+ each machine starts with the whole toolchain installed, with no setup limit, and the team's licenses,
373
+ such as Visual Studio's, stay in their own image. The Launcher, the program the team runs in their
374
+ cloud, starts Windows VMs from the image its environment names. The Launcher runs on Azure (the
375
+ orchestra skill, section 18). The team bakes the image on Windows Server 2025 and adds their own
376
+ toolchain: git, MSBuild and .NET are theirs to install. Windows 11 is not supported, and a plain
377
+ captured Windows VM does not register. The image must contain these three parts:
378
+ - The worker's release package, for example at `C:\ProgramData\sfdk\worker\package`.
379
+ - The worker's Windows service, `SfdkWorker`. It runs `worker.exe run --root C:\ProgramData\sfdk\worker
380
+ --service` as LocalSystem. It is demand-start (`Manual`), not automatic. On a failure it restarts
381
+ three times, 2 seconds apart, and a clean stop with a non-zero exit code counts as a failure.
382
+ - The startup task `orchestra-azure-userdata`. It runs `azure-userdata.ps1` as SYSTEM at each boot
383
+ (`AtStartup`). The script writes the files that the VM's startup data carries, then starts
384
+ `SfdkWorker`.
385
+
386
+ Our image builds the same parts: `install-vm-runtime.ps1` and the image template
387
+ `infra/packer/azure-windows-runtime.pkr.hcl`. Under a Launcher, the image needs no WinDivert, no
388
+ redirect firewall rule, no Docker, no Node and no preinstalled harness: a harness installs itself on
389
+ its first turn, in about 60 seconds. Credentials are the team's to set on the VM (part C, "Tokens on a
390
+ compute provider's machines"). Our own image is in a public Azure gallery:
391
+ `/CommunityGalleries/orchestraworks-881a796f-0a84-4be1-af80-0a38564a406a/Images/runtime-win/Versions/0.0.136`
392
+ (Gen2). An environment that names no image boots its `Versions/latest`. Not released yet: a one-command
393
+ installer for a team's own image, the Launcher on AWS, and a team's own image on hosted Windows.
394
+ 3. **Then keep machines ready, for speed.** `standbyCapacity` on the agent (`Agent` in the kit) keeps
395
+ `count` machines started, set up and with the agent installed, on a schedule or always. A new
396
+ conversation then starts at once, with no wait for a Windows first boot. The platform refuses it only
397
+ for an enrolled environment or a `custom` harness, so it applies to hosted Windows and to a compute
398
+ provider. Proven on a compute provider's Windows VM: a new conversation got a ready machine, and its
399
+ turn started in 3.5 seconds. A standby minute is billed: the plan page shows the price.
400
+ `npx orchestra agents get <agent>` shows `standbyStatus`: how many machines are ready now, and why
401
+ fewer when that is so.
402
+
403
+ #### macOS
404
+
405
+ Code that needs Xcode, the iOS Simulator or another Apple tool.
406
+
407
+ Not released yet: Orchestra launches no Mac. A Mac works only as the team's own enrolled machine
408
+ (`host`), with the worker installed on it, no network rules of ours and no keys added at the edge. Agree it
409
+ with the Orchestra team first (the orchestra skill, section 18).
410
+
411
+ #### A custom image
412
+
413
+ A team's own image, when the stock image plus a setup script is too slow or cannot hold the toolchain.
414
+
415
+ - Build it `FROM` our runtime image, so it keeps the worker and the harnesses. The public name is
416
+ `public.ecr.aws/orchestraworks/runtime` (until AWS approves that alias: `public.ecr.aws/z8d3m6s5/runtime`).
417
+ Pin it by digest; the Orchestra team gives the current one.
418
+ - Push it to the team's own registry. `Image.fromBuild` builds and pushes it at apply. The environment names
419
+ a pull key Secret in `imagePullCredential` (`provisionSpec.imagePullSecretId` on the platform), made with
420
+ `SecretValue.registryCredential(<user>, <password>)` or `SecretValue.ecrCredential(<key id>, <secret>)`.
421
+ The platform reads it at each machine create, and never gives it to the agent. The bug-fix starter's
422
+ `main.ts` shows the code.
423
+ - Not released yet: a registry hosted by Orchestra.
424
+ - A custom image applies to `microvm`. An EC2 VM starts from our machine image, not from a container image.
425
+
426
+ #### On this computer
427
+
428
+ `orchestra local` runs Linux containers only, on Docker Desktop, OrbStack or Docker Engine. On an
429
+ Apple-silicon Mac it runs an `amd64` environment natively as `arm64` when the image carries that pair, and
430
+ never by emulation. Docker set to Windows containers is refused.
431
+
432
+ A Windows agent runs locally only as an enrolled machine: `orchestra outpost up --agent <id>` on a Windows
433
+ PC, against the local environment (section 4, "Host outpost"). Use it to work out the build, run and test
434
+ commands before the cloud.
435
+
436
+ Locally the network edge does nothing: no egress rule is enforced, no key is added, and no certificate is
437
+ re-signed. The cloud proves those.
438
+
439
+ #### Which to pick
440
+
441
+ Pick `microvm` when the code runs on Linux, with or without Docker. This is most code.
442
+ Pick `vm` when the code needs Windows, an Android device or a kernel of its own.
443
+ Pick `host` when the code must run on the team's own machine, such as a Mac.
444
+
335
445
  ### A. Containers on Linux
336
446
 
337
447
  Choose A when the code and its services run on Linux, in Docker, Docker Compose, or a setup script. Most
@@ -349,7 +459,7 @@ agent can run the team's own `docker compose up` unchanged.
349
459
  machine's processes, the agent included, read every value.
350
460
  3. Put each dev server's port in `PORTS`, with a short name. The agent can then show the app at a
351
461
  *machine endpoint*, a web address that only signed-in members of the organization can open.
352
- 4. Write the app's own settings files (`.env.local`) into the Set up item's instructions, because the code
462
+ 4. Write the app's own settings files (`.env.local`) into the Set up item's description, because the code
353
463
  is not on the machine when the setup script runs. Put only local or test values there. A real secret
354
464
  becomes a Secret plus a rule that adds it.
355
465
  5. Choose the size by what CI uses for the same work. The template's sizes are fixed per agent: lg is
@@ -358,6 +468,28 @@ agent can run the team's own `docker compose up` unchanged.
358
468
  the inner Docker's images across machine starts (next part).
359
469
  7. Not released yet: `workingDirectory`, the folder where every conversation starts. Today each agent clones
360
470
  or uses its code under `/work` in its own first turn, as the starter's agents do.
471
+ 8. To keep the agent's home, such as a harness sign-in, across machines, mount one volume at `/home` on
472
+ every environment that shares it. Make the volume once with `npx orchestra volumes create`, then add
473
+ `volumeMounts: [{ volume: Volume.fromSlug(factory, "<slug>"), mountPath: "/home" }]`. Without it,
474
+ nothing in `/home` outlives the machine.
475
+
476
+ #### Network
477
+
478
+ Egress starts open, and stays open for the first run: `EgressPolicy.allowAll()`. Any host is reachable, and
479
+ only the hosts that need a key, such as the model gateway, have rules that add one. Never close it while the
480
+ factory is being set up.
481
+
482
+ Tightening is a later, optional step, after the factory works and the developer asks for it:
483
+
484
+ 1. Start from `EgressPolicy.denyAll()`. A host that no rule allows is refused.
485
+ 2. Add `applyPreset(egressPreset.softwareDevelopment())`: package and container registries, and reads
486
+ from common services, with no key.
487
+ 3. Keep `routeModelsViaGateway(...)` or the model key's rule, and every token or connection rule.
488
+ 4. Add one `allow` rule for each other host the agents reach, with `priority: 100` and the methods it needs.
489
+
490
+ Prove the closed list on Orchestra's cloud, not locally: a local run enforces no egress rule ("On this
491
+ computer" above). Apply the tightened policy, then ask an agent to run the build and the tests once on a cloud
492
+ machine. A refused host shows as `destination is not allowed` (`troubleshooting.md`).
361
493
 
362
494
  #### Setup script or a baked image
363
495
 
@@ -392,27 +524,152 @@ Choose B when the code needs a particular kernel or operating system.
392
524
 
393
525
  - **Windows:** possible. Set `platform: { os: "windows", arch: "amd64", runtime: "vm" }` on the
394
526
  environment. A Windows machine is a full EC2 virtual machine with 4 or 8 CPU. Docker data disks are not
395
- available on Windows, so remove `disks` and the Docker setup. The Linux `setup.sh` cannot run there. Ask the Orchestra team
396
- how a setup script runs on Windows before you rely on one.
527
+ available on Windows, so remove `disks` and the Docker setup. The Linux `setup.sh` cannot run there: write
528
+ a PowerShell script from "A Windows setup script" below. Follow "Windows in three stages" in section 5.
397
529
  - **Linux on a full VM:** possible with `runtime: "vm"`, at 2, 4 or 8 CPU.
398
530
  - **macOS:** only as the team's own Mac, enrolled with the worker. Say what that needs before you offer it
399
531
  (the orchestra skill, section 18), and agree it with the Orchestra team first.
400
532
 
401
- ### C. The team's private network
402
-
403
- Choose C when development needs services or data inside their VPN or their own cloud.
404
-
405
- Orchestra's machines cannot reach a private network today. The planned answer is the *Launcher*, which
406
- runs machines inside the team's own cloud; it does not exist yet, and there is no Azure support. Tell the
407
- developer:
408
-
409
- - what their code needs from the private network, host by host;
410
- - that this needs a later Orchestra release, or one of their Macs or Linux servers enrolled as a machine
411
- (the orchestra skill, section 18);
412
- - that they can still see a first fix today on the todo sample, or on the parts of the code that need no
413
- private service.
414
-
415
- Write down what is missing and stop here. Report it to the developer, and go back to the orchestra-fdk skill.
533
+ ### A Windows setup script
534
+
535
+ Tried by us: not yet.
536
+
537
+ A Windows machine runs the setup script with PowerShell 5.1 (`powershell -NonInteractive -NoProfile
538
+ -ExecutionPolicy Bypass -File setup.ps1`), as the worker's service account, once per machine. A parked VM that
539
+ starts again does not run it again. A new VM does, for example after `ttl` deletes the old one. So write each
540
+ step so that it can run again: check before you install, as the template does. Start from this template. Keep the steps in this order, and give each one its own exit code. The work folder is
541
+ `C:\work\code`. The setup script does not clone the code. It runs before any code host key exists, so a
542
+ clone of a private repository fails, and the machine start fails with it. The agent clones the code in its
543
+ turn, from a git bundle or a public address (`phases/5-prove.md`, section 1).
544
+
545
+ ```powershell
546
+ $ErrorActionPreference = 'Stop'
547
+ $ProgressPreference = 'SilentlyContinue'
548
+ [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
549
+
550
+ # 10: the egress edge's certificate authority is trusted machine-wide. The worker hands the script its path.
551
+ $ca = $env:GIT_SSL_CAINFO
552
+ if ($ca) {
553
+ try {
554
+ $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($ca)
555
+ if (-not (Test-Path "Cert:\LocalMachine\Root\$($cert.Thumbprint)")) {
556
+ Import-Certificate -FilePath $ca -CertStoreLocation Cert:\LocalMachine\Root | Out-Null
557
+ }
558
+ } catch { Write-Output "trusting the edge authority failed: $_"; exit 10 }
559
+ }
560
+
561
+ # 11: the work folder, for the service account and the administrators only.
562
+ try { New-Item -ItemType Directory -Force -Path C:\work | Out-Null } catch { exit 11 }
563
+ icacls C:\work /inheritance:r /grant:r '*S-1-5-18:(OI)(CI)F' '*S-1-5-32-544:(OI)(CI)F' | Out-Null
564
+ if ($LASTEXITCODE -ne 0) { exit 11 }
565
+
566
+ # 12: Git for Windows. Set the version the team uses.
567
+ $git = 'C:\Program Files\Git\cmd\git.exe'
568
+ if (-not (Test-Path $git)) {
569
+ $version = '<version, such as 2.47.1>'
570
+ $installer = 'C:\work\git-setup.exe'
571
+ try {
572
+ Invoke-WebRequest -UseBasicParsing -OutFile $installer `
573
+ -Uri "https://github.com/git-for-windows/git/releases/download/v$version.windows.1/Git-$version-64-bit.exe"
574
+ } catch { exit 12 }
575
+ $run = Start-Process -FilePath $installer -ArgumentList '/VERYSILENT', '/NORESTART', '/NOCANCEL', '/SP-' -Wait -PassThru
576
+ if ($run.ExitCode -ne 0) { exit 12 }
577
+ }
578
+ # For the rest of this script only. The agent does not get this PATH.
579
+ $env:Path = "C:\Program Files\Git\cmd;$env:Path"
580
+
581
+ # 13: git trusts the Windows certificate store, for every process on the machine.
582
+ & $git config --system http.sslBackend schannel
583
+ if ($LASTEXITCODE -ne 0) { exit 13 }
584
+
585
+ # 14 and on: the team's toolchain that fits in the time limit, one exit code per step.
586
+ ```
587
+
588
+ Why each step is there:
589
+
590
+ - `$ErrorActionPreference = 'Stop'` stops on a failing PowerShell command, but not on a failing program such as
591
+ `icacls` or `git`. So each program call is followed by a `$LASTEXITCODE` check that exits non-zero.
592
+ - The worker already imports the edge's authority into `Cert:\LocalMachine\Root` before the script runs, and
593
+ logs a failure without stopping. Step 10 checks it, and imports it when it is missing. The worker sets each
594
+ certificate variable a harness reads, `GIT_SSL_CAINFO` among them, to the authority's file.
595
+ - PowerShell 5.1 does not always offer TLS 1.2, so a download can fail before it reaches the edge.
596
+ - The Windows image has no git.
597
+ - The agent does not find git on its PATH. Its PATH is the worker's, fixed when the worker started, before
598
+ the setup script ran. The installer's change to the machine PATH and the script's `$env:Path` do not
599
+ reach it. So the agent calls git by its full path, `C:\Program Files\Git\cmd\git.exe`. Write this in the
600
+ agent's instructions or in the codebase skill.
601
+ - Git for Windows reads its own certificate bundle, not the Windows store. The worker sets `GIT_SSL_CAINFO` for
602
+ the setup script and the harness only, so git run any other way fails on the edge's certificate. The
603
+ `schannel` setting makes every git on the machine read the Windows store.
604
+ - The SIDs `S-1-5-18` (the service account, LocalSystem) and `S-1-5-32-544` (the administrators) work on every
605
+ language of Windows, where the account names do not. On Windows the agent runs as the worker's account.
606
+ - The setup script has 10 minutes, and the limit is fixed for now. A toolchain such as Visual Studio Build
607
+ Tools can take 10 to 20 minutes to install. Leave such an install to the agent's first turn: a Windows
608
+ machine is parked when idle and keeps its disk, so it stays installed. The agent waits for the install in
609
+ the turn: a park kills an install that is still running. A process the setup script leaves running is
610
+ killed the same way. For machines that start with it
611
+ installed, use the team's own image ("Windows in three stages", stage 2).
612
+ - The output is kept as it is. Never print a token.
613
+
614
+ ### C. Where the machines run, when the code needs private services
615
+
616
+ Choose here when development needs a database, internal APIs or a package feed inside the team's network
617
+ or cloud. List what the code needs, host by host, before you choose.
618
+
619
+ | | Hosted | A compute provider in their cloud | Their own machine | The whole platform in their cloud |
620
+ |---|---|---|---|---|
621
+ | Benefit | The simplest start. Nothing to run. Keys added at our network edge, machine endpoints and views, machines kept ready, and we keep it running. | Keeps their setup, networks, images and private services inside their own cloud, under their own account and controls. | Their own machine or network, as it is. | Nothing leaves their cloud. |
622
+ | What reaches what | Our machines reach their services over the internet, through the network edge | Their Launcher asks our platform for orders over HTTPS. Their machines connect out to our platform. Nothing connects in. | The worker on their machine connects out to our platform | All inside their cloud |
623
+ | Where keys live | Secrets, added at our network edge | On their machines, set by their own boot step. No network edge of ours stands in front of their machines yet | On their machine | In their cloud |
624
+ | Where files rest | Our object store (S3) | Not stated yet | Not stated yet | Their cloud |
625
+ | Setup | None | Make a compute provider record, deploy the Launcher template to their Azure subscription, name the record in `provisionSpec.computeProviderId` | Enroll the machine (`orchestra worker enroll`) | An installation of the platform's Helm chart |
626
+ | Status | Released | Released on Azure. Not released yet: AWS | Released | Not released yet |
627
+
628
+ Pick hosted when the private services can be reached over the internet with a key.
629
+ Pick a compute provider when the services must stay inside their cloud, and they use Azure.
630
+ Pick their own machine when the code needs one machine they already run, such as a Mac.
631
+
632
+ Tell the developer the benefit of each choice first. The limits are for troubleshooting. Do not lead with
633
+ them when you present the choice.
634
+
635
+ Cannot do:
636
+
637
+ - Hosted: reach a service that is not on the internet.
638
+ - A compute provider: run on AWS or Google Cloud; run on arm64; keep `/home` on a Kata pod target; add
639
+ keys at our network edge.
640
+
641
+ Tokens on a compute provider's machines:
642
+
643
+ - The team manages every credential on their own machines. The platform delivers none there.
644
+ - The model sign-in goes in the worker service's own environment, by harness:
645
+ - `claude` with a Claude subscription token: `ORCHESTRA_WORKER_CLAUDE_OAUTH_TOKEN`.
646
+ - `claude` with an Anthropic API key or an Orchestra gateway key: `ANTHROPIC_API_KEY`. This value
647
+ replaces the placeholder that our image sets. With a gateway key, keep the agent's model gateway on:
648
+ the platform sets the gateway address.
649
+ - `codex`: `ORCHESTRA_WORKER_OPENAI_API_KEY`, or `ORCHESTRA_WORKER_CODEX_PERSONAL_ACCESS_TOKEN`.
650
+ - On Windows, the worker service is `SfdkWorker`, and its environment is the service's `Environment`
651
+ registry value.
652
+ - Other tokens, such as for git, a package feed or an Azure DevOps personal access token: the team's own
653
+ boot step sets them. For example, the step reads their Key Vault with a managed identity on the VM.
654
+ - The worker reads its environment when its service starts. So the boot step runs before the worker
655
+ starts, or restarts the worker service after it sets the values. On our Windows image, the startup task
656
+ `orchestra-azure-userdata` starts `SfdkWorker` at each boot.
657
+ - Do not put a token in the environment's `env` (`provisionSpec.env`). The platform stores it, an
658
+ environment read returns it, and it travels in plain text in the VM's startup data.
659
+ - The Launcher attaches no managed identity to the VMs it creates. The team's automation finds the VMs by
660
+ two tags: `orchestra-launcher` holds the compute provider record's id, and `orchestra-machine` holds
661
+ the machine's id. Not released yet: a managed identity attached when the Launcher creates a VM.
662
+ - Never bake a credential into an image: that is not supported.
663
+ - Not released yet: our network edge for machines in the team's own network, which adds keys from
664
+ Secrets as it does for hosted machines.
665
+
666
+ The Launcher's VM targets use the `Dsv5` size family by default. A subscription with no `Dsv5` capacity
667
+ sets `vmSizeFamily: Dsv6` on each VM target in the Launcher's settings.
668
+ - Their own machine: hold network rules; add keys at the edge; start a machine on demand.
669
+
670
+ When no choice fits, write down what is missing and stop here. Report it to the developer, and go back to
671
+ the orchestra-fdk skill. They can still see a first fix on the todo sample, or on the parts of the code
672
+ that need no private service.
416
673
 
417
674
  ## 6. Write and check
418
675
 
@@ -421,38 +678,34 @@ Write down what is missing and stop here. Report it to the developer, and go bac
421
678
  2. In `<factory>`, run `npm run typecheck`, then `npx orchestra fdk synth`. The starter is one program, at the folder's
422
679
  root.
423
680
  3. Read `<factory>/fdk.out/plan.json`. Every environment has your setup script, ports and settings, and
424
- the model rule from step 6 of the orchestra-fdk skill: the `model-gateway` rule,
425
- or a Secret's rule on the provider's host. On a new factory, no environment has a Bitbucket or Jira rule
426
- yet: those come with the tokens, in step 12 of the orchestra-fdk skill. On an existing factory, with its
427
- inputs loaded, the rules it has now stay as they are.
681
+ the model rule of the orchestra-fdk skill's phase 2: the `model-gateway` rule, or a Secret's rule on the
682
+ provider's host. On a new factory, no environment has a code host or tracker rule yet: phase 3 adds them
683
+ after the first run. On an existing factory, with its token file loaded, the rules it has now stay as
684
+ they are.
428
685
  4. Write `ENVIRONMENT.md` in `<factory>`: what you found and where, the mode you proved in and its result
429
686
  for each success criterion, the commands, every outbound attempt the proof logged, and what is still
430
687
  unknown.
431
688
 
432
689
  **Check:** the typecheck and the synth pass, and the plan is as in item 3. Go back to the orchestra-fdk
433
- step that sent you for the apply.
690
+ skill's phase 4 for the apply.
434
691
 
435
692
  ## 7. The cloud
436
693
 
437
694
  The cloud is the fallback when no local mode can run. It is also the confirmation after the local proof:
438
- the Manager Agent's "Set up" item, which step 10 of the orchestra-fdk skill starts. It proves what only the
439
- cloud can: the micro VM, Docker, the network rules and the tokens. The Engineer Agents' machines cannot clone from
440
- Bitbucket, so the Set up item also proves the tests run from a git bundle.
695
+ the Set up item, which phase 5 of the orchestra-fdk skill starts. It proves what only the cloud can: the
696
+ micro VM, Docker, the network edge and the machine endpoints. The Engineer Agents start each item from a git
697
+ bundle, so Set up also proves the tests run from one.
441
698
 
442
699
  It is slower. Each try is an apply plus a machine start, and access problems show one at a time.
443
700
 
444
- To prove in the cloud, write the environment as in sections 5 and 6, apply it, and run Set up with the git
445
- bundle. Keep the safety rule:
701
+ To prove in the cloud, write the environment as in sections 5 and 6, apply it, and run Set up. Egress stays
702
+ open. Keep the safety rule this way:
446
703
 
447
- 1. For the proof, set the environment's default action to `deny`. Allow only the package registries and
448
- image registries the install uses, and keep the `model-gateway` rule. Calls to the Orchestra platform
449
- skip these rules.
450
- 2. Use only local settings in the Set up item's instructions.
451
- 3. Ask the Manager Agent to report every refused host, and to note any production host it sees and
452
- continue.
704
+ 1. Use only local settings in the Set up item's description.
705
+ 2. Ask the Manager Agent to note any production host it sees in a setting or a log, and to continue.
453
706
 
454
- When a step fails, fix it here, prove the fix locally if a local mode runs, apply again, and assign the
455
- item again.
707
+ When a step fails, fix it here, prove the fix locally if a local mode runs, apply again, and assign Set up
708
+ again. `troubleshooting.md` names each failure.
456
709
 
457
710
  ### The model in the cloud: subscription, model gateway, or own key via the vault
458
711
 
@@ -515,8 +768,9 @@ Use the orchestra skill to build an answer for a case the paths do not cover. Ne
515
768
  yet" lines. The sections this work needs:
516
769
 
517
770
  - Section 4: environments, machines, sizes, images, setup scripts, disks, Windows and full VMs.
518
- - Section 5: network rules, their live effect on running machines, and commissioning.
771
+ - Section 5: network rules, and their live effect on running machines.
519
772
  - Section 6: secrets, and where their values come from.
520
773
  - Section 7: the model gateway rule every environment needs.
521
- - Section 17: connections, the later option for the code host and the tracker.
774
+ - Section 17: connections. The files under `references/integrations/` say how to give access to each
775
+ service.
522
776
  - Section 18: the team's own machines, the local environment, and private networks.
@@ -0,0 +1,18 @@
1
+ # Analytics
2
+
3
+ The agents read product usage to judge a change, or pull it into the platform's custom metrics. A pull that
4
+ needs no judgment fits a `script` agent on a schedule (orchestra skill, section 2). Give access with a Secret
5
+ the network edge adds, with read scopes only. Egress is open, so add only the rule that adds the credential.
6
+ The agent installs or uses whatever client it prefers. The edge adds the credential to its requests.
7
+
8
+ Phase 3, "From a recipe to code", turns a recipe into a Secret and a rule.
9
+
10
+ | Provider | Access | Scopes | Check command |
11
+ |---|---|---|---|
12
+ | Pendo | `app.pendo.io → x-pendo-integration-key: <SECRET>`. The EU region is `app.eu.pendo.io` | A read-only integration key | `curl -fsS https://app.pendo.io/api/v1/page -H 'Content-Type: application/json'` (check the vendor page) |
13
+ | Mixpanel | `mixpanel.com → Authorization: Basic <service account user>:<SECRET>` | A service account with the Consumer role | `curl -fsS "https://mixpanel.com/api/app/me"` (check the vendor page) |
14
+ | Amplitude | `amplitude.com → Authorization: Basic <api key>:<SECRET>`, with the secret key as the Secret | The project's API key and secret key | `curl -fsS "https://amplitude.com/api/2/events/list"` (check the vendor page) |
15
+ | Google Analytics | Not released yet: its Data API takes short-lived OAuth tokens | The Viewer role, when it is released | Not released yet |
16
+
17
+ Token pages: Pendo **Settings › Integrations › Integration Keys**; Mixpanel **Organization Settings ›
18
+ Service Accounts**; Amplitude **Settings › Projects**.
@@ -0,0 +1,20 @@
1
+ # CI and CD
2
+
3
+ The agents read build results and logs to find why a check failed. Give access with a Secret the network edge
4
+ adds, or reuse the code host's access where the CI lives on the code host. Egress is open, so add only the
5
+ rule that adds the credential. Read access is enough for most work. The agent installs or uses whatever
6
+ client it prefers. The edge adds the credential to its requests.
7
+
8
+ Phase 3, "From a recipe to code", turns a recipe into a Secret and a rule.
9
+
10
+ | Provider | Access | Scopes | Check command |
11
+ |---|---|---|---|
12
+ | GitHub Actions | The GitHub access of `code-repo.md`. A GitHub App connection adds `actions:read` to `install.permissions` | Actions: read | `curl -fsS "https://api.github.com/repos/<owner>/<name>/actions/runs?per_page=1"` |
13
+ | Azure Pipelines | The Azure DevOps access of `code-repo.md` | Build (Read) | `curl -fsS "https://dev.azure.com/<organization>/<project>/_apis/build/builds?api-version=7.1&\$top=1"` |
14
+ | Jenkins | `<jenkins host> → Authorization: Basic <user>:<SECRET>`, with the user's API token | A user with read access to the jobs | `curl -fsS https://<jenkins host>/api/json` |
15
+ | CircleCI | `circleci.com → Circle-Token: <SECRET>` | Personal API token | `curl -fsS https://circleci.com/api/v2/me` |
16
+
17
+ Token pages: Jenkins, the user's **Configure › API Token**; CircleCI **User Settings › Personal API Tokens**.
18
+
19
+ A Jenkins server inside the team's network is not on the internet. Hosted machines cannot reach it.
20
+ `../environment.md`, section 5, part C, says where the machines can run instead.
@@ -0,0 +1,19 @@
1
+ # Cloud accounts
2
+
3
+ Cloud access is read-only: the agents read resources, logs and settings, and change nothing. The network
4
+ edge adds a credential as a header. The three cloud APIs below do not take a fixed key in a header: AWS signs
5
+ each request with its key, and Azure and Google Cloud take short-lived tokens. So the edge cannot add their
6
+ credentials today, and none of them is released yet. Egress is open, so a public endpoint is reachable with
7
+ no key.
8
+
9
+ Never put a cloud key in an env value, the setup script or the agent's instructions to work around this.
10
+ Every process on the machine reads them.
11
+
12
+ | Provider | Access | Scopes | Check command |
13
+ |---|---|---|---|
14
+ | AWS | Not released yet: each request is signed with the key | A read-only role, such as `ReadOnlyAccess`, when it is released | Not released yet |
15
+ | Azure | Not released yet: Entra tokens expire within hours | The Reader role, when it is released | Not released yet |
16
+ | Google Cloud | Not released yet: OAuth tokens expire within an hour | The Viewer role, when it is released | Not released yet |
17
+
18
+ Until it is released, the agent asks a person in the item for what it needs from the cloud, such as a log
19
+ excerpt.
@@ -0,0 +1,76 @@
1
+ # Code hosts
2
+
3
+ Give access with a Secret the network edge adds, or with the provider's platform connection. Egress is open,
4
+ so add only the rule that adds the credential. Git over HTTPS and the REST API often take the token in
5
+ different forms: give each its own rule, scoped by host or by path. A connection also brings events, which
6
+ a `Trigger` turns into work. The agent installs or uses whatever git or API client it prefers. The edge adds
7
+ the credential to its requests.
8
+
9
+ Phase 3, "From a recipe to code", turns a recipe into a Secret and a rule.
10
+
11
+ | Provider | Access | Scopes | Check command |
12
+ |---|---|---|---|
13
+ | GitHub | Platform connection `github` (the Orchestra GitHub App), with `.applyPreset(github.egressPolicy())`. Or a token: `api.github.com → Authorization: Bearer <SECRET>` and `github.com → Authorization: Basic x-access-token:<SECRET>` | Fine-grained token for the repository: Contents, Pull requests and Issues, read and write | `curl -fsS https://api.github.com/repos/<owner>/<name>` |
14
+ | Bitbucket Cloud | `api.bitbucket.org → Authorization: Bearer <SECRET>` and `bitbucket.org → Authorization: Basic x-bitbucket-api-token-auth:<SECRET>`. Platform connection `bitbucket` for events | API token with the repository and pull request read and write scopes | `curl -fsS https://api.bitbucket.org/2.0/repositories/<workspace>/<repository>` |
15
+ | GitLab | `gitlab.com`, paths `/api/*`, priority 310 → `PRIVATE-TOKEN: <SECRET>`, and `gitlab.com`, priority 300 → `Authorization: Basic oauth2:<SECRET>`. Platform connection `gitlab` for events | Personal or project access token with `api` | `curl -fsS https://gitlab.com/api/v4/projects/<url-encoded group/project>` |
16
+ | Azure DevOps | `dev.azure.com → Authorization: Basic pat:<SECRET>`, for the API and git. Platform connection `azure-devops` for events | Personal access token: Code (Read & write), and Work Items (Read & write) for Boards | `curl -fsS "https://dev.azure.com/<organization>/_apis/projects?api-version=7.1"` |
17
+
18
+ Token pages: GitHub `https://github.com/settings/personal-access-tokens`; Bitbucket
19
+ `https://id.atlassian.com/manage-profile/security/api-tokens`; GitLab **Settings › Access tokens** in the
20
+ project or the profile; Azure DevOps **User settings › Personal access tokens**.
21
+
22
+ ## Git over HTTPS
23
+
24
+ Git sends Basic auth. The edge adds it, so the agent clones `https://<host>/<path>.git` with no user name
25
+ and no password in the address.
26
+
27
+ - **GitHub:** the user name is `x-access-token`, and the password is the token:
28
+ `SecretValue.basicAuth("x-access-token", SecretValue.fromEnv("ORCHESTRA_FDK_GITHUB_TOKEN"))`. The GitHub
29
+ App connection's preset adds git on `github.com` and `codeload.github.com` itself. Its `{ git: "read" }`
30
+ option gives clone and fetch, and no push.
31
+ - **Bitbucket:** the fixed user name `x-bitbucket-api-token-auth`. The Bitbucket connection adds its key on
32
+ `api.bitbucket.org` only, so git keeps this rule beside the connection.
33
+ - **GitLab:** the user name `oauth2`. The GitLab connection declares no git transport, so git keeps this
34
+ rule beside the connection.
35
+ - **Azure DevOps:** the user name is not checked, and the kit refuses an empty one, so use `pat`. One rule on
36
+ `dev.azure.com` serves the API and git.
37
+
38
+ ## GitLab: two rules on one host
39
+
40
+ The API and git are both on `gitlab.com`. Two credentialed rules on one host at one priority are a tie, and
41
+ the first declared wins for every request. So scope the API rule to `paths: ["/api/*"]` and give it the higher
42
+ priority, 310. The git rule at 300 takes the rest of the host.
43
+
44
+ The API rule replaces the `PRIVATE-TOKEN` header. A project access token must be sent this way: sent as
45
+ `Authorization: Bearer` beside a placeholder `PRIVATE-TOKEN`, GitLab answers 401. A personal token works the
46
+ same way.
47
+
48
+ With the `gitlab` connection and `Auth.oauth()`, use `.allow(gitlab, { paths: ["/api/*"], priority: 310 })`
49
+ for the API instead, and keep the git rule. GitLab does not let the platform register the webhook. The
50
+ developer adds it in the project, under **Settings › Webhooks**, with the connection's address. Write the
51
+ address to a file the developer can read, and never print it:
52
+ `npx orchestra connections rotate-webhook-token gitlab --output-file <path>`. Each run makes a new address and
53
+ ends the old one. The platform's GitLab connection covers `gitlab.com` only.
54
+
55
+ ## Connections and events
56
+
57
+ - **GitHub:** `Auth.githubApp()`. `install.permissions` adds to the default the platform gives
58
+ (`contents:read`, `metadata:read`, `pull_requests:write`), as `<permission>:<level>`, such as
59
+ `contents:write`. The apply prints an install link once. Give it to the developer only after they approved
60
+ the diff, and run the same apply again when the app is installed. Events: `PullRequest`, `Issues`,
61
+ `IssueComment`.
62
+ - **Bitbucket:** `Auth.customerManagedToken(<secret>)`, or `Auth.oauth()` once the organization registers
63
+ its own Bitbucket OAuth consumer. Install fields `workspace` and `repository`. The platform registers the
64
+ webhook. Run `orchestra connections list-event-types <connection>` for the events.
65
+ - **GitLab:** install field `projectPath` or `projectId`. Events: `Push`, `MergeRequestOpened`,
66
+ `MergeRequestUpdated`, `IssueOpened`, `IssueUpdated`, `NoteCreated`.
67
+ - **Azure DevOps:** `Auth.oauth()`: a Microsoft work account consents. Install fields `organization` and
68
+ `project`. `.allow(<connection>)` adds the key on `dev.azure.com` for the API. Git keeps the token rule,
69
+ scoped to `paths: ["*/info/refs", "*/git-upload-pack", "*/git-receive-pack"]` at priority 310, so the two
70
+ rules do not tie on one host. A path pattern that starts with `*` matches the end of the path only, so
71
+ a `*` in the middle of a pattern matches nothing. To allow clone and fetch without push, add
72
+ `.deny("azure-devops-no-push", { hosts: ["dev.azure.com"], paths: ["*/git-receive-pack"] })`. A deny at its
73
+ default priority, 900, wins over both rules. Leaving `*/git-receive-pack` out of the git rule does not stop
74
+ a push, because the connection's rule covers every path on the host. Or use a read-only token.
75
+ The platform registers the webhooks. The events fire for every repository in the project, so narrow a
76
+ trigger with `where`.
@@ -0,0 +1,22 @@
1
+ # Databases
2
+
3
+ Use a staging database or a read replica only, through a read-only user. Never give the agents a production
4
+ database, and never a user that can write to production.
5
+
6
+ The network edge adds a credential to HTTPS requests only. A database's own protocol, such as PostgreSQL's,
7
+ carries the password inside its connection, where the edge cannot add it. A database reached over an HTTPS
8
+ API can take a Secret like any other service. Egress is open. The agent installs or uses whatever client it
9
+ prefers.
10
+
11
+ Phase 3, "From a recipe to code", turns a recipe into a Secret and a rule.
12
+
13
+ | Provider | Access | Scopes | Check command |
14
+ |---|---|---|---|
15
+ | PostgreSQL, MySQL, SQL Server (their own protocol) | Not released yet: the password would sit on the machine | A read-only user on staging or a replica, when it is released | Not released yet |
16
+ | Supabase (a staging project) | `<project ref>.supabase.co → apikey: <SECRET>` and `Authorization: Bearer <SECRET>`, one Secret on two headers | The project's `anon` key, with row-level security on (check the vendor page) | `curl -fsS "https://<project ref>.supabase.co/rest/v1/<table>?limit=1"` |
17
+
18
+ For local work, the codebase's own local database, such as one from its compose file, needs no access: the
19
+ agent starts it on its machine (`../environment.md`).
20
+
21
+ Never put a database password in an env value, the setup script or the agent's instructions. Every process
22
+ on the machine reads them.