@indigoai-us/hq-cli 5.342.18 → 5.343.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/CHANGELOG.md +5 -0
- package/dist/command-catalog.generated.d.ts +11 -3
- package/dist/command-catalog.generated.js +13 -3
- package/dist/commands/company.d.ts +12 -0
- package/dist/commands/company.js +103 -6
- package/dist/commands/mesh.js +6 -2
- package/dist/commands/pack-install.d.ts +2 -0
- package/dist/commands/pack-install.js +7 -0
- package/dist/commands/pkg-update.d.ts +2 -0
- package/dist/commands/pkg-update.js +5 -1
- package/dist/commands/secrets.js +2 -3
- package/dist/lib/doctor/checks/work-context.js +5 -0
- package/dist/lib/mesh/client.js +11 -0
- package/dist/lib/mesh/denial-codes.d.ts +13 -2
- package/dist/lib/mesh/denial-codes.js +25 -1
- package/dist/lib/mesh/live/daemon/doctor.js +4 -0
- package/dist/lib/work-context/outbox.js +8 -2
- package/dist/utils/resident-package-preload.d.ts +1 -1
- package/dist/utils/resident-package-preload.js +44 -0
- package/dist/utils/secrets-sandbox-resident.d.ts +5 -0
- package/dist/utils/secrets-sandbox-resident.js +8 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.343.0] — 2026-10-04
|
|
6
|
+
- `hq company --company <slug> settings set --work-registry-enabled <true|false>` and `--work-mesh-live-enabled <true|false>` let a company owner turn work tracking on or off. Work tracking needs both switches; after either is set the command says whether work tracking is on and prints the exact command for the switch that is still off. `hq company --company <slug> settings get` now also shows both switches for an owner or admin.
|
|
7
|
+
- `hq mesh context requeue` now also re-sends, by default, sessions that were refused while work tracking was off. `hq doctor` and `hq mesh daemon doctor` explain those refusals in plain words.
|
|
8
|
+
- Release the hq-cli package-use lease before the secrets sandbox poll and bounded package downloads after preloading their lazy runtime imports.
|
|
9
|
+
|
|
5
10
|
## [5.342.18] — 2026-10-04
|
|
6
11
|
- Preserve confirmed remote lane-message responses for in-process monitor delivery.
|
|
7
12
|
- Use native TypeScript renderers for `hq core rebuild-index` commands.
|
|
@@ -5334,7 +5334,7 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
5334
5334
|
readonly options: readonly [];
|
|
5335
5335
|
readonly subcommands: readonly [{
|
|
5336
5336
|
readonly name: "set";
|
|
5337
|
-
readonly description: "Set per-company settings (PUT /company-settings). Require at least one of --crm-enabled / --ontology-enabled / --accounting-enabled / --checkpoint-gate-enabled.";
|
|
5337
|
+
readonly description: "Set per-company settings (PUT /company-settings). Require at least one of --crm-enabled / --ontology-enabled / --accounting-enabled / --checkpoint-gate-enabled / --work-registry-enabled / --work-mesh-live-enabled.";
|
|
5338
5338
|
readonly aliases: readonly [];
|
|
5339
5339
|
readonly hidden: false;
|
|
5340
5340
|
readonly helpOption: true;
|
|
@@ -5358,11 +5358,19 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
5358
5358
|
readonly flags: "--checkpoint-gate-enabled <true|false>";
|
|
5359
5359
|
readonly description: "Require (true) or stop requiring (false) a checkpoint before HQ sessions in this company end a turn";
|
|
5360
5360
|
readonly hidden: false;
|
|
5361
|
+
}, {
|
|
5362
|
+
readonly flags: "--work-registry-enabled <true|false>";
|
|
5363
|
+
readonly description: "Turn work-session registration on or off for this company (default off). Work tracking needs this and --work-mesh-live-enabled";
|
|
5364
|
+
readonly hidden: false;
|
|
5365
|
+
}, {
|
|
5366
|
+
readonly flags: "--work-mesh-live-enabled <true|false>";
|
|
5367
|
+
readonly description: "Turn live work tracking on or off for this company (default off). Work tracking needs this and --work-registry-enabled";
|
|
5368
|
+
readonly hidden: false;
|
|
5361
5369
|
}];
|
|
5362
5370
|
readonly subcommands: readonly [];
|
|
5363
5371
|
}, {
|
|
5364
5372
|
readonly name: "get";
|
|
5365
|
-
readonly description: "Show whether the checkpoint Stop gate is on for this company (GET /company-settings/checkpoint-gate; any member may read it).";
|
|
5373
|
+
readonly description: "Show whether the checkpoint Stop gate is on for this company (GET /company-settings/checkpoint-gate; any member may read it) and, for an owner or admin, the two work tracking switches (GET /company-settings).";
|
|
5366
5374
|
readonly aliases: readonly [];
|
|
5367
5375
|
readonly hidden: false;
|
|
5368
5376
|
readonly helpOption: true;
|
|
@@ -9635,7 +9643,7 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
9635
9643
|
readonly subcommands: readonly [];
|
|
9636
9644
|
}, {
|
|
9637
9645
|
readonly name: "requeue";
|
|
9638
|
-
readonly description: "Requeue quarantined outbox operations (default:
|
|
9646
|
+
readonly description: "Requeue quarantined outbox operations (default: AUTH_DENIED - work-mesh-live gap 10 recovery - plus sessions refused while work tracking was off). Run once after the company owner turns work tracking on";
|
|
9639
9647
|
readonly aliases: readonly [];
|
|
9640
9648
|
readonly hidden: false;
|
|
9641
9649
|
readonly helpOption: true;
|
|
@@ -6478,7 +6478,7 @@ export const COMMAND_CATALOG = [
|
|
|
6478
6478
|
"subcommands": [
|
|
6479
6479
|
{
|
|
6480
6480
|
"name": "set",
|
|
6481
|
-
"description": "Set per-company settings (PUT /company-settings). Require at least one of --crm-enabled / --ontology-enabled / --accounting-enabled / --checkpoint-gate-enabled.",
|
|
6481
|
+
"description": "Set per-company settings (PUT /company-settings). Require at least one of --crm-enabled / --ontology-enabled / --accounting-enabled / --checkpoint-gate-enabled / --work-registry-enabled / --work-mesh-live-enabled.",
|
|
6482
6482
|
"aliases": [],
|
|
6483
6483
|
"hidden": false,
|
|
6484
6484
|
"helpOption": true,
|
|
@@ -6506,13 +6506,23 @@ export const COMMAND_CATALOG = [
|
|
|
6506
6506
|
"flags": "--checkpoint-gate-enabled <true|false>",
|
|
6507
6507
|
"description": "Require (true) or stop requiring (false) a checkpoint before HQ sessions in this company end a turn",
|
|
6508
6508
|
"hidden": false
|
|
6509
|
+
},
|
|
6510
|
+
{
|
|
6511
|
+
"flags": "--work-registry-enabled <true|false>",
|
|
6512
|
+
"description": "Turn work-session registration on or off for this company (default off). Work tracking needs this and --work-mesh-live-enabled",
|
|
6513
|
+
"hidden": false
|
|
6514
|
+
},
|
|
6515
|
+
{
|
|
6516
|
+
"flags": "--work-mesh-live-enabled <true|false>",
|
|
6517
|
+
"description": "Turn live work tracking on or off for this company (default off). Work tracking needs this and --work-registry-enabled",
|
|
6518
|
+
"hidden": false
|
|
6509
6519
|
}
|
|
6510
6520
|
],
|
|
6511
6521
|
"subcommands": []
|
|
6512
6522
|
},
|
|
6513
6523
|
{
|
|
6514
6524
|
"name": "get",
|
|
6515
|
-
"description": "Show whether the checkpoint Stop gate is on for this company (GET /company-settings/checkpoint-gate; any member may read it).",
|
|
6525
|
+
"description": "Show whether the checkpoint Stop gate is on for this company (GET /company-settings/checkpoint-gate; any member may read it) and, for an owner or admin, the two work tracking switches (GET /company-settings).",
|
|
6516
6526
|
"aliases": [],
|
|
6517
6527
|
"hidden": false,
|
|
6518
6528
|
"helpOption": true,
|
|
@@ -11686,7 +11696,7 @@ export const COMMAND_CATALOG = [
|
|
|
11686
11696
|
},
|
|
11687
11697
|
{
|
|
11688
11698
|
"name": "requeue",
|
|
11689
|
-
"description": "Requeue quarantined outbox operations (default:
|
|
11699
|
+
"description": "Requeue quarantined outbox operations (default: AUTH_DENIED - work-mesh-live gap 10 recovery - plus sessions refused while work tracking was off). Run once after the company owner turns work tracking on",
|
|
11690
11700
|
"aliases": [],
|
|
11691
11701
|
"hidden": false,
|
|
11692
11702
|
"helpOption": true,
|
|
@@ -1,3 +1,15 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
+
/**
|
|
3
|
+
* The two per-company switches that together turn work tracking on. The server
|
|
4
|
+
* refuses work-session registration unless both are true. `null` means the
|
|
5
|
+
* values could not be read.
|
|
6
|
+
*/
|
|
7
|
+
interface WorkTrackingSettings {
|
|
8
|
+
workRegistryEnabled: boolean;
|
|
9
|
+
workMeshLiveEnabled: boolean;
|
|
10
|
+
}
|
|
11
|
+
/** Plain next steps after a work tracking switch was set, from the effective settings. */
|
|
12
|
+
export declare function workTrackingNextSteps(companySlug: string, settings: WorkTrackingSettings | null): string[];
|
|
2
13
|
export declare function registerCompanyCommand(program: Command): void;
|
|
14
|
+
export {};
|
|
3
15
|
//# sourceMappingURL=company.d.ts.map
|
package/dist/commands/company.js
CHANGED
|
@@ -4,6 +4,64 @@ import { vaultApiFetch, getEntityUid } from "../utils/vault-api.js";
|
|
|
4
4
|
import { registerCompanyTransferCommand } from "./company-transfer.js";
|
|
5
5
|
import { registerCompanyRenameCommand } from "./company-rename.js";
|
|
6
6
|
import { describeRefreshOutcome, refreshCheckpointGateSetting, } from "./core-checkpoint-gate-setting.js";
|
|
7
|
+
/** Both switches from a settings response body, or null unless both are booleans. */
|
|
8
|
+
function workTrackingFromBody(body) {
|
|
9
|
+
const { workRegistryEnabled, workMeshLiveEnabled } = body;
|
|
10
|
+
return typeof workRegistryEnabled === "boolean" && typeof workMeshLiveEnabled === "boolean"
|
|
11
|
+
? { workRegistryEnabled, workMeshLiveEnabled }
|
|
12
|
+
: null;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Read both switches from GET /company-settings (owner or admin only). The
|
|
16
|
+
* server returns effective values, so an absent field means the default (off).
|
|
17
|
+
* A refused or failed read returns null rather than a guess.
|
|
18
|
+
*/
|
|
19
|
+
async function readWorkTrackingSettings(token, companyUid) {
|
|
20
|
+
try {
|
|
21
|
+
const res = await vaultApiFetch({
|
|
22
|
+
token,
|
|
23
|
+
path: "/company-settings",
|
|
24
|
+
query: { companyUid },
|
|
25
|
+
});
|
|
26
|
+
if (!res.ok)
|
|
27
|
+
return null;
|
|
28
|
+
const body = (await res.json().catch(() => ({})));
|
|
29
|
+
return {
|
|
30
|
+
workRegistryEnabled: body.workRegistryEnabled === true,
|
|
31
|
+
workMeshLiveEnabled: body.workMeshLiveEnabled === true,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Plain next steps after a work tracking switch was set, from the effective settings. */
|
|
39
|
+
export function workTrackingNextSteps(companySlug, settings) {
|
|
40
|
+
const command = `hq company --company ${companySlug} settings`;
|
|
41
|
+
if (!settings) {
|
|
42
|
+
return [`Could not read the settings back. Check both switches with: ${command} get`];
|
|
43
|
+
}
|
|
44
|
+
if (settings.workRegistryEnabled && settings.workMeshLiveEnabled) {
|
|
45
|
+
return [
|
|
46
|
+
"Work tracking is on.",
|
|
47
|
+
"Sessions refused while it was off are held on each machine. " +
|
|
48
|
+
"Each person should run once: hq mesh context requeue",
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
if (settings.workRegistryEnabled) {
|
|
52
|
+
return [
|
|
53
|
+
"Work tracking is not on yet. Sessions will still be refused until live tracking is also on. " +
|
|
54
|
+
`Run: ${command} set --work-mesh-live-enabled true`,
|
|
55
|
+
];
|
|
56
|
+
}
|
|
57
|
+
if (settings.workMeshLiveEnabled) {
|
|
58
|
+
return [
|
|
59
|
+
"Work tracking is not on yet. Sessions will still be refused until the work registry is also on. " +
|
|
60
|
+
`Run: ${command} set --work-registry-enabled true`,
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
return [`Work tracking is off for ${companySlug}.`];
|
|
64
|
+
}
|
|
7
65
|
/**
|
|
8
66
|
* Parse a `--flag <true|false>` string into a boolean, or throw. Commander
|
|
9
67
|
* passes the raw string; we validate strictly so a typo never silently writes
|
|
@@ -32,11 +90,14 @@ export function registerCompanyCommand(program) {
|
|
|
32
90
|
.command("set")
|
|
33
91
|
.description("Set per-company settings (PUT /company-settings). Require at least one " +
|
|
34
92
|
"of --crm-enabled / --ontology-enabled / --accounting-enabled / " +
|
|
35
|
-
"--checkpoint-gate-enabled
|
|
93
|
+
"--checkpoint-gate-enabled / --work-registry-enabled / " +
|
|
94
|
+
"--work-mesh-live-enabled.")
|
|
36
95
|
.option("--crm-enabled <true|false>", "Enable/disable the native CRM for this company")
|
|
37
96
|
.option("--ontology-enabled <true|false>", "Enable/disable the ontology gardener for this company")
|
|
38
97
|
.option("--accounting-enabled <true|false>", "Enable/disable the accounting pack for this company")
|
|
39
98
|
.option("--checkpoint-gate-enabled <true|false>", "Require (true) or stop requiring (false) a checkpoint before HQ sessions in this company end a turn")
|
|
99
|
+
.option("--work-registry-enabled <true|false>", "Turn work-session registration on or off for this company (default off). Work tracking needs this and --work-mesh-live-enabled")
|
|
100
|
+
.option("--work-mesh-live-enabled <true|false>", "Turn live work tracking on or off for this company (default off). Work tracking needs this and --work-registry-enabled")
|
|
40
101
|
.action(async (opts) => {
|
|
41
102
|
try {
|
|
42
103
|
const companySlug = company.opts().company;
|
|
@@ -47,8 +108,10 @@ export function registerCompanyCommand(program) {
|
|
|
47
108
|
if (opts.crmEnabled === undefined &&
|
|
48
109
|
opts.ontologyEnabled === undefined &&
|
|
49
110
|
opts.accountingEnabled === undefined &&
|
|
50
|
-
opts.checkpointGateEnabled === undefined
|
|
51
|
-
|
|
111
|
+
opts.checkpointGateEnabled === undefined &&
|
|
112
|
+
opts.workRegistryEnabled === undefined &&
|
|
113
|
+
opts.workMeshLiveEnabled === undefined) {
|
|
114
|
+
console.error(chalk.red("Error: provide at least one of --crm-enabled / --ontology-enabled / --accounting-enabled / --checkpoint-gate-enabled / --work-registry-enabled / --work-mesh-live-enabled."));
|
|
52
115
|
process.exit(1);
|
|
53
116
|
}
|
|
54
117
|
const body = {};
|
|
@@ -64,6 +127,14 @@ export function registerCompanyCommand(program) {
|
|
|
64
127
|
if (opts.checkpointGateEnabled !== undefined) {
|
|
65
128
|
body.checkpointGateEnabled = parseBoolFlag(opts.checkpointGateEnabled, "--checkpoint-gate-enabled");
|
|
66
129
|
}
|
|
130
|
+
if (opts.workRegistryEnabled !== undefined) {
|
|
131
|
+
body.workRegistryEnabled = parseBoolFlag(opts.workRegistryEnabled, "--work-registry-enabled");
|
|
132
|
+
}
|
|
133
|
+
if (opts.workMeshLiveEnabled !== undefined) {
|
|
134
|
+
body.workMeshLiveEnabled = parseBoolFlag(opts.workMeshLiveEnabled, "--work-mesh-live-enabled");
|
|
135
|
+
}
|
|
136
|
+
const setsWorkTracking = body.workRegistryEnabled !== undefined ||
|
|
137
|
+
body.workMeshLiveEnabled !== undefined;
|
|
67
138
|
const token = await ensureCognitoToken();
|
|
68
139
|
const companyUid = await getEntityUid(token, { companySlug });
|
|
69
140
|
body.companyUid = companyUid;
|
|
@@ -76,7 +147,9 @@ export function registerCompanyCommand(program) {
|
|
|
76
147
|
if (!res.ok) {
|
|
77
148
|
const errBody = (await res.json().catch(() => ({})));
|
|
78
149
|
if (res.status === 403) {
|
|
79
|
-
console.error(chalk.red(
|
|
150
|
+
console.error(chalk.red(setsWorkTracking
|
|
151
|
+
? "Only the company owner can change this setting."
|
|
152
|
+
: "Requires owner role on this company to change its settings."));
|
|
80
153
|
process.exit(1);
|
|
81
154
|
}
|
|
82
155
|
console.error(chalk.red(`Failed to update company settings: ${errBody.error ?? res.statusText}`));
|
|
@@ -98,6 +171,16 @@ export function registerCompanyCommand(program) {
|
|
|
98
171
|
// The setting is saved; the cache refreshes on the next Stop.
|
|
99
172
|
}
|
|
100
173
|
}
|
|
174
|
+
if (setsWorkTracking) {
|
|
175
|
+
// Registration needs both switches, so report the effective pair:
|
|
176
|
+
// from the PUT response when it echoes both, otherwise from a GET.
|
|
177
|
+
const resBody = (await res.json().catch(() => ({})));
|
|
178
|
+
const effective = workTrackingFromBody(resBody) ??
|
|
179
|
+
(await readWorkTrackingSettings(token, companyUid));
|
|
180
|
+
for (const line of workTrackingNextSteps(companySlug, effective)) {
|
|
181
|
+
console.log(line);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
101
184
|
}
|
|
102
185
|
catch (err) {
|
|
103
186
|
console.error(chalk.red("Error:"), err instanceof Error ? err.message : String(err));
|
|
@@ -107,7 +190,8 @@ export function registerCompanyCommand(program) {
|
|
|
107
190
|
settings
|
|
108
191
|
.command("get")
|
|
109
192
|
.description("Show whether the checkpoint Stop gate is on for this company " +
|
|
110
|
-
"(GET /company-settings/checkpoint-gate; any member may read it)
|
|
193
|
+
"(GET /company-settings/checkpoint-gate; any member may read it) and, " +
|
|
194
|
+
"for an owner or admin, the two work tracking switches (GET /company-settings).")
|
|
111
195
|
.option("--json", "Print the result as JSON")
|
|
112
196
|
.action(async (opts) => {
|
|
113
197
|
try {
|
|
@@ -137,11 +221,24 @@ export function registerCompanyCommand(program) {
|
|
|
137
221
|
console.error(chalk.red("Failed to read company settings: no checkpointGateEnabled in the response."));
|
|
138
222
|
process.exit(1);
|
|
139
223
|
}
|
|
224
|
+
// The work tracking switches are only on the owner/admin settings
|
|
225
|
+
// route. A refused or failed read is reported as unknown, not guessed.
|
|
226
|
+
const workTracking = await readWorkTrackingSettings(token, companyUid);
|
|
140
227
|
if (opts.json) {
|
|
141
|
-
console.log(JSON.stringify({
|
|
228
|
+
console.log(JSON.stringify({
|
|
229
|
+
company: companySlug,
|
|
230
|
+
checkpointGateEnabled: enabled,
|
|
231
|
+
workRegistryEnabled: workTracking?.workRegistryEnabled ?? null,
|
|
232
|
+
workMeshLiveEnabled: workTracking?.workMeshLiveEnabled ?? null,
|
|
233
|
+
}));
|
|
142
234
|
}
|
|
143
235
|
else {
|
|
144
236
|
console.log(`checkpointGateEnabled=${enabled}`);
|
|
237
|
+
for (const key of ["workRegistryEnabled", "workMeshLiveEnabled"]) {
|
|
238
|
+
console.log(workTracking
|
|
239
|
+
? `${key}=${workTracking[key]}`
|
|
240
|
+
: `${key}=unknown (only the company owner or an admin can read this setting)`);
|
|
241
|
+
}
|
|
145
242
|
}
|
|
146
243
|
}
|
|
147
244
|
catch (err) {
|
package/dist/commands/mesh.js
CHANGED
|
@@ -1424,7 +1424,9 @@ async function runContextRequeue(opts) {
|
|
|
1424
1424
|
}
|
|
1425
1425
|
const scope = errorCode === null
|
|
1426
1426
|
? "all quarantine reasons"
|
|
1427
|
-
:
|
|
1427
|
+
: errorCode === undefined
|
|
1428
|
+
? "lastErrorCode=AUTH_DENIED or refused while work tracking was off"
|
|
1429
|
+
: `lastErrorCode=${errorCode}`;
|
|
1428
1430
|
console.log(`Requeued ${requeued.length} quarantined outbox operation${requeued.length === 1 ? "" : "s"} (${scope}). The mesh daemon will retry them on its next replay.`);
|
|
1429
1431
|
}
|
|
1430
1432
|
async function runContextUntracked(sessionId, opts) {
|
|
@@ -2016,7 +2018,9 @@ export function registerMeshCommand(program) {
|
|
|
2016
2018
|
.action((opts) => wrap(() => runContextCorrect(opts))());
|
|
2017
2019
|
context
|
|
2018
2020
|
.command("requeue")
|
|
2019
|
-
.description("Requeue quarantined outbox operations (default:
|
|
2021
|
+
.description("Requeue quarantined outbox operations (default: AUTH_DENIED - work-mesh-live gap 10 recovery - " +
|
|
2022
|
+
"plus sessions refused while work tracking was off). " +
|
|
2023
|
+
"Run once after the company owner turns work tracking on")
|
|
2020
2024
|
.option("--all", "Requeue every quarantined op regardless of lastErrorCode")
|
|
2021
2025
|
.option("--error-code <code>", "Requeue quarantined ops with this lastErrorCode")
|
|
2022
2026
|
.option("--json", "Print machine-readable JSON")
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
* from each pack's package.yaml; rationale lives in the layout-fix PR.)
|
|
35
35
|
*/
|
|
36
36
|
import { type KeyObject } from 'node:crypto';
|
|
37
|
+
import { type ResidentCommandLeaseOptions } from '../utils/resident-package-preload.js';
|
|
37
38
|
import { type SecretResolver } from './mcp-registration.js';
|
|
38
39
|
import type { PackManifest } from '../types.js';
|
|
39
40
|
export interface ResolveLatestOptions {
|
|
@@ -447,6 +448,7 @@ export interface InstallPackOptions {
|
|
|
447
448
|
*/
|
|
448
449
|
requireSignature?: boolean;
|
|
449
450
|
}
|
|
451
|
+
export declare function runPackInstallWithLease<T>(run: () => Promise<T>, leaseOptions?: ResidentCommandLeaseOptions): Promise<T>;
|
|
450
452
|
export declare function installPack(source: string, opts?: InstallPackOptions): Promise<void>;
|
|
451
453
|
export {};
|
|
452
454
|
//# sourceMappingURL=pack-install.d.ts.map
|
|
@@ -50,6 +50,7 @@ import { codexTargets } from '../lib/install/codex-targets.js';
|
|
|
50
50
|
import { readHqVersion, routeContribution, listInstalledPacks, mcpServerNameForContribution } from '../utils/pack-contributions.js';
|
|
51
51
|
import { CONTRIBUTION_TABLE, payloadFor } from '../utils/contribution-table.js';
|
|
52
52
|
import { safeExtractTarball } from './safe-extract.js';
|
|
53
|
+
import { runResidentCommandWithPackageLease } from '../utils/resident-package-preload.js';
|
|
53
54
|
import { getCompanyUid, vaultApiFetch, vaultApiFetchPublic, } from '../utils/vault-api.js';
|
|
54
55
|
import { ensureCognitoToken } from '../utils/cognito-session.js';
|
|
55
56
|
import { formatApiKeyCapabilityDenial, peekHqApiKey, } from '../utils/resolve-vault-credential.js';
|
|
@@ -1677,7 +1678,13 @@ export function runScanPackages(hqRoot, opts = {}) {
|
|
|
1677
1678
|
console.log(chalk.yellow(' scan-packages.sh exited non-zero; see output above.'));
|
|
1678
1679
|
}
|
|
1679
1680
|
}
|
|
1681
|
+
export function runPackInstallWithLease(run, leaseOptions) {
|
|
1682
|
+
return runResidentCommandWithPackageLease("pack-install", run, leaseOptions);
|
|
1683
|
+
}
|
|
1680
1684
|
export async function installPack(source, opts = {}) {
|
|
1685
|
+
return runPackInstallWithLease(() => installPackWithoutLease(source, opts));
|
|
1686
|
+
}
|
|
1687
|
+
async function installPackWithoutLease(source, opts) {
|
|
1681
1688
|
// NOTE: the HQ_API_KEY fail-closed gate is NOT enforced here. `installPack`
|
|
1682
1689
|
// is a shared primitive called both by the top-level `hq install` CLI route
|
|
1683
1690
|
// (where Cognito-only is the right gate — checked there instead) AND by
|
|
@@ -5,5 +5,7 @@
|
|
|
5
5
|
* If slug given: update only that package.
|
|
6
6
|
*/
|
|
7
7
|
import { Command } from 'commander';
|
|
8
|
+
import { type ResidentCommandLeaseOptions } from '../utils/resident-package-preload.js';
|
|
8
9
|
export declare function registerPackageUpdateCommand(parent: Command): void;
|
|
10
|
+
export declare function runPackageUpdateWithLease<T>(run: () => Promise<T>, leaseOptions?: ResidentCommandLeaseOptions): Promise<T>;
|
|
9
11
|
//# sourceMappingURL=pkg-update.d.ts.map
|
|
@@ -9,6 +9,7 @@ import * as os from 'os';
|
|
|
9
9
|
import * as path from 'path';
|
|
10
10
|
import { parseUserYaml } from '../utils/user-yaml-error.js';
|
|
11
11
|
import { execSync } from 'child_process';
|
|
12
|
+
import { runResidentCommandWithPackageLease } from '../utils/resident-package-preload.js';
|
|
12
13
|
import chalk from 'chalk';
|
|
13
14
|
import { ensureCognitoToken } from '../utils/cognito-session.js';
|
|
14
15
|
import { resolveDefaultHqRoot } from '../utils/cognito-session.js';
|
|
@@ -21,7 +22,7 @@ export function registerPackageUpdateCommand(parent) {
|
|
|
21
22
|
.description('Check for and apply package updates')
|
|
22
23
|
.action(async (slug) => {
|
|
23
24
|
try {
|
|
24
|
-
await updatePackages(slug);
|
|
25
|
+
await runPackageUpdateWithLease(() => updatePackages(slug));
|
|
25
26
|
}
|
|
26
27
|
catch (error) {
|
|
27
28
|
console.error(chalk.red('Update failed:'), error instanceof Error ? error.message : 'Unknown error');
|
|
@@ -29,6 +30,9 @@ export function registerPackageUpdateCommand(parent) {
|
|
|
29
30
|
}
|
|
30
31
|
});
|
|
31
32
|
}
|
|
33
|
+
export function runPackageUpdateWithLease(run, leaseOptions) {
|
|
34
|
+
return runResidentCommandWithPackageLease("pkg-update", run, leaseOptions);
|
|
35
|
+
}
|
|
32
36
|
async function updatePackages(slug) {
|
|
33
37
|
const hqRoot = resolveDefaultHqRoot({ onMissing: 'throw' });
|
|
34
38
|
const entries = readRegistry(hqRoot);
|
package/dist/commands/secrets.js
CHANGED
|
@@ -10,6 +10,7 @@ import { SECRET_NAME_PATTERN, GROUP_ID_PATTERN, EMAIL_PATTERN } from "./_pattern
|
|
|
10
10
|
import { describeSecretsScope, formatSecretSaved, formatSecretsListEmpty, formatSecretsListHeader, } from "./secrets-scope.js";
|
|
11
11
|
import { vaultApiFetch, getCompanyUid, getEntityUid, looksLikeCompanyUid, } from "../utils/vault-api.js";
|
|
12
12
|
import { formatApiKeyCapabilityDenial, requireApiKeyCapability, resolveVaultCredentialForCapability, } from "../utils/resolve-vault-credential.js";
|
|
13
|
+
import { runSandboxJobAfterSubmission } from "../utils/secrets-sandbox-resident.js";
|
|
13
14
|
export { vaultApiFetch, getCompanyUid, getEntityUid };
|
|
14
15
|
/**
|
|
15
16
|
* Mirrors `RESOURCE_SURFACES` in hq-pro
|
|
@@ -1061,9 +1062,7 @@ export function registerSecretsCommand(program) {
|
|
|
1061
1062
|
secretNames: keys,
|
|
1062
1063
|
command,
|
|
1063
1064
|
});
|
|
1064
|
-
const job =
|
|
1065
|
-
? await client.getJob(token, started.jobId)
|
|
1066
|
-
: await client.pollJob(token, started.jobId);
|
|
1065
|
+
const job = await runSandboxJobAfterSubmission(client, token, started);
|
|
1067
1066
|
renderSandboxJobResult(job, keys);
|
|
1068
1067
|
const exitCode = typeof job.exitCode === "number" ? job.exitCode : undefined;
|
|
1069
1068
|
if (job.success === false || (exitCode !== undefined && exitCode !== 0) || job.status === "failed") {
|
|
@@ -13,6 +13,7 @@ import { workContextRoot, workContextSessionsDir } from "../../work-context/path
|
|
|
13
13
|
import { countDistinctHeldEvents, countJsonlLines, deadLetterNonEmpty, } from "../../mesh/live/spool.js";
|
|
14
14
|
import { workMeshDeadLetterPath, workMeshHeldPath, workMeshRoot, workMeshSpoolPath, } from "../../mesh/live/paths.js";
|
|
15
15
|
import { collectDaemonDoctor, formatDaemonDoctor, } from "../../mesh/live/daemon/doctor.js";
|
|
16
|
+
import { workSessionDenialReason } from "../../mesh/denial-codes.js";
|
|
16
17
|
export const WORK_CONTEXT_FAMILY_ID = "work-context";
|
|
17
18
|
export const WORK_CONTEXT_FAMILY_TITLE = "Work context";
|
|
18
19
|
const DEFAULT_DEPS = {
|
|
@@ -97,6 +98,9 @@ function runChecks(deps) {
|
|
|
97
98
|
]
|
|
98
99
|
.filter(Boolean)
|
|
99
100
|
.join(" ");
|
|
101
|
+
const quarantineDenialReason = showQuarantineReason
|
|
102
|
+
? workSessionDenialReason(stats.lastQuarantineServerCode)
|
|
103
|
+
: undefined;
|
|
100
104
|
results.push({
|
|
101
105
|
status: stats.quarantined > 0 ? "WARN" : "PASS",
|
|
102
106
|
checkId: "work-context.outbox-quarantined",
|
|
@@ -104,6 +108,7 @@ function runChecks(deps) {
|
|
|
104
108
|
message: `Outbox quarantined count=${stats.quarantined}${showQuarantineReason
|
|
105
109
|
? ` (last reason=${stats.lastQuarantineReason ?? "unknown"}${quarantineDetails ? `; ${quarantineDetails}` : ""})`
|
|
106
110
|
: ""}.`,
|
|
111
|
+
...(quarantineDenialReason ? { remediation: quarantineDenialReason } : {}),
|
|
107
112
|
});
|
|
108
113
|
// Default-company mode + migration capability (US-017B)
|
|
109
114
|
try {
|
package/dist/lib/mesh/client.js
CHANGED
|
@@ -79,6 +79,17 @@ export function createWorkSessionDeliverer(opts) {
|
|
|
79
79
|
if (status === 429 || (status >= 500 && status <= 599)) {
|
|
80
80
|
return { ok: false, retryable: true, code: `HTTP_${status}` };
|
|
81
81
|
}
|
|
82
|
+
if (status === 404 && isWorkSessionDenialCode(errorFields.code)) {
|
|
83
|
+
// Keep the allowlisted code (FEATURE_DISABLED) so the refusal can be
|
|
84
|
+
// explained and picked up by the default requeue filter.
|
|
85
|
+
return {
|
|
86
|
+
ok: false,
|
|
87
|
+
retryable: false,
|
|
88
|
+
code: "HTTP_404",
|
|
89
|
+
httpStatus: 404,
|
|
90
|
+
serverCode: errorFields.code,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
82
93
|
if (status === 404 ||
|
|
83
94
|
status === 409 ||
|
|
84
95
|
status === 410 ||
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Explicit refusal codes returned by hq-pro's work-session registration path:
|
|
3
|
+
* the 401/403 denials, plus the 404 FEATURE_DISABLED answer given while the
|
|
4
|
+
* company's Work Mesh Live setting is off.
|
|
5
|
+
*/
|
|
6
|
+
export declare const WORK_SESSION_DENIAL_CODES: readonly ["AUTH_REQUIRED", "AGENT_IDENTITY_UNVERIFIED", "IMPERSONATION_FORBIDDEN", "NO_PERSON_ENTITY", "INVALID_COMPANY", "WORK_REGISTRY_DISABLED", "FEATURE_DISABLED"];
|
|
7
|
+
/**
|
|
8
|
+
* Refusals that end once the company owner turns a setting on. The default
|
|
9
|
+
* `hq mesh context requeue` filter re-sends operations stored with these.
|
|
10
|
+
*/
|
|
11
|
+
export declare const WORK_TRACKING_OFF_DENIAL_CODES: readonly WorkSessionDenialCode[];
|
|
3
12
|
export type WorkSessionDenialCode = (typeof WORK_SESSION_DENIAL_CODES)[number];
|
|
4
13
|
export declare function isWorkSessionDenialCode(value: unknown): value is WorkSessionDenialCode;
|
|
14
|
+
/** Plain reason for a server denial code, or undefined when there is none. */
|
|
15
|
+
export declare function workSessionDenialReason(value: unknown): string | undefined;
|
|
5
16
|
//# sourceMappingURL=denial-codes.d.ts.map
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Explicit refusal codes returned by hq-pro's work-session registration path:
|
|
3
|
+
* the 401/403 denials, plus the 404 FEATURE_DISABLED answer given while the
|
|
4
|
+
* company's Work Mesh Live setting is off.
|
|
5
|
+
*/
|
|
2
6
|
export const WORK_SESSION_DENIAL_CODES = [
|
|
3
7
|
"AUTH_REQUIRED",
|
|
4
8
|
"AGENT_IDENTITY_UNVERIFIED",
|
|
@@ -6,9 +10,29 @@ export const WORK_SESSION_DENIAL_CODES = [
|
|
|
6
10
|
"NO_PERSON_ENTITY",
|
|
7
11
|
"INVALID_COMPANY",
|
|
8
12
|
"WORK_REGISTRY_DISABLED",
|
|
13
|
+
"FEATURE_DISABLED",
|
|
14
|
+
];
|
|
15
|
+
/**
|
|
16
|
+
* Refusals that end once the company owner turns a setting on. The default
|
|
17
|
+
* `hq mesh context requeue` filter re-sends operations stored with these.
|
|
18
|
+
*/
|
|
19
|
+
export const WORK_TRACKING_OFF_DENIAL_CODES = [
|
|
20
|
+
"WORK_REGISTRY_DISABLED",
|
|
21
|
+
"FEATURE_DISABLED",
|
|
9
22
|
];
|
|
10
23
|
export function isWorkSessionDenialCode(value) {
|
|
11
24
|
return typeof value === "string" &&
|
|
12
25
|
WORK_SESSION_DENIAL_CODES.includes(value);
|
|
13
26
|
}
|
|
27
|
+
/** Plain-language reasons for denial codes the user can act on. */
|
|
28
|
+
const WORK_SESSION_DENIAL_REASONS = {
|
|
29
|
+
WORK_REGISTRY_DISABLED: "Work tracking is turned off for this company. The company owner can turn it on with: hq company --company <slug> settings set --work-registry-enabled true",
|
|
30
|
+
FEATURE_DISABLED: "Live work tracking is turned off for this company. The company owner can turn it on with: hq company --company <slug> settings set --work-mesh-live-enabled true",
|
|
31
|
+
};
|
|
32
|
+
/** Plain reason for a server denial code, or undefined when there is none. */
|
|
33
|
+
export function workSessionDenialReason(value) {
|
|
34
|
+
return isWorkSessionDenialCode(value)
|
|
35
|
+
? WORK_SESSION_DENIAL_REASONS[value]
|
|
36
|
+
: undefined;
|
|
37
|
+
}
|
|
14
38
|
//# sourceMappingURL=denial-codes.js.map
|
|
@@ -23,6 +23,7 @@ import { readDaemonState } from "./state.js";
|
|
|
23
23
|
import { CLI_VERSION } from "../../../../cli-version.js";
|
|
24
24
|
import { resolveRunningCliEntry } from "./install.js";
|
|
25
25
|
import { readInstalledCliVersion } from "./version-drift.js";
|
|
26
|
+
import { workSessionDenialReason } from "../../denial-codes.js";
|
|
26
27
|
import { LEGACY_LISTENER_DOCTOR_LINE, legacyListenInstalled, } from "./legacy-listen.js";
|
|
27
28
|
export const UNHEALTHY_SPOOL_AGE_MS = 60_000;
|
|
28
29
|
function oldestJsonlAgeMs(filePath, nowMs) {
|
|
@@ -321,6 +322,9 @@ export function formatDaemonDoctor(report) {
|
|
|
321
322
|
.filter(Boolean)
|
|
322
323
|
.join(" ");
|
|
323
324
|
lines.push(`outbox quarantined: ${report.outboxQuarantined} (last reason=${report.outboxLastQuarantineReason ?? "unknown"}${quarantineDetails ? `; ${quarantineDetails}` : ""})`);
|
|
325
|
+
const denialReason = workSessionDenialReason(report.outboxLastQuarantineServerCode);
|
|
326
|
+
if (denialReason)
|
|
327
|
+
lines.push(denialReason);
|
|
324
328
|
}
|
|
325
329
|
if (report.emitMode !== "legacy" && report.heldCount > 0) {
|
|
326
330
|
lines.push(`held: ${report.heldCount} (needs_company; not sent as NONE)`);
|
|
@@ -8,7 +8,7 @@ import * as path from "node:path";
|
|
|
8
8
|
import { WORK_CONTEXT_CONTRACT_VERSION } from "./contract.js";
|
|
9
9
|
import { atomicWriteJson, ensureOwnerDir } from "./atomic.js";
|
|
10
10
|
import { NotTrackingError } from "./errors.js";
|
|
11
|
-
import { isWorkSessionDenialCode } from "../mesh/denial-codes.js";
|
|
11
|
+
import { isWorkSessionDenialCode, WORK_TRACKING_OFF_DENIAL_CODES, } from "../mesh/denial-codes.js";
|
|
12
12
|
import { readSessionState, stripRegisterReceiptEpisodes, updateSessionState, writeAcknowledgedRegisterBinding, } from "./state.js";
|
|
13
13
|
import { isSafeWorkContextSegment, workContextOutboxDir, workContextOutboxPath, } from "./paths.js";
|
|
14
14
|
/** Base delay for outbox retry backoff (attempt 1 → 30s). */
|
|
@@ -390,8 +390,14 @@ export function requeueQuarantinedOutbox(root, opts = {}) {
|
|
|
390
390
|
for (const op of listOutboxOperations(root)) {
|
|
391
391
|
if (op.delivery !== "quarantined")
|
|
392
392
|
continue;
|
|
393
|
-
|
|
393
|
+
// Default filter: AUTH_DENIED, plus refusals stored with a server code
|
|
394
|
+
// that means work tracking was off for the company (a 404 FEATURE_DISABLED
|
|
395
|
+
// is stored as HTTP_404). An explicit errorCode matches lastErrorCode only.
|
|
396
|
+
const workTrackingWasOff = opts.errorCode === undefined &&
|
|
397
|
+
WORK_TRACKING_OFF_DENIAL_CODES.includes(op.lastServerErrorCode ?? "");
|
|
398
|
+
if (errorCode !== null && op.lastErrorCode !== errorCode && !workTrackingWasOff) {
|
|
394
399
|
continue;
|
|
400
|
+
}
|
|
395
401
|
op.delivery = "queued";
|
|
396
402
|
op.attemptCount = 0;
|
|
397
403
|
op.lastErrorCode = undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type ResidentPackagePath = "agent-kit" | "agent-mcp" | "auth-login" | "agents-terminal" | "bot" | "bot-logs-follow" | "childWrapper" | "coreJobRun" | "login" | "mcp" | "daemon" | "daemon-logs-follow" | "mesh-daemon" | "lanes-watch" | "monitor-wait" | "monitor-run" | "agents-message-wait" | "integrations-oauth-wait";
|
|
1
|
+
export type ResidentPackagePath = "agent-kit" | "agent-mcp" | "auth-login" | "agents-terminal" | "bot" | "bot-logs-follow" | "childWrapper" | "coreJobRun" | "login" | "mcp" | "daemon" | "daemon-logs-follow" | "mesh-daemon" | "lanes-watch" | "monitor-wait" | "monitor-run" | "agents-message-wait" | "integrations-oauth-wait" | "secrets-sandbox" | "pkg-update" | "pack-install";
|
|
2
2
|
/** Runtime modules that resident commands may need after a wait starts. */
|
|
3
3
|
export declare const RESIDENT_PACKAGE_MODULES: Record<ResidentPackagePath, readonly string[]>;
|
|
4
4
|
export declare class ResidentPackagePreloadError extends Error {
|
|
@@ -63,6 +63,23 @@ export const RESIDENT_PACKAGE_MODULES = {
|
|
|
63
63
|
"monitor-run": ["../commands/lanes.js", "../lib/plan-limit-nag.js", "../utils/plan-gate-error.js", "../sentry.js", "open", "../utils/cognito-session.js", "../lib/first-sync-next-step.js", "@indigoai-us/hq-cloud"],
|
|
64
64
|
"agents-message-wait": ["../sentry.js", "../lib/plan-limit-nag.js", "../utils/plan-gate-error.js", "open", "../utils/cognito-session.js", "../lib/first-sync-next-step.js", "@indigoai-us/hq-cloud"],
|
|
65
65
|
"integrations-oauth-wait": ["../sentry.js", "../lib/plan-limit-nag.js", "../utils/plan-gate-error.js", "open", "../utils/cognito-session.js", "../lib/first-sync-next-step.js", "@indigoai-us/hq-cloud"],
|
|
66
|
+
"secrets-sandbox": [],
|
|
67
|
+
"pkg-update": ["../sentry.js", "../utils/cognito-session.js", "@indigoai-us/hq-cloud"],
|
|
68
|
+
"pack-install": [
|
|
69
|
+
"../sentry.js",
|
|
70
|
+
"../lib/plan-limit-nag.js",
|
|
71
|
+
"../utils/plan-gate-error.js",
|
|
72
|
+
"open",
|
|
73
|
+
"../commands/mcp-serve.js",
|
|
74
|
+
"../lib/daemon/mcp-oauth.js",
|
|
75
|
+
"../lib/mcp/tools.js",
|
|
76
|
+
"../lib/mcp/prompts.js",
|
|
77
|
+
"../utils/sandbox-runner-client.js",
|
|
78
|
+
"../utils/cli-telemetry.js",
|
|
79
|
+
"../utils/cognito-session.js",
|
|
80
|
+
"../lib/first-sync-next-step.js",
|
|
81
|
+
"@indigoai-us/hq-cloud",
|
|
82
|
+
],
|
|
66
83
|
};
|
|
67
84
|
const LOADERS = {
|
|
68
85
|
"agent-kit": [
|
|
@@ -248,6 +265,33 @@ const LOADERS = {
|
|
|
248
265
|
() => import("../lib/first-sync-next-step.js"),
|
|
249
266
|
() => import("@indigoai-us/hq-cloud"),
|
|
250
267
|
],
|
|
268
|
+
"secrets-sandbox": [],
|
|
269
|
+
"pkg-update": [
|
|
270
|
+
async () => {
|
|
271
|
+
const { preloadSentrySdk } = await import("../sentry.js");
|
|
272
|
+
preloadSentrySdk();
|
|
273
|
+
},
|
|
274
|
+
() => import("../utils/cognito-session.js"),
|
|
275
|
+
() => import("@indigoai-us/hq-cloud"),
|
|
276
|
+
],
|
|
277
|
+
"pack-install": [
|
|
278
|
+
async () => {
|
|
279
|
+
const { preloadSentrySdk } = await import("../sentry.js");
|
|
280
|
+
preloadSentrySdk();
|
|
281
|
+
},
|
|
282
|
+
() => import("../lib/plan-limit-nag.js"),
|
|
283
|
+
() => import("../utils/plan-gate-error.js"),
|
|
284
|
+
() => import("open"),
|
|
285
|
+
() => import("../commands/mcp-serve.js"),
|
|
286
|
+
() => import("../lib/daemon/mcp-oauth.js"),
|
|
287
|
+
() => import("../lib/mcp/tools.js"),
|
|
288
|
+
() => import("../lib/mcp/prompts.js"),
|
|
289
|
+
() => import("../utils/sandbox-runner-client.js"),
|
|
290
|
+
() => import("../utils/cli-telemetry.js"),
|
|
291
|
+
() => import("../utils/cognito-session.js"),
|
|
292
|
+
() => import("../lib/first-sync-next-step.js"),
|
|
293
|
+
() => import("@indigoai-us/hq-cloud"),
|
|
294
|
+
],
|
|
251
295
|
};
|
|
252
296
|
export class ResidentPackagePreloadError extends Error {
|
|
253
297
|
moduleSpecifier;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { SandboxRunnerClient, SandboxRunnerJob, SandboxRunnerStartResponse } from "./sandbox-runner-client.js";
|
|
2
|
+
import { type ResidentCommandLeaseOptions } from "./resident-package-preload.js";
|
|
3
|
+
/** Poll a submitted remote job after loading local result and error-path modules. */
|
|
4
|
+
export declare function runSandboxJobAfterSubmission(client: Pick<SandboxRunnerClient, "getJob" | "pollJob">, token: string, started: SandboxRunnerStartResponse, leaseOptions?: ResidentCommandLeaseOptions): Promise<SandboxRunnerJob>;
|
|
5
|
+
//# sourceMappingURL=secrets-sandbox-resident.d.ts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { runResidentCommandWithPackageLease } from "./resident-package-preload.js";
|
|
2
|
+
/** Poll a submitted remote job after loading local result and error-path modules. */
|
|
3
|
+
export function runSandboxJobAfterSubmission(client, token, started, leaseOptions) {
|
|
4
|
+
return runResidentCommandWithPackageLease("secrets-sandbox", () => started.status === "succeeded" || started.status === "failed"
|
|
5
|
+
? client.getJob(token, started.jobId)
|
|
6
|
+
: client.pollJob(token, started.jobId), leaseOptions);
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=secrets-sandbox-resident.js.map
|