@dreamboard-games/cli 0.1.30-alpha.29 → 0.1.30-alpha.30
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/README.md +2 -1
- package/dist/agent-verifier/agent-workspace-verifier.mjs +360 -17
- package/dist/agent-verifier/agent-workspace-verifier.mjs.map +1 -1
- package/dist/agent-verifier/{chunk-IWB4L2HV.mjs → chunk-FNSHNMDY.mjs} +51 -5
- package/dist/agent-verifier/chunk-FNSHNMDY.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-RDYXWXXC.mjs → chunk-LMW66VBH.mjs} +2 -11
- package/dist/agent-verifier/{chunk-RDYXWXXC.mjs.map → chunk-LMW66VBH.mjs.map} +1 -1
- package/dist/agent-verifier/{chunk-TIDX3YLW.mjs → chunk-M6YNQZCC.mjs} +2 -2
- package/dist/agent-verifier/{chunk-Z7UBAREF.mjs → chunk-QMOBTQ5G.mjs} +7 -9
- package/dist/agent-verifier/chunk-QMOBTQ5G.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-F2DIOJJZ.mjs → chunk-XCQQIPCO.mjs} +5 -46
- package/dist/agent-verifier/chunk-XCQQIPCO.mjs.map +1 -0
- package/dist/agent-verifier/{global-config-IXZLY4BS.mjs → global-config-SWWR2LP4.mjs} +3 -4
- package/dist/agent-verifier/{materialize-workspace-XYYCQQGB.mjs → materialize-workspace-K4WYFG5E.mjs} +5 -5
- package/dist/agent-verifier/{reducer-native-test-harness-BY5SZ7XE.mjs → reducer-native-test-harness-UFMSNNDY.mjs} +49 -576
- package/dist/agent-verifier/reducer-native-test-harness-UFMSNNDY.mjs.map +1 -0
- package/dist/agent-verifier/{static-scaffold-M7QPX76Z.mjs → static-scaffold-MHVM63HU.mjs} +4 -4
- package/dist/authoring-compatibility-internal.js +1 -1
- package/dist/{chunk-QIVDPQME.js → chunk-I4SZ7FA4.js} +9 -64
- package/dist/{chunk-QIVDPQME.js.map → chunk-I4SZ7FA4.js.map} +1 -1
- package/dist/{chunk-NFCRMXEV.js → chunk-RTNKVNQA.js} +52 -624
- package/dist/chunk-RTNKVNQA.js.map +1 -0
- package/dist/index.js +318 -369
- package/dist/index.js.map +1 -1
- package/dist/internal.js +23 -3
- package/dist/internal.js.map +1 -1
- package/package.json +1 -1
- package/release/authoring-release-set.json +2 -2
- package/skills/dreamboard/SKILL.md +1 -1
- package/skills/dreamboard/references/cli.md +2 -3
- package/skills/dreamboard/references/quickstart.md +1 -1
- package/skills/dreamboard/references/testing.md +0 -7
- package/dist/agent-verifier/chunk-B7M2TJSP.mjs +0 -363
- package/dist/agent-verifier/chunk-B7M2TJSP.mjs.map +0 -1
- package/dist/agent-verifier/chunk-F2DIOJJZ.mjs.map +0 -1
- package/dist/agent-verifier/chunk-IWB4L2HV.mjs.map +0 -1
- package/dist/agent-verifier/chunk-UXGTT25Q.mjs +0 -59
- package/dist/agent-verifier/chunk-UXGTT25Q.mjs.map +0 -1
- package/dist/agent-verifier/chunk-Z7UBAREF.mjs.map +0 -1
- package/dist/agent-verifier/reducer-native-test-harness-BY5SZ7XE.mjs.map +0 -1
- package/dist/chunk-NFCRMXEV.js.map +0 -1
- /package/dist/agent-verifier/{chunk-TIDX3YLW.mjs.map → chunk-M6YNQZCC.mjs.map} +0 -0
- /package/dist/agent-verifier/{global-config-IXZLY4BS.mjs.map → global-config-SWWR2LP4.mjs.map} +0 -0
- /package/dist/agent-verifier/{materialize-workspace-XYYCQQGB.mjs.map → materialize-workspace-K4WYFG5E.mjs.map} +0 -0
- /package/dist/agent-verifier/{static-scaffold-M7QPX76Z.mjs.map → static-scaffold-MHVM63HU.mjs.map} +0 -0
package/README.md
CHANGED
|
@@ -112,7 +112,8 @@ dreamboard dev
|
|
|
112
112
|
## Notes
|
|
113
113
|
|
|
114
114
|
- Project state lives in `.dreamboard/project.json`.
|
|
115
|
-
- Published/public CLI installs target Node 20+ and support
|
|
115
|
+
- Published/public CLI installs target Node 20+ and support commit-scoped
|
|
116
|
+
build, preview, release, and status workflows.
|
|
116
117
|
- Published/public CLI builds are production-only; they do not support environment overrides or direct JWT injection.
|
|
117
118
|
- Local embedded-harness testing remains Bun-only and requires a source checkout with local backend support.
|
|
118
119
|
- Internal source-checkout builds may expose extra auth and environment helpers, but those are not part of the published CLI contract.
|
|
@@ -2,24 +2,18 @@
|
|
|
2
2
|
import {
|
|
3
3
|
findProjectRoot,
|
|
4
4
|
loadProjectConfig
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-M6YNQZCC.mjs";
|
|
6
6
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import {
|
|
13
|
-
loadGlobalConfig
|
|
14
|
-
} from "./chunk-UXGTT25Q.mjs";
|
|
15
|
-
import {
|
|
16
|
-
getStoredSession
|
|
17
|
-
} from "./chunk-IWB4L2HV.mjs";
|
|
7
|
+
clearCredentials,
|
|
8
|
+
getStoredSession,
|
|
9
|
+
loadGlobalConfig,
|
|
10
|
+
withCredentialLock
|
|
11
|
+
} from "./chunk-FNSHNMDY.mjs";
|
|
18
12
|
import "./chunk-GWRZRWCF.mjs";
|
|
19
13
|
import {
|
|
20
14
|
readJsonFile,
|
|
21
15
|
readTextFileIfExists
|
|
22
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-LMW66VBH.mjs";
|
|
23
17
|
import {
|
|
24
18
|
client
|
|
25
19
|
} from "./chunk-MYMVXTZT.mjs";
|
|
@@ -1134,6 +1128,356 @@ function _getDefaultLogLevel() {
|
|
|
1134
1128
|
}
|
|
1135
1129
|
var consola = createConsola2();
|
|
1136
1130
|
|
|
1131
|
+
// src/build-target.ts
|
|
1132
|
+
var injectedBuildChannel = true ? "development" : void 0;
|
|
1133
|
+
var BUILD_CHANNEL = injectedBuildChannel === "published" ? "published" : "development";
|
|
1134
|
+
var IS_PUBLISHED_BUILD = BUILD_CHANNEL === "published";
|
|
1135
|
+
var PUBLISHED_ENVIRONMENT = "prod";
|
|
1136
|
+
|
|
1137
|
+
// src/auth/clerk-oauth.ts
|
|
1138
|
+
import crypto from "crypto";
|
|
1139
|
+
async function refreshClerkOAuthToken(input) {
|
|
1140
|
+
const { clientId, tokenUrl } = assertConfigured(input.config);
|
|
1141
|
+
const body = new URLSearchParams({
|
|
1142
|
+
grant_type: "refresh_token",
|
|
1143
|
+
client_id: clientId,
|
|
1144
|
+
refresh_token: input.refreshToken
|
|
1145
|
+
});
|
|
1146
|
+
return requestClerkToken(tokenUrl, body);
|
|
1147
|
+
}
|
|
1148
|
+
function assertConfigured(config) {
|
|
1149
|
+
const issuer = config.issuer?.trim().replace(/\/$/, "");
|
|
1150
|
+
const clientId = config.clientId?.trim();
|
|
1151
|
+
if (!issuer || !clientId) {
|
|
1152
|
+
throw new Error(
|
|
1153
|
+
[
|
|
1154
|
+
"Clerk OAuth CLI is not configured for this environment.",
|
|
1155
|
+
"The CLI expects first-party environments to be configured in its built-in registry.",
|
|
1156
|
+
"If this environment has no registered public Clerk OAuth client, create one and release a CLI with its client id.",
|
|
1157
|
+
"For emergency overrides, set the environment-specific DREAMBOARD_<ENV>_CLERK_OAUTH_* variables or DREAMBOARD_CLERK_OAUTH_*.",
|
|
1158
|
+
"For local harness auth, use `pnpm auth:local` or the auto-bootstrapped local harness flows instead."
|
|
1159
|
+
].join(" ")
|
|
1160
|
+
);
|
|
1161
|
+
}
|
|
1162
|
+
return {
|
|
1163
|
+
issuer,
|
|
1164
|
+
clientId,
|
|
1165
|
+
tokenUrl: config.tokenUrl?.trim() || new URL("/oauth/token", issuer).toString(),
|
|
1166
|
+
scope: config.scope?.trim() || void 0
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
1169
|
+
async function requestClerkToken(tokenUrl, body) {
|
|
1170
|
+
const response = await fetch(tokenUrl, {
|
|
1171
|
+
method: "POST",
|
|
1172
|
+
headers: {
|
|
1173
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
1174
|
+
Accept: "application/json"
|
|
1175
|
+
},
|
|
1176
|
+
body
|
|
1177
|
+
});
|
|
1178
|
+
if (!response.ok) {
|
|
1179
|
+
const detail = await response.text();
|
|
1180
|
+
throw new Error(
|
|
1181
|
+
`Clerk OAuth token request failed (${response.status}): ${detail}`
|
|
1182
|
+
);
|
|
1183
|
+
}
|
|
1184
|
+
const payload = await response.json();
|
|
1185
|
+
if (typeof payload.access_token !== "string") {
|
|
1186
|
+
throw new Error("Clerk OAuth token response did not include access_token.");
|
|
1187
|
+
}
|
|
1188
|
+
if (typeof payload.refresh_token !== "string") {
|
|
1189
|
+
throw new Error(
|
|
1190
|
+
"Clerk OAuth token response did not include refresh_token."
|
|
1191
|
+
);
|
|
1192
|
+
}
|
|
1193
|
+
const expiresAt = typeof payload.expires_in === "number" ? new Date(Date.now() + payload.expires_in * 1e3).toISOString() : void 0;
|
|
1194
|
+
return {
|
|
1195
|
+
accessToken: payload.access_token,
|
|
1196
|
+
refreshToken: payload.refresh_token,
|
|
1197
|
+
expiresAt,
|
|
1198
|
+
tokenUrl
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
// src/auth/token-exchange.ts
|
|
1203
|
+
async function exchangeDreamboardUserToken(input) {
|
|
1204
|
+
const fetchImpl = input.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
1205
|
+
const response = await fetchImpl(
|
|
1206
|
+
new URL("/api/auth/token-exchange", input.apiBaseUrl),
|
|
1207
|
+
{
|
|
1208
|
+
method: "POST",
|
|
1209
|
+
headers: {
|
|
1210
|
+
Authorization: `Bearer ${input.clerkAccessToken}`,
|
|
1211
|
+
"Content-Type": "application/json",
|
|
1212
|
+
Accept: "application/json"
|
|
1213
|
+
},
|
|
1214
|
+
body: JSON.stringify({ audience: input.audience })
|
|
1215
|
+
}
|
|
1216
|
+
);
|
|
1217
|
+
if (!response.ok) {
|
|
1218
|
+
throw new Error(
|
|
1219
|
+
`Dreamboard token exchange failed (${response.status}). Run \`dreamboard auth login\` to authenticate again.`
|
|
1220
|
+
);
|
|
1221
|
+
}
|
|
1222
|
+
const payload = await response.json();
|
|
1223
|
+
if (typeof payload.accessToken !== "string" || payload.accessToken === "") {
|
|
1224
|
+
throw new Error("Dreamboard token exchange response omitted accessToken.");
|
|
1225
|
+
}
|
|
1226
|
+
if (payload.tokenType !== "Bearer") {
|
|
1227
|
+
throw new Error(
|
|
1228
|
+
"Dreamboard token exchange response had invalid tokenType."
|
|
1229
|
+
);
|
|
1230
|
+
}
|
|
1231
|
+
if (payload.audience !== input.audience) {
|
|
1232
|
+
throw new Error("Dreamboard token exchange response had wrong audience.");
|
|
1233
|
+
}
|
|
1234
|
+
const expiresIn = typeof payload.expiresIn === "number" && Number.isFinite(payload.expiresIn) ? payload.expiresIn : void 0;
|
|
1235
|
+
return {
|
|
1236
|
+
accessToken: payload.accessToken,
|
|
1237
|
+
tokenType: "Bearer",
|
|
1238
|
+
audience: input.audience,
|
|
1239
|
+
expiresIn,
|
|
1240
|
+
expiresAt: expiresIn === void 0 ? void 0 : new Date(Date.now() + expiresIn * 1e3).toISOString()
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
// src/auth/user-token-manager.ts
|
|
1245
|
+
var TOKEN_REFRESH_WINDOW_MS = 60 * 1e3;
|
|
1246
|
+
function createUserTokenManager(config) {
|
|
1247
|
+
return {
|
|
1248
|
+
async resolveApiToken() {
|
|
1249
|
+
const localOrInjected = resolveNonStoredToken(config, "dreamboard-api");
|
|
1250
|
+
if (localOrInjected) return localOrInjected;
|
|
1251
|
+
if (!usesStoredSession(config)) return null;
|
|
1252
|
+
return withCredentialLock(async (ops) => {
|
|
1253
|
+
const stored = await ops.read();
|
|
1254
|
+
const apiToken = freshStoredApiToken(stored);
|
|
1255
|
+
if (apiToken) return apiToken;
|
|
1256
|
+
const clerk = await resolveFreshClerkAccessToken(config, stored);
|
|
1257
|
+
const exchanged = await exchangeDreamboardUserToken({
|
|
1258
|
+
apiBaseUrl: config.apiBaseUrl,
|
|
1259
|
+
clerkAccessToken: clerk.accessToken,
|
|
1260
|
+
audience: "dreamboard-api"
|
|
1261
|
+
});
|
|
1262
|
+
await ops.writeFull({
|
|
1263
|
+
...clerk,
|
|
1264
|
+
dreamboardApiToken: exchanged.accessToken,
|
|
1265
|
+
dreamboardApiExpiresAt: exchanged.expiresAt
|
|
1266
|
+
});
|
|
1267
|
+
return {
|
|
1268
|
+
token: exchanged.accessToken,
|
|
1269
|
+
expiresAt: exchanged.expiresAt,
|
|
1270
|
+
audience: "dreamboard-api"
|
|
1271
|
+
};
|
|
1272
|
+
});
|
|
1273
|
+
},
|
|
1274
|
+
async resolveGitToken() {
|
|
1275
|
+
if (!usesStoredSession(config) && config.authToken) {
|
|
1276
|
+
const exchanged = await exchangeDreamboardUserToken({
|
|
1277
|
+
apiBaseUrl: config.apiBaseUrl,
|
|
1278
|
+
clerkAccessToken: config.authToken,
|
|
1279
|
+
audience: "dreamboard-git"
|
|
1280
|
+
});
|
|
1281
|
+
return {
|
|
1282
|
+
token: exchanged.accessToken,
|
|
1283
|
+
expiresAt: exchanged.expiresAt,
|
|
1284
|
+
audience: "dreamboard-git"
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
1287
|
+
if (!usesStoredSession(config)) {
|
|
1288
|
+
throw new Error(
|
|
1289
|
+
"Missing Dreamboard session. Run `dreamboard auth login` to authenticate."
|
|
1290
|
+
);
|
|
1291
|
+
}
|
|
1292
|
+
return withCredentialLock(async (ops) => {
|
|
1293
|
+
const stored = await ops.read();
|
|
1294
|
+
const clerk = await resolveFreshClerkAccessToken(config, stored);
|
|
1295
|
+
const exchanged = await exchangeDreamboardUserToken({
|
|
1296
|
+
apiBaseUrl: config.apiBaseUrl,
|
|
1297
|
+
clerkAccessToken: clerk.accessToken,
|
|
1298
|
+
audience: "dreamboard-git"
|
|
1299
|
+
});
|
|
1300
|
+
await ops.writeFull(clerk);
|
|
1301
|
+
return {
|
|
1302
|
+
token: exchanged.accessToken,
|
|
1303
|
+
expiresAt: exchanged.expiresAt,
|
|
1304
|
+
audience: "dreamboard-git"
|
|
1305
|
+
};
|
|
1306
|
+
});
|
|
1307
|
+
},
|
|
1308
|
+
async logout() {
|
|
1309
|
+
await clearCredentials("user_token_manager_logout");
|
|
1310
|
+
}
|
|
1311
|
+
};
|
|
1312
|
+
}
|
|
1313
|
+
function resolveNonStoredToken(config, audience) {
|
|
1314
|
+
if (usesStoredSession(config)) return null;
|
|
1315
|
+
if (!config.authToken) return null;
|
|
1316
|
+
return {
|
|
1317
|
+
token: config.authToken,
|
|
1318
|
+
expiresAt: config.tokenExpiresAt,
|
|
1319
|
+
audience
|
|
1320
|
+
};
|
|
1321
|
+
}
|
|
1322
|
+
function freshStoredApiToken(stored) {
|
|
1323
|
+
if (!stored?.dreamboardApiToken) return null;
|
|
1324
|
+
if (isFresh(stored.dreamboardApiExpiresAt, stored.dreamboardApiToken)) {
|
|
1325
|
+
return {
|
|
1326
|
+
token: stored.dreamboardApiToken,
|
|
1327
|
+
expiresAt: stored.dreamboardApiExpiresAt,
|
|
1328
|
+
audience: "dreamboard-api"
|
|
1329
|
+
};
|
|
1330
|
+
}
|
|
1331
|
+
return null;
|
|
1332
|
+
}
|
|
1333
|
+
async function resolveFreshClerkAccessToken(config, stored) {
|
|
1334
|
+
const accessToken = stored?.accessToken ?? config.clerkAccessToken;
|
|
1335
|
+
const refreshToken = stored?.refreshToken ?? config.refreshToken;
|
|
1336
|
+
const tokenExpiresAt = stored?.tokenExpiresAt ?? config.clerkAccessExpiresAt;
|
|
1337
|
+
if (!refreshToken) {
|
|
1338
|
+
throw new Error(
|
|
1339
|
+
"Stored Dreamboard session is missing its refresh token. Run `dreamboard auth login` to authenticate again."
|
|
1340
|
+
);
|
|
1341
|
+
}
|
|
1342
|
+
if (accessToken && isFresh(tokenExpiresAt, accessToken)) {
|
|
1343
|
+
return {
|
|
1344
|
+
accessToken,
|
|
1345
|
+
refreshToken,
|
|
1346
|
+
tokenExpiresAt,
|
|
1347
|
+
dreamboardApiToken: stored?.dreamboardApiToken,
|
|
1348
|
+
dreamboardApiExpiresAt: stored?.dreamboardApiExpiresAt,
|
|
1349
|
+
clerkOAuthIssuer: stored?.clerkOAuthIssuer ?? config.clerkOAuthIssuer,
|
|
1350
|
+
clerkOAuthClientId: stored?.clerkOAuthClientId ?? config.clerkOAuthClientId,
|
|
1351
|
+
clerkOAuthTokenUrl: stored?.clerkOAuthTokenUrl ?? config.clerkOAuthTokenUrl,
|
|
1352
|
+
environment: stored?.environment ?? config.environment
|
|
1353
|
+
};
|
|
1354
|
+
}
|
|
1355
|
+
const payload = await refreshClerkOAuthToken({
|
|
1356
|
+
config: {
|
|
1357
|
+
issuer: stored?.clerkOAuthIssuer ?? config.clerkOAuthIssuer,
|
|
1358
|
+
clientId: stored?.clerkOAuthClientId ?? config.clerkOAuthClientId,
|
|
1359
|
+
tokenUrl: stored?.clerkOAuthTokenUrl ?? config.clerkOAuthTokenUrl
|
|
1360
|
+
},
|
|
1361
|
+
refreshToken
|
|
1362
|
+
});
|
|
1363
|
+
return {
|
|
1364
|
+
accessToken: payload.accessToken,
|
|
1365
|
+
refreshToken: payload.refreshToken,
|
|
1366
|
+
tokenExpiresAt: payload.expiresAt,
|
|
1367
|
+
clerkOAuthIssuer: stored?.clerkOAuthIssuer ?? config.clerkOAuthIssuer,
|
|
1368
|
+
clerkOAuthClientId: stored?.clerkOAuthClientId ?? config.clerkOAuthClientId,
|
|
1369
|
+
clerkOAuthTokenUrl: payload.tokenUrl,
|
|
1370
|
+
environment: stored?.environment ?? config.environment
|
|
1371
|
+
};
|
|
1372
|
+
}
|
|
1373
|
+
function isFresh(expiresAt, token) {
|
|
1374
|
+
const expiry = expiresAt ? new Date(expiresAt) : getJwtExpiry(token);
|
|
1375
|
+
return expiry !== null && Number.isFinite(expiry.getTime()) && expiry.getTime() > Date.now() + TOKEN_REFRESH_WINDOW_MS;
|
|
1376
|
+
}
|
|
1377
|
+
function getJwtExpiry(accessToken) {
|
|
1378
|
+
if (!accessToken) return null;
|
|
1379
|
+
const parts = accessToken.split(".");
|
|
1380
|
+
if (parts.length !== 3) return null;
|
|
1381
|
+
try {
|
|
1382
|
+
const payload = JSON.parse(
|
|
1383
|
+
Buffer.from(parts[1], "base64url").toString("utf8")
|
|
1384
|
+
);
|
|
1385
|
+
if (typeof payload.exp !== "number" || !Number.isFinite(payload.exp)) {
|
|
1386
|
+
return null;
|
|
1387
|
+
}
|
|
1388
|
+
return new Date(payload.exp * 1e3);
|
|
1389
|
+
} catch {
|
|
1390
|
+
return null;
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
function usesStoredSession(config) {
|
|
1394
|
+
return config.refreshTokenSource === "global";
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
// src/config/local-harness-auth.ts
|
|
1398
|
+
import { createHmac, randomUUID } from "crypto";
|
|
1399
|
+
var DEFAULT_SUBJECT = "harness-smoke-local@dreamboard.local";
|
|
1400
|
+
var DEFAULT_ISSUER = "dreamboard-local-harness";
|
|
1401
|
+
var DEFAULT_SECRET = "dreamboard-local-harness-token-secret";
|
|
1402
|
+
var LOCAL_AWS_ISSUER = "dreamboard-local-aws-harness";
|
|
1403
|
+
var LOCAL_AWS_SECRET = "dreamboard-local-aws-harness-token-secret";
|
|
1404
|
+
var DEFAULT_TTL_SECONDS = 8 * 60 * 60;
|
|
1405
|
+
var mintedTokens = /* @__PURE__ */ new Map();
|
|
1406
|
+
function resolveLocalHarnessAccessToken(config) {
|
|
1407
|
+
if (IS_PUBLISHED_BUILD || config.environment !== "local") {
|
|
1408
|
+
return void 0;
|
|
1409
|
+
}
|
|
1410
|
+
const profile = inferLocalHarnessProfile(config);
|
|
1411
|
+
if (config.authToken && (profile !== "local-aws" || isExplicitTokenSource(config.authTokenSource))) {
|
|
1412
|
+
return void 0;
|
|
1413
|
+
}
|
|
1414
|
+
const cacheKey = [
|
|
1415
|
+
profile,
|
|
1416
|
+
process.env.LOCAL_HARNESS_TOKEN_ISSUER ?? "",
|
|
1417
|
+
process.env.LOCAL_HARNESS_TOKEN_SECRET ?? "",
|
|
1418
|
+
process.env.LOCAL_HARNESS_SUBJECT ?? "",
|
|
1419
|
+
process.env.HARNESS_USER_EMAIL ?? "",
|
|
1420
|
+
process.env.LOCAL_HARNESS_EMAIL ?? "",
|
|
1421
|
+
process.env.LOCAL_HARNESS_TOKEN_TTL_SECONDS ?? ""
|
|
1422
|
+
].join("\0");
|
|
1423
|
+
const cached = mintedTokens.get(cacheKey);
|
|
1424
|
+
if (cached) return cached;
|
|
1425
|
+
const token = mintLocalHarnessToken(profile);
|
|
1426
|
+
mintedTokens.set(cacheKey, token);
|
|
1427
|
+
return token;
|
|
1428
|
+
}
|
|
1429
|
+
function isExplicitTokenSource(source) {
|
|
1430
|
+
return source === "flag" || source === "env" || source === "agent-env";
|
|
1431
|
+
}
|
|
1432
|
+
function inferLocalHarnessProfile(config) {
|
|
1433
|
+
return isLocalAwsUrl(config.apiBaseUrl) || isLocalAwsUrl(config.webBaseUrl) ? "local-aws" : "local";
|
|
1434
|
+
}
|
|
1435
|
+
function mintLocalHarnessToken(profile) {
|
|
1436
|
+
const subject = envValue(process.env.LOCAL_HARNESS_SUBJECT) ?? envValue(process.env.HARNESS_USER_EMAIL) ?? DEFAULT_SUBJECT;
|
|
1437
|
+
const email = envValue(process.env.LOCAL_HARNESS_EMAIL) ?? (subject.includes("@") ? subject : void 0);
|
|
1438
|
+
const issuer = envValue(process.env.LOCAL_HARNESS_TOKEN_ISSUER) ?? (profile === "local-aws" ? LOCAL_AWS_ISSUER : DEFAULT_ISSUER);
|
|
1439
|
+
const secret = envValue(process.env.LOCAL_HARNESS_TOKEN_SECRET) ?? (profile === "local-aws" ? LOCAL_AWS_SECRET : DEFAULT_SECRET);
|
|
1440
|
+
const ttlSeconds = Number(
|
|
1441
|
+
envValue(process.env.LOCAL_HARNESS_TOKEN_TTL_SECONDS) ?? String(DEFAULT_TTL_SECONDS)
|
|
1442
|
+
);
|
|
1443
|
+
if (!Number.isFinite(ttlSeconds) || ttlSeconds <= 0) {
|
|
1444
|
+
throw new Error(
|
|
1445
|
+
"LOCAL_HARNESS_TOKEN_TTL_SECONDS must be a positive number."
|
|
1446
|
+
);
|
|
1447
|
+
}
|
|
1448
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
1449
|
+
const payload = {
|
|
1450
|
+
typ: "local_harness_access",
|
|
1451
|
+
dreamboard_provider: "local-harness",
|
|
1452
|
+
dreamboard_provider_subject: subject,
|
|
1453
|
+
...email ? { email } : {},
|
|
1454
|
+
iss: issuer,
|
|
1455
|
+
sub: subject,
|
|
1456
|
+
iat: now,
|
|
1457
|
+
exp: now + Math.floor(ttlSeconds),
|
|
1458
|
+
jti: randomUUID()
|
|
1459
|
+
};
|
|
1460
|
+
const headerPart = base64UrlJson({ alg: "HS256", typ: "JWT" });
|
|
1461
|
+
const payloadPart = base64UrlJson(payload);
|
|
1462
|
+
const signature = createHmac("sha256", secret).update(`${headerPart}.${payloadPart}`).digest("base64url");
|
|
1463
|
+
return `${headerPart}.${payloadPart}.${signature}`;
|
|
1464
|
+
}
|
|
1465
|
+
function base64UrlJson(value) {
|
|
1466
|
+
return Buffer.from(JSON.stringify(value), "utf8").toString("base64url");
|
|
1467
|
+
}
|
|
1468
|
+
function envValue(raw) {
|
|
1469
|
+
return typeof raw === "string" && raw.trim().length > 0 ? raw.trim() : void 0;
|
|
1470
|
+
}
|
|
1471
|
+
function isLocalAwsUrl(rawUrl) {
|
|
1472
|
+
if (!rawUrl) return false;
|
|
1473
|
+
try {
|
|
1474
|
+
const url = new URL(rawUrl);
|
|
1475
|
+
return (url.hostname === "localhost" || url.hostname === "127.0.0.1") && (url.port === "18080" || url.port === "8088");
|
|
1476
|
+
} catch {
|
|
1477
|
+
return false;
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1137
1481
|
// src/config/resolve.ts
|
|
1138
1482
|
var DEFAULT_REFRESH_WINDOW_MS = 5 * 60 * 1e3;
|
|
1139
1483
|
var TRANSIENT_READ_RETRY_DELAYS_MS = [100, 300];
|
|
@@ -1535,7 +1879,7 @@ Usage:
|
|
|
1535
1879
|
}
|
|
1536
1880
|
async function materializePreparedWorkspace(args) {
|
|
1537
1881
|
const inputPath = readRequiredOption(args, "--input");
|
|
1538
|
-
const { materializeWorkspaceProject } = await import("./materialize-workspace-
|
|
1882
|
+
const { materializeWorkspaceProject } = await import("./materialize-workspace-K4WYFG5E.mjs");
|
|
1539
1883
|
const input = JSON.parse(await readFile(inputPath, "utf8"));
|
|
1540
1884
|
await materializeWorkspaceProject({
|
|
1541
1885
|
...input,
|
|
@@ -1603,7 +1947,7 @@ async function runCloudLocalVerification(projectRoot, projectConfig, config) {
|
|
|
1603
1947
|
{ assertReducerContractPreflight },
|
|
1604
1948
|
{ getProjectLocalMaintainerRegistry }
|
|
1605
1949
|
] = await Promise.all([
|
|
1606
|
-
import("./static-scaffold-
|
|
1950
|
+
import("./static-scaffold-MHVM63HU.mjs"),
|
|
1607
1951
|
import("./local-files-OF4QFISU.mjs"),
|
|
1608
1952
|
import("./workspace-codegen-SPPVHURX.mjs"),
|
|
1609
1953
|
import("./workspace-dependencies-5HEEKZFP.mjs"),
|
|
@@ -1641,7 +1985,7 @@ async function runCloudLocalVerification(projectRoot, projectConfig, config) {
|
|
|
1641
1985
|
generateReducerNativeArtifacts,
|
|
1642
1986
|
isReducerNativeTestingWorkspace,
|
|
1643
1987
|
runReducerNativeScenarios
|
|
1644
|
-
} = await import("./reducer-native-test-harness-
|
|
1988
|
+
} = await import("./reducer-native-test-harness-UFMSNNDY.mjs");
|
|
1645
1989
|
if (await isReducerNativeTestingWorkspace(projectRoot)) {
|
|
1646
1990
|
const { bases } = await generateReducerNativeArtifacts({
|
|
1647
1991
|
projectRoot,
|
|
@@ -1652,7 +1996,6 @@ async function runCloudLocalVerification(projectRoot, projectConfig, config) {
|
|
|
1652
1996
|
projectRoot,
|
|
1653
1997
|
projectConfig,
|
|
1654
1998
|
resolvedConfig: config,
|
|
1655
|
-
runner: "reducer",
|
|
1656
1999
|
gameId: projectConfig.gameId,
|
|
1657
2000
|
compiledResultId: projectConfig.compile?.latestSuccessful?.resultId
|
|
1658
2001
|
});
|