terminalhire 0.42.26 → 0.42.27
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/bin/jpi-claim.js +54 -8
- package/dist/bin/jpi-dispatch.js +54 -8
- package/dist/bin/jpi-mcp.js +54 -8
- package/dist/bin/jpi-run.js +54 -8
- package/package.json +1 -1
package/dist/bin/jpi-claim.js
CHANGED
|
@@ -29714,7 +29714,10 @@ var init_result = __esm({
|
|
|
29714
29714
|
"detected",
|
|
29715
29715
|
"none",
|
|
29716
29716
|
"operator-declared",
|
|
29717
|
-
"developer-declared"
|
|
29717
|
+
"developer-declared",
|
|
29718
|
+
// TERM-1221: the mapping chose the image from a runtime the POSTER declared, because the
|
|
29719
|
+
// repository's own files named none.
|
|
29720
|
+
"founder-declared"
|
|
29718
29721
|
];
|
|
29719
29722
|
RUN_RESULT_SCHEMA = "terminalhire.verification-run/1";
|
|
29720
29723
|
RUN_RESULT_FIELDS = [
|
|
@@ -30072,6 +30075,10 @@ var init_attestation2 = __esm({
|
|
|
30072
30075
|
};
|
|
30073
30076
|
IMAGE_SOURCE_IS_SIGNABLE = {
|
|
30074
30077
|
detected: () => null,
|
|
30078
|
+
// The command table's `founder-declared` reasoning, applied to the environment: the poster
|
|
30079
|
+
// chose the runtime and the poster is paying, so a runtime they declared is theirs to stand
|
|
30080
|
+
// behind. The image itself is still the runtime mapping's pick, not a name anyone typed.
|
|
30081
|
+
"founder-declared": () => null,
|
|
30075
30082
|
"operator-declared": () => "had its container image chosen by an operator out of band, and the signed vocabulary has no member for that. Signing it would present a hand-picked environment as the one the runtime mapping selected.",
|
|
30076
30083
|
"developer-declared": () => "had its container image supplied by the developer whose work is under verification. A chosen interpreter turns a red suite green as surely as a chosen test command.",
|
|
30077
30084
|
// `none` means no image was booted, so an image name beside it is a contradiction — the
|
|
@@ -30758,8 +30765,14 @@ import { createHash as createHash9, X509Certificate } from "crypto";
|
|
|
30758
30765
|
import { chmodSync as chmodSync3, existsSync as existsSync11, mkdtempSync as mkdtempSync3, readFileSync as readFileSync11, rmSync as rmSync8, writeFileSync as writeFileSync13 } from "fs";
|
|
30759
30766
|
import { request as httpsRequest } from "https";
|
|
30760
30767
|
import { createServer } from "net";
|
|
30761
|
-
import {
|
|
30768
|
+
import { posix as posix3 } from "path";
|
|
30762
30769
|
import { tmpdir as tmpdir3 } from "os";
|
|
30770
|
+
function refuseUnsupportedHost(io) {
|
|
30771
|
+
const platform = io.platform ?? process.platform;
|
|
30772
|
+
if (platform === "win32") {
|
|
30773
|
+
throw new HostedVenueError("the hosted venue cannot run from a Windows host: it reaches the venue daemon through an ssh-forwarded Unix socket, and OpenSSH on Windows cannot forward to a local socket path. Run from Linux, macOS or WSL, or use --placement local-docker.", "ours");
|
|
30774
|
+
}
|
|
30775
|
+
}
|
|
30763
30776
|
function credentialInGitConfig(text) {
|
|
30764
30777
|
for (const match2 of text.matchAll(/\b([a-z][a-z0-9+.-]*):\/\/(\S+)/gi)) {
|
|
30765
30778
|
const scheme = (match2[1] ?? "").toLowerCase();
|
|
@@ -31296,6 +31309,7 @@ function hostedVenueAvailable(opts = {}, io = defaultHostedVenueIo) {
|
|
|
31296
31309
|
const config = opts.gcloudConfig ?? VENUE_GCLOUD_CONFIG;
|
|
31297
31310
|
const env = venueGcloudEnv(config);
|
|
31298
31311
|
try {
|
|
31312
|
+
refuseUnsupportedHost(io);
|
|
31299
31313
|
assertServiceCredentials(config, io);
|
|
31300
31314
|
} catch {
|
|
31301
31315
|
return false;
|
|
@@ -31736,6 +31750,7 @@ function hostedVenue(opts = {}, io = defaultHostedVenueIo) {
|
|
|
31736
31750
|
...image
|
|
31737
31751
|
};
|
|
31738
31752
|
let bootArgv = gcpBootArgv(bootParams(CLIENT_CERT_STAND_IN));
|
|
31753
|
+
refuseUnsupportedHost(io);
|
|
31739
31754
|
ensureVenueServiceCredentials(gcloudConfig, keyFile, io);
|
|
31740
31755
|
const clientTls = csImageDigest === null ? null : { ...makeClientTls(io, allocated, vm), imageDigest: csImageDigest };
|
|
31741
31756
|
if (clientTls !== null)
|
|
@@ -32029,7 +32044,8 @@ function makeLease(p) {
|
|
|
32029
32044
|
throw new HostedVenueError(`could not stage ${from} onto ${p.vm}: ${execDetail(res).slice(0, 300)}`);
|
|
32030
32045
|
}
|
|
32031
32046
|
};
|
|
32032
|
-
const
|
|
32047
|
+
const localJail = join24(local.scratchRoot, JAIL_SEGMENT);
|
|
32048
|
+
const localTmp = join24(local.scratchRoot, JAIL_TMP_SEGMENT);
|
|
32033
32049
|
const required = [
|
|
32034
32050
|
localTmp,
|
|
32035
32051
|
join24(localJail, JAIL_PASSWD_FILE),
|
|
@@ -32178,7 +32194,7 @@ function makeLease(p) {
|
|
|
32178
32194
|
}
|
|
32179
32195
|
};
|
|
32180
32196
|
}
|
|
32181
|
-
var SSH_READY_BUDGET_MS, SSH_PROBE_INTERVAL_MS, SSH_PROBE_TIMEOUT_MS, TUNNEL_BUDGET_MS, TUNNEL_POLL_INTERVAL_MS, GOOGLE_JWKS_URL, JWKS_FETCH_TIMEOUT_MS, CREDENTIAL_QUERY_PARAM, UNDECODABLE, STAGE_PUSH_TIMEOUT_MS, DISPATCHED_PROBE_TIMEOUT_MS, DISPATCHED_STATUS_ARGV, DISPATCHED_GIT_CANDIDATES, PROXY_CLEANUP_TIMEOUT_MS, OWNER_PROBE_TIMEOUT_MS, BOOT_TIMEOUT_MS, MKDIR_TIMEOUT_MS, DELETE_TIMEOUT_MS, LOCAL_GCLOUD_TIMEOUT_MS, SERVICE_ACCOUNT_ACTIVATE_TIMEOUT_MS, SOCKET_DIR_PREFIX, VENUE_SOCKET_NAME, HostedVenueError, VENUE_GCLOUD_CONFIG, SERVICE_ACCOUNT_SUFFIX, GCLOUD_PRINCIPAL_OVERRIDES, defaultHostedVenueIo, VENUE_SSH_USER, GCE_METADATA_IDENTITY_URL, COMPACT_JWT, VOLUME_CREATE_TIMEOUT_MS, EXEC_PROBE_TIMEOUT_MS, POPULATE_TIMEOUT_MS, STAGE_PROOF_PREFIX, IAP_NOT_READY, IAP_BACKEND_UNREACHABLE, IAP_DENIED, TERMINAL_GCP, INSTANCE_NOT_RUNNING, PREEMPTED, HOST_KEY_MISMATCH, SSH_KEY_NOT_READY, DAEMON_NOT_READY, SSH_NOT_ANSWERING, CS_ATTEST_PORT, CS_DOCKER_PORT, CS_READY_BUDGET_MS, CS_ATTEST_TIMEOUT_MS, CS_PULL_TIMEOUT_MS, CS_ATTEST_INTERVAL_MS, OPENSSL_TIMEOUT_MS, CS_RUN_ARGS, CS_GUEST_USER, CS_STAGE_ROOT, CLIENT_CERT_STAND_IN;
|
|
32197
|
+
var join24, SSH_READY_BUDGET_MS, SSH_PROBE_INTERVAL_MS, SSH_PROBE_TIMEOUT_MS, TUNNEL_BUDGET_MS, TUNNEL_POLL_INTERVAL_MS, GOOGLE_JWKS_URL, JWKS_FETCH_TIMEOUT_MS, CREDENTIAL_QUERY_PARAM, UNDECODABLE, STAGE_PUSH_TIMEOUT_MS, DISPATCHED_PROBE_TIMEOUT_MS, DISPATCHED_STATUS_ARGV, DISPATCHED_GIT_CANDIDATES, PROXY_CLEANUP_TIMEOUT_MS, OWNER_PROBE_TIMEOUT_MS, BOOT_TIMEOUT_MS, MKDIR_TIMEOUT_MS, DELETE_TIMEOUT_MS, LOCAL_GCLOUD_TIMEOUT_MS, SERVICE_ACCOUNT_ACTIVATE_TIMEOUT_MS, SOCKET_DIR_PREFIX, VENUE_SOCKET_NAME, HostedVenueError, VENUE_GCLOUD_CONFIG, SERVICE_ACCOUNT_SUFFIX, GCLOUD_PRINCIPAL_OVERRIDES, defaultHostedVenueIo, VENUE_SSH_USER, GCE_METADATA_IDENTITY_URL, COMPACT_JWT, VOLUME_CREATE_TIMEOUT_MS, EXEC_PROBE_TIMEOUT_MS, POPULATE_TIMEOUT_MS, STAGE_PROOF_PREFIX, IAP_NOT_READY, IAP_BACKEND_UNREACHABLE, IAP_DENIED, TERMINAL_GCP, INSTANCE_NOT_RUNNING, PREEMPTED, HOST_KEY_MISMATCH, SSH_KEY_NOT_READY, DAEMON_NOT_READY, SSH_NOT_ANSWERING, CS_ATTEST_PORT, CS_DOCKER_PORT, CS_READY_BUDGET_MS, CS_ATTEST_TIMEOUT_MS, CS_PULL_TIMEOUT_MS, CS_ATTEST_INTERVAL_MS, OPENSSL_TIMEOUT_MS, CS_RUN_ARGS, CS_GUEST_USER, CS_STAGE_ROOT, CLIENT_CERT_STAND_IN;
|
|
32182
32198
|
var init_hostedVenue = __esm({
|
|
32183
32199
|
"../../packages/envrun/dist/hostedVenue.js"() {
|
|
32184
32200
|
"use strict";
|
|
@@ -32190,6 +32206,7 @@ var init_hostedVenue = __esm({
|
|
|
32190
32206
|
init_labels();
|
|
32191
32207
|
init_venueProof();
|
|
32192
32208
|
init_venue();
|
|
32209
|
+
({ join: join24 } = posix3);
|
|
32193
32210
|
SSH_READY_BUDGET_MS = 18e4;
|
|
32194
32211
|
SSH_PROBE_INTERVAL_MS = 5e3;
|
|
32195
32212
|
SSH_PROBE_TIMEOUT_MS = 25e3;
|
|
@@ -34340,8 +34357,11 @@ function publishableTarget(url) {
|
|
|
34340
34357
|
if (separatorInTarget(url) !== null)
|
|
34341
34358
|
return UNPARSEABLE_TARGET;
|
|
34342
34359
|
const m = /^([A-Za-z][A-Za-z0-9+.-]*:\/\/)([^/?#]*)([^?#]*)/.exec(url);
|
|
34343
|
-
if (m === null)
|
|
34344
|
-
|
|
34360
|
+
if (m === null) {
|
|
34361
|
+
if (url.includes("?"))
|
|
34362
|
+
return UNPARSEABLE_TARGET;
|
|
34363
|
+
return WINDOWS_ABSOLUTE.test(url) ? redactWindowsPathCredentials(url) : redactPathCredentials(url);
|
|
34364
|
+
}
|
|
34345
34365
|
const authority = m[2] ?? "";
|
|
34346
34366
|
const at = authority.lastIndexOf("@");
|
|
34347
34367
|
const path5 = m[3] ?? "";
|
|
@@ -34355,6 +34375,16 @@ function redactPathCredentials(path5) {
|
|
|
34355
34375
|
return /:[^@]*@/.test(seen) ? WITHHELD_SEGMENT : segment;
|
|
34356
34376
|
});
|
|
34357
34377
|
}
|
|
34378
|
+
function redactWindowsPathCredentials(path5) {
|
|
34379
|
+
const rest = path5.slice(2);
|
|
34380
|
+
for (const m of rest.matchAll(/[^\\/]+/g)) {
|
|
34381
|
+
const seen = decodeToFixedPoint(m[0]);
|
|
34382
|
+
if (seen === null || seen.includes(":")) {
|
|
34383
|
+
return path5.slice(0, 2) + rest.slice(0, m.index) + WITHHELD_SEGMENT;
|
|
34384
|
+
}
|
|
34385
|
+
}
|
|
34386
|
+
return path5;
|
|
34387
|
+
}
|
|
34358
34388
|
function decodeToFixedPoint(s) {
|
|
34359
34389
|
let current = s;
|
|
34360
34390
|
for (let round = 0; round < 4; round += 1) {
|
|
@@ -34543,6 +34573,21 @@ async function releaseWithoutThrowing(lease, progress) {
|
|
|
34543
34573
|
);
|
|
34544
34574
|
}
|
|
34545
34575
|
}
|
|
34576
|
+
function resolveRunEnvironment(derived, req) {
|
|
34577
|
+
const runtimeDeclared = req.runtimeOverride !== void 0 && req.runtimeOverride !== "unknown" && derived.runtime === "unknown";
|
|
34578
|
+
const withRuntime = runtimeDeclared ? {
|
|
34579
|
+
...derived,
|
|
34580
|
+
runtime: req.runtimeOverride,
|
|
34581
|
+
unresolved: derived.unresolved.filter((r) => r.kind !== "unknown-runtime")
|
|
34582
|
+
} : derived;
|
|
34583
|
+
const spec = req.testCommandOverride === void 0 ? withRuntime : { ...withRuntime, testCommand: req.testCommandOverride };
|
|
34584
|
+
const imageSource = req.image !== void 0 ? req.imageOrigin === "operator" ? "operator-declared" : "developer-declared" : runtimeDeclared ? (
|
|
34585
|
+
// Attributed only when the caller says the poster chose it. An unattributed override
|
|
34586
|
+
// defaults the way `testCommandSource` does, to the developer, which does not sign.
|
|
34587
|
+
req.runtimeOverrideOrigin === "founder" ? "founder-declared" : "developer-declared"
|
|
34588
|
+
) : "detected";
|
|
34589
|
+
return { spec, imageSource };
|
|
34590
|
+
}
|
|
34546
34591
|
async function verifyWorkingDiff(req) {
|
|
34547
34592
|
const ctx = {
|
|
34548
34593
|
startedAt: Date.now(),
|
|
@@ -34740,7 +34785,7 @@ async function runVerification(req, ctx) {
|
|
|
34740
34785
|
const treeDigest = patchedTreeDigest(cloneDir);
|
|
34741
34786
|
const baselinePatchSha256 = hasBaselinePatch ? sha256Hex(baselinePatch ?? "") : null;
|
|
34742
34787
|
const derived = deriveEnvironmentSpec(cloneDir);
|
|
34743
|
-
const spec
|
|
34788
|
+
const { spec, imageSource } = resolveRunEnvironment(derived, req);
|
|
34744
34789
|
progress("derive", `runtime=${spec.runtime} install=${String(spec.installCommand)} test=${String(spec.testCommand)}`);
|
|
34745
34790
|
refuseUnbuildableSpec(spec);
|
|
34746
34791
|
const image = placement.imageFor(spec.runtime, req.image, spec.runtimeVersion, imageVariantFor(spec));
|
|
@@ -34845,7 +34890,7 @@ async function runVerification(req, ctx) {
|
|
|
34845
34890
|
// `developer-declared` is deliberate and matches `testCommandSource`: `th run --image`
|
|
34846
34891
|
// runs on the developer's machine, judging the developer's work, so attributing it to
|
|
34847
34892
|
// the operator would sign our name onto their choice.
|
|
34848
|
-
imageSource
|
|
34893
|
+
imageSource,
|
|
34849
34894
|
leaksClean: verdict.leaks.clean,
|
|
34850
34895
|
leakState: verdict.leaks.state,
|
|
34851
34896
|
// Built from the LEASE, over the client that ran the steps — never from
|
|
@@ -35908,6 +35953,7 @@ __export(dist_exports, {
|
|
|
35908
35953
|
renderVerdictLine: () => renderVerdictLine,
|
|
35909
35954
|
resolveImageForSpec: () => resolveImageForSpec,
|
|
35910
35955
|
resolveLease: () => resolveLease,
|
|
35956
|
+
resolveRunEnvironment: () => resolveRunEnvironment,
|
|
35911
35957
|
runEnvironmentSpec: () => runEnvironmentSpec,
|
|
35912
35958
|
runLabels: () => runLabels,
|
|
35913
35959
|
setManifestProbe: () => setManifestProbe,
|
package/dist/bin/jpi-dispatch.js
CHANGED
|
@@ -35457,7 +35457,10 @@ var init_result = __esm({
|
|
|
35457
35457
|
"detected",
|
|
35458
35458
|
"none",
|
|
35459
35459
|
"operator-declared",
|
|
35460
|
-
"developer-declared"
|
|
35460
|
+
"developer-declared",
|
|
35461
|
+
// TERM-1221: the mapping chose the image from a runtime the POSTER declared, because the
|
|
35462
|
+
// repository's own files named none.
|
|
35463
|
+
"founder-declared"
|
|
35461
35464
|
];
|
|
35462
35465
|
RUN_RESULT_SCHEMA = "terminalhire.verification-run/1";
|
|
35463
35466
|
RUN_RESULT_FIELDS = [
|
|
@@ -35815,6 +35818,10 @@ var init_attestation2 = __esm({
|
|
|
35815
35818
|
};
|
|
35816
35819
|
IMAGE_SOURCE_IS_SIGNABLE = {
|
|
35817
35820
|
detected: () => null,
|
|
35821
|
+
// The command table's `founder-declared` reasoning, applied to the environment: the poster
|
|
35822
|
+
// chose the runtime and the poster is paying, so a runtime they declared is theirs to stand
|
|
35823
|
+
// behind. The image itself is still the runtime mapping's pick, not a name anyone typed.
|
|
35824
|
+
"founder-declared": () => null,
|
|
35818
35825
|
"operator-declared": () => "had its container image chosen by an operator out of band, and the signed vocabulary has no member for that. Signing it would present a hand-picked environment as the one the runtime mapping selected.",
|
|
35819
35826
|
"developer-declared": () => "had its container image supplied by the developer whose work is under verification. A chosen interpreter turns a red suite green as surely as a chosen test command.",
|
|
35820
35827
|
// `none` means no image was booted, so an image name beside it is a contradiction — the
|
|
@@ -36501,8 +36508,14 @@ import { createHash as createHash10, X509Certificate } from "crypto";
|
|
|
36501
36508
|
import { chmodSync as chmodSync3, existsSync as existsSync18, mkdtempSync as mkdtempSync3, readFileSync as readFileSync25, rmSync as rmSync10, writeFileSync as writeFileSync22 } from "fs";
|
|
36502
36509
|
import { request as httpsRequest } from "https";
|
|
36503
36510
|
import { createServer } from "net";
|
|
36504
|
-
import {
|
|
36511
|
+
import { posix as posix3 } from "path";
|
|
36505
36512
|
import { tmpdir as tmpdir3 } from "os";
|
|
36513
|
+
function refuseUnsupportedHost(io) {
|
|
36514
|
+
const platform = io.platform ?? process.platform;
|
|
36515
|
+
if (platform === "win32") {
|
|
36516
|
+
throw new HostedVenueError("the hosted venue cannot run from a Windows host: it reaches the venue daemon through an ssh-forwarded Unix socket, and OpenSSH on Windows cannot forward to a local socket path. Run from Linux, macOS or WSL, or use --placement local-docker.", "ours");
|
|
36517
|
+
}
|
|
36518
|
+
}
|
|
36506
36519
|
function credentialInGitConfig(text) {
|
|
36507
36520
|
for (const match2 of text.matchAll(/\b([a-z][a-z0-9+.-]*):\/\/(\S+)/gi)) {
|
|
36508
36521
|
const scheme = (match2[1] ?? "").toLowerCase();
|
|
@@ -37039,6 +37052,7 @@ function hostedVenueAvailable(opts = {}, io = defaultHostedVenueIo) {
|
|
|
37039
37052
|
const config2 = opts.gcloudConfig ?? VENUE_GCLOUD_CONFIG;
|
|
37040
37053
|
const env = venueGcloudEnv(config2);
|
|
37041
37054
|
try {
|
|
37055
|
+
refuseUnsupportedHost(io);
|
|
37042
37056
|
assertServiceCredentials(config2, io);
|
|
37043
37057
|
} catch {
|
|
37044
37058
|
return false;
|
|
@@ -37479,6 +37493,7 @@ function hostedVenue(opts = {}, io = defaultHostedVenueIo) {
|
|
|
37479
37493
|
...image
|
|
37480
37494
|
};
|
|
37481
37495
|
let bootArgv = gcpBootArgv(bootParams(CLIENT_CERT_STAND_IN));
|
|
37496
|
+
refuseUnsupportedHost(io);
|
|
37482
37497
|
ensureVenueServiceCredentials(gcloudConfig, keyFile, io);
|
|
37483
37498
|
const clientTls = csImageDigest === null ? null : { ...makeClientTls(io, allocated, vm), imageDigest: csImageDigest };
|
|
37484
37499
|
if (clientTls !== null)
|
|
@@ -37772,7 +37787,8 @@ function makeLease(p) {
|
|
|
37772
37787
|
throw new HostedVenueError(`could not stage ${from} onto ${p.vm}: ${execDetail(res).slice(0, 300)}`);
|
|
37773
37788
|
}
|
|
37774
37789
|
};
|
|
37775
|
-
const
|
|
37790
|
+
const localJail = join40(local.scratchRoot, JAIL_SEGMENT);
|
|
37791
|
+
const localTmp = join40(local.scratchRoot, JAIL_TMP_SEGMENT);
|
|
37776
37792
|
const required2 = [
|
|
37777
37793
|
localTmp,
|
|
37778
37794
|
join40(localJail, JAIL_PASSWD_FILE),
|
|
@@ -37921,7 +37937,7 @@ function makeLease(p) {
|
|
|
37921
37937
|
}
|
|
37922
37938
|
};
|
|
37923
37939
|
}
|
|
37924
|
-
var SSH_READY_BUDGET_MS, SSH_PROBE_INTERVAL_MS, SSH_PROBE_TIMEOUT_MS, TUNNEL_BUDGET_MS, TUNNEL_POLL_INTERVAL_MS, GOOGLE_JWKS_URL, JWKS_FETCH_TIMEOUT_MS, CREDENTIAL_QUERY_PARAM, UNDECODABLE, STAGE_PUSH_TIMEOUT_MS, DISPATCHED_PROBE_TIMEOUT_MS, DISPATCHED_STATUS_ARGV, DISPATCHED_GIT_CANDIDATES, PROXY_CLEANUP_TIMEOUT_MS, OWNER_PROBE_TIMEOUT_MS, BOOT_TIMEOUT_MS, MKDIR_TIMEOUT_MS, DELETE_TIMEOUT_MS, LOCAL_GCLOUD_TIMEOUT_MS, SERVICE_ACCOUNT_ACTIVATE_TIMEOUT_MS, SOCKET_DIR_PREFIX, VENUE_SOCKET_NAME, HostedVenueError, VENUE_GCLOUD_CONFIG, SERVICE_ACCOUNT_SUFFIX, GCLOUD_PRINCIPAL_OVERRIDES, defaultHostedVenueIo, VENUE_SSH_USER, GCE_METADATA_IDENTITY_URL, COMPACT_JWT, VOLUME_CREATE_TIMEOUT_MS, EXEC_PROBE_TIMEOUT_MS, POPULATE_TIMEOUT_MS, STAGE_PROOF_PREFIX, IAP_NOT_READY, IAP_BACKEND_UNREACHABLE, IAP_DENIED, TERMINAL_GCP, INSTANCE_NOT_RUNNING, PREEMPTED, HOST_KEY_MISMATCH, SSH_KEY_NOT_READY, DAEMON_NOT_READY, SSH_NOT_ANSWERING, CS_ATTEST_PORT, CS_DOCKER_PORT, CS_READY_BUDGET_MS, CS_ATTEST_TIMEOUT_MS, CS_PULL_TIMEOUT_MS, CS_ATTEST_INTERVAL_MS, OPENSSL_TIMEOUT_MS, CS_RUN_ARGS, CS_GUEST_USER, CS_STAGE_ROOT, CLIENT_CERT_STAND_IN;
|
|
37940
|
+
var join40, SSH_READY_BUDGET_MS, SSH_PROBE_INTERVAL_MS, SSH_PROBE_TIMEOUT_MS, TUNNEL_BUDGET_MS, TUNNEL_POLL_INTERVAL_MS, GOOGLE_JWKS_URL, JWKS_FETCH_TIMEOUT_MS, CREDENTIAL_QUERY_PARAM, UNDECODABLE, STAGE_PUSH_TIMEOUT_MS, DISPATCHED_PROBE_TIMEOUT_MS, DISPATCHED_STATUS_ARGV, DISPATCHED_GIT_CANDIDATES, PROXY_CLEANUP_TIMEOUT_MS, OWNER_PROBE_TIMEOUT_MS, BOOT_TIMEOUT_MS, MKDIR_TIMEOUT_MS, DELETE_TIMEOUT_MS, LOCAL_GCLOUD_TIMEOUT_MS, SERVICE_ACCOUNT_ACTIVATE_TIMEOUT_MS, SOCKET_DIR_PREFIX, VENUE_SOCKET_NAME, HostedVenueError, VENUE_GCLOUD_CONFIG, SERVICE_ACCOUNT_SUFFIX, GCLOUD_PRINCIPAL_OVERRIDES, defaultHostedVenueIo, VENUE_SSH_USER, GCE_METADATA_IDENTITY_URL, COMPACT_JWT, VOLUME_CREATE_TIMEOUT_MS, EXEC_PROBE_TIMEOUT_MS, POPULATE_TIMEOUT_MS, STAGE_PROOF_PREFIX, IAP_NOT_READY, IAP_BACKEND_UNREACHABLE, IAP_DENIED, TERMINAL_GCP, INSTANCE_NOT_RUNNING, PREEMPTED, HOST_KEY_MISMATCH, SSH_KEY_NOT_READY, DAEMON_NOT_READY, SSH_NOT_ANSWERING, CS_ATTEST_PORT, CS_DOCKER_PORT, CS_READY_BUDGET_MS, CS_ATTEST_TIMEOUT_MS, CS_PULL_TIMEOUT_MS, CS_ATTEST_INTERVAL_MS, OPENSSL_TIMEOUT_MS, CS_RUN_ARGS, CS_GUEST_USER, CS_STAGE_ROOT, CLIENT_CERT_STAND_IN;
|
|
37925
37941
|
var init_hostedVenue = __esm({
|
|
37926
37942
|
"../../packages/envrun/dist/hostedVenue.js"() {
|
|
37927
37943
|
"use strict";
|
|
@@ -37933,6 +37949,7 @@ var init_hostedVenue = __esm({
|
|
|
37933
37949
|
init_labels();
|
|
37934
37950
|
init_venueProof();
|
|
37935
37951
|
init_venue();
|
|
37952
|
+
({ join: join40 } = posix3);
|
|
37936
37953
|
SSH_READY_BUDGET_MS = 18e4;
|
|
37937
37954
|
SSH_PROBE_INTERVAL_MS = 5e3;
|
|
37938
37955
|
SSH_PROBE_TIMEOUT_MS = 25e3;
|
|
@@ -40083,8 +40100,11 @@ function publishableTarget(url) {
|
|
|
40083
40100
|
if (separatorInTarget(url) !== null)
|
|
40084
40101
|
return UNPARSEABLE_TARGET;
|
|
40085
40102
|
const m = /^([A-Za-z][A-Za-z0-9+.-]*:\/\/)([^/?#]*)([^?#]*)/.exec(url);
|
|
40086
|
-
if (m === null)
|
|
40087
|
-
|
|
40103
|
+
if (m === null) {
|
|
40104
|
+
if (url.includes("?"))
|
|
40105
|
+
return UNPARSEABLE_TARGET;
|
|
40106
|
+
return WINDOWS_ABSOLUTE.test(url) ? redactWindowsPathCredentials(url) : redactPathCredentials(url);
|
|
40107
|
+
}
|
|
40088
40108
|
const authority = m[2] ?? "";
|
|
40089
40109
|
const at = authority.lastIndexOf("@");
|
|
40090
40110
|
const path6 = m[3] ?? "";
|
|
@@ -40098,6 +40118,16 @@ function redactPathCredentials(path6) {
|
|
|
40098
40118
|
return /:[^@]*@/.test(seen) ? WITHHELD_SEGMENT : segment;
|
|
40099
40119
|
});
|
|
40100
40120
|
}
|
|
40121
|
+
function redactWindowsPathCredentials(path6) {
|
|
40122
|
+
const rest = path6.slice(2);
|
|
40123
|
+
for (const m of rest.matchAll(/[^\\/]+/g)) {
|
|
40124
|
+
const seen = decodeToFixedPoint(m[0]);
|
|
40125
|
+
if (seen === null || seen.includes(":")) {
|
|
40126
|
+
return path6.slice(0, 2) + rest.slice(0, m.index) + WITHHELD_SEGMENT;
|
|
40127
|
+
}
|
|
40128
|
+
}
|
|
40129
|
+
return path6;
|
|
40130
|
+
}
|
|
40101
40131
|
function decodeToFixedPoint(s) {
|
|
40102
40132
|
let current = s;
|
|
40103
40133
|
for (let round2 = 0; round2 < 4; round2 += 1) {
|
|
@@ -40286,6 +40316,21 @@ async function releaseWithoutThrowing(lease, progress) {
|
|
|
40286
40316
|
);
|
|
40287
40317
|
}
|
|
40288
40318
|
}
|
|
40319
|
+
function resolveRunEnvironment(derived, req) {
|
|
40320
|
+
const runtimeDeclared = req.runtimeOverride !== void 0 && req.runtimeOverride !== "unknown" && derived.runtime === "unknown";
|
|
40321
|
+
const withRuntime = runtimeDeclared ? {
|
|
40322
|
+
...derived,
|
|
40323
|
+
runtime: req.runtimeOverride,
|
|
40324
|
+
unresolved: derived.unresolved.filter((r) => r.kind !== "unknown-runtime")
|
|
40325
|
+
} : derived;
|
|
40326
|
+
const spec = req.testCommandOverride === void 0 ? withRuntime : { ...withRuntime, testCommand: req.testCommandOverride };
|
|
40327
|
+
const imageSource = req.image !== void 0 ? req.imageOrigin === "operator" ? "operator-declared" : "developer-declared" : runtimeDeclared ? (
|
|
40328
|
+
// Attributed only when the caller says the poster chose it. An unattributed override
|
|
40329
|
+
// defaults the way `testCommandSource` does, to the developer, which does not sign.
|
|
40330
|
+
req.runtimeOverrideOrigin === "founder" ? "founder-declared" : "developer-declared"
|
|
40331
|
+
) : "detected";
|
|
40332
|
+
return { spec, imageSource };
|
|
40333
|
+
}
|
|
40289
40334
|
async function verifyWorkingDiff(req) {
|
|
40290
40335
|
const ctx = {
|
|
40291
40336
|
startedAt: Date.now(),
|
|
@@ -40483,7 +40528,7 @@ async function runVerification(req, ctx) {
|
|
|
40483
40528
|
const treeDigest = patchedTreeDigest(cloneDir);
|
|
40484
40529
|
const baselinePatchSha256 = hasBaselinePatch ? sha256Hex(baselinePatch ?? "") : null;
|
|
40485
40530
|
const derived = deriveEnvironmentSpec(cloneDir);
|
|
40486
|
-
const spec
|
|
40531
|
+
const { spec, imageSource } = resolveRunEnvironment(derived, req);
|
|
40487
40532
|
progress("derive", `runtime=${spec.runtime} install=${String(spec.installCommand)} test=${String(spec.testCommand)}`);
|
|
40488
40533
|
refuseUnbuildableSpec(spec);
|
|
40489
40534
|
const image = placement.imageFor(spec.runtime, req.image, spec.runtimeVersion, imageVariantFor(spec));
|
|
@@ -40588,7 +40633,7 @@ async function runVerification(req, ctx) {
|
|
|
40588
40633
|
// `developer-declared` is deliberate and matches `testCommandSource`: `th run --image`
|
|
40589
40634
|
// runs on the developer's machine, judging the developer's work, so attributing it to
|
|
40590
40635
|
// the operator would sign our name onto their choice.
|
|
40591
|
-
imageSource
|
|
40636
|
+
imageSource,
|
|
40592
40637
|
leaksClean: verdict.leaks.clean,
|
|
40593
40638
|
leakState: verdict.leaks.state,
|
|
40594
40639
|
// Built from the LEASE, over the client that ran the steps — never from
|
|
@@ -41651,6 +41696,7 @@ __export(dist_exports, {
|
|
|
41651
41696
|
renderVerdictLine: () => renderVerdictLine,
|
|
41652
41697
|
resolveImageForSpec: () => resolveImageForSpec,
|
|
41653
41698
|
resolveLease: () => resolveLease,
|
|
41699
|
+
resolveRunEnvironment: () => resolveRunEnvironment,
|
|
41654
41700
|
runEnvironmentSpec: () => runEnvironmentSpec,
|
|
41655
41701
|
runLabels: () => runLabels,
|
|
41656
41702
|
setManifestProbe: () => setManifestProbe,
|
package/dist/bin/jpi-mcp.js
CHANGED
|
@@ -30232,7 +30232,10 @@ var init_result = __esm({
|
|
|
30232
30232
|
"detected",
|
|
30233
30233
|
"none",
|
|
30234
30234
|
"operator-declared",
|
|
30235
|
-
"developer-declared"
|
|
30235
|
+
"developer-declared",
|
|
30236
|
+
// TERM-1221: the mapping chose the image from a runtime the POSTER declared, because the
|
|
30237
|
+
// repository's own files named none.
|
|
30238
|
+
"founder-declared"
|
|
30236
30239
|
];
|
|
30237
30240
|
RUN_RESULT_SCHEMA = "terminalhire.verification-run/1";
|
|
30238
30241
|
RUN_RESULT_FIELDS = [
|
|
@@ -30590,6 +30593,10 @@ var init_attestation2 = __esm({
|
|
|
30590
30593
|
};
|
|
30591
30594
|
IMAGE_SOURCE_IS_SIGNABLE = {
|
|
30592
30595
|
detected: () => null,
|
|
30596
|
+
// The command table's `founder-declared` reasoning, applied to the environment: the poster
|
|
30597
|
+
// chose the runtime and the poster is paying, so a runtime they declared is theirs to stand
|
|
30598
|
+
// behind. The image itself is still the runtime mapping's pick, not a name anyone typed.
|
|
30599
|
+
"founder-declared": () => null,
|
|
30593
30600
|
"operator-declared": () => "had its container image chosen by an operator out of band, and the signed vocabulary has no member for that. Signing it would present a hand-picked environment as the one the runtime mapping selected.",
|
|
30594
30601
|
"developer-declared": () => "had its container image supplied by the developer whose work is under verification. A chosen interpreter turns a red suite green as surely as a chosen test command.",
|
|
30595
30602
|
// `none` means no image was booted, so an image name beside it is a contradiction — the
|
|
@@ -31276,8 +31283,14 @@ import { createHash as createHash9, X509Certificate } from "crypto";
|
|
|
31276
31283
|
import { chmodSync as chmodSync3, existsSync as existsSync11, mkdtempSync as mkdtempSync3, readFileSync as readFileSync13, rmSync as rmSync8, writeFileSync as writeFileSync15 } from "fs";
|
|
31277
31284
|
import { request as httpsRequest } from "https";
|
|
31278
31285
|
import { createServer } from "net";
|
|
31279
|
-
import {
|
|
31286
|
+
import { posix as posix3 } from "path";
|
|
31280
31287
|
import { tmpdir as tmpdir3 } from "os";
|
|
31288
|
+
function refuseUnsupportedHost(io) {
|
|
31289
|
+
const platform = io.platform ?? process.platform;
|
|
31290
|
+
if (platform === "win32") {
|
|
31291
|
+
throw new HostedVenueError("the hosted venue cannot run from a Windows host: it reaches the venue daemon through an ssh-forwarded Unix socket, and OpenSSH on Windows cannot forward to a local socket path. Run from Linux, macOS or WSL, or use --placement local-docker.", "ours");
|
|
31292
|
+
}
|
|
31293
|
+
}
|
|
31281
31294
|
function credentialInGitConfig(text) {
|
|
31282
31295
|
for (const match2 of text.matchAll(/\b([a-z][a-z0-9+.-]*):\/\/(\S+)/gi)) {
|
|
31283
31296
|
const scheme = (match2[1] ?? "").toLowerCase();
|
|
@@ -31814,6 +31827,7 @@ function hostedVenueAvailable(opts = {}, io = defaultHostedVenueIo) {
|
|
|
31814
31827
|
const config2 = opts.gcloudConfig ?? VENUE_GCLOUD_CONFIG;
|
|
31815
31828
|
const env = venueGcloudEnv(config2);
|
|
31816
31829
|
try {
|
|
31830
|
+
refuseUnsupportedHost(io);
|
|
31817
31831
|
assertServiceCredentials(config2, io);
|
|
31818
31832
|
} catch {
|
|
31819
31833
|
return false;
|
|
@@ -32254,6 +32268,7 @@ function hostedVenue(opts = {}, io = defaultHostedVenueIo) {
|
|
|
32254
32268
|
...image
|
|
32255
32269
|
};
|
|
32256
32270
|
let bootArgv = gcpBootArgv(bootParams(CLIENT_CERT_STAND_IN));
|
|
32271
|
+
refuseUnsupportedHost(io);
|
|
32257
32272
|
ensureVenueServiceCredentials(gcloudConfig, keyFile, io);
|
|
32258
32273
|
const clientTls = csImageDigest === null ? null : { ...makeClientTls(io, allocated, vm), imageDigest: csImageDigest };
|
|
32259
32274
|
if (clientTls !== null)
|
|
@@ -32547,7 +32562,8 @@ function makeLease(p) {
|
|
|
32547
32562
|
throw new HostedVenueError(`could not stage ${from} onto ${p.vm}: ${execDetail(res).slice(0, 300)}`);
|
|
32548
32563
|
}
|
|
32549
32564
|
};
|
|
32550
|
-
const
|
|
32565
|
+
const localJail = join26(local.scratchRoot, JAIL_SEGMENT);
|
|
32566
|
+
const localTmp = join26(local.scratchRoot, JAIL_TMP_SEGMENT);
|
|
32551
32567
|
const required2 = [
|
|
32552
32568
|
localTmp,
|
|
32553
32569
|
join26(localJail, JAIL_PASSWD_FILE),
|
|
@@ -32696,7 +32712,7 @@ function makeLease(p) {
|
|
|
32696
32712
|
}
|
|
32697
32713
|
};
|
|
32698
32714
|
}
|
|
32699
|
-
var SSH_READY_BUDGET_MS, SSH_PROBE_INTERVAL_MS, SSH_PROBE_TIMEOUT_MS, TUNNEL_BUDGET_MS, TUNNEL_POLL_INTERVAL_MS, GOOGLE_JWKS_URL, JWKS_FETCH_TIMEOUT_MS, CREDENTIAL_QUERY_PARAM, UNDECODABLE, STAGE_PUSH_TIMEOUT_MS, DISPATCHED_PROBE_TIMEOUT_MS, DISPATCHED_STATUS_ARGV, DISPATCHED_GIT_CANDIDATES, PROXY_CLEANUP_TIMEOUT_MS, OWNER_PROBE_TIMEOUT_MS, BOOT_TIMEOUT_MS, MKDIR_TIMEOUT_MS, DELETE_TIMEOUT_MS, LOCAL_GCLOUD_TIMEOUT_MS, SERVICE_ACCOUNT_ACTIVATE_TIMEOUT_MS, SOCKET_DIR_PREFIX, VENUE_SOCKET_NAME, HostedVenueError, VENUE_GCLOUD_CONFIG, SERVICE_ACCOUNT_SUFFIX, GCLOUD_PRINCIPAL_OVERRIDES, defaultHostedVenueIo, VENUE_SSH_USER, GCE_METADATA_IDENTITY_URL, COMPACT_JWT, VOLUME_CREATE_TIMEOUT_MS, EXEC_PROBE_TIMEOUT_MS, POPULATE_TIMEOUT_MS, STAGE_PROOF_PREFIX, IAP_NOT_READY, IAP_BACKEND_UNREACHABLE, IAP_DENIED, TERMINAL_GCP, INSTANCE_NOT_RUNNING, PREEMPTED, HOST_KEY_MISMATCH, SSH_KEY_NOT_READY, DAEMON_NOT_READY, SSH_NOT_ANSWERING, CS_ATTEST_PORT, CS_DOCKER_PORT, CS_READY_BUDGET_MS, CS_ATTEST_TIMEOUT_MS, CS_PULL_TIMEOUT_MS, CS_ATTEST_INTERVAL_MS, OPENSSL_TIMEOUT_MS, CS_RUN_ARGS, CS_GUEST_USER, CS_STAGE_ROOT, CLIENT_CERT_STAND_IN;
|
|
32715
|
+
var join26, SSH_READY_BUDGET_MS, SSH_PROBE_INTERVAL_MS, SSH_PROBE_TIMEOUT_MS, TUNNEL_BUDGET_MS, TUNNEL_POLL_INTERVAL_MS, GOOGLE_JWKS_URL, JWKS_FETCH_TIMEOUT_MS, CREDENTIAL_QUERY_PARAM, UNDECODABLE, STAGE_PUSH_TIMEOUT_MS, DISPATCHED_PROBE_TIMEOUT_MS, DISPATCHED_STATUS_ARGV, DISPATCHED_GIT_CANDIDATES, PROXY_CLEANUP_TIMEOUT_MS, OWNER_PROBE_TIMEOUT_MS, BOOT_TIMEOUT_MS, MKDIR_TIMEOUT_MS, DELETE_TIMEOUT_MS, LOCAL_GCLOUD_TIMEOUT_MS, SERVICE_ACCOUNT_ACTIVATE_TIMEOUT_MS, SOCKET_DIR_PREFIX, VENUE_SOCKET_NAME, HostedVenueError, VENUE_GCLOUD_CONFIG, SERVICE_ACCOUNT_SUFFIX, GCLOUD_PRINCIPAL_OVERRIDES, defaultHostedVenueIo, VENUE_SSH_USER, GCE_METADATA_IDENTITY_URL, COMPACT_JWT, VOLUME_CREATE_TIMEOUT_MS, EXEC_PROBE_TIMEOUT_MS, POPULATE_TIMEOUT_MS, STAGE_PROOF_PREFIX, IAP_NOT_READY, IAP_BACKEND_UNREACHABLE, IAP_DENIED, TERMINAL_GCP, INSTANCE_NOT_RUNNING, PREEMPTED, HOST_KEY_MISMATCH, SSH_KEY_NOT_READY, DAEMON_NOT_READY, SSH_NOT_ANSWERING, CS_ATTEST_PORT, CS_DOCKER_PORT, CS_READY_BUDGET_MS, CS_ATTEST_TIMEOUT_MS, CS_PULL_TIMEOUT_MS, CS_ATTEST_INTERVAL_MS, OPENSSL_TIMEOUT_MS, CS_RUN_ARGS, CS_GUEST_USER, CS_STAGE_ROOT, CLIENT_CERT_STAND_IN;
|
|
32700
32716
|
var init_hostedVenue = __esm({
|
|
32701
32717
|
"../../packages/envrun/dist/hostedVenue.js"() {
|
|
32702
32718
|
"use strict";
|
|
@@ -32708,6 +32724,7 @@ var init_hostedVenue = __esm({
|
|
|
32708
32724
|
init_labels();
|
|
32709
32725
|
init_venueProof();
|
|
32710
32726
|
init_venue();
|
|
32727
|
+
({ join: join26 } = posix3);
|
|
32711
32728
|
SSH_READY_BUDGET_MS = 18e4;
|
|
32712
32729
|
SSH_PROBE_INTERVAL_MS = 5e3;
|
|
32713
32730
|
SSH_PROBE_TIMEOUT_MS = 25e3;
|
|
@@ -34858,8 +34875,11 @@ function publishableTarget(url) {
|
|
|
34858
34875
|
if (separatorInTarget(url) !== null)
|
|
34859
34876
|
return UNPARSEABLE_TARGET;
|
|
34860
34877
|
const m = /^([A-Za-z][A-Za-z0-9+.-]*:\/\/)([^/?#]*)([^?#]*)/.exec(url);
|
|
34861
|
-
if (m === null)
|
|
34862
|
-
|
|
34878
|
+
if (m === null) {
|
|
34879
|
+
if (url.includes("?"))
|
|
34880
|
+
return UNPARSEABLE_TARGET;
|
|
34881
|
+
return WINDOWS_ABSOLUTE.test(url) ? redactWindowsPathCredentials(url) : redactPathCredentials(url);
|
|
34882
|
+
}
|
|
34863
34883
|
const authority = m[2] ?? "";
|
|
34864
34884
|
const at = authority.lastIndexOf("@");
|
|
34865
34885
|
const path5 = m[3] ?? "";
|
|
@@ -34873,6 +34893,16 @@ function redactPathCredentials(path5) {
|
|
|
34873
34893
|
return /:[^@]*@/.test(seen) ? WITHHELD_SEGMENT : segment;
|
|
34874
34894
|
});
|
|
34875
34895
|
}
|
|
34896
|
+
function redactWindowsPathCredentials(path5) {
|
|
34897
|
+
const rest = path5.slice(2);
|
|
34898
|
+
for (const m of rest.matchAll(/[^\\/]+/g)) {
|
|
34899
|
+
const seen = decodeToFixedPoint(m[0]);
|
|
34900
|
+
if (seen === null || seen.includes(":")) {
|
|
34901
|
+
return path5.slice(0, 2) + rest.slice(0, m.index) + WITHHELD_SEGMENT;
|
|
34902
|
+
}
|
|
34903
|
+
}
|
|
34904
|
+
return path5;
|
|
34905
|
+
}
|
|
34876
34906
|
function decodeToFixedPoint(s) {
|
|
34877
34907
|
let current = s;
|
|
34878
34908
|
for (let round = 0; round < 4; round += 1) {
|
|
@@ -35061,6 +35091,21 @@ async function releaseWithoutThrowing(lease, progress) {
|
|
|
35061
35091
|
);
|
|
35062
35092
|
}
|
|
35063
35093
|
}
|
|
35094
|
+
function resolveRunEnvironment(derived, req) {
|
|
35095
|
+
const runtimeDeclared = req.runtimeOverride !== void 0 && req.runtimeOverride !== "unknown" && derived.runtime === "unknown";
|
|
35096
|
+
const withRuntime = runtimeDeclared ? {
|
|
35097
|
+
...derived,
|
|
35098
|
+
runtime: req.runtimeOverride,
|
|
35099
|
+
unresolved: derived.unresolved.filter((r) => r.kind !== "unknown-runtime")
|
|
35100
|
+
} : derived;
|
|
35101
|
+
const spec = req.testCommandOverride === void 0 ? withRuntime : { ...withRuntime, testCommand: req.testCommandOverride };
|
|
35102
|
+
const imageSource = req.image !== void 0 ? req.imageOrigin === "operator" ? "operator-declared" : "developer-declared" : runtimeDeclared ? (
|
|
35103
|
+
// Attributed only when the caller says the poster chose it. An unattributed override
|
|
35104
|
+
// defaults the way `testCommandSource` does, to the developer, which does not sign.
|
|
35105
|
+
req.runtimeOverrideOrigin === "founder" ? "founder-declared" : "developer-declared"
|
|
35106
|
+
) : "detected";
|
|
35107
|
+
return { spec, imageSource };
|
|
35108
|
+
}
|
|
35064
35109
|
async function verifyWorkingDiff(req) {
|
|
35065
35110
|
const ctx = {
|
|
35066
35111
|
startedAt: Date.now(),
|
|
@@ -35258,7 +35303,7 @@ async function runVerification(req, ctx) {
|
|
|
35258
35303
|
const treeDigest = patchedTreeDigest(cloneDir);
|
|
35259
35304
|
const baselinePatchSha256 = hasBaselinePatch ? sha256Hex(baselinePatch ?? "") : null;
|
|
35260
35305
|
const derived = deriveEnvironmentSpec(cloneDir);
|
|
35261
|
-
const spec
|
|
35306
|
+
const { spec, imageSource } = resolveRunEnvironment(derived, req);
|
|
35262
35307
|
progress("derive", `runtime=${spec.runtime} install=${String(spec.installCommand)} test=${String(spec.testCommand)}`);
|
|
35263
35308
|
refuseUnbuildableSpec(spec);
|
|
35264
35309
|
const image = placement.imageFor(spec.runtime, req.image, spec.runtimeVersion, imageVariantFor(spec));
|
|
@@ -35363,7 +35408,7 @@ async function runVerification(req, ctx) {
|
|
|
35363
35408
|
// `developer-declared` is deliberate and matches `testCommandSource`: `th run --image`
|
|
35364
35409
|
// runs on the developer's machine, judging the developer's work, so attributing it to
|
|
35365
35410
|
// the operator would sign our name onto their choice.
|
|
35366
|
-
imageSource
|
|
35411
|
+
imageSource,
|
|
35367
35412
|
leaksClean: verdict.leaks.clean,
|
|
35368
35413
|
leakState: verdict.leaks.state,
|
|
35369
35414
|
// Built from the LEASE, over the client that ran the steps — never from
|
|
@@ -36426,6 +36471,7 @@ __export(dist_exports, {
|
|
|
36426
36471
|
renderVerdictLine: () => renderVerdictLine,
|
|
36427
36472
|
resolveImageForSpec: () => resolveImageForSpec,
|
|
36428
36473
|
resolveLease: () => resolveLease,
|
|
36474
|
+
resolveRunEnvironment: () => resolveRunEnvironment,
|
|
36429
36475
|
runEnvironmentSpec: () => runEnvironmentSpec,
|
|
36430
36476
|
runLabels: () => runLabels,
|
|
36431
36477
|
setManifestProbe: () => setManifestProbe,
|
package/dist/bin/jpi-run.js
CHANGED
|
@@ -3707,7 +3707,10 @@ var init_result = __esm({
|
|
|
3707
3707
|
"detected",
|
|
3708
3708
|
"none",
|
|
3709
3709
|
"operator-declared",
|
|
3710
|
-
"developer-declared"
|
|
3710
|
+
"developer-declared",
|
|
3711
|
+
// TERM-1221: the mapping chose the image from a runtime the POSTER declared, because the
|
|
3712
|
+
// repository's own files named none.
|
|
3713
|
+
"founder-declared"
|
|
3711
3714
|
];
|
|
3712
3715
|
RUN_RESULT_SCHEMA = "terminalhire.verification-run/1";
|
|
3713
3716
|
RUN_RESULT_FIELDS = [
|
|
@@ -4065,6 +4068,10 @@ var init_attestation2 = __esm({
|
|
|
4065
4068
|
};
|
|
4066
4069
|
IMAGE_SOURCE_IS_SIGNABLE = {
|
|
4067
4070
|
detected: () => null,
|
|
4071
|
+
// The command table's `founder-declared` reasoning, applied to the environment: the poster
|
|
4072
|
+
// chose the runtime and the poster is paying, so a runtime they declared is theirs to stand
|
|
4073
|
+
// behind. The image itself is still the runtime mapping's pick, not a name anyone typed.
|
|
4074
|
+
"founder-declared": () => null,
|
|
4068
4075
|
"operator-declared": () => "had its container image chosen by an operator out of band, and the signed vocabulary has no member for that. Signing it would present a hand-picked environment as the one the runtime mapping selected.",
|
|
4069
4076
|
"developer-declared": () => "had its container image supplied by the developer whose work is under verification. A chosen interpreter turns a red suite green as surely as a chosen test command.",
|
|
4070
4077
|
// `none` means no image was booted, so an image name beside it is a contradiction — the
|
|
@@ -4751,8 +4758,14 @@ import { createHash as createHash4, X509Certificate } from "crypto";
|
|
|
4751
4758
|
import { chmodSync as chmodSync2, existsSync as existsSync6, mkdtempSync as mkdtempSync3, readFileSync as readFileSync4, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "fs";
|
|
4752
4759
|
import { request as httpsRequest } from "https";
|
|
4753
4760
|
import { createServer } from "net";
|
|
4754
|
-
import {
|
|
4761
|
+
import { posix as posix3 } from "path";
|
|
4755
4762
|
import { tmpdir as tmpdir3 } from "os";
|
|
4763
|
+
function refuseUnsupportedHost(io) {
|
|
4764
|
+
const platform = io.platform ?? process.platform;
|
|
4765
|
+
if (platform === "win32") {
|
|
4766
|
+
throw new HostedVenueError("the hosted venue cannot run from a Windows host: it reaches the venue daemon through an ssh-forwarded Unix socket, and OpenSSH on Windows cannot forward to a local socket path. Run from Linux, macOS or WSL, or use --placement local-docker.", "ours");
|
|
4767
|
+
}
|
|
4768
|
+
}
|
|
4756
4769
|
function credentialInGitConfig(text) {
|
|
4757
4770
|
for (const match of text.matchAll(/\b([a-z][a-z0-9+.-]*):\/\/(\S+)/gi)) {
|
|
4758
4771
|
const scheme = (match[1] ?? "").toLowerCase();
|
|
@@ -5289,6 +5302,7 @@ function hostedVenueAvailable(opts = {}, io = defaultHostedVenueIo) {
|
|
|
5289
5302
|
const config = opts.gcloudConfig ?? VENUE_GCLOUD_CONFIG;
|
|
5290
5303
|
const env = venueGcloudEnv(config);
|
|
5291
5304
|
try {
|
|
5305
|
+
refuseUnsupportedHost(io);
|
|
5292
5306
|
assertServiceCredentials(config, io);
|
|
5293
5307
|
} catch {
|
|
5294
5308
|
return false;
|
|
@@ -5729,6 +5743,7 @@ function hostedVenue(opts = {}, io = defaultHostedVenueIo) {
|
|
|
5729
5743
|
...image
|
|
5730
5744
|
};
|
|
5731
5745
|
let bootArgv = gcpBootArgv(bootParams(CLIENT_CERT_STAND_IN));
|
|
5746
|
+
refuseUnsupportedHost(io);
|
|
5732
5747
|
ensureVenueServiceCredentials(gcloudConfig, keyFile, io);
|
|
5733
5748
|
const clientTls = csImageDigest === null ? null : { ...makeClientTls(io, allocated, vm), imageDigest: csImageDigest };
|
|
5734
5749
|
if (clientTls !== null)
|
|
@@ -6022,7 +6037,8 @@ function makeLease(p) {
|
|
|
6022
6037
|
throw new HostedVenueError(`could not stage ${from} onto ${p.vm}: ${execDetail(res).slice(0, 300)}`);
|
|
6023
6038
|
}
|
|
6024
6039
|
};
|
|
6025
|
-
const
|
|
6040
|
+
const localJail = join11(local.scratchRoot, JAIL_SEGMENT);
|
|
6041
|
+
const localTmp = join11(local.scratchRoot, JAIL_TMP_SEGMENT);
|
|
6026
6042
|
const required = [
|
|
6027
6043
|
localTmp,
|
|
6028
6044
|
join11(localJail, JAIL_PASSWD_FILE),
|
|
@@ -6171,7 +6187,7 @@ function makeLease(p) {
|
|
|
6171
6187
|
}
|
|
6172
6188
|
};
|
|
6173
6189
|
}
|
|
6174
|
-
var SSH_READY_BUDGET_MS, SSH_PROBE_INTERVAL_MS, SSH_PROBE_TIMEOUT_MS, TUNNEL_BUDGET_MS, TUNNEL_POLL_INTERVAL_MS, GOOGLE_JWKS_URL, JWKS_FETCH_TIMEOUT_MS, CREDENTIAL_QUERY_PARAM, UNDECODABLE, STAGE_PUSH_TIMEOUT_MS, DISPATCHED_PROBE_TIMEOUT_MS, DISPATCHED_STATUS_ARGV, DISPATCHED_GIT_CANDIDATES, PROXY_CLEANUP_TIMEOUT_MS, OWNER_PROBE_TIMEOUT_MS, BOOT_TIMEOUT_MS, MKDIR_TIMEOUT_MS, DELETE_TIMEOUT_MS, LOCAL_GCLOUD_TIMEOUT_MS, SERVICE_ACCOUNT_ACTIVATE_TIMEOUT_MS, SOCKET_DIR_PREFIX, VENUE_SOCKET_NAME, HostedVenueError, VENUE_GCLOUD_CONFIG, SERVICE_ACCOUNT_SUFFIX, GCLOUD_PRINCIPAL_OVERRIDES, defaultHostedVenueIo, VENUE_SSH_USER, GCE_METADATA_IDENTITY_URL, COMPACT_JWT, VOLUME_CREATE_TIMEOUT_MS, EXEC_PROBE_TIMEOUT_MS, POPULATE_TIMEOUT_MS, STAGE_PROOF_PREFIX, IAP_NOT_READY, IAP_BACKEND_UNREACHABLE, IAP_DENIED, TERMINAL_GCP, INSTANCE_NOT_RUNNING, PREEMPTED, HOST_KEY_MISMATCH, SSH_KEY_NOT_READY, DAEMON_NOT_READY, SSH_NOT_ANSWERING, CS_ATTEST_PORT, CS_DOCKER_PORT, CS_READY_BUDGET_MS, CS_ATTEST_TIMEOUT_MS, CS_PULL_TIMEOUT_MS, CS_ATTEST_INTERVAL_MS, OPENSSL_TIMEOUT_MS, CS_RUN_ARGS, CS_GUEST_USER, CS_STAGE_ROOT, CLIENT_CERT_STAND_IN;
|
|
6190
|
+
var join11, SSH_READY_BUDGET_MS, SSH_PROBE_INTERVAL_MS, SSH_PROBE_TIMEOUT_MS, TUNNEL_BUDGET_MS, TUNNEL_POLL_INTERVAL_MS, GOOGLE_JWKS_URL, JWKS_FETCH_TIMEOUT_MS, CREDENTIAL_QUERY_PARAM, UNDECODABLE, STAGE_PUSH_TIMEOUT_MS, DISPATCHED_PROBE_TIMEOUT_MS, DISPATCHED_STATUS_ARGV, DISPATCHED_GIT_CANDIDATES, PROXY_CLEANUP_TIMEOUT_MS, OWNER_PROBE_TIMEOUT_MS, BOOT_TIMEOUT_MS, MKDIR_TIMEOUT_MS, DELETE_TIMEOUT_MS, LOCAL_GCLOUD_TIMEOUT_MS, SERVICE_ACCOUNT_ACTIVATE_TIMEOUT_MS, SOCKET_DIR_PREFIX, VENUE_SOCKET_NAME, HostedVenueError, VENUE_GCLOUD_CONFIG, SERVICE_ACCOUNT_SUFFIX, GCLOUD_PRINCIPAL_OVERRIDES, defaultHostedVenueIo, VENUE_SSH_USER, GCE_METADATA_IDENTITY_URL, COMPACT_JWT, VOLUME_CREATE_TIMEOUT_MS, EXEC_PROBE_TIMEOUT_MS, POPULATE_TIMEOUT_MS, STAGE_PROOF_PREFIX, IAP_NOT_READY, IAP_BACKEND_UNREACHABLE, IAP_DENIED, TERMINAL_GCP, INSTANCE_NOT_RUNNING, PREEMPTED, HOST_KEY_MISMATCH, SSH_KEY_NOT_READY, DAEMON_NOT_READY, SSH_NOT_ANSWERING, CS_ATTEST_PORT, CS_DOCKER_PORT, CS_READY_BUDGET_MS, CS_ATTEST_TIMEOUT_MS, CS_PULL_TIMEOUT_MS, CS_ATTEST_INTERVAL_MS, OPENSSL_TIMEOUT_MS, CS_RUN_ARGS, CS_GUEST_USER, CS_STAGE_ROOT, CLIENT_CERT_STAND_IN;
|
|
6175
6191
|
var init_hostedVenue = __esm({
|
|
6176
6192
|
"../../packages/envrun/dist/hostedVenue.js"() {
|
|
6177
6193
|
"use strict";
|
|
@@ -6183,6 +6199,7 @@ var init_hostedVenue = __esm({
|
|
|
6183
6199
|
init_labels();
|
|
6184
6200
|
init_venueProof();
|
|
6185
6201
|
init_venue();
|
|
6202
|
+
({ join: join11 } = posix3);
|
|
6186
6203
|
SSH_READY_BUDGET_MS = 18e4;
|
|
6187
6204
|
SSH_PROBE_INTERVAL_MS = 5e3;
|
|
6188
6205
|
SSH_PROBE_TIMEOUT_MS = 25e3;
|
|
@@ -8333,8 +8350,11 @@ function publishableTarget(url) {
|
|
|
8333
8350
|
if (separatorInTarget(url) !== null)
|
|
8334
8351
|
return UNPARSEABLE_TARGET;
|
|
8335
8352
|
const m = /^([A-Za-z][A-Za-z0-9+.-]*:\/\/)([^/?#]*)([^?#]*)/.exec(url);
|
|
8336
|
-
if (m === null)
|
|
8337
|
-
|
|
8353
|
+
if (m === null) {
|
|
8354
|
+
if (url.includes("?"))
|
|
8355
|
+
return UNPARSEABLE_TARGET;
|
|
8356
|
+
return WINDOWS_ABSOLUTE.test(url) ? redactWindowsPathCredentials(url) : redactPathCredentials(url);
|
|
8357
|
+
}
|
|
8338
8358
|
const authority = m[2] ?? "";
|
|
8339
8359
|
const at = authority.lastIndexOf("@");
|
|
8340
8360
|
const path = m[3] ?? "";
|
|
@@ -8348,6 +8368,16 @@ function redactPathCredentials(path) {
|
|
|
8348
8368
|
return /:[^@]*@/.test(seen) ? WITHHELD_SEGMENT : segment;
|
|
8349
8369
|
});
|
|
8350
8370
|
}
|
|
8371
|
+
function redactWindowsPathCredentials(path) {
|
|
8372
|
+
const rest = path.slice(2);
|
|
8373
|
+
for (const m of rest.matchAll(/[^\\/]+/g)) {
|
|
8374
|
+
const seen = decodeToFixedPoint(m[0]);
|
|
8375
|
+
if (seen === null || seen.includes(":")) {
|
|
8376
|
+
return path.slice(0, 2) + rest.slice(0, m.index) + WITHHELD_SEGMENT;
|
|
8377
|
+
}
|
|
8378
|
+
}
|
|
8379
|
+
return path;
|
|
8380
|
+
}
|
|
8351
8381
|
function decodeToFixedPoint(s) {
|
|
8352
8382
|
let current = s;
|
|
8353
8383
|
for (let round = 0; round < 4; round += 1) {
|
|
@@ -8536,6 +8566,21 @@ async function releaseWithoutThrowing(lease, progress) {
|
|
|
8536
8566
|
);
|
|
8537
8567
|
}
|
|
8538
8568
|
}
|
|
8569
|
+
function resolveRunEnvironment(derived, req) {
|
|
8570
|
+
const runtimeDeclared = req.runtimeOverride !== void 0 && req.runtimeOverride !== "unknown" && derived.runtime === "unknown";
|
|
8571
|
+
const withRuntime = runtimeDeclared ? {
|
|
8572
|
+
...derived,
|
|
8573
|
+
runtime: req.runtimeOverride,
|
|
8574
|
+
unresolved: derived.unresolved.filter((r) => r.kind !== "unknown-runtime")
|
|
8575
|
+
} : derived;
|
|
8576
|
+
const spec = req.testCommandOverride === void 0 ? withRuntime : { ...withRuntime, testCommand: req.testCommandOverride };
|
|
8577
|
+
const imageSource = req.image !== void 0 ? req.imageOrigin === "operator" ? "operator-declared" : "developer-declared" : runtimeDeclared ? (
|
|
8578
|
+
// Attributed only when the caller says the poster chose it. An unattributed override
|
|
8579
|
+
// defaults the way `testCommandSource` does, to the developer, which does not sign.
|
|
8580
|
+
req.runtimeOverrideOrigin === "founder" ? "founder-declared" : "developer-declared"
|
|
8581
|
+
) : "detected";
|
|
8582
|
+
return { spec, imageSource };
|
|
8583
|
+
}
|
|
8539
8584
|
async function verifyWorkingDiff(req) {
|
|
8540
8585
|
const ctx = {
|
|
8541
8586
|
startedAt: Date.now(),
|
|
@@ -8733,7 +8778,7 @@ async function runVerification(req, ctx) {
|
|
|
8733
8778
|
const treeDigest = patchedTreeDigest(cloneDir);
|
|
8734
8779
|
const baselinePatchSha256 = hasBaselinePatch ? sha256Hex(baselinePatch ?? "") : null;
|
|
8735
8780
|
const derived = deriveEnvironmentSpec(cloneDir);
|
|
8736
|
-
const spec
|
|
8781
|
+
const { spec, imageSource } = resolveRunEnvironment(derived, req);
|
|
8737
8782
|
progress("derive", `runtime=${spec.runtime} install=${String(spec.installCommand)} test=${String(spec.testCommand)}`);
|
|
8738
8783
|
refuseUnbuildableSpec(spec);
|
|
8739
8784
|
const image = placement.imageFor(spec.runtime, req.image, spec.runtimeVersion, imageVariantFor(spec));
|
|
@@ -8838,7 +8883,7 @@ async function runVerification(req, ctx) {
|
|
|
8838
8883
|
// `developer-declared` is deliberate and matches `testCommandSource`: `th run --image`
|
|
8839
8884
|
// runs on the developer's machine, judging the developer's work, so attributing it to
|
|
8840
8885
|
// the operator would sign our name onto their choice.
|
|
8841
|
-
imageSource
|
|
8886
|
+
imageSource,
|
|
8842
8887
|
leaksClean: verdict.leaks.clean,
|
|
8843
8888
|
leakState: verdict.leaks.state,
|
|
8844
8889
|
// Built from the LEASE, over the client that ran the steps — never from
|
|
@@ -9901,6 +9946,7 @@ __export(dist_exports, {
|
|
|
9901
9946
|
renderVerdictLine: () => renderVerdictLine,
|
|
9902
9947
|
resolveImageForSpec: () => resolveImageForSpec,
|
|
9903
9948
|
resolveLease: () => resolveLease,
|
|
9949
|
+
resolveRunEnvironment: () => resolveRunEnvironment,
|
|
9904
9950
|
runEnvironmentSpec: () => runEnvironmentSpec,
|
|
9905
9951
|
runLabels: () => runLabels,
|
|
9906
9952
|
setManifestProbe: () => setManifestProbe,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "terminalhire",
|
|
3
|
-
"version": "0.42.
|
|
3
|
+
"version": "0.42.27",
|
|
4
4
|
"description": "Developer jobs and paid bounties, matched in the terminal — ambient matches in the Claude Code spinner. Claim a scoped bounty and get paid when the poster accepts it.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|