@ganju/utils 0.0.2 → 0.0.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.
@@ -1,6 +1,7 @@
1
1
  export declare const CLI_OAUTH_CLIENT_NAME = "Ganju CLI";
2
2
  export declare const CLI_OAUTH_REDIRECT_PATH = "/callback";
3
3
  export declare const CLI_OAUTH_REDIRECT_PORTS: number[];
4
+ export declare const CONTROL_PLANE_SCOPE = "ganju:manage";
4
5
  export declare const CLI_OAUTH_SCOPES: string[];
5
6
  export declare const CLI_TOKEN_REFRESH_SKEW_SECONDS = 60;
6
7
  export declare const CUSTOM_CODE_SDK_SPECIFIER = "./ganju-sdk.js";
@@ -1 +1 @@
1
- {"version":3,"file":"cliConstants.d.ts","sourceRoot":"","sources":["../src/cliConstants.ts"],"names":[],"mappings":"AAqBA,eAAO,MAAM,qBAAqB,cAAc,CAAC;AACjD,eAAO,MAAM,uBAAuB,cAAc,CAAC;AACnD,eAAO,MAAM,wBAAwB,UAAiC,CAAC;AAIvE,eAAO,MAAM,gBAAgB,UAK5B,CAAC;AAIF,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAIjD,eAAO,MAAM,yBAAyB,mBAAmB,CAAC;AAI1D,eAAO,MAAM,4BAA4B,QAAkB,CAAC;AAK5D,eAAO,MAAM,+BAA+B,EAAoB,aAAa,CAAC"}
1
+ {"version":3,"file":"cliConstants.d.ts","sourceRoot":"","sources":["../src/cliConstants.ts"],"names":[],"mappings":"AAqBA,eAAO,MAAM,qBAAqB,cAAc,CAAC;AACjD,eAAO,MAAM,uBAAuB,cAAc,CAAC;AACnD,eAAO,MAAM,wBAAwB,UAAiC,CAAC;AAOvE,eAAO,MAAM,mBAAmB,iBAAiB,CAAC;AAUlD,eAAO,MAAM,gBAAgB,UAM5B,CAAC;AAIF,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAIjD,eAAO,MAAM,yBAAyB,mBAAmB,CAAC;AAI1D,eAAO,MAAM,4BAA4B,QAAkB,CAAC;AAK5D,eAAO,MAAM,+BAA+B,EAAoB,aAAa,CAAC"}
@@ -12,7 +12,7 @@
12
12
  // The rule for this file: nothing lands here unless the CLI reads it, and it
13
13
  // imports nothing.
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.CREDENTIAL_PROVIDER_CUSTOM_CODE = exports.CUSTOM_CODE_MAX_BUNDLE_BYTES = exports.CUSTOM_CODE_SDK_SPECIFIER = exports.CLI_TOKEN_REFRESH_SKEW_SECONDS = exports.CLI_OAUTH_SCOPES = exports.CLI_OAUTH_REDIRECT_PORTS = exports.CLI_OAUTH_REDIRECT_PATH = exports.CLI_OAUTH_CLIENT_NAME = void 0;
15
+ exports.CREDENTIAL_PROVIDER_CUSTOM_CODE = exports.CUSTOM_CODE_MAX_BUNDLE_BYTES = exports.CUSTOM_CODE_SDK_SPECIFIER = exports.CLI_TOKEN_REFRESH_SKEW_SECONDS = exports.CLI_OAUTH_SCOPES = exports.CONTROL_PLANE_SCOPE = exports.CLI_OAUTH_REDIRECT_PORTS = exports.CLI_OAUTH_REDIRECT_PATH = exports.CLI_OAUTH_CLIENT_NAME = void 0;
16
16
  // How `ganju login` identifies itself, and where it listens for the redirect.
17
17
  //
18
18
  // A fixed port would fail whenever something else already held it, so the CLI
@@ -24,13 +24,26 @@ exports.CREDENTIAL_PROVIDER_CUSTOM_CODE = exports.CUSTOM_CODE_MAX_BUNDLE_BYTES =
24
24
  exports.CLI_OAUTH_CLIENT_NAME = 'Ganju CLI';
25
25
  exports.CLI_OAUTH_REDIRECT_PATH = '/callback';
26
26
  exports.CLI_OAUTH_REDIRECT_PORTS = [8976, 8977, 8978, 8979, 8980];
27
+ // What the API requires before a bearer token may act on the control plane —
28
+ // publish code, read and rotate secrets, change billing. Lives here because the
29
+ // CLI is the client that asks for it; the API's own copy is the re-export in
30
+ // `constants.ts`, so the string the CLI requests and the string the middleware
31
+ // demands cannot drift apart.
32
+ exports.CONTROL_PLANE_SCOPE = 'ganju:manage';
27
33
  // `offline_access` is what mints the refresh token; without it a CLI session
28
34
  // would end an hour after login.
35
+ //
36
+ // An MCP client reads the discovery document to decide what to ask for, and
37
+ // that document does not list `ganju:manage` — so a token minted for someone's
38
+ // MCP server can reach that server and nothing else, while this one can deploy.
39
+ // The consent screen names the scope, which is the point: deploying code as
40
+ // someone is worth showing them.
29
41
  exports.CLI_OAUTH_SCOPES = [
30
42
  'openid',
31
43
  'profile',
32
44
  'email',
33
- 'offline_access'
45
+ 'offline_access',
46
+ exports.CONTROL_PLANE_SCOPE
34
47
  ];
35
48
  // Refresh this far before the access token actually expires, so a long command
36
49
  // can't have its token die mid-request.
@@ -519,6 +519,10 @@ export declare const constants: {
519
519
  CUSTOM_CODE_MAX_FILE_PATH: number;
520
520
  CUSTOM_CODE_VERSION_STATUSES: ("draft" | "published" | "archived")[];
521
521
  CUSTOM_CODE_SCRIPT_NAME_PREFIX: string;
522
+ CUSTOM_CODE_SCRIPT_NAME_MAX: number;
523
+ CUSTOM_CODE_UPLOAD_SUFFIX_CHARS: number;
524
+ CUSTOM_CODE_SWEEP_GRACE_MS: number;
525
+ CUSTOM_CODE_SWEEP_MAX_DELETES: number;
522
526
  CUSTOM_CODE_PREVIEW_SCRIPT_SUFFIX: string;
523
527
  CUSTOM_CODE_PREVIEW_TOKEN_TTL_MS: number;
524
528
  CUSTOM_CODE_TEST_TIMEOUT_MS: number;
@@ -539,6 +543,7 @@ export declare const constants: {
539
543
  OUTPUT_SCHEMA_NOT_OBJECT_MESSAGE: string;
540
544
  CUSTOM_CODE_BINDING_TOKEN: string;
541
545
  CUSTOM_CODE_BINDING_BROKER: string;
546
+ CUSTOM_CODE_BINDING_VERSION: string;
542
547
  CUSTOM_CODE_BROKER_ORIGIN: string;
543
548
  CUSTOM_CODE_BROKER_PATH_CONNECTION: string;
544
549
  CUSTOM_CODE_BROKER_PATH_SECRET: string;
@@ -559,6 +564,8 @@ export declare const constants: {
559
564
  CUSTOM_CODE_BROKER_SERVICE_ENV: string;
560
565
  CUSTOM_CODE_COMPATIBILITY_DATE: string;
561
566
  CUSTOM_CODE_SCRIPT_CPU_MS: number;
567
+ CUSTOM_CODE_REGISTER_TIMEOUT_MS: number;
568
+ CUSTOM_CODE_REGISTER_INTERVAL_MS: number;
562
569
  CUSTOM_CODE_MAX_LOGS: number;
563
570
  CUSTOM_CODE_MAX_LOG_LENGTH: number;
564
571
  CUSTOM_CODE_SEND_FILE_TARGET_GMAIL: "gmail";
@@ -605,6 +612,7 @@ export declare const constants: {
605
612
  OAUTH_SCOPES_SUPPORTED: string[];
606
613
  MCP_SCOPE_READ: string;
607
614
  ARTIFACT_SCOPE_PREFIX: string;
615
+ CONTROL_PLANE_SCOPE: string;
608
616
  CLI_OAUTH_CLIENT_NAME: string;
609
617
  CLI_OAUTH_REDIRECT_PATH: string;
610
618
  CLI_OAUTH_REDIRECT_PORTS: number[];
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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"}
package/dist/constants.js CHANGED
@@ -1041,9 +1041,36 @@ const CUSTOM_CODE_MAIN_MODULE = 'index.js';
1041
1041
  // object read on every deploy.
1042
1042
  const CUSTOM_CODE_MAX_FILES = 25;
1043
1043
  const CUSTOM_CODE_MAX_FILE_PATH = 100;
1044
- // WfP script name: `artifact_<artifactId>`. The id, never the slug — slugs are
1045
- // user-editable and a rename would orphan the deployed script.
1044
+ // WfP script name: `artifact_<artifactId>_<upload>`. The id, never the slug —
1045
+ // slugs are user-editable and a rename would orphan the deployed script.
1046
+ //
1047
+ // The trailing segment is minted per upload rather than derived from anything,
1048
+ // which is the whole point: uploading over a name that already exists is not
1049
+ // read-your-writes, so a deploy that replaces a script can serve the previous
1050
+ // edition for up to half a minute. A name nothing has ever used cannot, and
1051
+ // costs nothing to mint. Everything a publish used to do to survive that race —
1052
+ // waiting on an edition marker, refusing with a 503, putting the previous bundle
1053
+ // back when validation failed — went with the reuse that caused it.
1046
1054
  const CUSTOM_CODE_SCRIPT_NAME_PREFIX = 'artifact_';
1055
+ // Worker names cap at 63 characters, and `artifact_<uuid>` already spends 45.
1056
+ // That leaves 17 for a separator and a suffix, so a second uuid does not fit and
1057
+ // neither does a hex-32 digest. Twelve hex characters is 48 bits against a
1058
+ // namespace holding at most a few hundred names for any one artifact — not a
1059
+ // collision worth checking for, and an upload to a name in use would fail loudly
1060
+ // rather than quietly serve the wrong code.
1061
+ const CUSTOM_CODE_SCRIPT_NAME_MAX = 63;
1062
+ const CUSTOM_CODE_UPLOAD_SUFFIX_CHARS = 12;
1063
+ // How long a superseded script stays in the namespace before the hourly sweep
1064
+ // may collect it.
1065
+ //
1066
+ // Deleting at publish time would race the thing it deletes: a tool call that
1067
+ // resolved the old pointer a moment earlier is still in flight, and the pointer
1068
+ // moving does not recall it. An hour is far longer than any call can take, and
1069
+ // the wait costs $0.02 per script per month against an allowance of 1,000.
1070
+ const CUSTOM_CODE_SWEEP_GRACE_MS = 60 * 60 * 1_000;
1071
+ // Deletes per sweep. A backlog drains over several hourly runs rather than
1072
+ // making one run unbounded — the same shape the retention purge uses.
1073
+ const CUSTOM_CODE_SWEEP_MAX_DELETES = 200;
1047
1074
  // A second script per artifact, `artifact_<id>_preview`, that the Test panel
1048
1075
  // deploys a draft into and calls.
1049
1076
  //
@@ -1228,6 +1255,17 @@ const CUSTOM_CODE_COMPATIBILITY_DATE = '2025-11-17';
1228
1255
  // tighter than our own workers' 30s — this is the technical cap that bounds
1229
1256
  // what one adversarial call can cost us, so an infinite loop in a customer's
1230
1257
  // tool is billed as five seconds rather than as whatever it wanted.
1258
+ // How long a deploy waits for a freshly minted script name to become
1259
+ // dispatchable, and how often it asks.
1260
+ //
1261
+ // Every upload goes to a name that has never been used, which is
1262
+ // read-your-writes: ~2s end to end against the deployed namespace, against the
1263
+ // 20-41s a replacement could take. So this bounds how long a brand-new name
1264
+ // takes to register, never how long an old edition takes to stop answering —
1265
+ // there is no old edition. It is short for that reason, and a script that
1266
+ // answers with the wrong edition now fails outright instead of being waited on.
1267
+ const CUSTOM_CODE_REGISTER_TIMEOUT_MS = 8_000;
1268
+ const CUSTOM_CODE_REGISTER_INTERVAL_MS = 500;
1231
1269
  const CUSTOM_CODE_SCRIPT_CPU_MS = 5_000;
1232
1270
  // The ctx.log() caps also live in ./sdkConstants — the buffer that enforces them
1233
1271
  // runs inside the isolate.
@@ -1375,6 +1413,20 @@ const OAUTH_SCOPES_SUPPORTED = ['openid', 'profile', 'email', 'offline_access'];
1375
1413
  // TODO: Net: mcp:read is a cosmetic claim on bot tokens; artifact: is a code path that can't fire. Neither affects security today. They become real only if you build the per-server confinement feature (which would make artifact:<slug> issued + enforced). This is more for OIDC.
1376
1414
  const MCP_SCOPE_READ = 'mcp:read';
1377
1415
  const ARTIFACT_SCOPE_PREFIX = 'artifact:';
1416
+ // `CONTROL_PLANE_SCOPE` (defined in ./cliConstants, re-exported below) is what
1417
+ // a bearer token needs before it may act as the user on the control plane —
1418
+ // publish code, read and rotate secrets, change billing.
1419
+ //
1420
+ // Access tokens are minted for MCP clients too: a customer who connects Claude
1421
+ // Desktop to one of their MCP servers hands it a token for their own account,
1422
+ // and `/oauth2/userinfo` will happily confirm that it is theirs. Without a scope
1423
+ // that separates the two, "this token belongs to the user" would be the same
1424
+ // sentence as "this token may deploy code as the user", and connecting an MCP
1425
+ // client would silently be an act of full delegation.
1426
+ //
1427
+ // Deliberately outside OAUTH_SCOPES_SUPPORTED: it is allowlisted on the provider
1428
+ // so the CLI can request it, and left out of discovery, which is what an MCP
1429
+ // client reads to decide what to ask for.
1378
1430
  // The CLI signs in as a public OAuth client through a loopback redirect
1379
1431
  // (RFC 8252) — the flow `wrangler`, `gh` and `vercel` all use. It registers
1380
1432
  // itself through RFC 7591 dynamic registration on first login rather than
@@ -2116,6 +2168,10 @@ exports.constants = {
2116
2168
  CUSTOM_CODE_MAX_FILE_PATH,
2117
2169
  CUSTOM_CODE_VERSION_STATUSES,
2118
2170
  CUSTOM_CODE_SCRIPT_NAME_PREFIX,
2171
+ CUSTOM_CODE_SCRIPT_NAME_MAX,
2172
+ CUSTOM_CODE_UPLOAD_SUFFIX_CHARS,
2173
+ CUSTOM_CODE_SWEEP_GRACE_MS,
2174
+ CUSTOM_CODE_SWEEP_MAX_DELETES,
2119
2175
  CUSTOM_CODE_PREVIEW_SCRIPT_SUFFIX,
2120
2176
  CUSTOM_CODE_PREVIEW_TOKEN_TTL_MS,
2121
2177
  CUSTOM_CODE_TEST_TIMEOUT_MS,
@@ -2136,6 +2192,7 @@ exports.constants = {
2136
2192
  OUTPUT_SCHEMA_NOT_OBJECT_MESSAGE,
2137
2193
  CUSTOM_CODE_BINDING_TOKEN: sdkConstants_1.CUSTOM_CODE_BINDING_TOKEN,
2138
2194
  CUSTOM_CODE_BINDING_BROKER: sdkConstants_1.CUSTOM_CODE_BINDING_BROKER,
2195
+ CUSTOM_CODE_BINDING_VERSION: sdkConstants_1.CUSTOM_CODE_BINDING_VERSION,
2139
2196
  CUSTOM_CODE_BROKER_ORIGIN: sdkConstants_1.CUSTOM_CODE_BROKER_ORIGIN,
2140
2197
  CUSTOM_CODE_BROKER_PATH_CONNECTION: sdkConstants_1.CUSTOM_CODE_BROKER_PATH_CONNECTION,
2141
2198
  CUSTOM_CODE_BROKER_PATH_SECRET: sdkConstants_1.CUSTOM_CODE_BROKER_PATH_SECRET,
@@ -2156,6 +2213,8 @@ exports.constants = {
2156
2213
  CUSTOM_CODE_BROKER_SERVICE_ENV,
2157
2214
  CUSTOM_CODE_COMPATIBILITY_DATE,
2158
2215
  CUSTOM_CODE_SCRIPT_CPU_MS,
2216
+ CUSTOM_CODE_REGISTER_TIMEOUT_MS,
2217
+ CUSTOM_CODE_REGISTER_INTERVAL_MS,
2159
2218
  CUSTOM_CODE_MAX_LOGS: sdkConstants_1.CUSTOM_CODE_MAX_LOGS,
2160
2219
  CUSTOM_CODE_MAX_LOG_LENGTH: sdkConstants_1.CUSTOM_CODE_MAX_LOG_LENGTH,
2161
2220
  CUSTOM_CODE_SEND_FILE_TARGET_GMAIL,
@@ -2202,6 +2261,7 @@ exports.constants = {
2202
2261
  OAUTH_SCOPES_SUPPORTED,
2203
2262
  MCP_SCOPE_READ,
2204
2263
  ARTIFACT_SCOPE_PREFIX,
2264
+ CONTROL_PLANE_SCOPE: cliConstants_1.CONTROL_PLANE_SCOPE,
2205
2265
  CLI_OAUTH_CLIENT_NAME: cliConstants_1.CLI_OAUTH_CLIENT_NAME,
2206
2266
  CLI_OAUTH_REDIRECT_PATH: cliConstants_1.CLI_OAUTH_REDIRECT_PATH,
2207
2267
  CLI_OAUTH_REDIRECT_PORTS: cliConstants_1.CLI_OAUTH_REDIRECT_PORTS,
@@ -24,18 +24,53 @@ export declare const mintCustomCodeToken: (payload: Omit<CustomCodeTokenPayload,
24
24
  */
25
25
  export declare const verifyCustomCodeToken: (token: string, secret: string, now?: number) => Promise<CustomCodeTokenPayload | null>;
26
26
  /**
27
- * The dispatch-namespace script name for an artifact: `artifact_<id>`.
27
+ * The legacy dispatch-namespace script name for an artifact: `artifact_<id>`.
28
28
  *
29
29
  * The id, never the slug — slugs are user-editable and a rename would orphan the
30
30
  * deployed script while the database still pointed at a live version.
31
+ *
32
+ * Nothing uploads to this name any more; every deploy mints its own. It survives
33
+ * as the fallback for a version published before `script_name` existed, whose
34
+ * bundle really is sitting under this name. Tightening a rule must never stop an
35
+ * already-published version from serving, because that failure is invisible to
36
+ * whoever owns it — the same reason the boot loop still accepts a stored tool key
37
+ * the current catalog no longer offers.
31
38
  */
32
39
  export declare const customCodeScriptName: (artifactId: string) => string;
33
40
  /**
34
- * The script name a test run deploys into: `artifact_<id>_preview`.
41
+ * The legacy preview script name: `artifact_<id>_preview`.
35
42
  *
36
- * A second script rather than a second version of the live one, because a test
37
- * must not be able to disturb what MCP clients are being served and the only
38
- * way to be certain of that is for it to run under a name nothing dispatches to.
43
+ * Kept for the same reason as the one above, and for one more: it is the prefix
44
+ * the sweep matches to recognise a preview script left behind by a test run that
45
+ * did not clean up after itself.
39
46
  */
40
47
  export declare const customCodePreviewScriptName: (artifactId: string) => string;
48
+ /**
49
+ * A dispatch-namespace name no upload has ever used:
50
+ * `artifact_<id>_<12 hex chars>`.
51
+ *
52
+ * Minted rather than derived, and that is the entire design. Uploading over an
53
+ * existing name is not read-your-writes — a replacement can serve the previous
54
+ * edition for tens of seconds — so a deploy that always writes to a new name is
55
+ * correct by construction rather than by waiting to see whether it worked.
56
+ *
57
+ * The suffix deliberately carries no meaning. The two candidates that did are
58
+ * both wrong: the bundle digest collides whenever a deploy reverts to bytes that
59
+ * shipped before, which is exactly what a rollback is, and the version id is one
60
+ * string across every re-upload of a single draft, which is every test run of it.
61
+ *
62
+ * Twelve hex characters is what fits. Worker names cap at 63 and
63
+ * `artifact_<uuid>` spends 45 of them.
64
+ */
65
+ export declare const customCodeUploadName: (artifactId: string) => string;
66
+ /**
67
+ * A preview name no test run has ever used:
68
+ * `artifact_<id>_preview_<12 hex chars>`.
69
+ *
70
+ * The sharper version of the same race. Every test used to deploy over one
71
+ * preview name, so a test could report the run before it — which reads as "my
72
+ * edit did nothing" from the one tool whose whole job is to say what an edit
73
+ * does. Nothing stores this: it is minted, used, and deleted inside one request.
74
+ */
75
+ export declare const customCodePreviewUploadName: (artifactId: string) => string;
41
76
  //# sourceMappingURL=customCodeToken.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"customCodeToken.d.ts","sourceRoot":"","sources":["../src/customCodeToken.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,sBAAsB;IAGrC,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;IAGnB,SAAS,EAAE,MAAM,CAAC;IAIlB,GAAG,EAAE,MAAM,CAAC;IAOZ,OAAO,CAAC,EAAE,OAAO,CAAC;IAGlB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AA0BD;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC9B,SAAS,IAAI,CAAC,sBAAsB,EAAE,GAAG,GAAG,KAAK,GAAG,KAAK,CAAC,GAAG;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,EACD,QAAQ,MAAM,EACd,WAAU,MAAmB,KAC5B,OAAO,CAAC,MAAM,CAmBhB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,GAChC,OAAO,MAAM,EACb,QAAQ,MAAM,EACd,MAAM,MAAM,KACX,OAAO,CAAC,sBAAsB,GAAG,IAAI,CA+DvC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAAI,YAAY,MAAM,KAAG,MACE,CAAC;AAE7D;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,GAAI,YAAY,MAAM,KAAG,MACoB,CAAC"}
1
+ {"version":3,"file":"customCodeToken.d.ts","sourceRoot":"","sources":["../src/customCodeToken.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,sBAAsB;IAGrC,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;IAGnB,SAAS,EAAE,MAAM,CAAC;IAIlB,GAAG,EAAE,MAAM,CAAC;IAOZ,OAAO,CAAC,EAAE,OAAO,CAAC;IAGlB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AA0BD;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC9B,SAAS,IAAI,CAAC,sBAAsB,EAAE,GAAG,GAAG,KAAK,GAAG,KAAK,CAAC,GAAG;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,EACD,QAAQ,MAAM,EACd,WAAU,MAAmB,KAC5B,OAAO,CAAC,MAAM,CAmBhB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,GAChC,OAAO,MAAM,EACb,QAAQ,MAAM,EACd,MAAM,MAAM,KACX,OAAO,CAAC,sBAAsB,GAAG,IAAI,CA+DvC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,oBAAoB,GAAI,YAAY,MAAM,KAAG,MACE,CAAC;AAE7D;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,GAAI,YAAY,MAAM,KAAG,MACoB,CAAC;AAEtF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,oBAAoB,GAAI,YAAY,MAAM,KAAG,MACR,CAAC;AAEnD;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,GAAI,YAAY,MAAM,KAAG,MACR,CAAC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.customCodePreviewScriptName = exports.customCodeScriptName = exports.verifyCustomCodeToken = exports.mintCustomCodeToken = void 0;
3
+ exports.customCodePreviewUploadName = exports.customCodeUploadName = exports.customCodePreviewScriptName = exports.customCodeScriptName = exports.verifyCustomCodeToken = exports.mintCustomCodeToken = void 0;
4
4
  const base64_1 = require("./base64");
5
5
  const constants_1 = require("./constants");
6
6
  const encoder = new TextEncoder();
@@ -97,19 +97,90 @@ const verifyCustomCodeToken = async (token, secret, now) => {
97
97
  };
98
98
  exports.verifyCustomCodeToken = verifyCustomCodeToken;
99
99
  /**
100
- * The dispatch-namespace script name for an artifact: `artifact_<id>`.
100
+ * The legacy dispatch-namespace script name for an artifact: `artifact_<id>`.
101
101
  *
102
102
  * The id, never the slug — slugs are user-editable and a rename would orphan the
103
103
  * deployed script while the database still pointed at a live version.
104
+ *
105
+ * Nothing uploads to this name any more; every deploy mints its own. It survives
106
+ * as the fallback for a version published before `script_name` existed, whose
107
+ * bundle really is sitting under this name. Tightening a rule must never stop an
108
+ * already-published version from serving, because that failure is invisible to
109
+ * whoever owns it — the same reason the boot loop still accepts a stored tool key
110
+ * the current catalog no longer offers.
104
111
  */
105
112
  const customCodeScriptName = (artifactId) => `${constants_1.constants.CUSTOM_CODE_SCRIPT_NAME_PREFIX}${artifactId}`;
106
113
  exports.customCodeScriptName = customCodeScriptName;
107
114
  /**
108
- * The script name a test run deploys into: `artifact_<id>_preview`.
115
+ * The legacy preview script name: `artifact_<id>_preview`.
109
116
  *
110
- * A second script rather than a second version of the live one, because a test
111
- * must not be able to disturb what MCP clients are being served and the only
112
- * way to be certain of that is for it to run under a name nothing dispatches to.
117
+ * Kept for the same reason as the one above, and for one more: it is the prefix
118
+ * the sweep matches to recognise a preview script left behind by a test run that
119
+ * did not clean up after itself.
113
120
  */
114
121
  const customCodePreviewScriptName = (artifactId) => `${(0, exports.customCodeScriptName)(artifactId)}${constants_1.constants.CUSTOM_CODE_PREVIEW_SCRIPT_SUFFIX}`;
115
122
  exports.customCodePreviewScriptName = customCodePreviewScriptName;
123
+ /**
124
+ * A dispatch-namespace name no upload has ever used:
125
+ * `artifact_<id>_<12 hex chars>`.
126
+ *
127
+ * Minted rather than derived, and that is the entire design. Uploading over an
128
+ * existing name is not read-your-writes — a replacement can serve the previous
129
+ * edition for tens of seconds — so a deploy that always writes to a new name is
130
+ * correct by construction rather than by waiting to see whether it worked.
131
+ *
132
+ * The suffix deliberately carries no meaning. The two candidates that did are
133
+ * both wrong: the bundle digest collides whenever a deploy reverts to bytes that
134
+ * shipped before, which is exactly what a rollback is, and the version id is one
135
+ * string across every re-upload of a single draft, which is every test run of it.
136
+ *
137
+ * Twelve hex characters is what fits. Worker names cap at 63 and
138
+ * `artifact_<uuid>` spends 45 of them.
139
+ */
140
+ const customCodeUploadName = (artifactId) => mintUploadName((0, exports.customCodeScriptName)(artifactId));
141
+ exports.customCodeUploadName = customCodeUploadName;
142
+ /**
143
+ * A preview name no test run has ever used:
144
+ * `artifact_<id>_preview_<12 hex chars>`.
145
+ *
146
+ * The sharper version of the same race. Every test used to deploy over one
147
+ * preview name, so a test could report the run before it — which reads as "my
148
+ * edit did nothing" from the one tool whose whole job is to say what an edit
149
+ * does. Nothing stores this: it is minted, used, and deleted inside one request.
150
+ */
151
+ const customCodePreviewUploadName = (artifactId) => mintUploadName((0, exports.customCodePreviewScriptName)(artifactId));
152
+ exports.customCodePreviewUploadName = customCodePreviewUploadName;
153
+ /**
154
+ * Append `_<hex>` to a base name, spending whatever the 63-character ceiling
155
+ * leaves and no more.
156
+ *
157
+ * The budget is genuinely tight, and the two names spend it differently:
158
+ *
159
+ * | name | base | separator | suffix | total |
160
+ * |---|---|---|---|---|
161
+ * | live | `artifact_<uuid>` = 45 | 1 | 12 | 58 |
162
+ * | preview | + `_preview` = 53 | 1 | 8 | 62 |
163
+ *
164
+ * Twelve hex characters is 48 bits and eight is 32, against a namespace holding
165
+ * a few hundred names for any one artifact — and a preview name lives for the
166
+ * seconds one test run takes. Neither is a collision worth checking for, and an
167
+ * upload to a name already in use fails loudly rather than quietly serving the
168
+ * wrong code, which is the failure that matters.
169
+ *
170
+ * The ceiling is asserted rather than assumed: it is one number away from being
171
+ * silently exceeded by a longer prefix, and a name Cloudflare refuses would
172
+ * surface as a failed publish with nothing explaining why.
173
+ */
174
+ const mintUploadName = (base) => {
175
+ const available = constants_1.constants.CUSTOM_CODE_SCRIPT_NAME_MAX - base.length - 1;
176
+ // Even, because each byte renders as two hex characters.
177
+ const chars = Math.min(constants_1.constants.CUSTOM_CODE_UPLOAD_SUFFIX_CHARS, available) & ~1;
178
+ if (chars < 4) {
179
+ throw new Error(`A dispatch script name based on "${base}" leaves no room for a unique suffix.`);
180
+ }
181
+ const bytes = new Uint8Array(chars / 2);
182
+ crypto.getRandomValues(bytes);
183
+ return `${base}_${Array.from(bytes)
184
+ .map(byte => byte.toString(16).padStart(2, '0'))
185
+ .join('')}`;
186
+ };
package/dist/index.d.ts CHANGED
@@ -2206,6 +2206,10 @@ export declare const utils: {
2206
2206
  CUSTOM_CODE_MAX_FILE_PATH: number;
2207
2207
  CUSTOM_CODE_VERSION_STATUSES: ("draft" | "published" | "archived")[];
2208
2208
  CUSTOM_CODE_SCRIPT_NAME_PREFIX: string;
2209
+ CUSTOM_CODE_SCRIPT_NAME_MAX: number;
2210
+ CUSTOM_CODE_UPLOAD_SUFFIX_CHARS: number;
2211
+ CUSTOM_CODE_SWEEP_GRACE_MS: number;
2212
+ CUSTOM_CODE_SWEEP_MAX_DELETES: number;
2209
2213
  CUSTOM_CODE_PREVIEW_SCRIPT_SUFFIX: string;
2210
2214
  CUSTOM_CODE_PREVIEW_TOKEN_TTL_MS: number;
2211
2215
  CUSTOM_CODE_TEST_TIMEOUT_MS: number;
@@ -2226,6 +2230,7 @@ export declare const utils: {
2226
2230
  OUTPUT_SCHEMA_NOT_OBJECT_MESSAGE: string;
2227
2231
  CUSTOM_CODE_BINDING_TOKEN: string;
2228
2232
  CUSTOM_CODE_BINDING_BROKER: string;
2233
+ CUSTOM_CODE_BINDING_VERSION: string;
2229
2234
  CUSTOM_CODE_BROKER_ORIGIN: string;
2230
2235
  CUSTOM_CODE_BROKER_PATH_CONNECTION: string;
2231
2236
  CUSTOM_CODE_BROKER_PATH_SECRET: string;
@@ -2246,6 +2251,8 @@ export declare const utils: {
2246
2251
  CUSTOM_CODE_BROKER_SERVICE_ENV: string;
2247
2252
  CUSTOM_CODE_COMPATIBILITY_DATE: string;
2248
2253
  CUSTOM_CODE_SCRIPT_CPU_MS: number;
2254
+ CUSTOM_CODE_REGISTER_TIMEOUT_MS: number;
2255
+ CUSTOM_CODE_REGISTER_INTERVAL_MS: number;
2249
2256
  CUSTOM_CODE_MAX_LOGS: number;
2250
2257
  CUSTOM_CODE_MAX_LOG_LENGTH: number;
2251
2258
  CUSTOM_CODE_SEND_FILE_TARGET_GMAIL: "gmail";
@@ -2292,6 +2299,7 @@ export declare const utils: {
2292
2299
  OAUTH_SCOPES_SUPPORTED: string[];
2293
2300
  MCP_SCOPE_READ: string;
2294
2301
  ARTIFACT_SCOPE_PREFIX: string;
2302
+ CONTROL_PLANE_SCOPE: string;
2295
2303
  CLI_OAUTH_CLIENT_NAME: string;
2296
2304
  CLI_OAUTH_REDIRECT_PATH: string;
2297
2305
  CLI_OAUTH_REDIRECT_PORTS: number[];
@@ -2349,6 +2357,8 @@ export declare const utils: {
2349
2357
  verifyCustomCodeToken: (token: string, secret: string, now?: number) => Promise<CustomCodeTokenPayload | null>;
2350
2358
  customCodeScriptName: (artifactId: string) => string;
2351
2359
  customCodePreviewScriptName: (artifactId: string) => string;
2360
+ customCodeUploadName: (artifactId: string) => string;
2361
+ customCodePreviewUploadName: (artifactId: string) => string;
2352
2362
  oauthProviders: Record<string, OAuthProviderConfig>;
2353
2363
  resolveAttachment: (resource: AttachmentResource, readObject: (key: string) => Promise<ArrayBuffer | null>, verb?: "attach" | "upload") => Promise<ResolveAttachmentResult>;
2354
2364
  isExposedResource: (resource: ExposableResource) => boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAlGhB,CAAC;;;;;;;;;;;;;;;;;;;;;;;kBAjHkB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBA0DF,CAAC;oBAEd,CAAC;;;;aA0BkB,CAAC;mBAA8B,CAAC;WACvC,CAAC;gBACf,CAAC;gBAA4B,CAAA;;;mBAmBK,CAAC;oBACtC,CAAC;;;;;;;;;;;;;;;kBA1DmB,CAAC;;;;;;;sBAqCR,CAAC;;;;;;;;;CAuOf,CAAC;AAEF,YAAY,EACV,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,YAAY,EACZ,OAAO,EACP,mBAAmB,EACnB,UAAU,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,8BAA8B,EAC9B,mBAAmB,EACnB,oBAAoB,EACpB,iCAAiC,EACjC,kBAAkB,EAClB,mBAAmB,EACnB,gCAAgC,EAChC,mBAAmB,EACnB,oBAAoB,EACpB,iCAAiC,EACjC,SAAS,EACT,SAAS,EACT,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,yBAAyB,EACzB,uBAAuB,EACvB,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,yBAAyB,EACzB,eAAe,EACf,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,EAClB,MAAM,EACN,kBAAkB,EAClB,YAAY,EACZ,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,EACtB,kBAAkB,EAClB,sBAAsB,EACtB,0BAA0B,EAC1B,wBAAwB,EACxB,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,EAClB,wBAAwB,EACxB,sBAAsB,EACtB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,EACvB,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACX,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aArGf,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;kBAhHiB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBA0DF,CAAC;oBAEd,CAAC;;;;aA0BkB,CAAC;mBAA8B,CAAC;WACvC,CAAC;gBACf,CAAC;gBAA4B,CAAA;;;mBAoBK,CAAC;oBACjC,CAAC;;;;;;;;;;;;;;;kBA3Dc,CAAC;;;;;;;sBAqCR,CAAC;;;;;;;;;CA2Of,CAAC;AAEF,YAAY,EACV,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,YAAY,EACZ,OAAO,EACP,mBAAmB,EACnB,UAAU,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,8BAA8B,EAC9B,mBAAmB,EACnB,oBAAoB,EACpB,iCAAiC,EACjC,kBAAkB,EAClB,mBAAmB,EACnB,gCAAgC,EAChC,mBAAmB,EACnB,oBAAoB,EACpB,iCAAiC,EACjC,SAAS,EACT,SAAS,EACT,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,yBAAyB,EACzB,uBAAuB,EACvB,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,yBAAyB,EACzB,eAAe,EACf,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,EAClB,MAAM,EACN,kBAAkB,EAClB,YAAY,EACZ,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,EACtB,kBAAkB,EAClB,sBAAsB,EACtB,0BAA0B,EAC1B,wBAAwB,EACxB,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,EAClB,wBAAwB,EACxB,sBAAsB,EACtB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,EACvB,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACX,CAAC"}
package/dist/index.js CHANGED
@@ -89,6 +89,8 @@ exports.utils = {
89
89
  verifyCustomCodeToken: customCodeToken_1.verifyCustomCodeToken,
90
90
  customCodeScriptName: customCodeToken_1.customCodeScriptName,
91
91
  customCodePreviewScriptName: customCodeToken_1.customCodePreviewScriptName,
92
+ customCodeUploadName: customCodeToken_1.customCodeUploadName,
93
+ customCodePreviewUploadName: customCodeToken_1.customCodePreviewUploadName,
92
94
  oauthProviders: oauthProviders_1.oauthProviders,
93
95
  resolveAttachment: attachment_1.resolveAttachment,
94
96
  isExposedResource: exposedResource_1.isExposedResource,
@@ -9,6 +9,7 @@ export declare const CUSTOM_CODE_BROKER_PATH_RESOURCES_LIST = "/resources/list";
9
9
  export declare const CUSTOM_CODE_BROKER_PATH_RESOURCES_CREATE = "/resources/create";
10
10
  export declare const CUSTOM_CODE_BROKER_PATH_RESOURCES_DELETE = "/resources/delete";
11
11
  export declare const CUSTOM_CODE_BROKER_PATH_SEND_FILE = "/send-file";
12
+ export declare const CUSTOM_CODE_BINDING_VERSION = "GANJU_SCRIPT_VERSION";
12
13
  export declare const CUSTOM_CODE_HEALTH_TOOL = "__ganju_health";
13
14
  export declare const CUSTOM_CODE_MAX_LOGS = 50;
14
15
  export declare const CUSTOM_CODE_MAX_LOG_LENGTH = 2000;
@@ -1 +1 @@
1
- {"version":3,"file":"sdkConstants.d.ts","sourceRoot":"","sources":["../src/sdkConstants.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,yBAAyB,qBAAqB,CAAC;AAC5D,eAAO,MAAM,0BAA0B,iBAAiB,CAAC;AAKzD,eAAO,MAAM,yBAAyB,kCAAkC,CAAC;AACzE,eAAO,MAAM,kCAAkC,gBAAgB,CAAC;AAChE,eAAO,MAAM,8BAA8B,YAAY,CAAC;AACxD,eAAO,MAAM,wCAAwC,sBAAsB,CAAC;AAC5E,eAAO,MAAM,sCAAsC,oBAAoB,CAAC;AACxE,eAAO,MAAM,sCAAsC,oBAAoB,CAAC;AACxE,eAAO,MAAM,wCAAwC,sBAAsB,CAAC;AAC5E,eAAO,MAAM,wCAAwC,sBAAsB,CAAC;AAC5E,eAAO,MAAM,iCAAiC,eAAe,CAAC;AAO9D,eAAO,MAAM,uBAAuB,mBAAmB,CAAC;AAKxD,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,0BAA0B,OAAQ,CAAC"}
1
+ {"version":3,"file":"sdkConstants.d.ts","sourceRoot":"","sources":["../src/sdkConstants.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,yBAAyB,qBAAqB,CAAC;AAC5D,eAAO,MAAM,0BAA0B,iBAAiB,CAAC;AAKzD,eAAO,MAAM,yBAAyB,kCAAkC,CAAC;AACzE,eAAO,MAAM,kCAAkC,gBAAgB,CAAC;AAChE,eAAO,MAAM,8BAA8B,YAAY,CAAC;AACxD,eAAO,MAAM,wCAAwC,sBAAsB,CAAC;AAC5E,eAAO,MAAM,sCAAsC,oBAAoB,CAAC;AACxE,eAAO,MAAM,sCAAsC,oBAAoB,CAAC;AACxE,eAAO,MAAM,wCAAwC,sBAAsB,CAAC;AAC5E,eAAO,MAAM,wCAAwC,sBAAsB,CAAC;AAC5E,eAAO,MAAM,iCAAiC,eAAe,CAAC;AAY9D,eAAO,MAAM,2BAA2B,yBAAyB,CAAC;AAOlE,eAAO,MAAM,uBAAuB,mBAAmB,CAAC;AAKxD,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,0BAA0B,OAAQ,CAAC"}
@@ -11,7 +11,7 @@
11
11
  // The rule for this file: nothing lands here unless the SDK reads it at runtime,
12
12
  // and it imports nothing.
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.CUSTOM_CODE_MAX_LOG_LENGTH = exports.CUSTOM_CODE_MAX_LOGS = exports.CUSTOM_CODE_HEALTH_TOOL = exports.CUSTOM_CODE_BROKER_PATH_SEND_FILE = exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_DELETE = exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_CREATE = exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_LIST = exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_READ = exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_SEARCH = exports.CUSTOM_CODE_BROKER_PATH_SECRET = exports.CUSTOM_CODE_BROKER_PATH_CONNECTION = exports.CUSTOM_CODE_BROKER_ORIGIN = exports.CUSTOM_CODE_BINDING_BROKER = exports.CUSTOM_CODE_BINDING_TOKEN = void 0;
14
+ exports.CUSTOM_CODE_MAX_LOG_LENGTH = exports.CUSTOM_CODE_MAX_LOGS = exports.CUSTOM_CODE_HEALTH_TOOL = exports.CUSTOM_CODE_BINDING_VERSION = exports.CUSTOM_CODE_BROKER_PATH_SEND_FILE = exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_DELETE = exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_CREATE = exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_LIST = exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_READ = exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_SEARCH = exports.CUSTOM_CODE_BROKER_PATH_SECRET = exports.CUSTOM_CODE_BROKER_PATH_CONNECTION = exports.CUSTOM_CODE_BROKER_ORIGIN = exports.CUSTOM_CODE_BINDING_BROKER = exports.CUSTOM_CODE_BINDING_TOKEN = void 0;
15
15
  // Bindings injected into every user script at upload time. The token is a
16
16
  // secret_text binding rotated on each publish; the broker is a service binding.
17
17
  // Names are part of the SDK's contract with the script, so they can't be
@@ -30,6 +30,17 @@ exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_LIST = '/resources/list';
30
30
  exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_CREATE = '/resources/create';
31
31
  exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_DELETE = '/resources/delete';
32
32
  exports.CUSTOM_CODE_BROKER_PATH_SEND_FILE = '/send-file';
33
+ // Injected at upload time and echoed back by the health probe below. Uploading a
34
+ // script into the dispatch namespace is not read-your-writes: dispatching to the
35
+ // name immediately afterwards can still reach the previous edition. Tool names
36
+ // alone cannot tell the two apart when a deploy does not rename anything, so the
37
+ // script carries the digest of the bytes it was uploaded from and the publish
38
+ // pipeline waits until the edition answering is the one it just wrote.
39
+ //
40
+ // The bytes rather than the version id: a draft is re-uploaded in place, so its
41
+ // id is the same string across every edit and could never separate this upload
42
+ // from the one before it.
43
+ exports.CUSTOM_CODE_BINDING_VERSION = 'GANJU_SCRIPT_VERSION';
33
44
  // The reserved tool name the publish pipeline calls against a freshly uploaded
34
45
  // script to ask which tools it actually exports — which is what turns "the
35
46
  // manifest declares lookup-order but the code exports lookupOrder" from a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ganju/utils",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Shared constants, schemas and helpers for Ganju",
5
5
  "license": "Apache-2.0",
6
6
  "author": "MontoyaAndres <andresmontoyafcb@gmail.com>",
@@ -23,13 +23,27 @@ export const CLI_OAUTH_CLIENT_NAME = 'Ganju CLI';
23
23
  export const CLI_OAUTH_REDIRECT_PATH = '/callback';
24
24
  export const CLI_OAUTH_REDIRECT_PORTS = [8976, 8977, 8978, 8979, 8980];
25
25
 
26
+ // What the API requires before a bearer token may act on the control plane —
27
+ // publish code, read and rotate secrets, change billing. Lives here because the
28
+ // CLI is the client that asks for it; the API's own copy is the re-export in
29
+ // `constants.ts`, so the string the CLI requests and the string the middleware
30
+ // demands cannot drift apart.
31
+ export const CONTROL_PLANE_SCOPE = 'ganju:manage';
32
+
26
33
  // `offline_access` is what mints the refresh token; without it a CLI session
27
34
  // would end an hour after login.
35
+ //
36
+ // An MCP client reads the discovery document to decide what to ask for, and
37
+ // that document does not list `ganju:manage` — so a token minted for someone's
38
+ // MCP server can reach that server and nothing else, while this one can deploy.
39
+ // The consent screen names the scope, which is the point: deploying code as
40
+ // someone is worth showing them.
28
41
  export const CLI_OAUTH_SCOPES = [
29
42
  'openid',
30
43
  'profile',
31
44
  'email',
32
- 'offline_access'
45
+ 'offline_access',
46
+ CONTROL_PLANE_SCOPE
33
47
  ];
34
48
 
35
49
  // Refresh this far before the access token actually expires, so a long command
package/src/constants.ts CHANGED
@@ -3,6 +3,7 @@ import {
3
3
  CLI_OAUTH_REDIRECT_PATH,
4
4
  CLI_OAUTH_REDIRECT_PORTS,
5
5
  CLI_OAUTH_SCOPES,
6
+ CONTROL_PLANE_SCOPE,
6
7
  CLI_TOKEN_REFRESH_SKEW_SECONDS,
7
8
  CUSTOM_CODE_SDK_SPECIFIER,
8
9
  CUSTOM_CODE_MAX_BUNDLE_BYTES,
@@ -11,6 +12,7 @@ import {
11
12
  import {
12
13
  CUSTOM_CODE_BINDING_TOKEN,
13
14
  CUSTOM_CODE_BINDING_BROKER,
15
+ CUSTOM_CODE_BINDING_VERSION,
14
16
  CUSTOM_CODE_BROKER_ORIGIN,
15
17
  CUSTOM_CODE_BROKER_PATH_CONNECTION,
16
18
  CUSTOM_CODE_BROKER_PATH_SECRET,
@@ -1237,10 +1239,40 @@ const CUSTOM_CODE_MAIN_MODULE = 'index.js';
1237
1239
  const CUSTOM_CODE_MAX_FILES = 25;
1238
1240
  const CUSTOM_CODE_MAX_FILE_PATH = 100;
1239
1241
 
1240
- // WfP script name: `artifact_<artifactId>`. The id, never the slug — slugs are
1241
- // user-editable and a rename would orphan the deployed script.
1242
+ // WfP script name: `artifact_<artifactId>_<upload>`. The id, never the slug —
1243
+ // slugs are user-editable and a rename would orphan the deployed script.
1244
+ //
1245
+ // The trailing segment is minted per upload rather than derived from anything,
1246
+ // which is the whole point: uploading over a name that already exists is not
1247
+ // read-your-writes, so a deploy that replaces a script can serve the previous
1248
+ // edition for up to half a minute. A name nothing has ever used cannot, and
1249
+ // costs nothing to mint. Everything a publish used to do to survive that race —
1250
+ // waiting on an edition marker, refusing with a 503, putting the previous bundle
1251
+ // back when validation failed — went with the reuse that caused it.
1242
1252
  const CUSTOM_CODE_SCRIPT_NAME_PREFIX = 'artifact_';
1243
1253
 
1254
+ // Worker names cap at 63 characters, and `artifact_<uuid>` already spends 45.
1255
+ // That leaves 17 for a separator and a suffix, so a second uuid does not fit and
1256
+ // neither does a hex-32 digest. Twelve hex characters is 48 bits against a
1257
+ // namespace holding at most a few hundred names for any one artifact — not a
1258
+ // collision worth checking for, and an upload to a name in use would fail loudly
1259
+ // rather than quietly serve the wrong code.
1260
+ const CUSTOM_CODE_SCRIPT_NAME_MAX = 63;
1261
+ const CUSTOM_CODE_UPLOAD_SUFFIX_CHARS = 12;
1262
+
1263
+ // How long a superseded script stays in the namespace before the hourly sweep
1264
+ // may collect it.
1265
+ //
1266
+ // Deleting at publish time would race the thing it deletes: a tool call that
1267
+ // resolved the old pointer a moment earlier is still in flight, and the pointer
1268
+ // moving does not recall it. An hour is far longer than any call can take, and
1269
+ // the wait costs $0.02 per script per month against an allowance of 1,000.
1270
+ const CUSTOM_CODE_SWEEP_GRACE_MS = 60 * 60 * 1_000;
1271
+
1272
+ // Deletes per sweep. A backlog drains over several hourly runs rather than
1273
+ // making one run unbounded — the same shape the retention purge uses.
1274
+ const CUSTOM_CODE_SWEEP_MAX_DELETES = 200;
1275
+
1244
1276
  // A second script per artifact, `artifact_<id>_preview`, that the Test panel
1245
1277
  // deploys a draft into and calls.
1246
1278
  //
@@ -1451,6 +1483,18 @@ const CUSTOM_CODE_COMPATIBILITY_DATE = '2025-11-17';
1451
1483
  // tighter than our own workers' 30s — this is the technical cap that bounds
1452
1484
  // what one adversarial call can cost us, so an infinite loop in a customer's
1453
1485
  // tool is billed as five seconds rather than as whatever it wanted.
1486
+ // How long a deploy waits for a freshly minted script name to become
1487
+ // dispatchable, and how often it asks.
1488
+ //
1489
+ // Every upload goes to a name that has never been used, which is
1490
+ // read-your-writes: ~2s end to end against the deployed namespace, against the
1491
+ // 20-41s a replacement could take. So this bounds how long a brand-new name
1492
+ // takes to register, never how long an old edition takes to stop answering —
1493
+ // there is no old edition. It is short for that reason, and a script that
1494
+ // answers with the wrong edition now fails outright instead of being waited on.
1495
+ const CUSTOM_CODE_REGISTER_TIMEOUT_MS = 8_000;
1496
+ const CUSTOM_CODE_REGISTER_INTERVAL_MS = 500;
1497
+
1454
1498
  const CUSTOM_CODE_SCRIPT_CPU_MS = 5_000;
1455
1499
 
1456
1500
  // The ctx.log() caps also live in ./sdkConstants — the buffer that enforces them
@@ -1623,6 +1667,21 @@ const OAUTH_SCOPES_SUPPORTED = ['openid', 'profile', 'email', 'offline_access'];
1623
1667
  const MCP_SCOPE_READ = 'mcp:read';
1624
1668
  const ARTIFACT_SCOPE_PREFIX = 'artifact:';
1625
1669
 
1670
+ // `CONTROL_PLANE_SCOPE` (defined in ./cliConstants, re-exported below) is what
1671
+ // a bearer token needs before it may act as the user on the control plane —
1672
+ // publish code, read and rotate secrets, change billing.
1673
+ //
1674
+ // Access tokens are minted for MCP clients too: a customer who connects Claude
1675
+ // Desktop to one of their MCP servers hands it a token for their own account,
1676
+ // and `/oauth2/userinfo` will happily confirm that it is theirs. Without a scope
1677
+ // that separates the two, "this token belongs to the user" would be the same
1678
+ // sentence as "this token may deploy code as the user", and connecting an MCP
1679
+ // client would silently be an act of full delegation.
1680
+ //
1681
+ // Deliberately outside OAUTH_SCOPES_SUPPORTED: it is allowlisted on the provider
1682
+ // so the CLI can request it, and left out of discovery, which is what an MCP
1683
+ // client reads to decide what to ask for.
1684
+
1626
1685
  // The CLI signs in as a public OAuth client through a loopback redirect
1627
1686
  // (RFC 8252) — the flow `wrangler`, `gh` and `vercel` all use. It registers
1628
1687
  // itself through RFC 7591 dynamic registration on first login rather than
@@ -2438,6 +2497,10 @@ export const constants = {
2438
2497
  CUSTOM_CODE_MAX_FILE_PATH,
2439
2498
  CUSTOM_CODE_VERSION_STATUSES,
2440
2499
  CUSTOM_CODE_SCRIPT_NAME_PREFIX,
2500
+ CUSTOM_CODE_SCRIPT_NAME_MAX,
2501
+ CUSTOM_CODE_UPLOAD_SUFFIX_CHARS,
2502
+ CUSTOM_CODE_SWEEP_GRACE_MS,
2503
+ CUSTOM_CODE_SWEEP_MAX_DELETES,
2441
2504
  CUSTOM_CODE_PREVIEW_SCRIPT_SUFFIX,
2442
2505
  CUSTOM_CODE_PREVIEW_TOKEN_TTL_MS,
2443
2506
  CUSTOM_CODE_TEST_TIMEOUT_MS,
@@ -2458,6 +2521,7 @@ export const constants = {
2458
2521
  OUTPUT_SCHEMA_NOT_OBJECT_MESSAGE,
2459
2522
  CUSTOM_CODE_BINDING_TOKEN,
2460
2523
  CUSTOM_CODE_BINDING_BROKER,
2524
+ CUSTOM_CODE_BINDING_VERSION,
2461
2525
  CUSTOM_CODE_BROKER_ORIGIN,
2462
2526
  CUSTOM_CODE_BROKER_PATH_CONNECTION,
2463
2527
  CUSTOM_CODE_BROKER_PATH_SECRET,
@@ -2478,6 +2542,8 @@ export const constants = {
2478
2542
  CUSTOM_CODE_BROKER_SERVICE_ENV,
2479
2543
  CUSTOM_CODE_COMPATIBILITY_DATE,
2480
2544
  CUSTOM_CODE_SCRIPT_CPU_MS,
2545
+ CUSTOM_CODE_REGISTER_TIMEOUT_MS,
2546
+ CUSTOM_CODE_REGISTER_INTERVAL_MS,
2481
2547
  CUSTOM_CODE_MAX_LOGS,
2482
2548
  CUSTOM_CODE_MAX_LOG_LENGTH,
2483
2549
  CUSTOM_CODE_SEND_FILE_TARGET_GMAIL,
@@ -2524,6 +2590,7 @@ export const constants = {
2524
2590
  OAUTH_SCOPES_SUPPORTED,
2525
2591
  MCP_SCOPE_READ,
2526
2592
  ARTIFACT_SCOPE_PREFIX,
2593
+ CONTROL_PLANE_SCOPE,
2527
2594
  CLI_OAUTH_CLIENT_NAME,
2528
2595
  CLI_OAUTH_REDIRECT_PATH,
2529
2596
  CLI_OAUTH_REDIRECT_PORTS,
@@ -179,20 +179,100 @@ export const verifyCustomCodeToken = async (
179
179
  };
180
180
 
181
181
  /**
182
- * The dispatch-namespace script name for an artifact: `artifact_<id>`.
182
+ * The legacy dispatch-namespace script name for an artifact: `artifact_<id>`.
183
183
  *
184
184
  * The id, never the slug — slugs are user-editable and a rename would orphan the
185
185
  * deployed script while the database still pointed at a live version.
186
+ *
187
+ * Nothing uploads to this name any more; every deploy mints its own. It survives
188
+ * as the fallback for a version published before `script_name` existed, whose
189
+ * bundle really is sitting under this name. Tightening a rule must never stop an
190
+ * already-published version from serving, because that failure is invisible to
191
+ * whoever owns it — the same reason the boot loop still accepts a stored tool key
192
+ * the current catalog no longer offers.
186
193
  */
187
194
  export const customCodeScriptName = (artifactId: string): string =>
188
195
  `${constants.CUSTOM_CODE_SCRIPT_NAME_PREFIX}${artifactId}`;
189
196
 
190
197
  /**
191
- * The script name a test run deploys into: `artifact_<id>_preview`.
198
+ * The legacy preview script name: `artifact_<id>_preview`.
192
199
  *
193
- * A second script rather than a second version of the live one, because a test
194
- * must not be able to disturb what MCP clients are being served and the only
195
- * way to be certain of that is for it to run under a name nothing dispatches to.
200
+ * Kept for the same reason as the one above, and for one more: it is the prefix
201
+ * the sweep matches to recognise a preview script left behind by a test run that
202
+ * did not clean up after itself.
196
203
  */
197
204
  export const customCodePreviewScriptName = (artifactId: string): string =>
198
205
  `${customCodeScriptName(artifactId)}${constants.CUSTOM_CODE_PREVIEW_SCRIPT_SUFFIX}`;
206
+
207
+ /**
208
+ * A dispatch-namespace name no upload has ever used:
209
+ * `artifact_<id>_<12 hex chars>`.
210
+ *
211
+ * Minted rather than derived, and that is the entire design. Uploading over an
212
+ * existing name is not read-your-writes — a replacement can serve the previous
213
+ * edition for tens of seconds — so a deploy that always writes to a new name is
214
+ * correct by construction rather than by waiting to see whether it worked.
215
+ *
216
+ * The suffix deliberately carries no meaning. The two candidates that did are
217
+ * both wrong: the bundle digest collides whenever a deploy reverts to bytes that
218
+ * shipped before, which is exactly what a rollback is, and the version id is one
219
+ * string across every re-upload of a single draft, which is every test run of it.
220
+ *
221
+ * Twelve hex characters is what fits. Worker names cap at 63 and
222
+ * `artifact_<uuid>` spends 45 of them.
223
+ */
224
+ export const customCodeUploadName = (artifactId: string): string =>
225
+ mintUploadName(customCodeScriptName(artifactId));
226
+
227
+ /**
228
+ * A preview name no test run has ever used:
229
+ * `artifact_<id>_preview_<12 hex chars>`.
230
+ *
231
+ * The sharper version of the same race. Every test used to deploy over one
232
+ * preview name, so a test could report the run before it — which reads as "my
233
+ * edit did nothing" from the one tool whose whole job is to say what an edit
234
+ * does. Nothing stores this: it is minted, used, and deleted inside one request.
235
+ */
236
+ export const customCodePreviewUploadName = (artifactId: string): string =>
237
+ mintUploadName(customCodePreviewScriptName(artifactId));
238
+
239
+ /**
240
+ * Append `_<hex>` to a base name, spending whatever the 63-character ceiling
241
+ * leaves and no more.
242
+ *
243
+ * The budget is genuinely tight, and the two names spend it differently:
244
+ *
245
+ * | name | base | separator | suffix | total |
246
+ * |---|---|---|---|---|
247
+ * | live | `artifact_<uuid>` = 45 | 1 | 12 | 58 |
248
+ * | preview | + `_preview` = 53 | 1 | 8 | 62 |
249
+ *
250
+ * Twelve hex characters is 48 bits and eight is 32, against a namespace holding
251
+ * a few hundred names for any one artifact — and a preview name lives for the
252
+ * seconds one test run takes. Neither is a collision worth checking for, and an
253
+ * upload to a name already in use fails loudly rather than quietly serving the
254
+ * wrong code, which is the failure that matters.
255
+ *
256
+ * The ceiling is asserted rather than assumed: it is one number away from being
257
+ * silently exceeded by a longer prefix, and a name Cloudflare refuses would
258
+ * surface as a failed publish with nothing explaining why.
259
+ */
260
+ const mintUploadName = (base: string): string => {
261
+ const available = constants.CUSTOM_CODE_SCRIPT_NAME_MAX - base.length - 1;
262
+ // Even, because each byte renders as two hex characters.
263
+ const chars =
264
+ Math.min(constants.CUSTOM_CODE_UPLOAD_SUFFIX_CHARS, available) & ~1;
265
+
266
+ if (chars < 4) {
267
+ throw new Error(
268
+ `A dispatch script name based on "${base}" leaves no room for a unique suffix.`
269
+ );
270
+ }
271
+
272
+ const bytes = new Uint8Array(chars / 2);
273
+ crypto.getRandomValues(bytes);
274
+
275
+ return `${base}_${Array.from(bytes)
276
+ .map(byte => byte.toString(16).padStart(2, '0'))
277
+ .join('')}`;
278
+ };
package/src/index.ts CHANGED
@@ -102,7 +102,9 @@ import {
102
102
  mintCustomCodeToken,
103
103
  verifyCustomCodeToken,
104
104
  customCodeScriptName,
105
- customCodePreviewScriptName
105
+ customCodePreviewScriptName,
106
+ customCodeUploadName,
107
+ customCodePreviewUploadName
106
108
  } from './customCodeToken';
107
109
  import type { CustomCodeTokenPayload } from './customCodeToken';
108
110
  import { oauthProviders } from './oauthProviders';
@@ -257,6 +259,8 @@ export const utils = {
257
259
  verifyCustomCodeToken,
258
260
  customCodeScriptName,
259
261
  customCodePreviewScriptName,
262
+ customCodeUploadName,
263
+ customCodePreviewUploadName,
260
264
  oauthProviders,
261
265
  resolveAttachment,
262
266
  isExposedResource,
@@ -30,6 +30,18 @@ export const CUSTOM_CODE_BROKER_PATH_RESOURCES_CREATE = '/resources/create';
30
30
  export const CUSTOM_CODE_BROKER_PATH_RESOURCES_DELETE = '/resources/delete';
31
31
  export const CUSTOM_CODE_BROKER_PATH_SEND_FILE = '/send-file';
32
32
 
33
+ // Injected at upload time and echoed back by the health probe below. Uploading a
34
+ // script into the dispatch namespace is not read-your-writes: dispatching to the
35
+ // name immediately afterwards can still reach the previous edition. Tool names
36
+ // alone cannot tell the two apart when a deploy does not rename anything, so the
37
+ // script carries the digest of the bytes it was uploaded from and the publish
38
+ // pipeline waits until the edition answering is the one it just wrote.
39
+ //
40
+ // The bytes rather than the version id: a draft is re-uploaded in place, so its
41
+ // id is the same string across every edit and could never separate this upload
42
+ // from the one before it.
43
+ export const CUSTOM_CODE_BINDING_VERSION = 'GANJU_SCRIPT_VERSION';
44
+
33
45
  // The reserved tool name the publish pipeline calls against a freshly uploaded
34
46
  // script to ask which tools it actually exports — which is what turns "the
35
47
  // manifest declares lookup-order but the code exports lookupOrder" from a