@indigoai-us/hq-cli 5.47.6 → 5.47.8
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/commands/files-browse.d.ts +46 -6
- package/dist/commands/files-browse.js +134 -40
- package/dist/commands/signals.js +8 -3
- package/dist/commands/sources.js +8 -3
- package/package.json +2 -2
- package/src/commands/files-browse.test.ts +205 -41
- package/src/commands/files-browse.ts +227 -48
- package/src/commands/signals.ts +6 -0
- package/src/commands/sources.ts +6 -0
- package/test/commands/signals.test.ts +15 -8
- package/test/commands/sources.test.ts +15 -10
- package/test/helpers/vault-service-mock.ts +72 -1
|
@@ -98,6 +98,15 @@ export type S3ClientFactory = (input: {
|
|
|
98
98
|
sessionToken: string;
|
|
99
99
|
};
|
|
100
100
|
}) => FilesBrowseS3Client;
|
|
101
|
+
/**
|
|
102
|
+
* Factory for the COMPANY-mode browse client. Injectable for tests; the
|
|
103
|
+
* production implementation is `createCompanyPresignClient`. Keyed by
|
|
104
|
+
* `companyUid` (resolved by the orchestrator) — the access token is captured
|
|
105
|
+
* by the closure at the CLI layer.
|
|
106
|
+
*/
|
|
107
|
+
export type CompanyBrowseClientFactory = (input: {
|
|
108
|
+
companyUid: string;
|
|
109
|
+
}) => FilesBrowseS3Client;
|
|
101
110
|
/**
|
|
102
111
|
* ACL provenance for a single listed key.
|
|
103
112
|
* - `shared-with-you`: an explicit grant the caller holds covers the key.
|
|
@@ -190,12 +199,23 @@ export interface RunBrowseInput {
|
|
|
190
199
|
*/
|
|
191
200
|
personalUid?: string;
|
|
192
201
|
vaultClient: FilesBrowseVaultClient;
|
|
193
|
-
|
|
202
|
+
/** PERSONAL mode: builds a direct-S3 client from vended creds. */
|
|
203
|
+
s3Factory?: S3ClientFactory;
|
|
204
|
+
/**
|
|
205
|
+
* COMPANY mode (HQ-59): builds the presign/list-backed client. Company
|
|
206
|
+
* browse no longer talks to S3 directly and does not vend STS creds.
|
|
207
|
+
*/
|
|
208
|
+
companyClient?: CompanyBrowseClientFactory;
|
|
194
209
|
region: string;
|
|
195
210
|
}
|
|
196
211
|
export interface RunBrowseResult {
|
|
197
212
|
rows: BrowseRow[];
|
|
198
|
-
|
|
213
|
+
/**
|
|
214
|
+
* Present ONLY for the PERSONAL (vendSelf + direct S3) path. Company mode
|
|
215
|
+
* goes through the presign/list API and does not vend, so this is undefined
|
|
216
|
+
* there.
|
|
217
|
+
*/
|
|
218
|
+
vend?: BrowseVendResult;
|
|
199
219
|
}
|
|
200
220
|
/**
|
|
201
221
|
* `hq files browse <path>` orchestrator.
|
|
@@ -230,7 +250,10 @@ export interface RunCatInput {
|
|
|
230
250
|
/** Canonical person-entity UID; required when `personalMode: true`. */
|
|
231
251
|
personalUid?: string;
|
|
232
252
|
vaultClient: FilesBrowseVaultClient;
|
|
233
|
-
|
|
253
|
+
/** PERSONAL mode: builds a direct-S3 client from vended creds. */
|
|
254
|
+
s3Factory?: S3ClientFactory;
|
|
255
|
+
/** COMPANY mode (HQ-59): builds the presign/list-backed client. */
|
|
256
|
+
companyClient?: CompanyBrowseClientFactory;
|
|
234
257
|
region: string;
|
|
235
258
|
/** Destination stream for the stdout path. Injectable for tests. */
|
|
236
259
|
stdout?: NodeJS.WritableStream;
|
|
@@ -243,7 +266,8 @@ export interface RunCatResult {
|
|
|
243
266
|
kind: "file";
|
|
244
267
|
absPath: string;
|
|
245
268
|
};
|
|
246
|
-
|
|
269
|
+
/** Present ONLY for the PERSONAL (vendSelf + direct S3) path. */
|
|
270
|
+
vend?: BrowseVendResult;
|
|
247
271
|
}
|
|
248
272
|
/**
|
|
249
273
|
* `hq files cat <path>` orchestrator. Vends with `purpose: 'browse'`, then
|
|
@@ -308,7 +332,10 @@ export interface RunSearchInput {
|
|
|
308
332
|
personalMode?: boolean;
|
|
309
333
|
personalUid?: string;
|
|
310
334
|
vaultClient: FilesBrowseVaultClient;
|
|
311
|
-
|
|
335
|
+
/** PERSONAL mode: direct-S3 client factory. */
|
|
336
|
+
s3Factory?: S3ClientFactory;
|
|
337
|
+
/** COMPANY mode (HQ-59): presign/list client factory. */
|
|
338
|
+
companyClient?: CompanyBrowseClientFactory;
|
|
312
339
|
region: string;
|
|
313
340
|
}
|
|
314
341
|
/**
|
|
@@ -348,7 +375,11 @@ export interface RunGetInput {
|
|
|
348
375
|
hqRoot: string;
|
|
349
376
|
companySlug?: string;
|
|
350
377
|
vaultClient: FilesBrowseVaultClient;
|
|
351
|
-
|
|
378
|
+
/**
|
|
379
|
+
* COMPANY mode (HQ-59): presign/list client factory. `get` is company-only,
|
|
380
|
+
* so it always goes through the API — no direct S3, no STS vend.
|
|
381
|
+
*/
|
|
382
|
+
companyClient?: CompanyBrowseClientFactory;
|
|
352
383
|
region: string;
|
|
353
384
|
}
|
|
354
385
|
export interface RunGetResult {
|
|
@@ -372,6 +403,15 @@ export interface RunGetResult {
|
|
|
372
403
|
* HQ root itself, which is too broad to do implicitly.
|
|
373
404
|
*/
|
|
374
405
|
export declare function runGet(input: RunGetInput): Promise<RunGetResult>;
|
|
406
|
+
/**
|
|
407
|
+
* Build a COMPANY-mode browse client backed by the list + presign API. The
|
|
408
|
+
* access token + companyUid are captured here; the orchestrator just calls
|
|
409
|
+
* `send(...)` as if it held an S3 client.
|
|
410
|
+
*/
|
|
411
|
+
export declare function createCompanyPresignClient(input: {
|
|
412
|
+
token: string;
|
|
413
|
+
companyUid: string;
|
|
414
|
+
}): FilesBrowseS3Client;
|
|
375
415
|
/**
|
|
376
416
|
* Wire `hq files browse` + `hq files cat` onto an existing `files`
|
|
377
417
|
* Commander group. `registerFilesCommand` in files.ts builds the group
|
|
@@ -34,15 +34,16 @@
|
|
|
34
34
|
* methods and `grantPathToPrefix` from hq-cloud.
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
37
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="76062756-52c6-58a0-a647-9fcc95550911")}catch(e){}}();
|
|
38
38
|
import chalk from "chalk";
|
|
39
39
|
import * as fs from "node:fs";
|
|
40
40
|
import * as path from "node:path";
|
|
41
|
+
import { Readable } from "node:stream";
|
|
41
42
|
import { pipeline } from "node:stream/promises";
|
|
42
43
|
import { S3Client, ListObjectsV2Command, GetObjectCommand, } from "@aws-sdk/client-s3";
|
|
43
44
|
import { VaultClient, grantPathToPrefix, } from "@indigoai-us/hq-cloud";
|
|
44
45
|
import { DEFAULT_HQ_ROOT, DEFAULT_COGNITO, ensureCognitoToken, buildVaultConfig, } from "../utils/cognito-session.js";
|
|
45
|
-
import { getCompanyUid } from "../utils/vault-api.js";
|
|
46
|
+
import { getCompanyUid, vaultApiFetch } from "../utils/vault-api.js";
|
|
46
47
|
import { resolveCanonicalPersonUid } from "./cloud.js";
|
|
47
48
|
// ── Pure helpers ────────────────────────────────────────────────────────────
|
|
48
49
|
/**
|
|
@@ -142,6 +143,20 @@ export function formatBrowseTable(rows) {
|
|
|
142
143
|
];
|
|
143
144
|
return lines.join("\n");
|
|
144
145
|
}
|
|
146
|
+
/** Guard: the personal path needs an S3 factory. */
|
|
147
|
+
function requirePersonalS3Factory(f) {
|
|
148
|
+
if (!f) {
|
|
149
|
+
throw new Error("Personal-vault browse requires an s3Factory (direct-S3 client).");
|
|
150
|
+
}
|
|
151
|
+
return f;
|
|
152
|
+
}
|
|
153
|
+
/** Guard: the company path needs the presign/list client factory. */
|
|
154
|
+
function requireCompanyClient(f) {
|
|
155
|
+
if (!f) {
|
|
156
|
+
throw new Error("Company browse requires a companyClient (presign/list client).");
|
|
157
|
+
}
|
|
158
|
+
return f;
|
|
159
|
+
}
|
|
145
160
|
/**
|
|
146
161
|
* `hq files browse <path>` orchestrator.
|
|
147
162
|
*
|
|
@@ -156,7 +171,7 @@ export function formatBrowseTable(rows) {
|
|
|
156
171
|
* Pure-ish: no console output, no process.exit — caller renders + exits.
|
|
157
172
|
*/
|
|
158
173
|
export async function runBrowse(input) {
|
|
159
|
-
const { pathPrefix, vaultClient,
|
|
174
|
+
const { pathPrefix, vaultClient, region, personalMode } = input;
|
|
160
175
|
// Branch by mode. Company mode parses slug from path and looks up by
|
|
161
176
|
// namespace; personal mode resolves the entity directly by the supplied
|
|
162
177
|
// person UID and skips the slug + grants machinery (a person bucket has
|
|
@@ -165,6 +180,7 @@ export async function runBrowse(input) {
|
|
|
165
180
|
let entityUid;
|
|
166
181
|
let slug;
|
|
167
182
|
let vend;
|
|
183
|
+
let s3;
|
|
168
184
|
if (personalMode) {
|
|
169
185
|
if (!input.personalUid) {
|
|
170
186
|
throw new Error("runBrowse: personalMode requires personalUid. Resolve via " +
|
|
@@ -176,7 +192,17 @@ export async function runBrowse(input) {
|
|
|
176
192
|
}
|
|
177
193
|
entityUid = entity.uid;
|
|
178
194
|
bucket = entity.bucketName;
|
|
195
|
+
// Personal vault keeps the direct-S3 path: vend self creds, build an S3
|
|
196
|
+
// client. (HQ-59 scopes the migration to COMPANY mode.)
|
|
179
197
|
vend = await vaultClient.sts.vendSelf({ personUid: entityUid });
|
|
198
|
+
s3 = requirePersonalS3Factory(input.s3Factory)({
|
|
199
|
+
region,
|
|
200
|
+
credentials: {
|
|
201
|
+
accessKeyId: vend.credentials.accessKeyId,
|
|
202
|
+
secretAccessKey: vend.credentials.secretAccessKey,
|
|
203
|
+
sessionToken: vend.credentials.sessionToken,
|
|
204
|
+
},
|
|
205
|
+
});
|
|
180
206
|
}
|
|
181
207
|
else {
|
|
182
208
|
slug = input.companySlug ?? parseCompanySlugFromPath(pathPrefix);
|
|
@@ -189,19 +215,10 @@ export async function runBrowse(input) {
|
|
|
189
215
|
}
|
|
190
216
|
entityUid = entity.uid;
|
|
191
217
|
bucket = entity.bucketName;
|
|
192
|
-
//
|
|
193
|
-
//
|
|
194
|
-
|
|
195
|
-
vend = await vaultClient.sts.vend({ companyUid: entityUid });
|
|
218
|
+
// COMPANY mode (HQ-59): list/get go through the presign/list API, which
|
|
219
|
+
// enforces the same per-file ACLs server-side. No STS vend, no direct S3.
|
|
220
|
+
s3 = requireCompanyClient(input.companyClient)({ companyUid: entityUid });
|
|
196
221
|
}
|
|
197
|
-
const s3 = s3Factory({
|
|
198
|
-
region,
|
|
199
|
-
credentials: {
|
|
200
|
-
accessKeyId: vend.credentials.accessKeyId,
|
|
201
|
-
secretAccessKey: vend.credentials.secretAccessKey,
|
|
202
|
-
sessionToken: vend.credentials.sessionToken,
|
|
203
|
-
},
|
|
204
|
-
});
|
|
205
222
|
// Company vault keys are company-relative (no `companies/<slug>/` prefix), so
|
|
206
223
|
// translate the CLI's anchored prefix into the bucket-relative form before
|
|
207
224
|
// listing. Personal-mode paths are already bucket-relative.
|
|
@@ -253,7 +270,7 @@ export async function runBrowse(input) {
|
|
|
253
270
|
* containment guard). Refuses ahead of any I/O when `--out` is unsafe.
|
|
254
271
|
*/
|
|
255
272
|
export async function runCat(input) {
|
|
256
|
-
const { key, vaultClient,
|
|
273
|
+
const { key, vaultClient, region, hqRoot, personalMode } = input;
|
|
257
274
|
// Acceptance 5: refuse BEFORE vending — no point pulling credentials
|
|
258
275
|
// for a request we're already going to abort.
|
|
259
276
|
let absOut;
|
|
@@ -265,6 +282,7 @@ export async function runCat(input) {
|
|
|
265
282
|
let bucket;
|
|
266
283
|
let s3Key;
|
|
267
284
|
let vend;
|
|
285
|
+
let s3;
|
|
268
286
|
if (personalMode) {
|
|
269
287
|
if (!input.personalUid) {
|
|
270
288
|
throw new Error("runCat: personalMode requires personalUid. Resolve via " +
|
|
@@ -277,6 +295,14 @@ export async function runCat(input) {
|
|
|
277
295
|
bucket = entity.bucketName;
|
|
278
296
|
s3Key = key; // personal-mode keys are already bucket-relative
|
|
279
297
|
vend = await vaultClient.sts.vendSelf({ personUid: entity.uid });
|
|
298
|
+
s3 = requirePersonalS3Factory(input.s3Factory)({
|
|
299
|
+
region,
|
|
300
|
+
credentials: {
|
|
301
|
+
accessKeyId: vend.credentials.accessKeyId,
|
|
302
|
+
secretAccessKey: vend.credentials.secretAccessKey,
|
|
303
|
+
sessionToken: vend.credentials.sessionToken,
|
|
304
|
+
},
|
|
305
|
+
});
|
|
280
306
|
}
|
|
281
307
|
else {
|
|
282
308
|
const slug = input.companySlug ?? parseCompanySlugFromPath(key);
|
|
@@ -290,16 +316,9 @@ export async function runCat(input) {
|
|
|
290
316
|
bucket = entity.bucketName;
|
|
291
317
|
// Translate the anchored CLI key into the company-relative bucket key.
|
|
292
318
|
s3Key = toBucketRelative(key, slug);
|
|
293
|
-
|
|
319
|
+
// COMPANY mode (HQ-59): GetObject → presign GET. No STS vend, no direct S3.
|
|
320
|
+
s3 = requireCompanyClient(input.companyClient)({ companyUid: entity.uid });
|
|
294
321
|
}
|
|
295
|
-
const s3 = s3Factory({
|
|
296
|
-
region,
|
|
297
|
-
credentials: {
|
|
298
|
-
accessKeyId: vend.credentials.accessKeyId,
|
|
299
|
-
secretAccessKey: vend.credentials.secretAccessKey,
|
|
300
|
-
sessionToken: vend.credentials.sessionToken,
|
|
301
|
-
},
|
|
302
|
-
});
|
|
303
322
|
const resp = (await s3.send(new GetObjectCommand({ Bucket: bucket, Key: s3Key })));
|
|
304
323
|
if (!resp.Body) {
|
|
305
324
|
throw new Error(`GetObject for '${key}' returned no body.`);
|
|
@@ -417,6 +436,7 @@ export async function runSearch(input) {
|
|
|
417
436
|
personalUid: input.personalUid,
|
|
418
437
|
vaultClient: input.vaultClient,
|
|
419
438
|
s3Factory: input.s3Factory,
|
|
439
|
+
companyClient: input.companyClient,
|
|
420
440
|
region: input.region,
|
|
421
441
|
});
|
|
422
442
|
const q = input.query.toLowerCase();
|
|
@@ -467,7 +487,7 @@ export function addPin(hqRoot, companySlug, prefix) {
|
|
|
467
487
|
* HQ root itself, which is too broad to do implicitly.
|
|
468
488
|
*/
|
|
469
489
|
export async function runGet(input) {
|
|
470
|
-
const { path: vaultPath, vaultClient,
|
|
490
|
+
const { path: vaultPath, vaultClient, hqRoot } = input;
|
|
471
491
|
const slug = input.companySlug ?? parseCompanySlugFromPath(vaultPath);
|
|
472
492
|
const entity = await vaultClient.entity.findInMyNamespace("company", slug);
|
|
473
493
|
if (!entity) {
|
|
@@ -477,15 +497,9 @@ export async function runGet(input) {
|
|
|
477
497
|
throw new Error(`Company '${slug}' (${entity.uid}) has no provisioned bucket.`);
|
|
478
498
|
}
|
|
479
499
|
const bucket = entity.bucketName;
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
credentials: {
|
|
484
|
-
accessKeyId: vend.credentials.accessKeyId,
|
|
485
|
-
secretAccessKey: vend.credentials.secretAccessKey,
|
|
486
|
-
sessionToken: vend.credentials.sessionToken,
|
|
487
|
-
},
|
|
488
|
-
});
|
|
500
|
+
// COMPANY mode (HQ-59): list + get through the presign/list API. No STS vend,
|
|
501
|
+
// no direct S3 — the server enforces the same per-file read ACLs.
|
|
502
|
+
const s3 = requireCompanyClient(input.companyClient)({ companyUid: entity.uid });
|
|
489
503
|
// Company-relative prefix to list/fetch (bucket keys carry no anchor).
|
|
490
504
|
const bucketPrefix = toBucketRelative(vaultPath, slug);
|
|
491
505
|
const keys = [];
|
|
@@ -544,6 +558,86 @@ export async function runGet(input) {
|
|
|
544
558
|
}
|
|
545
559
|
// ── CLI registration ────────────────────────────────────────────────────────
|
|
546
560
|
const defaultS3Factory = ({ region, credentials }) => new S3Client({ region, credentials });
|
|
561
|
+
/**
|
|
562
|
+
* Build a COMPANY-mode browse client backed by the list + presign API. The
|
|
563
|
+
* access token + companyUid are captured here; the orchestrator just calls
|
|
564
|
+
* `send(...)` as if it held an S3 client.
|
|
565
|
+
*/
|
|
566
|
+
export function createCompanyPresignClient(input) {
|
|
567
|
+
const { token, companyUid } = input;
|
|
568
|
+
async function listObjects(cmd) {
|
|
569
|
+
const prefix = cmd.input.Prefix ?? "";
|
|
570
|
+
const query = { company: companyUid };
|
|
571
|
+
if (prefix.length > 0)
|
|
572
|
+
query.prefix = prefix;
|
|
573
|
+
if (cmd.input.ContinuationToken)
|
|
574
|
+
query.cursor = cmd.input.ContinuationToken;
|
|
575
|
+
const res = await vaultApiFetch({ token, path: "/v1/files/list", query });
|
|
576
|
+
if (!res.ok) {
|
|
577
|
+
const body = (await res.json().catch(() => ({})));
|
|
578
|
+
throw new Error(body.message ?? body.error ?? `files list failed (${res.status})`);
|
|
579
|
+
}
|
|
580
|
+
const body = (await res.json());
|
|
581
|
+
return {
|
|
582
|
+
// Map the API's company-relative objects onto the ListObjectsV2 shape the
|
|
583
|
+
// orchestrators read (Key / Size / LastModified / ETag). Re-quote the
|
|
584
|
+
// etag to match S3's quoted form, in case any caller compares it.
|
|
585
|
+
Contents: (body.objects ?? []).map((o) => ({
|
|
586
|
+
Key: o.key,
|
|
587
|
+
Size: o.size,
|
|
588
|
+
LastModified: o.lastModified ? new Date(o.lastModified) : undefined,
|
|
589
|
+
ETag: o.etag != null ? `"${o.etag}"` : undefined,
|
|
590
|
+
})),
|
|
591
|
+
NextContinuationToken: body.cursor ?? undefined,
|
|
592
|
+
IsTruncated: Boolean(body.truncated),
|
|
593
|
+
// $metadata is required by the SDK output type; the orchestrators never
|
|
594
|
+
// read it, so a minimal stub is sufficient.
|
|
595
|
+
$metadata: {},
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
async function getObject(cmd) {
|
|
599
|
+
const key = cmd.input.Key;
|
|
600
|
+
const res = await vaultApiFetch({
|
|
601
|
+
token,
|
|
602
|
+
path: "/v1/files/presign",
|
|
603
|
+
method: "POST",
|
|
604
|
+
body: { company: companyUid, key, op: "get" },
|
|
605
|
+
});
|
|
606
|
+
if (!res.ok) {
|
|
607
|
+
const body = (await res.json().catch(() => ({})));
|
|
608
|
+
throw new Error(body.message ?? body.error ?? `presign failed (${res.status})`);
|
|
609
|
+
}
|
|
610
|
+
const body = (await res.json());
|
|
611
|
+
const first = body.results?.[0];
|
|
612
|
+
if (!first || !first.url) {
|
|
613
|
+
// Per-key denial/validation surfaces here (e.g. FILES_PRESIGN_FORBIDDEN).
|
|
614
|
+
throw new Error(first?.error ?? `No presigned URL returned for '${key}'`);
|
|
615
|
+
}
|
|
616
|
+
const dl = await fetch(first.url);
|
|
617
|
+
if (!dl.ok) {
|
|
618
|
+
throw new Error(`Failed to download '${key}' (HTTP ${dl.status})`);
|
|
619
|
+
}
|
|
620
|
+
// fetch() yields a web ReadableStream; the orchestrators consume Body as a
|
|
621
|
+
// Node Readable (body.on('data') + stream pipeline), so adapt it. An empty
|
|
622
|
+
// body (no stream) becomes an empty Readable.
|
|
623
|
+
const nodeBody = dl.body
|
|
624
|
+
? Readable.fromWeb(dl.body)
|
|
625
|
+
: Readable.from([]);
|
|
626
|
+
return { Body: nodeBody, $metadata: {} };
|
|
627
|
+
}
|
|
628
|
+
function send(cmd) {
|
|
629
|
+
if (cmd instanceof ListObjectsV2Command)
|
|
630
|
+
return listObjects(cmd);
|
|
631
|
+
if (cmd instanceof GetObjectCommand)
|
|
632
|
+
return getObject(cmd);
|
|
633
|
+
throw new Error("createCompanyPresignClient: unsupported S3 command");
|
|
634
|
+
}
|
|
635
|
+
return { send };
|
|
636
|
+
}
|
|
637
|
+
/** Production company-mode client factory — closes over the caller's token. */
|
|
638
|
+
function makeCompanyPresignFactory(token) {
|
|
639
|
+
return ({ companyUid }) => createCompanyPresignClient({ token, companyUid });
|
|
640
|
+
}
|
|
547
641
|
/**
|
|
548
642
|
* Wire `hq files browse` + `hq files cat` onto an existing `files`
|
|
549
643
|
* Commander group. `registerFilesCommand` in files.ts builds the group
|
|
@@ -622,7 +716,7 @@ export function registerFilesBrowseCommands(filesCmd) {
|
|
|
622
716
|
pathPrefix: pathArg,
|
|
623
717
|
companySlug: slug,
|
|
624
718
|
vaultClient: client,
|
|
625
|
-
|
|
719
|
+
companyClient: makeCompanyPresignFactory(accessToken),
|
|
626
720
|
region: DEFAULT_COGNITO.region,
|
|
627
721
|
});
|
|
628
722
|
console.log(formatBrowseTable(result.rows));
|
|
@@ -699,7 +793,7 @@ export function registerFilesBrowseCommands(filesCmd) {
|
|
|
699
793
|
hqRoot: options.hqRoot,
|
|
700
794
|
companySlug: slug,
|
|
701
795
|
vaultClient: client,
|
|
702
|
-
|
|
796
|
+
companyClient: makeCompanyPresignFactory(accessToken),
|
|
703
797
|
region: DEFAULT_COGNITO.region,
|
|
704
798
|
});
|
|
705
799
|
if (result.destination.kind === "file") {
|
|
@@ -781,7 +875,7 @@ export function registerFilesBrowseCommands(filesCmd) {
|
|
|
781
875
|
query,
|
|
782
876
|
companySlug: company,
|
|
783
877
|
vaultClient: client,
|
|
784
|
-
|
|
878
|
+
companyClient: makeCompanyPresignFactory(accessToken),
|
|
785
879
|
region: DEFAULT_COGNITO.region,
|
|
786
880
|
});
|
|
787
881
|
console.log(formatBrowseTable(rows));
|
|
@@ -824,7 +918,7 @@ export function registerFilesBrowseCommands(filesCmd) {
|
|
|
824
918
|
hqRoot: options.hqRoot,
|
|
825
919
|
companySlug: slug,
|
|
826
920
|
vaultClient: client,
|
|
827
|
-
|
|
921
|
+
companyClient: makeCompanyPresignFactory(accessToken),
|
|
828
922
|
region: DEFAULT_COGNITO.region,
|
|
829
923
|
});
|
|
830
924
|
console.error(chalk.green("✓"), `Materialized ${result.filesWritten} file(s), ${result.bytesWritten} bytes.`);
|
|
@@ -839,4 +933,4 @@ export function registerFilesBrowseCommands(filesCmd) {
|
|
|
839
933
|
});
|
|
840
934
|
}
|
|
841
935
|
//# sourceMappingURL=files-browse.js.map
|
|
842
|
-
//# debugId=
|
|
936
|
+
//# debugId=76062756-52c6-58a0-a647-9fcc95550911
|
package/dist/commands/signals.js
CHANGED
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
* --type flag parsing.
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
23
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="395fa417-375a-55e7-b881-e65431742835")}catch(e){}}();
|
|
24
24
|
import * as fs from "node:fs";
|
|
25
25
|
import * as path from "node:path";
|
|
26
26
|
import chalk from "chalk";
|
|
27
|
-
import { SIGNAL_TYPES, assertSignalType, resolveEntity, listAvailableEntities, listSignals, getSignal, } from "@indigoai-us/hq-cloud";
|
|
27
|
+
import { SIGNAL_TYPES, assertSignalType, resolveEntity, listAvailableEntities, listSignals, getSignal, VaultClient, } from "@indigoai-us/hq-cloud";
|
|
28
28
|
import { ensureCognitoToken, buildVaultConfig, DEFAULT_HQ_ROOT, } from "../utils/cognito-session.js";
|
|
29
29
|
import { Sentry } from "../sentry.js";
|
|
30
30
|
// ---------------------------------------------------------------------------
|
|
@@ -110,6 +110,9 @@ async function runList(options) {
|
|
|
110
110
|
limit,
|
|
111
111
|
continuationToken: options.pageToken,
|
|
112
112
|
includeFrontmatter: options.includeFrontmatter,
|
|
113
|
+
// HQ-59: route company (cmp_) reads through the ACL-filtered presign
|
|
114
|
+
// transport (no direct S3). Personal vaults / no-client stay on S3.
|
|
115
|
+
vault: new VaultClient(vaultConfig),
|
|
113
116
|
});
|
|
114
117
|
if (format === "json") {
|
|
115
118
|
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
@@ -138,6 +141,8 @@ async function runGet(options) {
|
|
|
138
141
|
entity,
|
|
139
142
|
signalType,
|
|
140
143
|
signalId: options.id,
|
|
144
|
+
// HQ-59: company (cmp_) reads over presign; personal/no-client stay on S3.
|
|
145
|
+
vault: new VaultClient(vaultConfig),
|
|
141
146
|
});
|
|
142
147
|
if (format === "json") {
|
|
143
148
|
process.stdout.write(JSON.stringify(doc, null, 2) + "\n");
|
|
@@ -237,4 +242,4 @@ export function registerSignalsCommand(program) {
|
|
|
237
242
|
.action(withErrorHandling(async (options) => runEntities(options)));
|
|
238
243
|
}
|
|
239
244
|
//# sourceMappingURL=signals.js.map
|
|
240
|
-
//# debugId=
|
|
245
|
+
//# debugId=395fa417-375a-55e7-b881-e65431742835
|
package/dist/commands/sources.js
CHANGED
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
* --limit 50.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
21
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="1123e933-4c37-5679-ae51-84cffd42e31b")}catch(e){}}();
|
|
22
22
|
import * as fs from "node:fs";
|
|
23
23
|
import * as path from "node:path";
|
|
24
24
|
import chalk from "chalk";
|
|
25
|
-
import { SOURCE_CHANNELS, assertSourceChannel, resolveEntity, listAvailableEntities, listSources, getSource, } from "@indigoai-us/hq-cloud";
|
|
25
|
+
import { SOURCE_CHANNELS, assertSourceChannel, resolveEntity, listAvailableEntities, listSources, getSource, VaultClient, } from "@indigoai-us/hq-cloud";
|
|
26
26
|
import { ensureCognitoToken, buildVaultConfig, DEFAULT_HQ_ROOT, } from "../utils/cognito-session.js";
|
|
27
27
|
import { Sentry } from "../sentry.js";
|
|
28
28
|
// ---------------------------------------------------------------------------
|
|
@@ -118,6 +118,9 @@ async function runList(options) {
|
|
|
118
118
|
limit,
|
|
119
119
|
continuationToken: options.pageToken,
|
|
120
120
|
includeFrontmatter: options.includeFrontmatter,
|
|
121
|
+
// HQ-59: route company (cmp_) reads through the ACL-filtered presign
|
|
122
|
+
// transport (no direct S3). Personal vaults / no-client stay on S3.
|
|
123
|
+
vault: new VaultClient(vaultConfig),
|
|
121
124
|
});
|
|
122
125
|
if (format === "json") {
|
|
123
126
|
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
@@ -147,6 +150,8 @@ async function runGet(options) {
|
|
|
147
150
|
channel,
|
|
148
151
|
sourceId: options.id,
|
|
149
152
|
includeRaw: options.includeRaw,
|
|
153
|
+
// HQ-59: company (cmp_) reads over presign; personal/no-client stay on S3.
|
|
154
|
+
vault: new VaultClient(vaultConfig),
|
|
150
155
|
});
|
|
151
156
|
if (format === "json") {
|
|
152
157
|
process.stdout.write(JSON.stringify(doc, null, 2) + "\n");
|
|
@@ -247,4 +252,4 @@ export function registerSourcesCommand(program) {
|
|
|
247
252
|
.action(withErrorHandling(async (options) => runEntities(options)));
|
|
248
253
|
}
|
|
249
254
|
//# sourceMappingURL=sources.js.map
|
|
250
|
-
//# debugId=
|
|
255
|
+
//# debugId=1123e933-4c37-5679-ae51-84cffd42e31b
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@indigoai-us/hq-cli",
|
|
3
|
-
"version": "5.47.
|
|
3
|
+
"version": "5.47.8",
|
|
4
4
|
"description": "HQ by Indigo management CLI — modules and cloud sync",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"clean": "rm -rf dist"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@indigoai-us/hq-cloud": "^6.11.
|
|
18
|
+
"@indigoai-us/hq-cloud": "^6.11.6",
|
|
19
19
|
"@indigoai-us/hq-onboarding": "^0.1.0",
|
|
20
20
|
"@sentry/node": "^10.49.0",
|
|
21
21
|
"chalk": "^5.3.0",
|