@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.
- package/dist/cliConstants.d.ts +1 -0
- package/dist/cliConstants.d.ts.map +1 -1
- package/dist/cliConstants.js +15 -2
- package/dist/constants.d.ts +8 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +62 -2
- package/dist/customCodeToken.d.ts +40 -5
- package/dist/customCodeToken.d.ts.map +1 -1
- package/dist/customCodeToken.js +77 -6
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/sdkConstants.d.ts +1 -0
- package/dist/sdkConstants.d.ts.map +1 -1
- package/dist/sdkConstants.js +12 -1
- package/package.json +1 -1
- package/src/cliConstants.ts +15 -1
- package/src/constants.ts +69 -2
- package/src/customCodeToken.ts +85 -5
- package/src/index.ts +5 -1
- package/src/sdkConstants.ts +12 -0
package/dist/cliConstants.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/cliConstants.js
CHANGED
|
@@ -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.
|
package/dist/constants.d.ts
CHANGED
|
@@ -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[];
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"
|
|
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 —
|
|
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
|
|
41
|
+
* The legacy preview script name: `artifact_<id>_preview`.
|
|
35
42
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
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
|
|
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"}
|
package/dist/customCodeToken.js
CHANGED
|
@@ -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
|
|
115
|
+
* The legacy preview script name: `artifact_<id>_preview`.
|
|
109
116
|
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
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;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,sBAAsB,EACtB,kBAAkB,EAClB,sBAAsB,EACtB,0BAA0B,EAC1B,wBAAwB,EACxB,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,EAClB,wBAAwB,EACzB,MAAM,UAAU,CAAC;AAElB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAyCvD,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,iCAAiC,EAClC,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EACV,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,8BAA8B,EAC/B,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EACnB,gCAAgC,EACjC,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,iCAAiC,EAClC,MAAM,gBAAgB,CAAC;AAKxB,OAAO,EACL,UAAU,EAGX,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,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,
|
package/dist/sdkConstants.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/sdkConstants.js
CHANGED
|
@@ -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
package/src/cliConstants.ts
CHANGED
|
@@ -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 —
|
|
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,
|
package/src/customCodeToken.ts
CHANGED
|
@@ -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
|
|
198
|
+
* The legacy preview script name: `artifact_<id>_preview`.
|
|
192
199
|
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
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,
|
package/src/sdkConstants.ts
CHANGED
|
@@ -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
|