@wrongstack/cli 1.0.4 → 1.0.6
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/{acp-AB54FWM2.js → acp-GOQURNC2.js} +9 -6
- package/dist/{auth-WDMSNZ3S.js → auth-WBXXIQUO.js} +2 -2
- package/dist/boot/short-circuit-desktop.d.ts +1 -0
- package/dist/{chunk-ONOT5OJ2.js → chunk-5A5GCSJC.js} +1 -1
- package/dist/{chunk-I7V2OYVH.js → chunk-5EA6OTLJ.js} +3 -6
- package/dist/{chunk-O4A3HHKD.js → chunk-672UXYL3.js} +2 -2
- package/dist/{chunk-U6PGWDMZ.js → chunk-NR7BD73C.js} +2 -2
- package/dist/{chunk-3I5ZJXM5.js → chunk-PQZPHGGD.js} +128 -61
- package/dist/{chunk-BIWE22O5.js → chunk-QDQPF4PB.js} +5 -5
- package/dist/{chunk-VFCJOWJB.js → chunk-VPS2SJW4.js} +4 -5
- package/dist/{cli-context-WFC3BNGM.js → cli-context-BYKJDAFF.js} +19 -10
- package/dist/{cli-main-GU3YZLMO.js → cli-main-5WZBH3WA.js} +127 -109
- package/dist/{execution-RAZDDQFC.js → execution-Z6A26EG6.js} +26 -26
- package/dist/{hq-5XHEIIH6.js → hq-V4PHEETW.js} +3 -3
- package/dist/hq-server/auth-state.d.ts +6 -0
- package/dist/hq-server/auth.d.ts +10 -1
- package/dist/hq-server/routes/auth/common.d.ts +34 -0
- package/dist/hq-server/routes/auth/password-routes.d.ts +4 -2
- package/dist/hq-server/types.d.ts +18 -0
- package/dist/{hq-server-CNUTBWTK.js → hq-server-MZ7DV6X7.js} +3 -3
- package/dist/index.js +8 -5
- package/dist/{mcp-HOMLC4WE.js → mcp-FX7TKPTV.js} +10 -8
- package/dist/mcp-serve.d.ts +31 -0
- package/dist/{short-circuit-flags-YDMLAQ5R.js → short-circuit-flags-KBTYSJTW.js} +2 -2
- package/dist/{subcommands-7N4RIK6H.js → subcommands-DEYSYHIM.js} +2 -2
- package/package.json +28 -28
|
@@ -1258,7 +1258,7 @@ import * as path7 from "node:path";
|
|
|
1258
1258
|
import { restoreSessionSubagentPolicy } from "@wrongstack/core/coordination";
|
|
1259
1259
|
import { attachTodosCheckpoint, loadTodosCheckpoint } from "@wrongstack/core/storage";
|
|
1260
1260
|
import { projectLastRequestTokens } from "@wrongstack/core/types/session-timeline";
|
|
1261
|
-
import { sessionScopedPath as sessionScopedPath2 } from "@wrongstack/core/utils";
|
|
1261
|
+
import { sessionScopedPath as sessionScopedPath2, toErrorMessage } from "@wrongstack/core/utils";
|
|
1262
1262
|
var RESERVATION_WINDOW_MS = 6e4;
|
|
1263
1263
|
var RESERVATION_RENEW_MS = 2e4;
|
|
1264
1264
|
function messageText(content) {
|
|
@@ -1288,7 +1288,7 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1288
1288
|
};
|
|
1289
1289
|
const warnings = [];
|
|
1290
1290
|
const warn = (label, err) => {
|
|
1291
|
-
warnings.push(`${label}: ${
|
|
1291
|
+
warnings.push(`${label}: ${toErrorMessage(err)}`);
|
|
1292
1292
|
};
|
|
1293
1293
|
let stage = "start";
|
|
1294
1294
|
const setStage = (next) => {
|
|
@@ -1309,7 +1309,7 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1309
1309
|
throw new TypeError("@wrongstack/tui does not export replaySessionMessages");
|
|
1310
1310
|
}
|
|
1311
1311
|
} catch (err) {
|
|
1312
|
-
return fail(stage,
|
|
1312
|
+
return fail(stage, toErrorMessage(err));
|
|
1313
1313
|
}
|
|
1314
1314
|
setStage("resolve_id");
|
|
1315
1315
|
let canonicalSessionId = sessionId;
|
|
@@ -1323,11 +1323,11 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1323
1323
|
level: "error",
|
|
1324
1324
|
event: "execution.resume_id_resolve_failed",
|
|
1325
1325
|
sessionId,
|
|
1326
|
-
message:
|
|
1326
|
+
message: toErrorMessage(err),
|
|
1327
1327
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1328
1328
|
})
|
|
1329
1329
|
);
|
|
1330
|
-
return fail(stage,
|
|
1330
|
+
return fail(stage, toErrorMessage(err));
|
|
1331
1331
|
}
|
|
1332
1332
|
const previousSessionId = agent.ctx.session?.id;
|
|
1333
1333
|
let hydrated;
|
|
@@ -1369,7 +1369,7 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1369
1369
|
level: "warn",
|
|
1370
1370
|
event: "execution.resume_reservation_renew_failed",
|
|
1371
1371
|
sessionId: canonicalSessionId,
|
|
1372
|
-
message:
|
|
1372
|
+
message: toErrorMessage(err),
|
|
1373
1373
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1374
1374
|
})
|
|
1375
1375
|
);
|
|
@@ -1441,7 +1441,7 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1441
1441
|
JSON.stringify({
|
|
1442
1442
|
level: "error",
|
|
1443
1443
|
event: "execution.resume_journal_flush_failed",
|
|
1444
|
-
message:
|
|
1444
|
+
message: toErrorMessage(err),
|
|
1445
1445
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1446
1446
|
})
|
|
1447
1447
|
);
|
|
@@ -1498,7 +1498,7 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1498
1498
|
event: "execution.resume_model_restore_failed",
|
|
1499
1499
|
provider: targetProviderId,
|
|
1500
1500
|
model: targetModel,
|
|
1501
|
-
message:
|
|
1501
|
+
message: toErrorMessage(err),
|
|
1502
1502
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1503
1503
|
})
|
|
1504
1504
|
);
|
|
@@ -1526,7 +1526,7 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1526
1526
|
JSON.stringify({
|
|
1527
1527
|
level: "error",
|
|
1528
1528
|
event: "execution.session_end_append_failed",
|
|
1529
|
-
message:
|
|
1529
|
+
message: toErrorMessage(err),
|
|
1530
1530
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1531
1531
|
})
|
|
1532
1532
|
);
|
|
@@ -1539,7 +1539,7 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1539
1539
|
JSON.stringify({
|
|
1540
1540
|
level: "error",
|
|
1541
1541
|
event: "execution.session_close_failed",
|
|
1542
|
-
message:
|
|
1542
|
+
message: toErrorMessage(err),
|
|
1543
1543
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1544
1544
|
})
|
|
1545
1545
|
);
|
|
@@ -1580,7 +1580,7 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1580
1580
|
level: "error",
|
|
1581
1581
|
event: "execution.resume_identity_rollback_failed",
|
|
1582
1582
|
sessionId: previousSessionId,
|
|
1583
|
-
message:
|
|
1583
|
+
message: toErrorMessage(rollbackErr),
|
|
1584
1584
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1585
1585
|
})
|
|
1586
1586
|
);
|
|
@@ -1602,7 +1602,7 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1602
1602
|
JSON.stringify({
|
|
1603
1603
|
level: "error",
|
|
1604
1604
|
event: "execution.resume_post_swap_rollback_failed",
|
|
1605
|
-
message:
|
|
1605
|
+
message: toErrorMessage(rollbackErr),
|
|
1606
1606
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1607
1607
|
})
|
|
1608
1608
|
);
|
|
@@ -1613,7 +1613,7 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1613
1613
|
JSON.stringify({
|
|
1614
1614
|
level: "error",
|
|
1615
1615
|
event: "execution.resume_opened_writer_close_failed",
|
|
1616
|
-
message:
|
|
1616
|
+
message: toErrorMessage(closeErr),
|
|
1617
1617
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1618
1618
|
})
|
|
1619
1619
|
);
|
|
@@ -1631,7 +1631,7 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1631
1631
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1632
1632
|
})
|
|
1633
1633
|
);
|
|
1634
|
-
const message =
|
|
1634
|
+
const message = toErrorMessage(err);
|
|
1635
1635
|
if (err instanceof Error && err.name === "SessionOwnershipConflictError") {
|
|
1636
1636
|
return fail(stage, message);
|
|
1637
1637
|
}
|
|
@@ -1670,7 +1670,7 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1670
1670
|
level: "error",
|
|
1671
1671
|
event: "execution.resume_readonly_render_failed",
|
|
1672
1672
|
sessionId: canonicalSessionId,
|
|
1673
|
-
message:
|
|
1673
|
+
message: toErrorMessage(renderErr),
|
|
1674
1674
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1675
1675
|
})
|
|
1676
1676
|
);
|
|
@@ -4592,7 +4592,7 @@ import {
|
|
|
4592
4592
|
color as color11,
|
|
4593
4593
|
estimateRequestTokensCalibrated as estimateRequestTokensCalibrated2,
|
|
4594
4594
|
hasOpenTodos as hasOpenTodos2,
|
|
4595
|
-
toErrorMessage as
|
|
4595
|
+
toErrorMessage as toErrorMessage4
|
|
4596
4596
|
} from "@wrongstack/core/utils";
|
|
4597
4597
|
import { readClipboardImage, routeImagesForModel } from "@wrongstack/runtime";
|
|
4598
4598
|
import { createAutoProceedLoopGuard } from "@wrongstack/tools/auto-proceed-loop-guard";
|
|
@@ -4820,11 +4820,11 @@ function registerReplClient(opts) {
|
|
|
4820
4820
|
|
|
4821
4821
|
// src/repl-eternal-loop.ts
|
|
4822
4822
|
import { goalFilePath as goalFilePath2, summarizeUsage } from "@wrongstack/core/goal";
|
|
4823
|
-
import { color as color8, toErrorMessage as
|
|
4823
|
+
import { color as color8, toErrorMessage as toErrorMessage3 } from "@wrongstack/core/utils";
|
|
4824
4824
|
|
|
4825
4825
|
// src/repl-goal-banner.ts
|
|
4826
4826
|
import { goalFilePath, loadGoal } from "@wrongstack/core/goal";
|
|
4827
|
-
import { color as color7, expectDefined, toErrorMessage } from "@wrongstack/core/utils";
|
|
4827
|
+
import { color as color7, expectDefined, toErrorMessage as toErrorMessage2 } from "@wrongstack/core/utils";
|
|
4828
4828
|
async function loadGoalSafe(opts) {
|
|
4829
4829
|
if (!opts.projectRoot) return null;
|
|
4830
4830
|
try {
|
|
@@ -4858,7 +4858,7 @@ async function renderGoalBanner(opts) {
|
|
|
4858
4858
|
try {
|
|
4859
4859
|
await opts.slashRegistry.dispatch("/autonomy eternal", opts.agent.ctx);
|
|
4860
4860
|
} catch (err) {
|
|
4861
|
-
opts.renderer.writeError(`Auto-resume failed: ${
|
|
4861
|
+
opts.renderer.writeError(`Auto-resume failed: ${toErrorMessage2(err)}`);
|
|
4862
4862
|
}
|
|
4863
4863
|
} else {
|
|
4864
4864
|
opts.renderer.write(
|
|
@@ -4934,7 +4934,7 @@ async function runReplEternalLoop(opts, onInterruptsReset) {
|
|
|
4934
4934
|
return true;
|
|
4935
4935
|
}
|
|
4936
4936
|
} catch (err) {
|
|
4937
|
-
opts.renderer.writeError(`[eternal] ${
|
|
4937
|
+
opts.renderer.writeError(`[eternal] ${toErrorMessage3(err)}`);
|
|
4938
4938
|
}
|
|
4939
4939
|
await new Promise((resolve4) => setTimeout(resolve4, 250));
|
|
4940
4940
|
return true;
|
|
@@ -5005,7 +5005,7 @@ async function runReplEternalLoop(opts, onInterruptsReset) {
|
|
|
5005
5005
|
return true;
|
|
5006
5006
|
}
|
|
5007
5007
|
} catch (err) {
|
|
5008
|
-
opts.renderer.writeError(`[parallel] ${
|
|
5008
|
+
opts.renderer.writeError(`[parallel] ${toErrorMessage3(err)}`);
|
|
5009
5009
|
}
|
|
5010
5010
|
await new Promise((resolve4) => setTimeout(resolve4, 250));
|
|
5011
5011
|
return true;
|
|
@@ -5245,7 +5245,7 @@ ${lines.join("\n")}
|
|
|
5245
5245
|
if (res?.message) opts.renderer.write(`${res.message}
|
|
5246
5246
|
`);
|
|
5247
5247
|
} catch (err) {
|
|
5248
|
-
opts.renderer.writeError(
|
|
5248
|
+
opts.renderer.writeError(toErrorMessage4(err));
|
|
5249
5249
|
}
|
|
5250
5250
|
continue;
|
|
5251
5251
|
}
|
|
@@ -5337,7 +5337,7 @@ ${color11.dim(taskList2)}
|
|
|
5337
5337
|
}
|
|
5338
5338
|
}
|
|
5339
5339
|
} catch (err) {
|
|
5340
|
-
opts.renderer.writeError(
|
|
5340
|
+
opts.renderer.writeError(toErrorMessage4(err));
|
|
5341
5341
|
}
|
|
5342
5342
|
continue;
|
|
5343
5343
|
}
|
|
@@ -5616,7 +5616,7 @@ ${color11.dim(lines)}
|
|
|
5616
5616
|
}
|
|
5617
5617
|
}
|
|
5618
5618
|
} catch (err) {
|
|
5619
|
-
opts.renderer.writeError(
|
|
5619
|
+
opts.renderer.writeError(toErrorMessage4(err));
|
|
5620
5620
|
} finally {
|
|
5621
5621
|
activeCtrl = void 0;
|
|
5622
5622
|
}
|
|
@@ -5642,7 +5642,7 @@ async function pasteClipboardImage(builder, opts) {
|
|
|
5642
5642
|
opts.renderer.write(color11.dim(` \u21B3 ${placeholder} (PNG ${kb}KB)
|
|
5643
5643
|
`));
|
|
5644
5644
|
} catch (err) {
|
|
5645
|
-
opts.renderer.writeError(`Clipboard image error: ${
|
|
5645
|
+
opts.renderer.writeError(`Clipboard image error: ${toErrorMessage4(err)}`);
|
|
5646
5646
|
}
|
|
5647
5647
|
}
|
|
5648
5648
|
|
|
@@ -6840,4 +6840,4 @@ export {
|
|
|
6840
6840
|
execute,
|
|
6841
6841
|
resolveReviewerFallbackModels
|
|
6842
6842
|
};
|
|
6843
|
-
//# sourceMappingURL=execution-
|
|
6843
|
+
//# sourceMappingURL=execution-Z6A26EG6.js.map
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
normalizeHqPublicOrigin,
|
|
9
9
|
resolveAuditActor
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-5EA6OTLJ.js";
|
|
11
11
|
import {
|
|
12
12
|
parseHqIpAllowlist
|
|
13
13
|
} from "./chunk-Q7E3BPDU.js";
|
|
@@ -62,7 +62,7 @@ var hqCmd = async (args, deps) => {
|
|
|
62
62
|
return 1;
|
|
63
63
|
};
|
|
64
64
|
async function startServer(deps) {
|
|
65
|
-
const { startHqServer } = await import("./hq-server-
|
|
65
|
+
const { startHqServer } = await import("./hq-server-MZ7DV6X7.js");
|
|
66
66
|
const dataDir = resolveDataDir(deps);
|
|
67
67
|
const flags = deps.flags ?? {};
|
|
68
68
|
const rawPublicUrl = typeof flags["hq-public-url"] === "string" ? flags["hq-public-url"] : process.env.WRONGSTACK_HQ_PUBLIC_URL;
|
|
@@ -827,4 +827,4 @@ export {
|
|
|
827
827
|
hqCmd,
|
|
828
828
|
resolveAuditActor
|
|
829
829
|
};
|
|
830
|
-
//# sourceMappingURL=hq-
|
|
830
|
+
//# sourceMappingURL=hq-V4PHEETW.js.map
|
|
@@ -6,6 +6,12 @@ export interface HqAuthState {
|
|
|
6
6
|
tokenStats(): NonNullable<HqSnapshot['totals']['tokenStats']>;
|
|
7
7
|
}
|
|
8
8
|
interface HqAuthStateOptions {
|
|
9
|
+
/**
|
|
10
|
+
* The server's `requireBrowserAuth` option, stamped onto the state so every
|
|
11
|
+
* `hqAuthRequired(mutableAuth)` gate observes it without having to be handed
|
|
12
|
+
* it separately. See the field's doc on `HqRouterMutableAuth`.
|
|
13
|
+
*/
|
|
14
|
+
requireBrowserAuth?: boolean | undefined;
|
|
9
15
|
/**
|
|
10
16
|
* Invoked after every {@link HqAuthState.apply}, with the freshly projected
|
|
11
17
|
* `mutableAuth`. The server wires this to the WS-010 exposure re-assessment
|
package/dist/hq-server/auth.d.ts
CHANGED
|
@@ -38,7 +38,16 @@ export type HqBrowserAuthResult = HqBrowserAuthContext | HqCookieAuthContext | u
|
|
|
38
38
|
* inline style is not script execution.
|
|
39
39
|
*/
|
|
40
40
|
export declare function setHqSecurityHeaders(res: http.ServerResponse): void;
|
|
41
|
-
export declare function hasTrustedBrowserOrigin(req: http.IncomingMessage, boundHost?: string, boundPort?: number, trustedPublicOrigins?: ReadonlySet<string>, allowFileOrigin?: boolean
|
|
41
|
+
export declare function hasTrustedBrowserOrigin(req: http.IncomingMessage, boundHost?: string, boundPort?: number, trustedPublicOrigins?: ReadonlySet<string>, allowFileOrigin?: boolean,
|
|
42
|
+
/**
|
|
43
|
+
* Whether this surface has any credential configured — pass
|
|
44
|
+
* `hqAuthRequired(mutableAuth, requireBrowserAuth)`.
|
|
45
|
+
*
|
|
46
|
+
* Defaults to `false`, the STRICT side, deliberately: a caller that forgets
|
|
47
|
+
* to wire it gets the tighter rule rather than the looser one. That is the
|
|
48
|
+
* opposite of how the WS-077 gates drifted.
|
|
49
|
+
*/
|
|
50
|
+
credentialedSurface?: boolean): boolean;
|
|
42
51
|
export declare function serializeHqSessionCookie(sessionId: string, secret: string): string;
|
|
43
52
|
export declare function parseHqSessionCookie(value: string, secret: string): string | undefined;
|
|
44
53
|
export declare function parseCookieHeader(cookieHeader: string | undefined): Record<string, string>;
|
|
@@ -1,7 +1,41 @@
|
|
|
1
1
|
import type * as http from 'node:http';
|
|
2
2
|
import { type HqAuthFile } from '@wrongstack/core/hq';
|
|
3
3
|
import { type HqBrowserAuthResult } from '../../auth.js';
|
|
4
|
+
import type { LoginAttemptStore } from '../../login-attempt-store.js';
|
|
4
5
|
import type { HqRouterMutableAuth, HqSessionEntry } from '../../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Record a failed second-factor confirmation and return the new failure count.
|
|
8
|
+
*
|
|
9
|
+
* Shared by every route that verifies a factor outside `/api/login`
|
|
10
|
+
* (totp/disable, password change). Kept here rather than copied per route: the
|
|
11
|
+
* whole point is that each of those routes feeds the SAME per-IP counter, so a
|
|
12
|
+
* attacker cannot get a fresh budget by switching endpoints.
|
|
13
|
+
*/
|
|
14
|
+
export declare function recordVerifyFailure(loginAttempts: LoginAttemptStore, clientIp: string): number;
|
|
15
|
+
/** Outcome of {@link consumeTotpCode}. */
|
|
16
|
+
export type TotpConsumeResult = 'ok' | 'invalid' | 'replayed';
|
|
17
|
+
/**
|
|
18
|
+
* Verify a TOTP code AND burn it, so it cannot be presented a second time.
|
|
19
|
+
*
|
|
20
|
+
* A TOTP code stays valid for its whole time step plus the verification
|
|
21
|
+
* window — roughly 90 seconds. Without a single-use record, one observed code
|
|
22
|
+
* can be replayed at a *different* endpoint for as long as that window lasts.
|
|
23
|
+
* That is not theoretical here: `/api/login/verify` advanced
|
|
24
|
+
* `totpLastUsedCounter` and the other two verification sites
|
|
25
|
+
* (`totp/disable`, `auth/password`) called the counter-less `verifyTotp`, so a
|
|
26
|
+
* code already spent on a login replayed into removing 2FA outright or
|
|
27
|
+
* rotating the password and cookie secret.
|
|
28
|
+
*
|
|
29
|
+
* Kept in this module for the same reason as {@link recordVerifyFailure}: the
|
|
30
|
+
* property only holds if EVERY site that verifies a code shares one counter.
|
|
31
|
+
* A route that verifies a TOTP code by any other means is a bug —
|
|
32
|
+
* `hq-totp-single-use.test.ts` enumerates the call sites to keep it that way.
|
|
33
|
+
*
|
|
34
|
+
* The counter is advanced in memory first and persisted best-effort, matching
|
|
35
|
+
* the pre-existing behaviour at `/api/login/verify`: a failed write must not
|
|
36
|
+
* turn a consumed code back into an unconsumed one for this process.
|
|
37
|
+
*/
|
|
38
|
+
export declare function consumeTotpCode(code: string, mutableAuth: HqRouterMutableAuth, dataDir: string, applyAuthFile: ApplyHqAuthFile): Promise<TotpConsumeResult>;
|
|
5
39
|
export declare function isLoopbackRequest(req: http.IncomingMessage): boolean;
|
|
6
40
|
export declare const HQ_AUTH_ADMIN_CAPABILITY = "auth.admin";
|
|
7
41
|
export declare function callerCanAdministerAuth(auth: HqBrowserAuthResult): boolean;
|
|
@@ -3,7 +3,9 @@ import type { LoginAttemptStore } from '../../login-attempt-store.js';
|
|
|
3
3
|
import type { HqRouterMutableAuth, HqSessionEntry } from '../../types.js';
|
|
4
4
|
import { type ApplyHqAuthFile } from './common.js';
|
|
5
5
|
export declare function handleApiAuthStatus(req: http.IncomingMessage, res: http.ServerResponse, url: URL, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, requireBrowserAuth: boolean | undefined, trustedPublicOrigins: Set<string>, secureCookies: boolean | undefined): Promise<void>;
|
|
6
|
-
export declare function handleApiLogin(req: http.IncomingMessage, res: http.ServerResponse, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, loginAttempts: LoginAttemptStore, secureCookies: boolean | undefined, trustedProxyHops: number,
|
|
6
|
+
export declare function handleApiLogin(req: http.IncomingMessage, res: http.ServerResponse, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, loginAttempts: LoginAttemptStore, secureCookies: boolean | undefined, trustedProxyHops: number,
|
|
7
|
+
/** Where `auth.json` lives — needed to persist a transparent KDF upgrade. */
|
|
8
|
+
dataDir: string, sessionCapabilities?: string[]): Promise<void>;
|
|
7
9
|
export declare function handleApiLogout(req: http.IncomingMessage, res: http.ServerResponse, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, secureCookies: boolean | undefined): Promise<void>;
|
|
8
|
-
export declare function handleApiPassword(req: http.IncomingMessage, res: http.ServerResponse, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, dataDir: string, secureCookies: boolean | undefined, requireBrowserAuth: boolean | undefined, applyAuthFile: ApplyHqAuthFile): Promise<void>;
|
|
10
|
+
export declare function handleApiPassword(req: http.IncomingMessage, res: http.ServerResponse, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, dataDir: string, secureCookies: boolean | undefined, requireBrowserAuth: boolean | undefined, applyAuthFile: ApplyHqAuthFile, loginAttempts: LoginAttemptStore, trustedProxyHops: number): Promise<void>;
|
|
9
11
|
//# sourceMappingURL=password-routes.d.ts.map
|
|
@@ -103,6 +103,24 @@ export interface HqRouterMutableAuth {
|
|
|
103
103
|
* the surface fails closed instead of opening up.
|
|
104
104
|
*/
|
|
105
105
|
requireAuthFloor?: boolean | undefined;
|
|
106
|
+
/**
|
|
107
|
+
* The server's `requireBrowserAuth` option, carried on the state rather than
|
|
108
|
+
* passed to every gate.
|
|
109
|
+
*
|
|
110
|
+
* `hqAuthRequired` takes it as an optional second argument, and five gates
|
|
111
|
+
* called it with one — `command-handlers`, three in `mailbox-handlers`, and
|
|
112
|
+
* `mailbox-gateway-manager` — so a public relay did not raise the auth
|
|
113
|
+
* requirement on those routes. That is the WS-077 drift class the helper's
|
|
114
|
+
* own docstring warns about, recurring on the same routes. Holding the value
|
|
115
|
+
* on the state makes the one-argument call correct instead of incomplete.
|
|
116
|
+
*
|
|
117
|
+
* Required, not optional, and deliberately so. Optional would mean a second
|
|
118
|
+
* construction site could omit it and every one-argument gate would silently
|
|
119
|
+
* read `undefined` — the same drift this field exists to end, one level down.
|
|
120
|
+
* With `exactOptionalPropertyTypes` the compiler now makes every builder say
|
|
121
|
+
* what it means, including `undefined`.
|
|
122
|
+
*/
|
|
123
|
+
requireBrowserAuth: boolean | undefined;
|
|
106
124
|
}
|
|
107
125
|
/**
|
|
108
126
|
* Session record stored in the server-side `sessions` Map.
|
|
@@ -10,9 +10,9 @@ import {
|
|
|
10
10
|
readLocalSubagentTranscript,
|
|
11
11
|
sanitizeApiError,
|
|
12
12
|
startHqServer
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-PQZPHGGD.js";
|
|
14
14
|
import "./chunk-HXJYHAR4.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-5EA6OTLJ.js";
|
|
16
16
|
import "./chunk-Q7E3BPDU.js";
|
|
17
17
|
export {
|
|
18
18
|
DEFAULT_HOST,
|
|
@@ -27,4 +27,4 @@ export {
|
|
|
27
27
|
sanitizeApiError,
|
|
28
28
|
startHqServer
|
|
29
29
|
};
|
|
30
|
-
//# sourceMappingURL=hq-server-
|
|
30
|
+
//# sourceMappingURL=hq-server-MZ7DV6X7.js.map
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
applyNodeEnvDefault,
|
|
4
4
|
applySessionShellDefault
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-672UXYL3.js";
|
|
6
6
|
import {
|
|
7
7
|
CLI_VERSION
|
|
8
8
|
} from "./chunk-XJXDOF63.js";
|
|
@@ -16,20 +16,21 @@ async function main(argv) {
|
|
|
16
16
|
applySessionShellDefault();
|
|
17
17
|
const earlyFlags = parseArgs(argv).flags;
|
|
18
18
|
if (earlyFlags["help"] === true || earlyFlags["version"] === true) {
|
|
19
|
-
const { handleHelpVersionShortCircuit } = await import("./short-circuit-flags-
|
|
19
|
+
const { handleHelpVersionShortCircuit } = await import("./short-circuit-flags-KBTYSJTW.js");
|
|
20
20
|
const earlyExit = await handleHelpVersionShortCircuit(argv);
|
|
21
21
|
if (earlyExit !== null) return earlyExit;
|
|
22
22
|
}
|
|
23
|
-
const { initializeCli } = await import("./cli-context-
|
|
23
|
+
const { initializeCli } = await import("./cli-context-BYKJDAFF.js");
|
|
24
24
|
const cliCtx = await initializeCli(argv);
|
|
25
25
|
if (typeof cliCtx === "number") return cliCtx;
|
|
26
|
-
const { runInteractive } = await import("./cli-main-
|
|
26
|
+
const { runInteractive } = await import("./cli-main-5WZBH3WA.js");
|
|
27
27
|
return runInteractive(cliCtx);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
// src/cli-entry-point.ts
|
|
31
31
|
import { resolve } from "node:path";
|
|
32
32
|
import { pathToFileURL } from "node:url";
|
|
33
|
+
import { scrubErrorText } from "@wrongstack/core/security";
|
|
33
34
|
import { installCrashShield, runFatalSalvageSync, writeErr } from "@wrongstack/core/utils";
|
|
34
35
|
var SQLITE_WARNING_RE = /sqlite is an experimental feature/i;
|
|
35
36
|
function installSqliteWarningFilter() {
|
|
@@ -128,7 +129,9 @@ function runAsMain(mainFn) {
|
|
|
128
129
|
},
|
|
129
130
|
(err) => {
|
|
130
131
|
runFatalSalvageSync();
|
|
131
|
-
writeErr(
|
|
132
|
+
writeErr(
|
|
133
|
+
scrubErrorText(err instanceof Error ? err.stack ?? err.message : String(err)) + "\n"
|
|
134
|
+
);
|
|
132
135
|
process.exitCode = 1;
|
|
133
136
|
scheduleForcedExit(1);
|
|
134
137
|
}
|
|
@@ -23,7 +23,11 @@ import { pathToFileURL } from "node:url";
|
|
|
23
23
|
import { Context } from "@wrongstack/core/agent";
|
|
24
24
|
import { ToolExecutor } from "@wrongstack/core/execution";
|
|
25
25
|
import { ToolRegistry } from "@wrongstack/core/registry";
|
|
26
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
AutoApprovePermissionPolicy,
|
|
28
|
+
DefaultSecretScrubber,
|
|
29
|
+
ToolCapabilities
|
|
30
|
+
} from "@wrongstack/core/security";
|
|
27
31
|
import { normalizeTokenSavingTier } from "@wrongstack/core/types";
|
|
28
32
|
import {
|
|
29
33
|
DEFAULT_MCP_INSERTION_MAX_BYTES,
|
|
@@ -33,11 +37,9 @@ import {
|
|
|
33
37
|
} from "@wrongstack/mcp";
|
|
34
38
|
import { registerBuiltinToolTier } from "@wrongstack/tools/tool-tier";
|
|
35
39
|
import { wireKanbanPorts } from "@wrongstack/runtime";
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
};
|
|
40
|
+
function yoloServePolicy() {
|
|
41
|
+
return new AutoApprovePermissionPolicy(Object.values(ToolCapabilities));
|
|
42
|
+
}
|
|
41
43
|
function parseToolsFlag(flags, positional) {
|
|
42
44
|
const raw = flags["tools"];
|
|
43
45
|
const csv = typeof raw === "string" ? raw : raw === true ? positional?.[0] ?? "" : "";
|
|
@@ -226,7 +228,7 @@ async function serveMcpStdio(deps, positional) {
|
|
|
226
228
|
controller.signal,
|
|
227
229
|
resolveServeFsRestriction(deps.config)
|
|
228
230
|
);
|
|
229
|
-
const permissionPolicy = yolo ?
|
|
231
|
+
const permissionPolicy = yolo ? yoloServePolicy() : new AutoApprovePermissionPolicy();
|
|
230
232
|
const executor = new ToolExecutor(registry, {
|
|
231
233
|
permissionPolicy,
|
|
232
234
|
secretScrubber: new DefaultSecretScrubber(),
|
|
@@ -440,4 +442,4 @@ function isRecord(value) {
|
|
|
440
442
|
export {
|
|
441
443
|
mcpCmd
|
|
442
444
|
};
|
|
443
|
-
//# sourceMappingURL=mcp-
|
|
445
|
+
//# sourceMappingURL=mcp-FX7TKPTV.js.map
|
package/dist/mcp-serve.d.ts
CHANGED
|
@@ -1,8 +1,39 @@
|
|
|
1
1
|
import { Context } from '@wrongstack/core/agent';
|
|
2
2
|
import { ToolRegistry } from '@wrongstack/core/registry';
|
|
3
|
+
import { AutoApprovePermissionPolicy } from '@wrongstack/core/security';
|
|
3
4
|
import type { PermissionPolicy, Tool } from '@wrongstack/core/types';
|
|
4
5
|
import { type MCPServerPrompt, type MCPServerResource } from '@wrongstack/mcp';
|
|
5
6
|
import type { SubcommandDeps } from './subcommands/contracts.js';
|
|
7
|
+
/**
|
|
8
|
+
* `--yolo` for `mcp serve`: widen the CAPABILITY allowlist, keep every guard.
|
|
9
|
+
*
|
|
10
|
+
* This replaced an `AllowAllPermissionPolicy extends AutoApprovePermissionPolicy`
|
|
11
|
+
* whose `evaluate()` returned `{ permission: 'auto' }` unconditionally. That
|
|
12
|
+
* override skipped the whole base implementation — the sensitive-read denial,
|
|
13
|
+
* the leader deny rules, the destructive-command classifier, the agent-state
|
|
14
|
+
* write guard, and `LOCKED_DESTRUCTIVE_KINDS`. It was the only place in the
|
|
15
|
+
* codebase where `agent-state` and `credential-bind` could be un-gated, so a
|
|
16
|
+
* third-party MCP client could have written `hooks` into config.json (boot-time
|
|
17
|
+
* RCE) or `auto: true` into trust.json.
|
|
18
|
+
*
|
|
19
|
+
* It did not actually get there — but only by accident, and the accident is the
|
|
20
|
+
* reason this is a rewrite rather than a patch. The override returned
|
|
21
|
+
* `source: 'default'` where the base class returns `source: 'yolo'`, so
|
|
22
|
+
* `ToolExecutor.capabilityDowngraded` re-armed and forced `confirm`; `mcp serve`
|
|
23
|
+
* has no confirmAwaiter, so the call hard-errored. Changing that one string
|
|
24
|
+
* literal to `'yolo'` — which reads as a trivial consistency cleanup — would
|
|
25
|
+
* have made the bypass live. Safety must not rest on a string nobody knows is
|
|
26
|
+
* load-bearing.
|
|
27
|
+
*
|
|
28
|
+
* Granting every capability is what `--yolo` actually means, and it is what
|
|
29
|
+
* lets `ToolExecutor` trust an `auto` instead of downgrading it (see the
|
|
30
|
+
* `dangerousNotAllowed` reasoning in `auto-approve-policy.ts`). The destructive
|
|
31
|
+
* classifier is deliberately NOT relaxed: `yoloConfirmKinds` is left at its
|
|
32
|
+
* default, which gates every destructive kind. Destructive calls therefore
|
|
33
|
+
* still require a confirmation this surface cannot answer, exactly as before —
|
|
34
|
+
* this change removes a latent bypass without widening anything.
|
|
35
|
+
*/
|
|
36
|
+
export declare function yoloServePolicy(): AutoApprovePermissionPolicy;
|
|
6
37
|
/**
|
|
7
38
|
* Resolve the `--tools` whitelist for `mcp serve`.
|
|
8
39
|
*
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
handleHelpVersionShortCircuit
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-NR7BD73C.js";
|
|
4
4
|
import "./chunk-6WRKAACA.js";
|
|
5
5
|
import "./chunk-XJXDOF63.js";
|
|
6
6
|
import "./chunk-EK2P53GL.js";
|
|
7
7
|
export {
|
|
8
8
|
handleHelpVersionShortCircuit
|
|
9
9
|
};
|
|
10
|
-
//# sourceMappingURL=short-circuit-flags-
|
|
10
|
+
//# sourceMappingURL=short-circuit-flags-KBTYSJTW.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrongstack/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "WrongStack CLI — terminal AI coding agent with provider catalog from models.dev. Provides `wrongstack` and `wstack` binaries.",
|
|
6
6
|
"keywords": [
|
|
@@ -41,36 +41,36 @@
|
|
|
41
41
|
"data"
|
|
42
42
|
],
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@wrongstack/acp": "1.0.
|
|
45
|
-
"@wrongstack/bench": "1.0.
|
|
46
|
-
"@wrongstack/core": "1.0.
|
|
47
|
-
"@wrongstack/primitives": "1.0.
|
|
48
|
-
"@wrongstack/kanban": "1.0.
|
|
49
|
-
"@wrongstack/mcp": "1.0.
|
|
50
|
-
"@wrongstack/persistence": "1.0.
|
|
51
|
-
"@wrongstack/plug-lsp": "1.0.
|
|
52
|
-
"@wrongstack/plugins": "1.0.
|
|
53
|
-
"@wrongstack/providers": "1.0.
|
|
54
|
-
"@wrongstack/requirement-intake": "1.0.
|
|
55
|
-
"@wrongstack/runtime": "1.0.
|
|
56
|
-
"@wrongstack/sage": "1.0.
|
|
57
|
-
"@wrongstack/sdd": "1.0.
|
|
58
|
-
"@wrongstack/security-scanner": "1.0.
|
|
59
|
-
"@wrongstack/simpleui": "1.0.
|
|
60
|
-
"@wrongstack/techstack": "1.0.
|
|
61
|
-
"@wrongstack/telegram": "1.0.
|
|
62
|
-
"@wrongstack/tools": "1.0.
|
|
63
|
-
"@wrongstack/tui": "1.0.
|
|
64
|
-
"@wrongstack/vector-memory": "1.0.
|
|
65
|
-
"@wrongstack/webui": "1.0.
|
|
66
|
-
"@wrongstack/webui-hq": "1.0.
|
|
67
|
-
"@wrongstack/webui-protocol": "1.0.
|
|
68
|
-
"@wrongstack/wrongtrace": "1.0.
|
|
69
|
-
"@wrongstack/webui-server": "1.0.
|
|
44
|
+
"@wrongstack/acp": "1.0.6",
|
|
45
|
+
"@wrongstack/bench": "1.0.6",
|
|
46
|
+
"@wrongstack/core": "1.0.6",
|
|
47
|
+
"@wrongstack/primitives": "1.0.6",
|
|
48
|
+
"@wrongstack/kanban": "1.0.6",
|
|
49
|
+
"@wrongstack/mcp": "1.0.6",
|
|
50
|
+
"@wrongstack/persistence": "1.0.6",
|
|
51
|
+
"@wrongstack/plug-lsp": "1.0.6",
|
|
52
|
+
"@wrongstack/plugins": "1.0.6",
|
|
53
|
+
"@wrongstack/providers": "1.0.6",
|
|
54
|
+
"@wrongstack/requirement-intake": "1.0.6",
|
|
55
|
+
"@wrongstack/runtime": "1.0.6",
|
|
56
|
+
"@wrongstack/sage": "1.0.6",
|
|
57
|
+
"@wrongstack/sdd": "1.0.6",
|
|
58
|
+
"@wrongstack/security-scanner": "1.0.6",
|
|
59
|
+
"@wrongstack/simpleui": "1.0.6",
|
|
60
|
+
"@wrongstack/techstack": "1.0.6",
|
|
61
|
+
"@wrongstack/telegram": "1.0.6",
|
|
62
|
+
"@wrongstack/tools": "1.0.6",
|
|
63
|
+
"@wrongstack/tui": "1.0.6",
|
|
64
|
+
"@wrongstack/vector-memory": "1.0.6",
|
|
65
|
+
"@wrongstack/webui": "1.0.6",
|
|
66
|
+
"@wrongstack/webui-hq": "1.0.6",
|
|
67
|
+
"@wrongstack/webui-protocol": "1.0.6",
|
|
68
|
+
"@wrongstack/wrongtrace": "1.0.6",
|
|
69
|
+
"@wrongstack/webui-server": "1.0.6",
|
|
70
70
|
"ws": "^8.21.3"
|
|
71
71
|
},
|
|
72
72
|
"optionalDependencies": {
|
|
73
|
-
"@wrongstack/desktop": "1.0.
|
|
73
|
+
"@wrongstack/desktop": "1.0.6"
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
76
|
"@types/node": "^26.2.0",
|