@wrongstack/cli 0.306.4 → 0.307.0
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/{auth-L3WGSGDX.js → auth-TVOOHL4Q.js} +45 -106
- package/dist/boot/short-circuit-flags.d.ts +2 -2
- package/dist/chimera-cascade-evidence.d.ts +1 -1
- package/dist/chunk-2VMJ3E5Z.js +71 -0
- package/dist/{chunk-RHLQT3EV.js → chunk-CB35UVXO.js} +1636 -1528
- package/dist/{chunk-YKBRFSGL.js → chunk-DOJLAULS.js} +28 -28
- package/dist/{chunk-KXN5HZDL.js → chunk-PKHGLWUJ.js} +24 -6
- package/dist/{chunk-HITHEXE3.js → chunk-TOG7OMKJ.js} +2 -2
- package/dist/{chunk-ARWGQUB3.js → chunk-XSG33WHN.js} +15 -5
- package/dist/{cli-main-4TZCCZR6.js → cli-main-YDOZZOZA.js} +21606 -20849
- package/dist/cli-main.d.ts +0 -20
- package/dist/{execution-547PM3NI.js → execution-CGT6J5ZN.js} +304 -272
- package/dist/fleet/host-learning-scheduler.d.ts +27 -0
- package/dist/fleet/host-shadow-manager.d.ts +64 -0
- package/dist/fleet/host.d.ts +5 -140
- package/dist/{hq-ZK6PGN3W.js → hq-PA6RH2UW.js} +2 -2
- package/dist/hq-server/mailbox-gateway-manager.d.ts +32 -0
- package/dist/hq-server/routes/auth/bootstrap-routes.d.ts +5 -0
- package/dist/hq-server/routes/auth/common.d.ts +11 -0
- package/dist/hq-server/routes/auth/password-routes.d.ts +9 -0
- package/dist/hq-server/routes/auth/session-audit-routes.d.ts +6 -0
- package/dist/hq-server/routes/auth/totp-routes.d.ts +9 -0
- package/dist/hq-server/routes/auth-handlers.d.ts +5 -132
- package/dist/hq-server/routes/command-handlers.d.ts +7 -0
- package/dist/hq-server/routes/data-handlers.d.ts +8 -0
- package/dist/hq-server/routes/mailbox-handlers.d.ts +22 -0
- package/dist/hq-server/routes.d.ts +3 -3
- package/dist/hq-server/server-lifecycle.d.ts +37 -0
- package/dist/hq-server/snapshot.d.ts +6 -5
- package/dist/hq-server/types.d.ts +4 -0
- package/dist/hq-server/upgrade-handler.d.ts +34 -0
- package/dist/hq-server/ws-client-events.d.ts +25 -0
- package/dist/hq-server/ws-leader.d.ts +47 -0
- package/dist/hq-server/ws-resume.d.ts +27 -0
- package/dist/hq-server/ws.d.ts +4 -71
- package/dist/{hq-server-IVZLVCFV.js → hq-server-PBRU275L.js} +2 -2
- package/dist/hq-server.d.ts +0 -38
- package/dist/index.js +1267 -122
- package/dist/{mcp-W7HHN7IA.js → mcp-CMLFHRG2.js} +14 -7
- package/dist/mcp-serve.d.ts +12 -1
- package/dist/{modeldiag-6VS5KDP5.js → modeldiag-ICMPHT5L.js} +868 -831
- package/dist/{providers-models-HQN3AT3K.js → providers-models-4FAKM2WO.js} +4 -4
- package/dist/repl-eternal-loop.d.ts +8 -0
- package/dist/repl-goal-banner.d.ts +21 -0
- package/dist/slash-commands/brain-council.d.ts +36 -0
- package/dist/slash-commands/brain-status.d.ts +12 -0
- package/dist/slash-commands/kanban-board-handlers.d.ts +13 -0
- package/dist/slash-commands/kanban-lifecycle-diagnostics.d.ts +16 -0
- package/dist/slash-commands/kanban-task-subcommands.d.ts +8 -0
- package/dist/slash-commands/memory-audience.d.ts +14 -0
- package/dist/slash-commands/memory-gather.d.ts +9 -0
- package/dist/slash-commands/memory-stats.d.ts +5 -0
- package/dist/slash-commands/settings-mutations.d.ts +6 -0
- package/dist/slash-commands/settings-view.d.ts +5 -0
- package/dist/subcommands/handlers/modeldiag-bench.d.ts +10 -0
- package/dist/subcommands/handlers/modeldiag-eval.d.ts +27 -0
- package/dist/subcommands/handlers/modeldiag-test.d.ts +8 -0
- package/dist/{version-help-ASKQYXDJ.js → version-help-TFD6VPF3.js} +2 -2
- package/dist/vibe-protocol-wiring.d.ts +10 -0
- package/dist/webui-server/credential-watcher.d.ts +15 -0
- package/dist/webui-server/domain-handlers.d.ts +21 -0
- package/dist/webui-server/route-contexts.d.ts +41 -0
- package/dist/{webui-server-FTG7JAZU.js → webui-server-IPHGJGXE.js} +515 -437
- package/dist/wiring/cli-execute-builder.d.ts +88 -0
- package/dist/wiring/cli-heap-watchdog.d.ts +33 -0
- package/dist/wiring/cli-prompt-and-tools-setup.d.ts +25 -0
- package/dist/wiring/cli-slash-commands-setup.d.ts +79 -0
- package/dist/wiring/heap-watchdog-setup.d.ts +53 -0
- package/dist/wiring/metrics.d.ts +1 -0
- package/dist/wiring/replay-governance-setup.d.ts +31 -0
- package/package.json +27 -27
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Learning optimization scheduler and dispatch classifier for MultiAgentHost.
|
|
3
|
+
*
|
|
4
|
+
* @module fleet/host-learning-scheduler
|
|
5
|
+
*/
|
|
6
|
+
import { LearningOptimizationScheduler, type LearningOptimizerLlm } from '@wrongstack/core/agent-catalog';
|
|
7
|
+
import type { MultiAgentDeps } from './host-types.js';
|
|
8
|
+
export declare class HostLearningScheduler {
|
|
9
|
+
private readonly deps;
|
|
10
|
+
private learningOptimizer;
|
|
11
|
+
private learningSwept;
|
|
12
|
+
constructor(deps: MultiAgentDeps);
|
|
13
|
+
getOptimizer(): LearningOptimizationScheduler | null;
|
|
14
|
+
notifyCaptured(role: string): void;
|
|
15
|
+
sweep(): void;
|
|
16
|
+
classifyDispatch(task: string, candidates: {
|
|
17
|
+
role: string;
|
|
18
|
+
name: string;
|
|
19
|
+
summary: string;
|
|
20
|
+
}[]): Promise<{
|
|
21
|
+
role: string;
|
|
22
|
+
reason?: string | undefined;
|
|
23
|
+
} | null>;
|
|
24
|
+
resolveOptimizerLlm(): Promise<LearningOptimizerLlm | undefined>;
|
|
25
|
+
dispose(): void;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=host-learning-scheduler.d.ts.map
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-level Shadow Agent lifecycle and observation management.
|
|
3
|
+
*
|
|
4
|
+
* @module fleet/host-shadow-manager
|
|
5
|
+
*/
|
|
6
|
+
import type { SubagentConfig } from '@wrongstack/core/types';
|
|
7
|
+
import type { Director } from '@wrongstack/core/coordination';
|
|
8
|
+
import type { MultiAgentDeps, MultiAgentHostOptions } from './host-types.js';
|
|
9
|
+
export interface HostShadowManagerContext {
|
|
10
|
+
deps: MultiAgentDeps;
|
|
11
|
+
opts: MultiAgentHostOptions;
|
|
12
|
+
getDirector: () => Director | undefined;
|
|
13
|
+
spawnAndAssign: (subagentConfig: SubagentConfig, description: string, opts?: {
|
|
14
|
+
internalTask?: boolean;
|
|
15
|
+
stopShadowAfterTask?: boolean;
|
|
16
|
+
shadowIntervalMs?: number | undefined;
|
|
17
|
+
taskContext?: {
|
|
18
|
+
kanban?: {
|
|
19
|
+
boardId?: string;
|
|
20
|
+
taskId?: string;
|
|
21
|
+
projectRoot?: string;
|
|
22
|
+
};
|
|
23
|
+
} | undefined;
|
|
24
|
+
}) => Promise<{
|
|
25
|
+
subagentId: string;
|
|
26
|
+
taskId: string;
|
|
27
|
+
}>;
|
|
28
|
+
}
|
|
29
|
+
export declare class HostShadowManager {
|
|
30
|
+
private readonly ctx;
|
|
31
|
+
private shadowAgentId;
|
|
32
|
+
private shadowTaskId;
|
|
33
|
+
private readonly shadowTaskIds;
|
|
34
|
+
private readonly shadowOutstandingTaskIds;
|
|
35
|
+
private readonly shadowStopAfterTaskIds;
|
|
36
|
+
private shadowHeartbeatIntervalMs;
|
|
37
|
+
private shadowAutoStartSuppressions;
|
|
38
|
+
private shadowObservedWorkDepth;
|
|
39
|
+
private shadowPassInFlight;
|
|
40
|
+
private shadowQueuedProblem;
|
|
41
|
+
private readonly shadowActivityOffHandles;
|
|
42
|
+
constructor(ctx: HostShadowManagerContext);
|
|
43
|
+
getTaskIds(): ReadonlySet<string>;
|
|
44
|
+
isShadowTask(taskId: string): boolean;
|
|
45
|
+
getAgentId(): string | null;
|
|
46
|
+
getTaskId(): string | null;
|
|
47
|
+
enterShadowSpawn(): void;
|
|
48
|
+
exitShadowSpawn(): void;
|
|
49
|
+
onShadowTaskCompleted(taskId: string, subagentId: string): void;
|
|
50
|
+
armIfNeeded(): void;
|
|
51
|
+
recordShadowAgent(subagentId: string, taskId: string, intervalMs?: number): void;
|
|
52
|
+
clearShadowAgent(subagentId?: string): void;
|
|
53
|
+
markShadowTask(taskId: string): void;
|
|
54
|
+
addStopAfterTaskId(taskId: string): void;
|
|
55
|
+
removeShadowTask(taskId: string): void;
|
|
56
|
+
isActiveSubagent(subagentId: string): boolean;
|
|
57
|
+
private noteShadowWorkStarted;
|
|
58
|
+
private noteShadowWorkCompleted;
|
|
59
|
+
requestShadowPass(reason: string): void;
|
|
60
|
+
runShadowPass(reason: string): Promise<void>;
|
|
61
|
+
private stopShadowAfterTask;
|
|
62
|
+
dispose(): void;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=host-shadow-manager.d.ts.map
|
package/dist/fleet/host.d.ts
CHANGED
|
@@ -39,30 +39,12 @@ export declare class MultiAgentHost {
|
|
|
39
39
|
* Bounded to 20 entries with LRU eviction to prevent unbounded memory growth. */
|
|
40
40
|
private readonly acpRunnerCache;
|
|
41
41
|
private readonly learningRoles;
|
|
42
|
-
|
|
43
|
-
private learningOptimizer;
|
|
44
|
-
private learningSwept;
|
|
42
|
+
private readonly learningScheduler;
|
|
45
43
|
/** Adaptive concurrency controller — created in buildDirector() when config has
|
|
46
44
|
* adaptiveConcurrency.enabled = true. Monitors FleetBus for 429 errors and
|
|
47
45
|
* automatically adjusts maxConcurrent to prevent rate limiting. */
|
|
48
46
|
private adaptiveConcurrencyController?;
|
|
49
|
-
|
|
50
|
-
private shadowAgentId;
|
|
51
|
-
/** Assigned monitoring task for the active Shadow Agent. */
|
|
52
|
-
private shadowTaskId;
|
|
53
|
-
/** All internal Shadow Agent startup/heartbeat task ids, excluded from fleet summaries. */
|
|
54
|
-
private readonly shadowTaskIds;
|
|
55
|
-
/** Shadow task ids assigned but not yet completed. Prevents heartbeat backlog. */
|
|
56
|
-
private readonly shadowOutstandingTaskIds;
|
|
57
|
-
/** Shadow task ids whose subagent should stop immediately after the one-shot pass. */
|
|
58
|
-
private readonly shadowStopAfterTaskIds;
|
|
59
|
-
private shadowHeartbeatIntervalMs;
|
|
60
|
-
/** Suppresses buildDirector() auto-start while /shadow start is explicitly spawning one. */
|
|
61
|
-
private shadowAutoStartSuppressions;
|
|
62
|
-
private shadowObservedWorkDepth;
|
|
63
|
-
private shadowPassInFlight;
|
|
64
|
-
private shadowQueuedProblem;
|
|
65
|
-
private readonly shadowActivityOffHandles;
|
|
47
|
+
private readonly shadowManager;
|
|
66
48
|
/** Peer-awareness status broadcaster (mailbox `status` mails on subagent
|
|
67
49
|
* transitions + rich registry heartbeats). Started in buildDirector(),
|
|
68
50
|
* stopped in dispose(). */
|
|
@@ -92,23 +74,10 @@ export declare class MultiAgentHost {
|
|
|
92
74
|
private getCoordinator;
|
|
93
75
|
/** Public accessor for the Director — used by buildRoutingRunner. */
|
|
94
76
|
getDirector(): Director | undefined;
|
|
77
|
+
/** Run one shadow review pass immediately. */
|
|
78
|
+
runShadowPass(reason: string): Promise<void>;
|
|
95
79
|
private ensureCoordinator;
|
|
96
80
|
private buildDirector;
|
|
97
|
-
/**
|
|
98
|
-
* Arm host-owned Shadow observation. Healthy work windows stay fully
|
|
99
|
-
* deterministic; a one-shot LLM Shadow pass runs only after problematic work
|
|
100
|
-
* finishes, or when the user explicitly invokes /shadow start.
|
|
101
|
-
*/
|
|
102
|
-
private armShadowAgentIfNeeded;
|
|
103
|
-
private recordShadowAgent;
|
|
104
|
-
private clearShadowAgent;
|
|
105
|
-
private markShadowTask;
|
|
106
|
-
private isActiveSubagent;
|
|
107
|
-
private noteShadowWorkStarted;
|
|
108
|
-
private noteShadowWorkCompleted;
|
|
109
|
-
private requestShadowPass;
|
|
110
|
-
private runShadowPass;
|
|
111
|
-
private stopShadowAfterTask;
|
|
112
81
|
/**
|
|
113
82
|
* Returns the FleetEmitTool for director-mode subagents, if the director
|
|
114
83
|
* has been built. Used by makeSubagentFactory to inject the tool into
|
|
@@ -118,127 +87,30 @@ export declare class MultiAgentHost {
|
|
|
118
87
|
/**
|
|
119
88
|
* Build a per-role subagent factory: given a SubagentConfig, construct a
|
|
120
89
|
* fresh, isolated Agent with the role's filtered tools and (when the config
|
|
121
|
-
* carries one) the role's persona as an appended system-prompt block.
|
|
122
|
-
* so the autonomy-parallel engine can reuse the exact same agent-construction
|
|
123
|
-
* path the director/spawn flow uses — each parallel slot then runs as a real,
|
|
124
|
-
* specialized, concurrency-safe agent instead of sharing the leader's Context.
|
|
90
|
+
* carries one) the role's persona as an appended system-prompt block.
|
|
125
91
|
*/
|
|
126
92
|
makeSubagentFactory(config: Config): AgentFactory;
|
|
127
93
|
/**
|
|
128
94
|
* Build the per-subagent runner.
|
|
129
|
-
*
|
|
130
|
-
* ACP agents (provider: 'acp') get their own runner via
|
|
131
|
-
* makeACPSubagentRunner — they run external processes and don't go
|
|
132
|
-
* through the Agent factory. Regular agents use the standard
|
|
133
|
-
* makeAgentSubagentRunner path.
|
|
134
95
|
*/
|
|
135
96
|
buildSubagentRunner(config: Config): Promise<SubagentRunner>;
|
|
136
97
|
buildACPRunner(subagentId: string): Promise<SubagentRunner>;
|
|
137
98
|
spawnACP(subagentId: string, task: string, config: Config): Promise<string>;
|
|
138
|
-
/** Returns a tool slice for the subagent — full set unless restricted. */
|
|
139
99
|
private filterTools;
|
|
140
|
-
/** Resolved shared-mailbox project dir — same as the leader's checker. */
|
|
141
100
|
private mailboxProjectDir;
|
|
142
|
-
/**
|
|
143
|
-
* Construct + start the brain-gated FleetSupervisor over this director's
|
|
144
|
-
* fleet. Requires a BrainArbiter (production always wires one); without
|
|
145
|
-
* it there is no safe decision path, so supervision stays off. All
|
|
146
|
-
* actions flow through Director APIs — the supervisor never touches
|
|
147
|
-
* coordinator internals or budget negotiation.
|
|
148
|
-
*/
|
|
149
101
|
private buildFleetSupervisor;
|
|
150
|
-
/**
|
|
151
|
-
* Fire-and-forget report-back (wired as the Director's
|
|
152
|
-
* `taskResultNotifier`): posts a non-awaited task's outcome to THIS
|
|
153
|
-
* session's leader via the project mailbox. The leader's mailbox checker
|
|
154
|
-
* injects it inline before the next step, so `assign_task`-without-await
|
|
155
|
-
* results reach the conversation without polling. The body carries a
|
|
156
|
-
* short excerpt only — the full result stays in the director's completed
|
|
157
|
-
* cache, retrievable via `await_tasks`/`roll_up`.
|
|
158
|
-
*/
|
|
159
102
|
private reportTaskResultToLeader;
|
|
160
103
|
private subagentToolRegistry;
|
|
161
|
-
/**
|
|
162
|
-
* Spawn a fresh subagent and assign a single task. Returns task id.
|
|
163
|
-
*
|
|
164
|
-
* Optional `opts` lets the caller (a `/spawn` slash command or the
|
|
165
|
-
* future director surface) override the subagent's provider, model,
|
|
166
|
-
* and tool slice on a per-spawn basis. Without options, the legacy
|
|
167
|
-
* behavior holds: the subagent uses the leader's provider/model and
|
|
168
|
-
* the full tool registry.
|
|
169
|
-
*/
|
|
170
104
|
spawn(description: string, opts?: HostSpawnOptions): Promise<{
|
|
171
105
|
subagentId: string;
|
|
172
106
|
taskId: string;
|
|
173
107
|
}>;
|
|
174
|
-
/**
|
|
175
|
-
* Spawn a fresh subagent, assign a task, and **await** its completion.
|
|
176
|
-
*
|
|
177
|
-
* Unlike `spawn()`, which returns immediately with spawn metadata, this
|
|
178
|
-
* method blocks until the subagent finishes (success, failure, or timeout)
|
|
179
|
-
* and returns the full `TaskResult`. Use this when the caller needs the
|
|
180
|
-
* subagent's actual output — e.g. `/techstack` displaying the generated report
|
|
181
|
-
* in chat, or `/spawn` showing the result inline.
|
|
182
|
-
*
|
|
183
|
-
* Optional `opts` lets the caller override the subagent's provider, model,
|
|
184
|
-
* and tool slice per spawn.
|
|
185
|
-
*/
|
|
186
108
|
spawnAndWait(description: string, opts?: HostSpawnAndWaitOptions): Promise<TaskResult>;
|
|
187
|
-
/**
|
|
188
|
-
* Common spawn + assign logic shared by both director mode and raw
|
|
189
|
-
* coordinator mode. Extracts the identical body from the two branches
|
|
190
|
-
* in `spawn()` so future changes (e.g. adding a new field to both
|
|
191
|
-
* paths) are made in one place.
|
|
192
|
-
*
|
|
193
|
-
* Returns `{ subagentId, taskId }`. Caller holds `pending` tracking
|
|
194
|
-
* and event emission — the helper only talks to the coordinator.
|
|
195
|
-
*/
|
|
196
109
|
private _spawnAndAssign;
|
|
197
|
-
/**
|
|
198
|
-
* Relay a `task.completed` notification (from either the Director or
|
|
199
|
-
* the raw coordinator) to the EventBus so non-director TUIs and any
|
|
200
|
-
* other observer can react. We forward the full result shape rather
|
|
201
|
-
* than mutating the existing `task.completed` schema — coordination
|
|
202
|
-
* code already binds to that event, and adding subscribers there
|
|
203
|
-
* would change ordering semantics for those listeners.
|
|
204
|
-
*/
|
|
205
110
|
private emitLifecycleCompleted;
|
|
206
111
|
private recordLearningRole;
|
|
207
112
|
private captureCompletedTaskLearning;
|
|
208
|
-
/**
|
|
209
|
-
* Lazily built so a session that never spawns a subagent pays nothing, and
|
|
210
|
-
* so the policy is read from the live config rather than frozen at boot.
|
|
211
|
-
* Returns null when auto-optimization is switched off.
|
|
212
|
-
*/
|
|
213
|
-
private getLearningOptimizer;
|
|
214
|
-
/**
|
|
215
|
-
* Break a dispatch tie with a model when the keyword heuristic is ambiguous.
|
|
216
|
-
*
|
|
217
|
-
* Routes through the `dispatcher` model-matrix slot when one is configured —
|
|
218
|
-
* picking a role is a short classification, so it belongs on a cheap fast
|
|
219
|
-
* model rather than the leader's — and the session default otherwise.
|
|
220
|
-
* Returning `null` on any failure leaves the dispatcher on its heuristic
|
|
221
|
-
* result, so routing degrades rather than breaking a spawn.
|
|
222
|
-
*/
|
|
223
|
-
private classifyDispatch;
|
|
224
|
-
/**
|
|
225
|
-
* Resolve a model for the distillation pass. Uses the `memory-curator` slot
|
|
226
|
-
* of the model matrix when one is configured — curating learned knowledge is
|
|
227
|
-
* exactly that role's job — and the session default otherwise. A failure
|
|
228
|
-
* here is not fatal: the pass still writes the deterministic skill addenda.
|
|
229
|
-
*/
|
|
230
|
-
private resolveOptimizerLlm;
|
|
231
|
-
/**
|
|
232
|
-
* Evaluate every role with learning data once per session. Without it, a
|
|
233
|
-
* role that became eligible before this session would wait for its next
|
|
234
|
-
* capture — which for a rarely-used role can be never.
|
|
235
|
-
*/
|
|
236
|
-
private sweepLearningOptimization;
|
|
237
113
|
status(): FleetHostStatus;
|
|
238
|
-
/**
|
|
239
|
-
* Read-only concurrency + lifetime spawn budget for `/fleet status` and
|
|
240
|
-
* resume diagnostics. Safe when no director/fleet is active yet.
|
|
241
|
-
*/
|
|
242
114
|
budgetView(): import('./host-status.js').FleetBudgetView;
|
|
243
115
|
usage(): FleetHostUsage;
|
|
244
116
|
manifest(): Promise<string | null>;
|
|
@@ -248,13 +120,6 @@ export declare class MultiAgentHost {
|
|
|
248
120
|
stopAll(): Promise<void>;
|
|
249
121
|
getMaxConcurrent(): number;
|
|
250
122
|
setMaxConcurrent(n: number): void;
|
|
251
|
-
/**
|
|
252
|
-
* Clean up all listeners and resources held by the host.
|
|
253
|
-
* Unregisters all EventBus/FleetBus listeners registered in `buildDirector`
|
|
254
|
-
* and stops the Director and its coordinator.
|
|
255
|
-
*
|
|
256
|
-
* Safe to call multiple times — subsequent calls are no-ops.
|
|
257
|
-
*/
|
|
258
123
|
dispose(): Promise<void>;
|
|
259
124
|
}
|
|
260
125
|
//# sourceMappingURL=host.d.ts.map
|
|
@@ -51,7 +51,7 @@ var hqCmd = async (args, deps) => {
|
|
|
51
51
|
return 1;
|
|
52
52
|
};
|
|
53
53
|
async function startServer(deps) {
|
|
54
|
-
const { startHqServer } = await import("./hq-server-
|
|
54
|
+
const { startHqServer } = await import("./hq-server-PBRU275L.js");
|
|
55
55
|
const dataDir = resolveDataDir(deps);
|
|
56
56
|
const flags = deps.flags ?? {};
|
|
57
57
|
const host = typeof flags["host"] === "string" ? flags["host"] : HQ_CLI_DEFAULT_HOST;
|
|
@@ -701,4 +701,4 @@ export {
|
|
|
701
701
|
hqCmd,
|
|
702
702
|
resolveAuditActor
|
|
703
703
|
};
|
|
704
|
-
//# sourceMappingURL=hq-
|
|
704
|
+
//# sourceMappingURL=hq-PA6RH2UW.js.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mailbox gateway management and idle eviction for HQ server.
|
|
3
|
+
*
|
|
4
|
+
* @module hq-server/mailbox-gateway-manager
|
|
5
|
+
*/
|
|
6
|
+
import type { IncomingMessage } from 'node:http';
|
|
7
|
+
import { type MailboxHttpAccessDecision, MailboxHttpRateLimiter } from '@wrongstack/core/coordination';
|
|
8
|
+
import type { HqAuthState } from './auth-state.js';
|
|
9
|
+
import { type HqRouterMailboxGateway } from './routes.js';
|
|
10
|
+
import type { HqSessionEntry } from './types.js';
|
|
11
|
+
export interface MailboxGatewayManagerDeps {
|
|
12
|
+
host: string;
|
|
13
|
+
port: number;
|
|
14
|
+
mutableAuth: HqAuthState['mutableAuth'];
|
|
15
|
+
sessions: Map<string, HqSessionEntry>;
|
|
16
|
+
}
|
|
17
|
+
export declare class MailboxGatewayManager {
|
|
18
|
+
private readonly deps;
|
|
19
|
+
readonly mailboxGateways: Map<string, HqRouterMailboxGateway>;
|
|
20
|
+
readonly mailboxGatewayLastUsed: Map<string, number>;
|
|
21
|
+
readonly mailboxGatewayRateLimiter: MailboxHttpRateLimiter;
|
|
22
|
+
private readonly rateLimitCleanupTimer;
|
|
23
|
+
private readonly sweepTimer;
|
|
24
|
+
private readonly MAILBOX_GATEWAY_IDLE_TTL_MS;
|
|
25
|
+
private readonly MAILBOX_GATEWAY_SWEEP_INTERVAL_MS;
|
|
26
|
+
constructor(deps: MailboxGatewayManagerDeps);
|
|
27
|
+
authorizeMailboxGateway(req: IncomingMessage, projectDir: string): MailboxHttpAccessDecision;
|
|
28
|
+
getMailboxGateway(projectDir: string): HqRouterMailboxGateway;
|
|
29
|
+
private evictIdleGateways;
|
|
30
|
+
close(): void;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=mailbox-gateway-manager.d.ts.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type * as http from 'node:http';
|
|
2
|
+
import type { HqRouterMutableAuth, HqSessionEntry } from '../../types.js';
|
|
3
|
+
export declare function handleApiBootstrap(req: http.IncomingMessage, res: http.ServerResponse, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, secureCookies: boolean | undefined, bootstrapStore: import('@wrongstack/core/hq').HqBootstrapCodeStore): Promise<void>;
|
|
4
|
+
export declare function handleApiTokenUpgrade(req: http.IncomingMessage, res: http.ServerResponse, url: URL, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, secureCookies: boolean | undefined): Promise<void>;
|
|
5
|
+
//# sourceMappingURL=bootstrap-routes.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type * as http from 'node:http';
|
|
2
|
+
import { type HqAuthFile } from '@wrongstack/core/hq';
|
|
3
|
+
import { type HqBrowserAuthResult } from '../../auth.js';
|
|
4
|
+
import type { HqRouterMutableAuth, HqSessionEntry } from '../../types.js';
|
|
5
|
+
export declare function isLoopbackRequest(req: http.IncomingMessage): boolean;
|
|
6
|
+
export declare const HQ_AUTH_ADMIN_CAPABILITY = "auth.admin";
|
|
7
|
+
export declare function callerCanAdministerAuth(auth: HqBrowserAuthResult): boolean;
|
|
8
|
+
export declare function writeAuthAdminRequired(res: http.ServerResponse): void;
|
|
9
|
+
export declare function authorizeAuthAdmin(req: http.IncomingMessage, res: http.ServerResponse, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>): HqBrowserAuthResult;
|
|
10
|
+
export type ApplyHqAuthFile = (next: HqAuthFile) => void;
|
|
11
|
+
//# sourceMappingURL=common.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type * as http from 'node:http';
|
|
2
|
+
import type { LoginAttemptStore } from '../../login-attempt-store.js';
|
|
3
|
+
import type { HqRouterMutableAuth, HqSessionEntry } from '../../types.js';
|
|
4
|
+
import { type ApplyHqAuthFile } from './common.js';
|
|
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): Promise<void>;
|
|
7
|
+
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>;
|
|
9
|
+
//# sourceMappingURL=password-routes.d.ts.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type * as http from 'node:http';
|
|
2
|
+
import type { HqRouterMutableAuth, HqSessionEntry } from '../../types.js';
|
|
3
|
+
export declare function handleApiAuthSessions(_req: http.IncomingMessage, res: http.ServerResponse, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>): void;
|
|
4
|
+
export declare function handleApiAuthSessionsRevoke(_req: http.IncomingMessage, res: http.ServerResponse, url: URL, sessions: Map<string, HqSessionEntry>): Promise<void>;
|
|
5
|
+
export declare function handleApiAuthAudit(_req: http.IncomingMessage, res: http.ServerResponse, dataDir: string): void;
|
|
6
|
+
//# sourceMappingURL=session-audit-routes.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type * as http from 'node:http';
|
|
2
|
+
import type { LoginAttemptStore } from '../../login-attempt-store.js';
|
|
3
|
+
import type { HqRouterMutableAuth, HqSessionEntry } from '../../types.js';
|
|
4
|
+
import { type ApplyHqAuthFile } from './common.js';
|
|
5
|
+
export declare function handleApiLoginVerify(req: http.IncomingMessage, res: http.ServerResponse, _url: URL, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, loginAttempts: LoginAttemptStore, dataDir: string, secureCookies: boolean | undefined, applyAuthFile: ApplyHqAuthFile, trustedProxyHops: number): Promise<void>;
|
|
6
|
+
export declare function handleApiTotpSetup(req: http.IncomingMessage, res: http.ServerResponse, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, dataDir: string, applyAuthFile: ApplyHqAuthFile): Promise<void>;
|
|
7
|
+
export declare function handleApiTotpEnable(req: http.IncomingMessage, res: http.ServerResponse, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, dataDir: string, applyAuthFile: ApplyHqAuthFile): Promise<void>;
|
|
8
|
+
export declare function handleApiTotpDisable(req: http.IncomingMessage, res: http.ServerResponse, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, loginAttempts: LoginAttemptStore, dataDir: string, applyAuthFile: ApplyHqAuthFile, trustedProxyHops: number): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=totp-routes.d.ts.map
|
|
@@ -1,133 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Capability required to operate the account-security surface: enrolling or
|
|
8
|
-
* removing 2FA, changing the password without knowing it, listing and revoking
|
|
9
|
-
* browser sessions, and reading the auth audit log.
|
|
10
|
-
*
|
|
11
|
-
* WS-102: these routes used to gate on `if (!auth)` alone, so ANY authenticated
|
|
12
|
-
* principal could reach them — including the least-privileged token HQ mints on
|
|
13
|
-
* first run (`capabilities: ['control.enqueue']`). That token could
|
|
14
|
-
* `POST /api/auth/totp/setup` → `/enable`, receive the recovery codes, and take
|
|
15
|
-
* the `sessions.clear()` that enrollment performs. The operator was then held
|
|
16
|
-
* at `totpRequired: true` on every password login with no authenticator and no
|
|
17
|
-
* recovery codes, and `/totp/disable` demands auth they could no longer obtain:
|
|
18
|
-
* a one-request, unrecoverable lockout from a token scoped to enqueueing
|
|
19
|
-
* commands. Editing `auth.json` by hand was the only way back.
|
|
20
|
-
*/
|
|
21
|
-
export declare const HQ_AUTH_ADMIN_CAPABILITY = "auth.admin";
|
|
22
|
-
/**
|
|
23
|
-
* True when `auth` may operate the account-security surface.
|
|
24
|
-
*
|
|
25
|
-
* - Password-origin cookie sessions (`kind: 'cookie'` with no `tokenId`) are
|
|
26
|
-
* the operator themselves — always allowed.
|
|
27
|
-
* - A token with no `capabilities` field is unrestricted by the documented
|
|
28
|
-
* contract in `HqToken.capabilities`, so it is allowed.
|
|
29
|
-
* - A capability-scoped token must list {@link HQ_AUTH_ADMIN_CAPABILITY}.
|
|
30
|
-
*
|
|
31
|
-
* Token-origin cookie sessions resolve their capabilities from the LIVE token
|
|
32
|
-
* record on every request (see `authenticateBrowserRequest`), so upgrading a
|
|
33
|
-
* token to a cookie never widens what it can do here.
|
|
34
|
-
*/
|
|
35
|
-
export declare function callerCanAdministerAuth(auth: HqBrowserAuthResult): boolean;
|
|
36
|
-
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>;
|
|
37
|
-
export declare function handleApiLogin(req: http.IncomingMessage, res: http.ServerResponse, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, loginAttempts: LoginAttemptStore, secureCookies: boolean | undefined, trustedProxyHops: number): Promise<void>;
|
|
38
|
-
export declare function handleApiLogout(req: http.IncomingMessage, res: http.ServerResponse, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, secureCookies: boolean | undefined): Promise<void>;
|
|
39
|
-
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>;
|
|
40
|
-
/**
|
|
41
|
-
* Applies a freshly-persisted `auth.json` to the live server state.
|
|
42
|
-
*
|
|
43
|
-
* WS-101: this used to be a second, hand-rolled copy of the projection in
|
|
44
|
-
* `hq-server/auth-state.ts`. The two drifted in exactly the ways duplicated
|
|
45
|
-
* security code drifts: this copy skipped the expired-token filter on the
|
|
46
|
-
* CLIENT scope (re-admitting expired `/ws/client` tokens, where the upgrade
|
|
47
|
-
* gate does no expiry check of its own), never refreshed the raw token lists
|
|
48
|
-
* behind `tokenStats()`, and — worst — never re-ran the WS-010 exposure
|
|
49
|
-
* assessment, so `DELETE /api/auth/password` on a non-loopback bind dropped
|
|
50
|
-
* every gate into open mode until the `fs.watch` debounce happened to fire.
|
|
51
|
-
*
|
|
52
|
-
* It is now a function type supplied by the server, bound to
|
|
53
|
-
* `HqAuthState.apply`, so the mutation routes and the reload watcher share one
|
|
54
|
-
* projection and one floor evaluation.
|
|
55
|
-
*/
|
|
56
|
-
export type ApplyHqAuthFile = (next: HqAuthFile) => void;
|
|
57
|
-
export declare function handleApiBootstrap(req: http.IncomingMessage, res: http.ServerResponse, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, secureCookies: boolean | undefined, bootstrapStore: import('@wrongstack/core/hq').HqBootstrapCodeStore): Promise<void>;
|
|
58
|
-
/**
|
|
59
|
-
* WS-065 — exchange a live browser token for an HttpOnly session cookie.
|
|
60
|
-
*
|
|
61
|
-
* The bootstrap flow above already gives fresh startup URLs a cookie and never
|
|
62
|
-
* persists a client-side credential. What it does not cover is the *legacy*
|
|
63
|
-
* paths: an older `?token=` startup URL, and manual token entry in the token
|
|
64
|
-
* gate. Both leave the raw token in `sessionStorage`, where any script on the
|
|
65
|
-
* origin can read it. This endpoint lets the SPA complete that migration on
|
|
66
|
-
* its own — authenticate once with the token it already holds, receive a
|
|
67
|
-
* cookie, and delete the stored copy.
|
|
68
|
-
*
|
|
69
|
-
* The minted session is exactly the one `handleApiBootstrap` mints: `kind:
|
|
70
|
-
* 'token'` carrying the source token's id. That matters because
|
|
71
|
-
* `authenticateBrowserRequest` re-resolves a token-origin session's
|
|
72
|
-
* capabilities from the LIVE token record on every request, so upgrading
|
|
73
|
-
* grants nothing the token did not already grant and dies the moment the token
|
|
74
|
-
* is revoked. No privilege boundary is crossed: the caller proved possession
|
|
75
|
-
* of the token, and the cookie is strictly weaker (HttpOnly, same-origin,
|
|
76
|
-
* server-expiring).
|
|
77
|
-
*/
|
|
78
|
-
export declare function handleApiTokenUpgrade(req: http.IncomingMessage, res: http.ServerResponse, url: URL, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, secureCookies: boolean | undefined): Promise<void>;
|
|
79
|
-
/**
|
|
80
|
-
* POST `/api/login/verify` — complete 2FA for a pending-2FA session.
|
|
81
|
-
* Accepts either a TOTP `code` or a `recoveryCode`. On success, the pending
|
|
82
|
-
* session is upgraded to a full session (pending2fa cleared). Recovery codes
|
|
83
|
-
* are single-use: the matched hash is removed from `auth.json` on success.
|
|
84
|
-
*/
|
|
85
|
-
export declare function handleApiLoginVerify(req: http.IncomingMessage, res: http.ServerResponse, _url: URL, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, loginAttempts: LoginAttemptStore, dataDir: string, secureCookies: boolean | undefined, applyAuthFile: ApplyHqAuthFile, trustedProxyHops: number): Promise<void>;
|
|
86
|
-
/**
|
|
87
|
-
* POST `/api/auth/totp/setup` — generate a new TOTP secret (not yet active).
|
|
88
|
-
* Returns the base32 secret + otpauth URI for QR display. The secret is
|
|
89
|
-
* persisted as `totpPendingSecret` — login does NOT check this field, so
|
|
90
|
-
* an unconfirmed setup cannot lock the operator out. 2FA becomes active
|
|
91
|
-
* only after `/api/auth/totp/enable` verifies a code.
|
|
92
|
-
*
|
|
93
|
-
* Requires existing auth (cookie or token) — only the operator can set up 2FA.
|
|
94
|
-
*/
|
|
95
|
-
export declare function handleApiTotpSetup(req: http.IncomingMessage, res: http.ServerResponse, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, dataDir: string, applyAuthFile: ApplyHqAuthFile): Promise<void>;
|
|
96
|
-
/**
|
|
97
|
-
* POST `/api/auth/totp/enable` — confirm 2FA enrollment by providing a valid
|
|
98
|
-
* TOTP code. Promotes `totpPendingSecret` → `totpSecret` (active), generates
|
|
99
|
-
* and returns recovery codes (shown once). After this, 2FA is required for
|
|
100
|
-
* password login.
|
|
101
|
-
*/
|
|
102
|
-
export declare function handleApiTotpEnable(req: http.IncomingMessage, res: http.ServerResponse, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, dataDir: string, applyAuthFile: ApplyHqAuthFile): Promise<void>;
|
|
103
|
-
/**
|
|
104
|
-
* POST `/api/auth/totp/disable` — remove TOTP 2FA entirely. Requires the
|
|
105
|
-
* current password (or a valid TOTP code) as confirmation.
|
|
106
|
-
*/
|
|
107
|
-
export declare function handleApiTotpDisable(req: http.IncomingMessage, res: http.ServerResponse, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, loginAttempts: LoginAttemptStore, dataDir: string, applyAuthFile: ApplyHqAuthFile, trustedProxyHops: number): Promise<void>;
|
|
108
|
-
/**
|
|
109
|
-
* GET `/api/auth/sessions` — list all active browser sessions for the
|
|
110
|
-
* session-management UI.
|
|
111
|
-
*
|
|
112
|
-
* The full session ID is returned because the revoke endpoint below is keyed
|
|
113
|
-
* on it. That is safe on its own — the cookie value is `<id>.<HMAC>` and the
|
|
114
|
-
* HMAC needs `cookieSecret` — but it does hand every reader a working revoke
|
|
115
|
-
* handle for every other session, so the route is gated on `auth.admin`
|
|
116
|
-
* (WS-102) rather than on "is authenticated" as it was.
|
|
117
|
-
*
|
|
118
|
-
* The previous docstring claimed the full ID was never returned while the code
|
|
119
|
-
* returned it; the code was right about what the UI needs, the docstring was
|
|
120
|
-
* right about it deserving a gate.
|
|
121
|
-
*/
|
|
122
|
-
export declare function handleApiAuthSessions(_req: http.IncomingMessage, res: http.ServerResponse, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>): void;
|
|
123
|
-
/**
|
|
124
|
-
* DELETE `/api/auth/sessions/:id` — revoke a single session by ID.
|
|
125
|
-
* DELETE `/api/auth/sessions` — revoke ALL sessions (force logout everyone).
|
|
126
|
-
*/
|
|
127
|
-
export declare function handleApiAuthSessionsRevoke(_req: http.IncomingMessage, res: http.ServerResponse, url: URL, sessions: Map<string, HqSessionEntry>): Promise<void>;
|
|
128
|
-
/**
|
|
129
|
-
* GET `/api/auth/audit` — recent auth events for the audit panel.
|
|
130
|
-
* Returns the last 50 entries from auth-audit.jsonl, newest first.
|
|
131
|
-
*/
|
|
132
|
-
export declare function handleApiAuthAudit(_req: http.IncomingMessage, res: http.ServerResponse, dataDir: string): void;
|
|
1
|
+
export { authorizeAuthAdmin, callerCanAdministerAuth, HQ_AUTH_ADMIN_CAPABILITY, isLoopbackRequest, writeAuthAdminRequired, type ApplyHqAuthFile, } from './auth/common.js';
|
|
2
|
+
export { handleApiAuthStatus, handleApiLogin, handleApiLogout, handleApiPassword, } from './auth/password-routes.js';
|
|
3
|
+
export { handleApiLoginVerify, handleApiTotpDisable, handleApiTotpEnable, handleApiTotpSetup, } from './auth/totp-routes.js';
|
|
4
|
+
export { handleApiBootstrap, handleApiTokenUpgrade, } from './auth/bootstrap-routes.js';
|
|
5
|
+
export { handleApiAuthAudit, handleApiAuthSessions, handleApiAuthSessionsRevoke, } from './auth/session-audit-routes.js';
|
|
133
6
|
//# sourceMappingURL=auth-handlers.d.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type * as http from 'node:http';
|
|
2
|
+
import type { HqCommandAuditLog } from '@wrongstack/core/hq';
|
|
3
|
+
import type { TrustBoundary } from '@wrongstack/core/security';
|
|
4
|
+
import type { WebSocket } from 'ws';
|
|
5
|
+
import type { ConnectedClient, HqRouterMutableAuth, HqSessionEntry } from '../types.js';
|
|
6
|
+
export declare function handleApiCommand(req: http.IncomingMessage, res: http.ServerResponse, url: URL, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, clients: Map<WebSocket, ConnectedClient>, browsers: Set<WebSocket>, auditLog: HqCommandAuditLog, trustBoundary: TrustBoundary): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=command-handlers.d.ts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type * as http from 'node:http';
|
|
2
|
+
import type { createHqPersistence } from '@wrongstack/core/hq';
|
|
3
|
+
import type { WebSocket } from 'ws';
|
|
4
|
+
import type { ConnectedClient } from '../types.js';
|
|
5
|
+
export declare function handleApiProjectDetail(_req: http.IncomingMessage, res: http.ServerResponse, url: URL, clients: Map<WebSocket, ConnectedClient>): Promise<void>;
|
|
6
|
+
export declare function handleApiEvents(req: http.IncomingMessage, res: http.ServerResponse, persistence: ReturnType<typeof createHqPersistence>): Promise<void>;
|
|
7
|
+
export declare function handleApiTrendsCost(req: http.IncomingMessage, res: http.ServerResponse, persistence: ReturnType<typeof createHqPersistence>): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=data-handlers.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type * as http from 'node:http';
|
|
2
|
+
import { type MailboxHttpAccessDecision } from '@wrongstack/core/coordination';
|
|
3
|
+
import { authenticateBrowserRequest } from '../auth.js';
|
|
4
|
+
import type { HqRouterMailboxGateway, HqRouterMutableAuth, HqSessionEntry } from '../types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Does this authenticated caller hold `control.enqueue`?
|
|
7
|
+
*
|
|
8
|
+
* WS-012: this predicate was inlined at two call sites with a subtly different
|
|
9
|
+
* unauthenticated fallback (`!inBrowserTokenMode` vs
|
|
10
|
+
* `mutableAuth.browserTokens.size === 0` — equivalent, but drifting), and a
|
|
11
|
+
* third route, `POST /api/mailbox/messages/:id/action`, skipped it entirely:
|
|
12
|
+
* its auth parameters were `_`-prefixed to mark them deliberately unused. That
|
|
13
|
+
* left mailbox mutation (mark-read, acknowledge, reopen, soft-delete, restore)
|
|
14
|
+
* reachable by any authenticated caller regardless of capability.
|
|
15
|
+
*
|
|
16
|
+
* One helper so the three cannot diverge again.
|
|
17
|
+
*/
|
|
18
|
+
export declare function callerCanEnqueue(auth: ReturnType<typeof authenticateBrowserRequest>, mutableAuth: HqRouterMutableAuth): boolean;
|
|
19
|
+
export declare function handleMailboxGateway(_req: http.IncomingMessage, res: http.ServerResponse, match: RegExpMatchArray, authorizeMailboxGateway: (req: http.IncomingMessage, projectDir: string) => MailboxHttpAccessDecision, getMailboxGateway: (projectDir: string) => HqRouterMailboxGateway, dataDir: string): Promise<void>;
|
|
20
|
+
export declare function handleApiMailboxSend(_req: http.IncomingMessage, res: http.ServerResponse, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, dataDir: string, getMailboxGateway: (projectDir: string) => HqRouterMailboxGateway, hqSessionTag: string): Promise<void>;
|
|
21
|
+
export declare function handleMailboxAction(_req: http.IncomingMessage, res: http.ServerResponse, match: RegExpMatchArray, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, dataDir: string, getMailboxGateway: (projectDir: string) => HqRouterMailboxGateway): Promise<void>;
|
|
22
|
+
//# sourceMappingURL=mailbox-handlers.d.ts.map
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import type * as http from 'node:http';
|
|
11
11
|
import type { createMailboxHttpRouter } from '@wrongstack/core/coordination';
|
|
12
|
-
import {
|
|
12
|
+
import type { Mailbox, MailboxHttpAccessDecision, MailboxHttpRateLimiter } from '@wrongstack/core/coordination';
|
|
13
13
|
import type { HqAlertEngine, HqCommandAuditLog, HqEventEnvelope, HqSnapshot, HqTranscriptEntry } from '@wrongstack/core/hq';
|
|
14
|
-
import {
|
|
14
|
+
import type { createHqPersistence } from '@wrongstack/core/hq';
|
|
15
15
|
import type { TrustBoundary } from '@wrongstack/core/security';
|
|
16
16
|
import type { WebSocket } from 'ws';
|
|
17
17
|
import * as HqServerAuth from './auth.js';
|
|
@@ -89,7 +89,7 @@ export interface HqRouterDeps {
|
|
|
89
89
|
bootstrapStore?: import('@wrongstack/core/hq').HqBootstrapCodeStore | undefined;
|
|
90
90
|
/**
|
|
91
91
|
* Applies a freshly-persisted `auth.json` to live server state. Bound to
|
|
92
|
-
|
|
92
|
+
* `HqAuthState.apply` so the in-process mutation routes share one projection
|
|
93
93
|
* — and one WS-010 exposure re-assessment — with the reload watcher.
|
|
94
94
|
*/
|
|
95
95
|
applyAuthFile: ApplyHqAuthFile;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HQ server lifecycle and shutdown management.
|
|
3
|
+
*
|
|
4
|
+
* @module hq-server/server-lifecycle
|
|
5
|
+
*/
|
|
6
|
+
import type { Server as HttpServer } from 'node:http';
|
|
7
|
+
import type { WebSocket, WebSocketServer } from 'ws';
|
|
8
|
+
import type { HqPersistence } from '@wrongstack/core/hq';
|
|
9
|
+
import type { LoginAttemptStore } from './login-attempt-store.js';
|
|
10
|
+
import type { MailboxGatewayManager } from './mailbox-gateway-manager.js';
|
|
11
|
+
export interface HqServerShutdownParams {
|
|
12
|
+
cleanupTimer: NodeJS.Timeout;
|
|
13
|
+
browserHeartbeatTimer: NodeJS.Timeout;
|
|
14
|
+
timeseriesFlushTimer: NodeJS.Timeout;
|
|
15
|
+
sessionCleanupTimer: NodeJS.Timeout;
|
|
16
|
+
loginAttempts: LoginAttemptStore;
|
|
17
|
+
stopAlertEngine: () => void;
|
|
18
|
+
authWatcher: {
|
|
19
|
+
close(): void;
|
|
20
|
+
};
|
|
21
|
+
snapshotBroadcaster: {
|
|
22
|
+
close(): void;
|
|
23
|
+
};
|
|
24
|
+
bootstrapStore: {
|
|
25
|
+
clear(): void;
|
|
26
|
+
};
|
|
27
|
+
persistence: HqPersistence;
|
|
28
|
+
browsers: Set<WebSocket>;
|
|
29
|
+
clients: Map<WebSocket, unknown>;
|
|
30
|
+
wss: WebSocketServer;
|
|
31
|
+
mailboxManager: MailboxGatewayManager;
|
|
32
|
+
httpServer: HttpServer;
|
|
33
|
+
dataDir: string;
|
|
34
|
+
hqUrl: string;
|
|
35
|
+
}
|
|
36
|
+
export declare function createHqServerShutdown(params: HqServerShutdownParams): () => Promise<void>;
|
|
37
|
+
//# sourceMappingURL=server-lifecycle.d.ts.map
|