@sellable/install 0.1.582 → 0.1.584

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.
@@ -280,8 +280,11 @@ export function installCustomerRuntimeSecrets({
280
280
  envelopes[name].secret
281
281
  );
282
282
  }
283
- mkdirSync(join(stagingRoot, "consumed-turns"), { mode: 0o700 });
284
- chmodSync(join(stagingRoot, "consumed-turns"), 0o700);
283
+ // Must match SELLABLE_AGENT_TURN_CONSUMED_ROOT exactly: the secret-root
284
+ // swap below discards the directory customer-runtime made at boot, and
285
+ // the MCP context proxy fails closed when the nonce directory is absent.
286
+ mkdirSync(join(stagingRoot, "turn-consumed"), { mode: 0o700 });
287
+ chmodSync(join(stagingRoot, "turn-consumed"), 0o700);
285
288
  if (existsSync(activeRoot)) {
286
289
  const active = lstatSync(activeRoot);
287
290
  if (active.isSymbolicLink() || !active.isDirectory())
@@ -9,24 +9,56 @@ import {
9
9
  executeExternalSkillsBridgeOperation,
10
10
  } from "./fly-skills-bridge.mjs";
11
11
 
12
- export async function runFlySkillsBridgeExecCli() {
13
- try {
14
- if (process.argv.length !== 2)
12
+ export const FLY_SKILLS_EXEC_ARGUMENT_MAX_BYTES = 96 * 1024;
13
+ export const FLY_SKILLS_EXEC_ARGUMENT_MAX_COUNT = 8;
14
+
15
+ const BASE64URL_CHUNK = /^[A-Za-z0-9_-]+$/;
16
+ const FLY_SKILLS_EXEC_ENCODED_MAX_BYTES =
17
+ Math.ceil(SKILLS_REQUEST_MAX_BYTES / 3) * 4;
18
+
19
+ export function decodeFlySkillsExecArguments(args) {
20
+ if (!Array.isArray(args) || args.length === 0) {
21
+ throw new FlySkillsBridgeError("skills_request_rejected");
22
+ }
23
+ if (args.length > FLY_SKILLS_EXEC_ARGUMENT_MAX_COUNT) {
24
+ throw new FlySkillsBridgeError("skills_request_too_large");
25
+ }
26
+ let encoded = "";
27
+ for (const chunk of args) {
28
+ if (typeof chunk !== "string" || !BASE64URL_CHUNK.test(chunk)) {
15
29
  throw new FlySkillsBridgeError("skills_request_rejected");
16
- const chunks = [];
17
- let total = 0;
18
- for await (const chunk of process.stdin) {
19
- total += chunk.length;
20
- if (total > SKILLS_REQUEST_MAX_BYTES)
21
- throw new FlySkillsBridgeError("skills_request_too_large");
22
- chunks.push(chunk);
23
30
  }
24
- let request;
25
- try {
26
- request = JSON.parse(Buffer.concat(chunks).toString("utf8"));
27
- } catch {
28
- throw new FlySkillsBridgeError("skills_request_rejected");
31
+ if (Buffer.byteLength(chunk, "utf8") > FLY_SKILLS_EXEC_ARGUMENT_MAX_BYTES) {
32
+ throw new FlySkillsBridgeError("skills_request_too_large");
33
+ }
34
+ encoded += chunk;
35
+ if (encoded.length > FLY_SKILLS_EXEC_ENCODED_MAX_BYTES) {
36
+ throw new FlySkillsBridgeError("skills_request_too_large");
29
37
  }
38
+ }
39
+ let bytes;
40
+ try {
41
+ bytes = Buffer.from(encoded, "base64url");
42
+ } catch {
43
+ throw new FlySkillsBridgeError("skills_request_rejected");
44
+ }
45
+ if (bytes.toString("base64url") !== encoded) {
46
+ throw new FlySkillsBridgeError("skills_request_rejected");
47
+ }
48
+ if (bytes.byteLength > SKILLS_REQUEST_MAX_BYTES) {
49
+ throw new FlySkillsBridgeError("skills_request_too_large");
50
+ }
51
+ try {
52
+ const json = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
53
+ return JSON.parse(json);
54
+ } catch {
55
+ throw new FlySkillsBridgeError("skills_request_rejected");
56
+ }
57
+ }
58
+
59
+ export async function runFlySkillsBridgeExecCli() {
60
+ try {
61
+ const request = decodeFlySkillsExecArguments(process.argv.slice(2));
30
62
  const result = executeExternalSkillsBridgeOperation(request);
31
63
  process.stdout.write(`${JSON.stringify(result)}\n`);
32
64
  process.exitCode = result.ok ? 0 : 2;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/install",
3
- "version": "0.1.582",
3
+ "version": "0.1.584",
4
4
  "type": "module",
5
5
  "description": "One-command installer for Sellable MCP in Claude Code, Codex, and Hermes",
6
6
  "bin": {