@avocadostudio-ai/orchestrator-core 0.11.0 → 0.11.2

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.
@@ -556,6 +556,27 @@ export function createOrchestrator(config = {}) {
556
556
  }, { cors });
557
557
  }
558
558
  if (request.method === "POST" && path === "/auth/verify") {
559
+ /*
560
+ * A closed mount must not hand out a token.
561
+ *
562
+ * `closed` is production with no credential configured, and every route
563
+ * behind this one answers 401. This one answered `{"ok":true,
564
+ * "accessToken":"..."}` — to any body, including `{}` and
565
+ * `{"password":"literally-anything"}`. The token opened nothing: all
566
+ * three transports (`Authorization: Bearer`, `x-access-token`,
567
+ * `?accessToken=`) were checked and every one still 401s.
568
+ *
569
+ * So it was never a hole, which is exactly what made it expensive. It is
570
+ * a login that says yes while the system is shut, and the operator who
571
+ * receives a token and then 401s everywhere has no way to connect the
572
+ * two. `/auth/status` one route over already reports the truth; this now
573
+ * reports the same truth, in the same words, with a status code that
574
+ * says "the server, not your password".
575
+ */
576
+ const verifyAuth = resolveAuth(config.auth);
577
+ if (verifyAuth.mode === "closed") {
578
+ return jsonResponse({ ok: false, error: "unavailable", reason: CLOSED_HINT }, { status: 503, cors });
579
+ }
559
580
  if (!isAccessGateEnabled()) {
560
581
  // Open by choice, or gated by something other than a password. Hand back
561
582
  // a token anyway so the client's code path is identical either way; if a
@@ -71,7 +71,21 @@ export class SiteContractPublishTarget {
71
71
  status: "failed",
72
72
  session,
73
73
  slugs,
74
- reason: siteResult.error ?? "site publish failed"
74
+ /*
75
+ * `reason` first, and it is not a nicety.
76
+ *
77
+ * Every refusal this route can produce puts the machine-readable
78
+ * verdict in `error` and the sentence a human can act on in
79
+ * `reason` — "refused" / "this publish would remove every page…",
80
+ * "unauthorized" / "set PUBLISH_TOKEN…". Reading only `error` threw
81
+ * the second half away, so the editor showed a user the word
82
+ * "unauthorized" and nothing about the variable that fixes it, and
83
+ * would have shown "refused" with nothing about `allowDelete`.
84
+ *
85
+ * A guard whose explanation never reaches the person who tripped it
86
+ * is the same failure as the one `CLOSED_HINT` exists to prevent.
87
+ */
88
+ reason: siteResult.reason ?? siteResult.error ?? "site publish failed"
75
89
  }
76
90
  };
77
91
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@avocadostudio-ai/orchestrator-core",
3
- "version": "0.11.0",
3
+ "version": "0.11.2",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./package.json": "./package.json",
@@ -22,8 +22,8 @@
22
22
  "openai": "^4.87.1",
23
23
  "sharp": "^0.35.4",
24
24
  "zod": "^4.3.6",
25
- "@avocadostudio-ai/shared": "^0.11.0",
26
- "@avocadostudio-ai/migration-sdk": "^0.11.0"
25
+ "@avocadostudio-ai/shared": "^0.11.2",
26
+ "@avocadostudio-ai/migration-sdk": "^0.11.2"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@anthropic-ai/claude-agent-sdk": "^0.3.220",