@indigoai-us/hq-cli 5.6.0 → 5.6.2
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.
|
@@ -55,10 +55,12 @@ export interface ProvisionResult {
|
|
|
55
55
|
manifest_patched: boolean;
|
|
56
56
|
config_written: boolean;
|
|
57
57
|
initial_sync: {
|
|
58
|
-
ok
|
|
58
|
+
ok?: boolean;
|
|
59
59
|
files_uploaded?: number;
|
|
60
60
|
bytes_uploaded?: number;
|
|
61
61
|
error?: string;
|
|
62
|
+
/** True if the caller passed --skip-initial-sync; ok/files/bytes will be absent. */
|
|
63
|
+
skipped?: boolean;
|
|
62
64
|
};
|
|
63
65
|
}
|
|
64
66
|
/** Options for the high-level `provisionCompany` orchestrator. */
|
|
@@ -68,6 +70,15 @@ export interface ProvisionCompanyOptions {
|
|
|
68
70
|
ownerUid?: string;
|
|
69
71
|
hqRoot: string;
|
|
70
72
|
vaultApiUrl: string;
|
|
73
|
+
/**
|
|
74
|
+
* Skip the initial-sync step. The vault entity, manifest patch, and
|
|
75
|
+
* `.hq/config.json` write still happen; the post-provision `share()` call
|
|
76
|
+
* is no-op'd. Use this when the caller has its own upload pipeline (e.g.
|
|
77
|
+
* AppBar HQ Sync's `first_push_company` with STS-vended credentials and
|
|
78
|
+
* Tauri progress events) and would otherwise double-upload the same files.
|
|
79
|
+
* When true, `initial_sync` in the result is `{ skipped: true }`.
|
|
80
|
+
*/
|
|
81
|
+
skipInitialSync?: boolean;
|
|
71
82
|
/** Injected vault HTTP client (override for tests). */
|
|
72
83
|
vaultClient?: VaultClient;
|
|
73
84
|
/** Injected access-token resolver (override for tests). */
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* `initial_sync.ok=false`). Manifest + config may have been written.
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
|
-
!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]="
|
|
28
|
+
!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]="aacb5bf2-8362-5336-b864-43296c30a1d6")}catch(e){}}();
|
|
29
29
|
import chalk from "chalk";
|
|
30
30
|
import * as fs from "node:fs";
|
|
31
31
|
import * as path from "node:path";
|
|
@@ -180,7 +180,7 @@ export function createDefaultVaultClient(apiUrl, accessToken) {
|
|
|
180
180
|
};
|
|
181
181
|
return {
|
|
182
182
|
async findCompanyBySlug(slug) {
|
|
183
|
-
const url = `${apiUrl.replace(/\/$/, "")}/
|
|
183
|
+
const url = `${apiUrl.replace(/\/$/, "")}/entity/by-slug/company/${encodeURIComponent(slug)}`;
|
|
184
184
|
const res = await fetch(url, { method: "GET", headers });
|
|
185
185
|
if (res.status === 404)
|
|
186
186
|
return null;
|
|
@@ -195,7 +195,7 @@ export function createDefaultVaultClient(apiUrl, accessToken) {
|
|
|
195
195
|
return data.entity;
|
|
196
196
|
},
|
|
197
197
|
async createCompanyEntity(input) {
|
|
198
|
-
const url = `${apiUrl.replace(/\/$/, "")}/
|
|
198
|
+
const url = `${apiUrl.replace(/\/$/, "")}/entity`;
|
|
199
199
|
const body = {
|
|
200
200
|
type: "company",
|
|
201
201
|
slug: input.slug,
|
|
@@ -213,11 +213,11 @@ export function createDefaultVaultClient(apiUrl, accessToken) {
|
|
|
213
213
|
// 409 means a concurrent client created it between our GET and POST —
|
|
214
214
|
// surface it as a vault error. The orchestrator is responsible for
|
|
215
215
|
// retrying GET if it wants idempotency on collisions.
|
|
216
|
-
throw new ProvisionError(1, `Vault POST /
|
|
216
|
+
throw new ProvisionError(1, `Vault POST /entity failed: ${res.status} ${res.statusText} — ${text}`);
|
|
217
217
|
}
|
|
218
218
|
const data = (await res.json());
|
|
219
219
|
if (!data.entity) {
|
|
220
|
-
throw new ProvisionError(1, `Vault POST /
|
|
220
|
+
throw new ProvisionError(1, `Vault POST /entity returned ${res.status} with no entity body`);
|
|
221
221
|
}
|
|
222
222
|
return data.entity;
|
|
223
223
|
},
|
|
@@ -317,39 +317,47 @@ export async function provisionCompany(options) {
|
|
|
317
317
|
vaultApiUrl: options.vaultApiUrl,
|
|
318
318
|
});
|
|
319
319
|
log(`wrote companies/${options.slug}/.hq/config.json`);
|
|
320
|
-
// Step 8: trigger initial sync (failure ⇒ exit 3 with cloud_uid populated)
|
|
321
|
-
|
|
320
|
+
// Step 8: trigger initial sync (failure ⇒ exit 3 with cloud_uid populated).
|
|
321
|
+
// Skipped when caller passed --skip-initial-sync (e.g. AppBar HQ Sync, which
|
|
322
|
+
// owns its own STS-credentialed upload pipeline + Tauri progress events).
|
|
322
323
|
let initialSync;
|
|
323
|
-
|
|
324
|
-
log(`
|
|
325
|
-
|
|
326
|
-
slug: options.slug,
|
|
327
|
-
hqRoot: options.hqRoot,
|
|
328
|
-
accessToken,
|
|
329
|
-
vaultApiUrl: options.vaultApiUrl,
|
|
330
|
-
});
|
|
331
|
-
initialSync = {
|
|
332
|
-
ok: true,
|
|
333
|
-
files_uploaded: sync.filesUploaded,
|
|
334
|
-
bytes_uploaded: sync.bytesUploaded,
|
|
335
|
-
};
|
|
336
|
-
log(`initial sync complete — files=${sync.filesUploaded} bytes=${sync.bytesUploaded}`);
|
|
324
|
+
if (options.skipInitialSync) {
|
|
325
|
+
log(`skipping initial sync (--skip-initial-sync)`);
|
|
326
|
+
initialSync = { skipped: true };
|
|
337
327
|
}
|
|
338
|
-
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
328
|
+
else {
|
|
329
|
+
const runner = options.runInitialSync ?? defaultRunInitialSync;
|
|
330
|
+
try {
|
|
331
|
+
log(`triggering initial sync via share()`);
|
|
332
|
+
const sync = await runner({
|
|
333
|
+
slug: options.slug,
|
|
334
|
+
hqRoot: options.hqRoot,
|
|
335
|
+
accessToken,
|
|
336
|
+
vaultApiUrl: options.vaultApiUrl,
|
|
337
|
+
});
|
|
338
|
+
initialSync = {
|
|
339
|
+
ok: true,
|
|
340
|
+
files_uploaded: sync.filesUploaded,
|
|
341
|
+
bytes_uploaded: sync.bytesUploaded,
|
|
342
|
+
};
|
|
343
|
+
log(`initial sync complete — files=${sync.filesUploaded} bytes=${sync.bytesUploaded}`);
|
|
344
|
+
}
|
|
345
|
+
catch (err) {
|
|
346
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
347
|
+
log(`initial sync failed: ${msg}`);
|
|
348
|
+
throw new ProvisionError(3, `Initial sync failed: ${msg}`, {
|
|
349
|
+
ok: false,
|
|
350
|
+
company_slug: options.slug,
|
|
351
|
+
cloud_uid: cloudUid,
|
|
352
|
+
bucket_name: bucketName,
|
|
353
|
+
vault_api_url: options.vaultApiUrl,
|
|
354
|
+
kms_key_id: kmsKeyId,
|
|
355
|
+
created_entity: createdEntity,
|
|
356
|
+
manifest_patched: true,
|
|
357
|
+
config_written: true,
|
|
358
|
+
initial_sync: { ok: false, error: msg },
|
|
359
|
+
});
|
|
360
|
+
}
|
|
353
361
|
}
|
|
354
362
|
return {
|
|
355
363
|
ok: true,
|
|
@@ -385,6 +393,9 @@ export function registerCloudProvisionCommands(program) {
|
|
|
385
393
|
.option("--owner <uid>", "Owner person UID (default: current Cognito user sub)")
|
|
386
394
|
.option("--hq-root <path>", `Local HQ tree root (default: ${DEFAULT_HQ_ROOT})`, DEFAULT_HQ_ROOT)
|
|
387
395
|
.option("--vault-api-url <url>", `Vault API URL (default: ${DEFAULT_VAULT_API_URL})`, DEFAULT_VAULT_API_URL)
|
|
396
|
+
.option("--skip-initial-sync", "Skip the post-provision share() initial sync. Use when the caller " +
|
|
397
|
+
"(e.g. AppBar HQ Sync) has its own upload pipeline. Result includes " +
|
|
398
|
+
"{ initial_sync: { skipped: true } } when set.")
|
|
388
399
|
.action(async (slug, options) => {
|
|
389
400
|
try {
|
|
390
401
|
const result = await provisionCompany({
|
|
@@ -393,6 +404,7 @@ export function registerCloudProvisionCommands(program) {
|
|
|
393
404
|
ownerUid: options.owner,
|
|
394
405
|
hqRoot: options.hqRoot,
|
|
395
406
|
vaultApiUrl: options.vaultApiUrl,
|
|
407
|
+
skipInitialSync: options.skipInitialSync,
|
|
396
408
|
});
|
|
397
409
|
// Final stdout line — single JSON document for downstream consumers
|
|
398
410
|
process.stdout.write(JSON.stringify(result) + "\n");
|
|
@@ -414,4 +426,4 @@ export function registerCloudProvisionCommands(program) {
|
|
|
414
426
|
});
|
|
415
427
|
}
|
|
416
428
|
//# sourceMappingURL=cloud-provision.js.map
|
|
417
|
-
//# debugId=
|
|
429
|
+
//# debugId=aacb5bf2-8362-5336-b864-43296c30a1d6
|
package/package.json
CHANGED
|
@@ -374,7 +374,7 @@ describe("createDefaultVaultClient", () => {
|
|
|
374
374
|
expect(out).toEqual(entity);
|
|
375
375
|
// Verify request shape
|
|
376
376
|
const call = fetchSpy.mock.calls[0];
|
|
377
|
-
expect(call[0]).toBe(`${apiUrl}/
|
|
377
|
+
expect(call[0]).toBe(`${apiUrl}/entity`);
|
|
378
378
|
expect((call[1] as RequestInit)?.method).toBe("POST");
|
|
379
379
|
const body = JSON.parse(((call[1] as RequestInit)?.body as string) ?? "{}");
|
|
380
380
|
expect(body).toEqual({ type: "company", slug: "indigo", name: "Indigo" });
|
|
@@ -649,4 +649,75 @@ describe("provisionCompany", () => {
|
|
|
649
649
|
ownerUid: undefined,
|
|
650
650
|
});
|
|
651
651
|
});
|
|
652
|
+
|
|
653
|
+
it("skipInitialSync=true — runner is NOT called; result has initial_sync.skipped", async () => {
|
|
654
|
+
setupValid();
|
|
655
|
+
const entity: VaultEntity = {
|
|
656
|
+
uid: "cmp_01H",
|
|
657
|
+
type: "company",
|
|
658
|
+
slug: "indigo",
|
|
659
|
+
name: "Indigo",
|
|
660
|
+
bucketName: "hq-vault-cmp-01H",
|
|
661
|
+
};
|
|
662
|
+
const vaultClient = makeVaultClient({
|
|
663
|
+
findCompanyBySlug: vi.fn().mockResolvedValue(null),
|
|
664
|
+
createCompanyEntity: vi.fn().mockResolvedValue(entity),
|
|
665
|
+
});
|
|
666
|
+
const runInitialSync = vi.fn();
|
|
667
|
+
|
|
668
|
+
const result = await provisionCompany({
|
|
669
|
+
slug: "indigo",
|
|
670
|
+
hqRoot: tmpRoot,
|
|
671
|
+
vaultApiUrl,
|
|
672
|
+
vaultClient,
|
|
673
|
+
resolveAccessToken: async () => accessToken,
|
|
674
|
+
runInitialSync,
|
|
675
|
+
skipInitialSync: true,
|
|
676
|
+
log: () => {},
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
expect(runInitialSync).not.toHaveBeenCalled();
|
|
680
|
+
expect(result.initial_sync).toEqual({ skipped: true });
|
|
681
|
+
expect(result.ok).toBe(true);
|
|
682
|
+
expect(result.cloud_uid).toBe("cmp_01H");
|
|
683
|
+
expect(result.manifest_patched).toBe(true);
|
|
684
|
+
expect(result.config_written).toBe(true);
|
|
685
|
+
});
|
|
686
|
+
|
|
687
|
+
it("skipInitialSync=true — manifest + .hq/config.json are STILL written", async () => {
|
|
688
|
+
setupValid();
|
|
689
|
+
const entity: VaultEntity = {
|
|
690
|
+
uid: "cmp_SKIP",
|
|
691
|
+
type: "company",
|
|
692
|
+
slug: "indigo",
|
|
693
|
+
name: "Indigo",
|
|
694
|
+
bucketName: "hq-vault-cmp-SKIP",
|
|
695
|
+
};
|
|
696
|
+
const vaultClient = makeVaultClient({
|
|
697
|
+
findCompanyBySlug: vi.fn().mockResolvedValue(null),
|
|
698
|
+
createCompanyEntity: vi.fn().mockResolvedValue(entity),
|
|
699
|
+
});
|
|
700
|
+
await provisionCompany({
|
|
701
|
+
slug: "indigo",
|
|
702
|
+
hqRoot: tmpRoot,
|
|
703
|
+
vaultApiUrl,
|
|
704
|
+
vaultClient,
|
|
705
|
+
resolveAccessToken: async () => accessToken,
|
|
706
|
+
runInitialSync: vi.fn(),
|
|
707
|
+
skipInitialSync: true,
|
|
708
|
+
log: () => {},
|
|
709
|
+
});
|
|
710
|
+
// Manifest patched on disk
|
|
711
|
+
const m = yaml.load(fs.readFileSync(manifestPath(tmpRoot), "utf-8")) as {
|
|
712
|
+
companies: Record<string, Record<string, unknown>>;
|
|
713
|
+
};
|
|
714
|
+
expect(m.companies.indigo.cloud_uid).toBe("cmp_SKIP");
|
|
715
|
+
expect(m.companies.indigo.bucket_name).toBe("hq-vault-cmp-SKIP");
|
|
716
|
+
// .hq/config.json written
|
|
717
|
+
const c = JSON.parse(
|
|
718
|
+
fs.readFileSync(companyConfigPath(tmpRoot, "indigo"), "utf-8"),
|
|
719
|
+
);
|
|
720
|
+
expect(c.companyUid).toBe("cmp_SKIP");
|
|
721
|
+
expect(c.bucketName).toBe("hq-vault-cmp-SKIP");
|
|
722
|
+
});
|
|
652
723
|
});
|
|
@@ -74,10 +74,12 @@ export interface ProvisionResult {
|
|
|
74
74
|
manifest_patched: boolean;
|
|
75
75
|
config_written: boolean;
|
|
76
76
|
initial_sync: {
|
|
77
|
-
ok
|
|
77
|
+
ok?: boolean;
|
|
78
78
|
files_uploaded?: number;
|
|
79
79
|
bytes_uploaded?: number;
|
|
80
80
|
error?: string;
|
|
81
|
+
/** True if the caller passed --skip-initial-sync; ok/files/bytes will be absent. */
|
|
82
|
+
skipped?: boolean;
|
|
81
83
|
};
|
|
82
84
|
}
|
|
83
85
|
|
|
@@ -88,6 +90,15 @@ export interface ProvisionCompanyOptions {
|
|
|
88
90
|
ownerUid?: string;
|
|
89
91
|
hqRoot: string;
|
|
90
92
|
vaultApiUrl: string;
|
|
93
|
+
/**
|
|
94
|
+
* Skip the initial-sync step. The vault entity, manifest patch, and
|
|
95
|
+
* `.hq/config.json` write still happen; the post-provision `share()` call
|
|
96
|
+
* is no-op'd. Use this when the caller has its own upload pipeline (e.g.
|
|
97
|
+
* AppBar HQ Sync's `first_push_company` with STS-vended credentials and
|
|
98
|
+
* Tauri progress events) and would otherwise double-upload the same files.
|
|
99
|
+
* When true, `initial_sync` in the result is `{ skipped: true }`.
|
|
100
|
+
*/
|
|
101
|
+
skipInitialSync?: boolean;
|
|
91
102
|
/** Injected vault HTTP client (override for tests). */
|
|
92
103
|
vaultClient?: VaultClient;
|
|
93
104
|
/** Injected access-token resolver (override for tests). */
|
|
@@ -335,7 +346,7 @@ export function createDefaultVaultClient(
|
|
|
335
346
|
};
|
|
336
347
|
return {
|
|
337
348
|
async findCompanyBySlug(slug: string): Promise<VaultEntity | null> {
|
|
338
|
-
const url = `${apiUrl.replace(/\/$/, "")}/
|
|
349
|
+
const url = `${apiUrl.replace(/\/$/, "")}/entity/by-slug/company/${encodeURIComponent(
|
|
339
350
|
slug,
|
|
340
351
|
)}`;
|
|
341
352
|
const res = await fetch(url, { method: "GET", headers });
|
|
@@ -361,7 +372,7 @@ export function createDefaultVaultClient(
|
|
|
361
372
|
name: string;
|
|
362
373
|
ownerUid?: string;
|
|
363
374
|
}): Promise<VaultEntity> {
|
|
364
|
-
const url = `${apiUrl.replace(/\/$/, "")}/
|
|
375
|
+
const url = `${apiUrl.replace(/\/$/, "")}/entity`;
|
|
365
376
|
const body: Record<string, unknown> = {
|
|
366
377
|
type: "company",
|
|
367
378
|
slug: input.slug,
|
|
@@ -380,14 +391,14 @@ export function createDefaultVaultClient(
|
|
|
380
391
|
// retrying GET if it wants idempotency on collisions.
|
|
381
392
|
throw new ProvisionError(
|
|
382
393
|
1,
|
|
383
|
-
`Vault POST /
|
|
394
|
+
`Vault POST /entity failed: ${res.status} ${res.statusText} — ${text}`,
|
|
384
395
|
);
|
|
385
396
|
}
|
|
386
397
|
const data = (await res.json()) as { entity?: VaultEntity };
|
|
387
398
|
if (!data.entity) {
|
|
388
399
|
throw new ProvisionError(
|
|
389
400
|
1,
|
|
390
|
-
`Vault POST /
|
|
401
|
+
`Vault POST /entity returned ${res.status} with no entity body`,
|
|
391
402
|
);
|
|
392
403
|
}
|
|
393
404
|
return data.entity;
|
|
@@ -510,40 +521,47 @@ export async function provisionCompany(
|
|
|
510
521
|
});
|
|
511
522
|
log(`wrote companies/${options.slug}/.hq/config.json`);
|
|
512
523
|
|
|
513
|
-
// Step 8: trigger initial sync (failure ⇒ exit 3 with cloud_uid populated)
|
|
514
|
-
|
|
524
|
+
// Step 8: trigger initial sync (failure ⇒ exit 3 with cloud_uid populated).
|
|
525
|
+
// Skipped when caller passed --skip-initial-sync (e.g. AppBar HQ Sync, which
|
|
526
|
+
// owns its own STS-credentialed upload pipeline + Tauri progress events).
|
|
515
527
|
let initialSync: ProvisionResult["initial_sync"];
|
|
516
|
-
|
|
517
|
-
log(`
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
528
|
+
if (options.skipInitialSync) {
|
|
529
|
+
log(`skipping initial sync (--skip-initial-sync)`);
|
|
530
|
+
initialSync = { skipped: true };
|
|
531
|
+
} else {
|
|
532
|
+
const runner = options.runInitialSync ?? defaultRunInitialSync;
|
|
533
|
+
try {
|
|
534
|
+
log(`triggering initial sync via share()`);
|
|
535
|
+
const sync = await runner({
|
|
536
|
+
slug: options.slug,
|
|
537
|
+
hqRoot: options.hqRoot,
|
|
538
|
+
accessToken,
|
|
539
|
+
vaultApiUrl: options.vaultApiUrl,
|
|
540
|
+
});
|
|
541
|
+
initialSync = {
|
|
542
|
+
ok: true,
|
|
543
|
+
files_uploaded: sync.filesUploaded,
|
|
544
|
+
bytes_uploaded: sync.bytesUploaded,
|
|
545
|
+
};
|
|
546
|
+
log(
|
|
547
|
+
`initial sync complete — files=${sync.filesUploaded} bytes=${sync.bytesUploaded}`,
|
|
548
|
+
);
|
|
549
|
+
} catch (err) {
|
|
550
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
551
|
+
log(`initial sync failed: ${msg}`);
|
|
552
|
+
throw new ProvisionError(3, `Initial sync failed: ${msg}`, {
|
|
553
|
+
ok: false,
|
|
554
|
+
company_slug: options.slug,
|
|
555
|
+
cloud_uid: cloudUid,
|
|
556
|
+
bucket_name: bucketName,
|
|
557
|
+
vault_api_url: options.vaultApiUrl,
|
|
558
|
+
kms_key_id: kmsKeyId,
|
|
559
|
+
created_entity: createdEntity,
|
|
560
|
+
manifest_patched: true,
|
|
561
|
+
config_written: true,
|
|
562
|
+
initial_sync: { ok: false, error: msg },
|
|
563
|
+
});
|
|
564
|
+
}
|
|
547
565
|
}
|
|
548
566
|
|
|
549
567
|
return {
|
|
@@ -593,6 +611,12 @@ export function registerCloudProvisionCommands(program: Command): void {
|
|
|
593
611
|
`Vault API URL (default: ${DEFAULT_VAULT_API_URL})`,
|
|
594
612
|
DEFAULT_VAULT_API_URL,
|
|
595
613
|
)
|
|
614
|
+
.option(
|
|
615
|
+
"--skip-initial-sync",
|
|
616
|
+
"Skip the post-provision share() initial sync. Use when the caller " +
|
|
617
|
+
"(e.g. AppBar HQ Sync) has its own upload pipeline. Result includes " +
|
|
618
|
+
"{ initial_sync: { skipped: true } } when set.",
|
|
619
|
+
)
|
|
596
620
|
.action(
|
|
597
621
|
async (
|
|
598
622
|
slug: string,
|
|
@@ -601,6 +625,7 @@ export function registerCloudProvisionCommands(program: Command): void {
|
|
|
601
625
|
owner?: string;
|
|
602
626
|
hqRoot: string;
|
|
603
627
|
vaultApiUrl: string;
|
|
628
|
+
skipInitialSync?: boolean;
|
|
604
629
|
},
|
|
605
630
|
) => {
|
|
606
631
|
try {
|
|
@@ -610,6 +635,7 @@ export function registerCloudProvisionCommands(program: Command): void {
|
|
|
610
635
|
ownerUid: options.owner,
|
|
611
636
|
hqRoot: options.hqRoot,
|
|
612
637
|
vaultApiUrl: options.vaultApiUrl,
|
|
638
|
+
skipInitialSync: options.skipInitialSync,
|
|
613
639
|
});
|
|
614
640
|
// Final stdout line — single JSON document for downstream consumers
|
|
615
641
|
process.stdout.write(JSON.stringify(result) + "\n");
|