@orchestraworks/worker-darwin-arm64 0.0.140 → 0.0.142

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchestraworks/worker-darwin-arm64",
3
- "version": "0.0.140",
3
+ "version": "0.0.142",
4
4
  "description": "Orchestra worker for darwin arm64.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Living Computers",
@@ -3,10 +3,10 @@
3
3
  // line-delimited stdio JSON-RPC. One process per bridge multiplexes every session over one stdio pipe,
4
4
  // so the read loop must never block on an in-flight command.
5
5
  //
6
- // Each turn ends by setting the session's outcome claim from the command's exit code. A machine the
7
- // customer enrolled, which the worker declares by setting `SFDK_MACHINE_ENROLLED`, has no edge of ours in
8
- // front of it, so every claim there would be refused: the harness makes no call at all and ends the turn
9
- // on the script's own answer.
6
+ // Each turn ends by setting the session's outcome claim from the command's exit code, sent with the agent's
7
+ // own token when the harness has one. A machine with no edge of ours in front of it, which the worker
8
+ // declares on each harness process, refuses a bare claim: with no token there the harness makes no call at
9
+ // all and ends the turn on the script's own answer.
10
10
 
11
11
  import { spawn } from "node:child_process";
12
12
  import { randomUUID } from "node:crypto";
@@ -18,7 +18,7 @@ import { createInterface } from "node:readline";
18
18
  import { describeFetchFailure } from "./fetch-failure.js";
19
19
 
20
20
  const HARNESS_NAME = "software-factory-script-harness";
21
- const HARNESS_VERSION = "0.0.140";
21
+ const HARNESS_VERSION = "0.0.142";
22
22
 
23
23
  const IS_WINDOWS = process.platform === "win32";
24
24
 
@@ -257,8 +257,6 @@ try {
257
257
  programReadError = `cannot read instructions file: ${error.message}`;
258
258
  }
259
259
 
260
- // NO Authorization header is ever attached — the egress broker mints and injects the short-lived agent
261
- // bearer for the agent-API destination (the agent runtime must never hold credentials).
262
260
  function agentApiBaseUrl() {
263
261
  const configured = (process.env.PLATFORM_BASE_URL || "").trim().replace(/\/+$/, "");
264
262
  if (!configured) {
@@ -269,22 +267,58 @@ function agentApiBaseUrl() {
269
267
 
270
268
  // The worker declares this on a machine the customer enrolled, and on no machine the platform launched.
271
269
  // Presence is the declaration. The worker answers it from that machine's own bootstrap rather than
272
- // passing a value through, so nothing running inside the machine can declare it of itself.
273
- const MACHINE_ENROLLED = "SFDK_MACHINE_ENROLLED";
270
+ // passing a value through, so nothing running inside the machine can declare it of itself. A worker built
271
+ // before the rename declares it under the former name alone, which is read second.
272
+ const MACHINE_ENROLLED = ["ORCHESTRA_MACHINE_ENROLLED", "SFDK_MACHINE_ENROLLED"];
273
+
274
+ /** The name the worker declared this machine enrolled under, or undefined on a machine the platform launched. */
275
+ function enrolledDeclaration() {
276
+ return MACHINE_ENROLLED.find((name) => (process.env[name] || "").trim() !== "");
277
+ }
278
+
279
+ // The worker renews the file in place, so it is read on every call. Behind our edge the edge replaces
280
+ // this bearer with one for the same agent.
281
+ function agentToken() {
282
+ const variable = (process.env.ORCHESTRA_API_TOKEN || "").trim();
283
+ if (variable) return variable;
284
+ const file = (process.env.ORCHESTRA_API_TOKEN_FILE || "").trim();
285
+ if (!file) return undefined;
286
+ try {
287
+ return readFileSync(file, "utf8").trim() || undefined;
288
+ } catch {
289
+ return undefined;
290
+ }
291
+ }
292
+
293
+ // The CLI's transport rule: a bearer goes over https, or over plain http only to this machine itself.
294
+ const LOOPBACK_HOSTS = new Set(["127.0.0.1", "localhost", "::1"]);
274
295
 
275
- function machineIsEnrolled() {
276
- return (process.env[MACHINE_ENROLLED] || "").trim() !== "";
296
+ function carriesBearer(baseUrl) {
297
+ let url;
298
+ try {
299
+ url = new URL(baseUrl);
300
+ } catch {
301
+ return false;
302
+ }
303
+ if (url.protocol === "https:") return true;
304
+ return url.protocol === "http:" && LOOPBACK_HOSTS.has(url.hostname.replace(/^\[|\]$/g, ""));
277
305
  }
278
306
 
279
- async function platformRequest(method, path, organizationId, body) {
307
+ async function platformRequest(method, path, organizationId, body, token = agentToken()) {
280
308
  let response;
281
309
  try {
282
- response = await fetch(`${agentApiBaseUrl()}${path}`, {
310
+ const baseUrl = agentApiBaseUrl();
311
+ if (token && !carriesBearer(baseUrl)) {
312
+ logDiagnostic("PLATFORM_BASE_URL is neither https nor this machine, so the agent token is not sent to it");
313
+ token = undefined;
314
+ }
315
+ response = await fetch(`${baseUrl}${path}`, {
283
316
  method,
284
317
  headers: {
285
318
  "Content-Type": "application/json",
286
319
  Accept: "application/json",
287
320
  "X-Organization-Id": organizationId,
321
+ ...(token ? { Authorization: `Bearer ${token}` } : {}),
288
322
  },
289
323
  body: body === undefined ? undefined : JSON.stringify(body),
290
324
  signal: AbortSignal.timeout(PLATFORM_REQUEST_TIMEOUT_MS),
@@ -660,16 +694,18 @@ async function claimPlatformState({
660
694
  }) {
661
695
  const { succeed, fail } = turnResponder(id, errorData, settlement);
662
696
 
663
- // On a machine the customer enrolled there is no edge of ours, so nothing authorizes a call to the
664
- // platform's API and every claim here would come back refused — failing a turn whose script succeeded
665
- // and whose answer is already on the session. The answer is then the whole of what the turn reports.
666
- // Read off the worker's declaration and not off a missing edge stamp: a machine the platform launched
667
- // can be missing that stamp too, and there the refusal is a deployment fault to surface rather than a
668
- // turn to settle quietly.
669
- if (machineIsEnrolled()) {
697
+ // On a machine with no edge of ours and no agent token, nothing authorizes a call to the platform's
698
+ // API and every claim would come back refused — failing a turn whose script succeeded and whose answer
699
+ // is already on the session. The answer is then the whole of what the turn reports. Read off the
700
+ // worker's declaration and not off a missing edge stamp: a machine the platform launched can be missing
701
+ // that stamp too, and there the refusal is a deployment fault to surface rather than a turn to settle
702
+ // quietly.
703
+ const token = agentToken();
704
+ const declaration = enrolledDeclaration();
705
+ if (declaration !== undefined && !token) {
670
706
  logDiagnostic(
671
- `${MACHINE_ENROLLED} is set, so this machine is one the platform did not launch and nothing ` +
672
- `authorizes its calls to the platform: this turn claims no session state and settles on its answer`,
707
+ `${declaration} is set and no agent token is readable, so nothing authorizes this machine's ` +
708
+ `calls to the platform: this turn claims no session state and settles on its answer`,
673
709
  );
674
710
  succeed(answerText);
675
711
  return;
@@ -680,7 +716,7 @@ async function claimPlatformState({
680
716
  ? { outcome: "ACHIEVED", summary: "exit 0" }
681
717
  : { outcome: "FAILED", summary: `exit ${exitCode}: ${tail(stderrTail, STDERR_TAIL_SUMMARY)}` };
682
718
  const sessionPath = `/sessions/${encodeURIComponent(platformSessionId)}`;
683
- const response = await platformRequest("PATCH", sessionPath, organizationId, body);
719
+ const response = await platformRequest("PATCH", sessionPath, organizationId, body, token);
684
720
  if (!response.ok && response.status !== 409) {
685
721
  fail(`claim rejected: ${response.status}`);
686
722
  return;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "software-factory-script-harness",
3
3
  "type": "module",
4
- "version": "0.0.140",
4
+ "version": "0.0.142",
5
5
  "scripts": {
6
6
  "test": "node --test test/*.test.js"
7
7
  }
package/worker CHANGED
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: package/worker
3
- size: 46312466 bytes
4
- sha256: eff614017d0d021de7a7d2cf54271777be1e6bedaac7c7dcbd12640af83f1060
3
+ size: 46512002 bytes
4
+ sha256: 7cbdd29779395d8ea71bb971f6810ebc09ec453f17388419b4c2a7f13f7b6e61