@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.
@@ -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
- s3Factory: S3ClientFactory;
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
- vend: BrowseVendResult;
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
- s3Factory: S3ClientFactory;
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
- vend: BrowseVendResult;
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
- s3Factory: S3ClientFactory;
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
- s3Factory: S3ClientFactory;
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]="cad165f9-6445-5434-969b-e0705274aa56")}catch(e){}}();
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, s3Factory, region, personalMode } = input;
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
- // Multi-tenant vend: the server resolves this company's bucket + applies
193
- // owner/admin role-bypass (full access) or member/guest ACL scoping. The
194
- // legacy `POST /vend` is unused here — see FilesBrowseVaultClient docs.
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, s3Factory, region, hqRoot, personalMode } = input;
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
- vend = await vaultClient.sts.vend({ companyUid: entity.uid });
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, s3Factory, region, hqRoot } = input;
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
- const vend = await vaultClient.sts.vend({ companyUid: entity.uid });
481
- const s3 = s3Factory({
482
- region,
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
- s3Factory: defaultS3Factory,
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
- s3Factory: defaultS3Factory,
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
- s3Factory: defaultS3Factory,
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
- s3Factory: defaultS3Factory,
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=cad165f9-6445-5434-969b-e0705274aa56
936
+ //# debugId=76062756-52c6-58a0-a647-9fcc95550911
@@ -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]="2088e3af-a005-57eb-b642-90aca198460b")}catch(e){}}();
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=2088e3af-a005-57eb-b642-90aca198460b
245
+ //# debugId=395fa417-375a-55e7-b881-e65431742835
@@ -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]="df18b298-4724-5557-a579-edfa0f468361")}catch(e){}}();
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=df18b298-4724-5557-a579-edfa0f468361
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.6",
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.4",
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",