@indigoai-us/hq-cloud 6.11.12 → 6.11.13
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/bin/sync-runner-company.d.ts +35 -0
- package/dist/bin/sync-runner-company.d.ts.map +1 -0
- package/dist/bin/sync-runner-company.js +290 -0
- package/dist/bin/sync-runner-company.js.map +1 -0
- package/dist/bin/sync-runner-events.d.ts +12 -0
- package/dist/bin/sync-runner-events.d.ts.map +1 -0
- package/dist/bin/sync-runner-events.js +12 -0
- package/dist/bin/sync-runner-events.js.map +1 -0
- package/dist/bin/sync-runner-planning.d.ts +53 -0
- package/dist/bin/sync-runner-planning.d.ts.map +1 -0
- package/dist/bin/sync-runner-planning.js +59 -0
- package/dist/bin/sync-runner-planning.js.map +1 -0
- package/dist/bin/sync-runner-rollup.d.ts +24 -0
- package/dist/bin/sync-runner-rollup.d.ts.map +1 -0
- package/dist/bin/sync-runner-rollup.js +46 -0
- package/dist/bin/sync-runner-rollup.js.map +1 -0
- package/dist/bin/sync-runner-telemetry.d.ts +5 -0
- package/dist/bin/sync-runner-telemetry.d.ts.map +1 -0
- package/dist/bin/sync-runner-telemetry.js +5 -0
- package/dist/bin/sync-runner-telemetry.js.map +1 -0
- package/dist/bin/sync-runner-watch-loop.d.ts +17 -0
- package/dist/bin/sync-runner-watch-loop.d.ts.map +1 -0
- package/dist/bin/sync-runner-watch-loop.js +372 -0
- package/dist/bin/sync-runner-watch-loop.js.map +1 -0
- package/dist/bin/sync-runner-watch-routes.d.ts +25 -0
- package/dist/bin/sync-runner-watch-routes.d.ts.map +1 -0
- package/dist/bin/sync-runner-watch-routes.js +74 -0
- package/dist/bin/sync-runner-watch-routes.js.map +1 -0
- package/dist/bin/sync-runner.d.ts +3 -54
- package/dist/bin/sync-runner.d.ts.map +1 -1
- package/dist/bin/sync-runner.js +73 -1154
- package/dist/bin/sync-runner.js.map +1 -1
- package/dist/cli/reindex.d.ts.map +1 -1
- package/dist/cli/reindex.js +34 -17
- package/dist/cli/reindex.js.map +1 -1
- package/dist/cli/reindex.test.js +39 -5
- package/dist/cli/reindex.test.js.map +1 -1
- package/dist/cli/rescue-classify-ordering.test.js +17 -0
- package/dist/cli/rescue-classify-ordering.test.js.map +1 -1
- package/dist/cli/rescue-core.d.ts +45 -0
- package/dist/cli/rescue-core.d.ts.map +1 -1
- package/dist/cli/rescue-core.js +197 -170
- package/dist/cli/rescue-core.js.map +1 -1
- package/dist/cli/share.d.ts.map +1 -1
- package/dist/cli/share.js +224 -676
- package/dist/cli/share.js.map +1 -1
- package/dist/cli/sync.d.ts.map +1 -1
- package/dist/cli/sync.js +399 -726
- package/dist/cli/sync.js.map +1 -1
- package/dist/cli/sync.test.js +20 -0
- package/dist/cli/sync.test.js.map +1 -1
- package/dist/daemon-worker.d.ts +2 -2
- package/dist/daemon-worker.js +3 -3
- package/dist/daemon-worker.js.map +1 -1
- package/dist/object-io.js +1 -1
- package/dist/object-io.js.map +1 -1
- package/dist/remote-pull.d.ts +2 -2
- package/dist/remote-pull.d.ts.map +1 -1
- package/dist/remote-pull.js +23 -3
- package/dist/remote-pull.js.map +1 -1
- package/dist/remote-pull.test.js +24 -2
- package/dist/remote-pull.test.js.map +1 -1
- package/dist/sync/push-receiver.d.ts +6 -0
- package/dist/sync/push-receiver.d.ts.map +1 -1
- package/dist/sync/push-receiver.js +32 -2
- package/dist/sync/push-receiver.js.map +1 -1
- package/dist/sync/push-receiver.test.js +31 -0
- package/dist/sync/push-receiver.test.js.map +1 -1
- package/dist/sync-core.d.ts +27 -0
- package/dist/sync-core.d.ts.map +1 -0
- package/dist/sync-core.js +54 -0
- package/dist/sync-core.js.map +1 -0
- package/dist/vault-client.d.ts.map +1 -1
- package/dist/vault-client.js +284 -36
- package/dist/vault-client.js.map +1 -1
- package/dist/vault-client.test.js +59 -0
- package/dist/vault-client.test.js.map +1 -1
- package/dist/watcher.d.ts +2 -20
- package/dist/watcher.d.ts.map +1 -1
- package/dist/watcher.js +3 -113
- package/dist/watcher.js.map +1 -1
- package/package.json +1 -1
- package/src/bin/sync-runner-company.ts +350 -0
- package/src/bin/sync-runner-events.ts +25 -0
- package/src/bin/sync-runner-planning.ts +121 -0
- package/src/bin/sync-runner-rollup.ts +72 -0
- package/src/bin/sync-runner-telemetry.ts +8 -0
- package/src/bin/sync-runner-watch-loop.ts +443 -0
- package/src/bin/sync-runner-watch-routes.ts +86 -0
- package/src/bin/sync-runner.ts +96 -1253
- package/src/cli/reindex.test.ts +41 -3
- package/src/cli/reindex.ts +35 -19
- package/src/cli/rescue-classify-ordering.test.ts +20 -0
- package/src/cli/rescue-core.ts +252 -176
- package/src/cli/share.ts +363 -705
- package/src/cli/sync.test.ts +25 -0
- package/src/cli/sync.ts +612 -802
- package/src/daemon-worker.ts +3 -3
- package/src/object-io.ts +1 -1
- package/src/remote-pull.test.ts +30 -1
- package/src/remote-pull.ts +29 -4
- package/src/sync/push-receiver.test.ts +35 -0
- package/src/sync/push-receiver.ts +41 -2
- package/src/sync-core.ts +58 -0
- package/src/vault-client.test.ts +74 -0
- package/src/vault-client.ts +395 -43
- package/src/watcher.ts +6 -141
package/src/vault-client.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import type { ClientInfo, VaultServiceConfig } from "./types.js";
|
|
10
10
|
import { buildClientHeaders } from "./client-info.js";
|
|
11
|
+
import { z } from "zod";
|
|
11
12
|
|
|
12
13
|
// ---------------------------------------------------------------------------
|
|
13
14
|
// Error classes
|
|
@@ -444,6 +445,306 @@ async function sleep(ms: number): Promise<void> {
|
|
|
444
445
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
445
446
|
}
|
|
446
447
|
|
|
448
|
+
// ---------------------------------------------------------------------------
|
|
449
|
+
// Response schemas
|
|
450
|
+
// ---------------------------------------------------------------------------
|
|
451
|
+
|
|
452
|
+
type VaultResponseSchema<T> = z.ZodType<T>;
|
|
453
|
+
|
|
454
|
+
const membershipRoleSchema = z.enum(["owner", "admin", "member", "guest"]);
|
|
455
|
+
const membershipStatusSchema = z.enum(["pending", "active", "revoked"]);
|
|
456
|
+
const grantPermissionSchema = z.enum(["read", "write", "admin"]);
|
|
457
|
+
const grantSourceSchema = z.enum(["person", "email", "group", "open"]);
|
|
458
|
+
const presignOpSchema = z.enum(["get", "put", "delete"]);
|
|
459
|
+
const syncModeSchema = z.enum(["shared", "all", "custom"]);
|
|
460
|
+
const vendPurposeSchema = z.enum(["sync", "browse"]);
|
|
461
|
+
const vaultOperationSchema = z.enum(["read-only", "read-write", "staged-write"]);
|
|
462
|
+
|
|
463
|
+
// Membership/entity rows are intentionally permissive on field optionality:
|
|
464
|
+
// current command tests and server flows use short rows outside sync decisions.
|
|
465
|
+
const membershipSchema = z
|
|
466
|
+
.object({
|
|
467
|
+
membershipKey: z.string().optional(),
|
|
468
|
+
personUid: z.string().optional(),
|
|
469
|
+
companyUid: z.string().optional(),
|
|
470
|
+
role: membershipRoleSchema.optional(),
|
|
471
|
+
status: membershipStatusSchema.optional(),
|
|
472
|
+
allowedPrefixes: z.array(z.string()).optional(),
|
|
473
|
+
inviteToken: z.string().optional(),
|
|
474
|
+
invitedBy: z.string().optional(),
|
|
475
|
+
invitedAt: z.string().optional(),
|
|
476
|
+
acceptedAt: z.string().optional(),
|
|
477
|
+
revokedAt: z.string().optional(),
|
|
478
|
+
createdAt: z.string().optional(),
|
|
479
|
+
updatedAt: z.string().optional(),
|
|
480
|
+
})
|
|
481
|
+
.strip() as unknown as VaultResponseSchema<Membership>;
|
|
482
|
+
|
|
483
|
+
const entityInfoSchema = z
|
|
484
|
+
.object({
|
|
485
|
+
uid: z.string(),
|
|
486
|
+
slug: z.string(),
|
|
487
|
+
type: z.string(),
|
|
488
|
+
name: z.string().optional(),
|
|
489
|
+
bucketName: z.string().optional(),
|
|
490
|
+
status: z.string(),
|
|
491
|
+
createdAt: z.string().optional(),
|
|
492
|
+
})
|
|
493
|
+
.strip() as unknown as VaultResponseSchema<EntityInfo>;
|
|
494
|
+
|
|
495
|
+
const pendingInviteByEmailSchema: VaultResponseSchema<PendingInviteByEmail> = z
|
|
496
|
+
.object({
|
|
497
|
+
membershipKey: z.string(),
|
|
498
|
+
companyUid: z.string(),
|
|
499
|
+
role: membershipRoleSchema,
|
|
500
|
+
inviteToken: z.string().optional(),
|
|
501
|
+
invitedBy: z.string(),
|
|
502
|
+
invitedAt: z.string(),
|
|
503
|
+
})
|
|
504
|
+
.strip();
|
|
505
|
+
|
|
506
|
+
const explicitGrantSchema: VaultResponseSchema<ExplicitGrant> = z
|
|
507
|
+
.object({
|
|
508
|
+
companyUid: z.string(),
|
|
509
|
+
path: z.string(),
|
|
510
|
+
permission: grantPermissionSchema,
|
|
511
|
+
source: grantSourceSchema,
|
|
512
|
+
})
|
|
513
|
+
.strip();
|
|
514
|
+
|
|
515
|
+
const vaultListedObjectSchema: VaultResponseSchema<VaultListedObject> = z
|
|
516
|
+
.object({
|
|
517
|
+
key: z.string(),
|
|
518
|
+
size: z.number(),
|
|
519
|
+
lastModified: z.string().nullable(),
|
|
520
|
+
etag: z.string().nullable(),
|
|
521
|
+
permission: grantPermissionSchema,
|
|
522
|
+
})
|
|
523
|
+
.strip();
|
|
524
|
+
|
|
525
|
+
const presignResultRowSchema: VaultResponseSchema<PresignResultRow> = z
|
|
526
|
+
.object({
|
|
527
|
+
key: z.string(),
|
|
528
|
+
op: presignOpSchema,
|
|
529
|
+
url: z.string().optional(),
|
|
530
|
+
headers: z.record(z.string(), z.string()).optional(),
|
|
531
|
+
expiresIn: z.number().optional(),
|
|
532
|
+
expiresAt: z.string().optional(),
|
|
533
|
+
error: z.string().optional(),
|
|
534
|
+
code: z.string().optional(),
|
|
535
|
+
})
|
|
536
|
+
.strip();
|
|
537
|
+
|
|
538
|
+
const membershipSyncConfigSchema: VaultResponseSchema<MembershipSyncConfig> = z
|
|
539
|
+
.object({
|
|
540
|
+
membershipId: z.string(),
|
|
541
|
+
syncMode: syncModeSchema,
|
|
542
|
+
customPaths: z.array(z.string()).optional(),
|
|
543
|
+
isDefault: z.boolean(),
|
|
544
|
+
updatedAt: z.string().optional(),
|
|
545
|
+
updatedBy: z.string().optional(),
|
|
546
|
+
})
|
|
547
|
+
.strip();
|
|
548
|
+
|
|
549
|
+
const vendCredentialsSchema: VaultResponseSchema<VendCredentials> = z
|
|
550
|
+
.object({
|
|
551
|
+
accessKeyId: z.string(),
|
|
552
|
+
secretAccessKey: z.string(),
|
|
553
|
+
sessionToken: z.string(),
|
|
554
|
+
expiration: z.string(),
|
|
555
|
+
})
|
|
556
|
+
.strip();
|
|
557
|
+
|
|
558
|
+
const stsCredentialsSchema: VaultResponseSchema<StsChildCredentials> = z
|
|
559
|
+
.object({
|
|
560
|
+
accessKeyId: z.string(),
|
|
561
|
+
secretAccessKey: z.string(),
|
|
562
|
+
sessionToken: z.string(),
|
|
563
|
+
})
|
|
564
|
+
.strip();
|
|
565
|
+
|
|
566
|
+
const telemetryOptInResponseSchema: VaultResponseSchema<TelemetryOptInResponse> =
|
|
567
|
+
z
|
|
568
|
+
.object({
|
|
569
|
+
enabled: z.boolean().default(false),
|
|
570
|
+
updatedAt: z.string().nullable().default(null),
|
|
571
|
+
})
|
|
572
|
+
.strip();
|
|
573
|
+
|
|
574
|
+
const usageIngestResultSchema: VaultResponseSchema<UsageIngestResult> = z
|
|
575
|
+
.object({
|
|
576
|
+
ok: z.boolean(),
|
|
577
|
+
written: z.number(),
|
|
578
|
+
skipped: z.array(
|
|
579
|
+
z
|
|
580
|
+
.object({
|
|
581
|
+
index: z.number(),
|
|
582
|
+
code: z.string(),
|
|
583
|
+
error: z.string(),
|
|
584
|
+
})
|
|
585
|
+
.strip(),
|
|
586
|
+
),
|
|
587
|
+
})
|
|
588
|
+
.strip();
|
|
589
|
+
|
|
590
|
+
const createInviteResponseSchema: VaultResponseSchema<CreateInviteResult> = z
|
|
591
|
+
.object({
|
|
592
|
+
membership: membershipSchema,
|
|
593
|
+
inviteToken: z.string(),
|
|
594
|
+
})
|
|
595
|
+
.strip();
|
|
596
|
+
|
|
597
|
+
const acceptInviteResponseSchema: VaultResponseSchema<AcceptInviteResult> = z
|
|
598
|
+
.object({
|
|
599
|
+
membership: membershipSchema,
|
|
600
|
+
})
|
|
601
|
+
.strip();
|
|
602
|
+
|
|
603
|
+
const membershipsResponseSchema: VaultResponseSchema<{ memberships: Membership[] }> =
|
|
604
|
+
z
|
|
605
|
+
.object({
|
|
606
|
+
memberships: z.array(membershipSchema),
|
|
607
|
+
})
|
|
608
|
+
.strip();
|
|
609
|
+
|
|
610
|
+
const pendingInvitesByEmailResponseSchema: VaultResponseSchema<{
|
|
611
|
+
invites?: PendingInviteByEmail[];
|
|
612
|
+
}> = z
|
|
613
|
+
.object({
|
|
614
|
+
invites: z.array(pendingInviteByEmailSchema).optional(),
|
|
615
|
+
})
|
|
616
|
+
.strip();
|
|
617
|
+
|
|
618
|
+
const membersResponseSchema: VaultResponseSchema<{ members: Membership[] }> = z
|
|
619
|
+
.object({
|
|
620
|
+
members: z.array(membershipSchema),
|
|
621
|
+
})
|
|
622
|
+
.strip();
|
|
623
|
+
|
|
624
|
+
const membershipResponseSchema: VaultResponseSchema<{ membership: Membership }> =
|
|
625
|
+
z
|
|
626
|
+
.object({
|
|
627
|
+
membership: membershipSchema,
|
|
628
|
+
})
|
|
629
|
+
.strip();
|
|
630
|
+
|
|
631
|
+
const invitesResponseSchema: VaultResponseSchema<{ invites: Membership[] }> = z
|
|
632
|
+
.object({
|
|
633
|
+
invites: z.array(membershipSchema),
|
|
634
|
+
})
|
|
635
|
+
.strip();
|
|
636
|
+
|
|
637
|
+
const explicitGrantsResponseSchema: VaultResponseSchema<{
|
|
638
|
+
grants?: ExplicitGrant[];
|
|
639
|
+
computedAt: string;
|
|
640
|
+
}> = z
|
|
641
|
+
.object({
|
|
642
|
+
grants: z.array(explicitGrantSchema).optional(),
|
|
643
|
+
computedAt: z.string(),
|
|
644
|
+
})
|
|
645
|
+
.strip();
|
|
646
|
+
|
|
647
|
+
const listFilesResponseSchema: VaultResponseSchema<{
|
|
648
|
+
objects: VaultListedObject[];
|
|
649
|
+
cursor: string | null;
|
|
650
|
+
truncated: boolean;
|
|
651
|
+
}> = z
|
|
652
|
+
.object({
|
|
653
|
+
objects: z.array(vaultListedObjectSchema).default([]),
|
|
654
|
+
cursor: z.string().nullable().default(null),
|
|
655
|
+
truncated: z.boolean().default(false),
|
|
656
|
+
})
|
|
657
|
+
.strip();
|
|
658
|
+
|
|
659
|
+
const presignResponseSchema: VaultResponseSchema<{
|
|
660
|
+
results: PresignResultRow[];
|
|
661
|
+
expiresAt: string;
|
|
662
|
+
}> = z
|
|
663
|
+
.object({
|
|
664
|
+
results: z.array(presignResultRowSchema),
|
|
665
|
+
expiresAt: z.string(),
|
|
666
|
+
})
|
|
667
|
+
.strip();
|
|
668
|
+
|
|
669
|
+
const entityResponseSchema: VaultResponseSchema<{ entity: EntityInfo }> = z
|
|
670
|
+
.object({
|
|
671
|
+
entity: entityInfoSchema,
|
|
672
|
+
})
|
|
673
|
+
.strip();
|
|
674
|
+
|
|
675
|
+
const checkSlugMeResponseSchema: VaultResponseSchema<{
|
|
676
|
+
available: boolean;
|
|
677
|
+
conflictingCompanyUid?: string;
|
|
678
|
+
}> = z
|
|
679
|
+
.object({
|
|
680
|
+
available: z.boolean(),
|
|
681
|
+
conflictingCompanyUid: z.string().optional(),
|
|
682
|
+
})
|
|
683
|
+
.strip();
|
|
684
|
+
|
|
685
|
+
const createEntityResponseSchema: VaultResponseSchema<CreateEntityResult> = z
|
|
686
|
+
.object({
|
|
687
|
+
entity: entityInfoSchema,
|
|
688
|
+
})
|
|
689
|
+
.strip();
|
|
690
|
+
|
|
691
|
+
const entitiesResponseSchema: VaultResponseSchema<{ entities?: EntityInfo[] }> =
|
|
692
|
+
z
|
|
693
|
+
.object({
|
|
694
|
+
entities: z.array(entityInfoSchema).optional(),
|
|
695
|
+
})
|
|
696
|
+
.strip();
|
|
697
|
+
|
|
698
|
+
const provisionBucketResponseSchema: VaultResponseSchema<{
|
|
699
|
+
bucketName: string;
|
|
700
|
+
kmsKeyId: string;
|
|
701
|
+
}> = z
|
|
702
|
+
.object({
|
|
703
|
+
bucketName: z.string(),
|
|
704
|
+
kmsKeyId: z.string(),
|
|
705
|
+
})
|
|
706
|
+
.strip();
|
|
707
|
+
|
|
708
|
+
const vendResponseSchema: VaultResponseSchema<VendResult> = z
|
|
709
|
+
.object({
|
|
710
|
+
credentials: vendCredentialsSchema,
|
|
711
|
+
paths: z.array(z.string()),
|
|
712
|
+
operations: vaultOperationSchema,
|
|
713
|
+
purpose: vendPurposeSchema,
|
|
714
|
+
policySize: z.number(),
|
|
715
|
+
requestId: z.string().optional(),
|
|
716
|
+
})
|
|
717
|
+
.strip();
|
|
718
|
+
|
|
719
|
+
const stsVendResponseSchema: VaultResponseSchema<{
|
|
720
|
+
credentials: StsChildCredentials;
|
|
721
|
+
expiresAt: string;
|
|
722
|
+
}> = z
|
|
723
|
+
.object({
|
|
724
|
+
credentials: stsCredentialsSchema,
|
|
725
|
+
expiresAt: z.string(),
|
|
726
|
+
})
|
|
727
|
+
.strip();
|
|
728
|
+
|
|
729
|
+
const vendChildResponseSchema: VaultResponseSchema<VendChildResult> = z
|
|
730
|
+
.object({
|
|
731
|
+
credentials: stsCredentialsSchema,
|
|
732
|
+
sessionName: z.string(),
|
|
733
|
+
expiresAt: z.string(),
|
|
734
|
+
})
|
|
735
|
+
.strip();
|
|
736
|
+
|
|
737
|
+
const emptyObjectResponseSchema = z.object({}).strip();
|
|
738
|
+
|
|
739
|
+
function summarizeZodIssues(issues: readonly z.core.$ZodIssue[]): string {
|
|
740
|
+
return issues
|
|
741
|
+
.map((issue) => {
|
|
742
|
+
const path = issue.path.length > 0 ? issue.path.join(".") : "<root>";
|
|
743
|
+
return `${path}: ${issue.message}`;
|
|
744
|
+
})
|
|
745
|
+
.join("; ");
|
|
746
|
+
}
|
|
747
|
+
|
|
447
748
|
// ---------------------------------------------------------------------------
|
|
448
749
|
// VaultClient
|
|
449
750
|
// ---------------------------------------------------------------------------
|
|
@@ -472,17 +773,19 @@ export class VaultClient {
|
|
|
472
773
|
// -- Membership operations ------------------------------------------------
|
|
473
774
|
|
|
474
775
|
async createInvite(input: CreateInviteInput): Promise<CreateInviteResult> {
|
|
475
|
-
const data = await this.post
|
|
776
|
+
const data = await this.post(
|
|
476
777
|
"/membership/invite",
|
|
477
778
|
input,
|
|
779
|
+
createInviteResponseSchema,
|
|
478
780
|
);
|
|
479
781
|
return data;
|
|
480
782
|
}
|
|
481
783
|
|
|
482
784
|
async acceptInvite(token: string, personUid: string): Promise<AcceptInviteResult> {
|
|
483
|
-
const data = await this.post
|
|
785
|
+
const data = await this.post(
|
|
484
786
|
"/membership/accept",
|
|
485
787
|
{ token, personUid },
|
|
788
|
+
acceptInviteResponseSchema,
|
|
486
789
|
);
|
|
487
790
|
return data;
|
|
488
791
|
}
|
|
@@ -494,7 +797,11 @@ export class VaultClient {
|
|
|
494
797
|
* alone without an extra DDB read, and the caller already knows it.)
|
|
495
798
|
*/
|
|
496
799
|
async revokeMembership(membershipKey: string, companyUid: string): Promise<void> {
|
|
497
|
-
await this.post(
|
|
800
|
+
await this.post(
|
|
801
|
+
"/membership/revoke",
|
|
802
|
+
{ membershipKey, companyUid },
|
|
803
|
+
emptyObjectResponseSchema,
|
|
804
|
+
);
|
|
498
805
|
}
|
|
499
806
|
|
|
500
807
|
/**
|
|
@@ -513,7 +820,7 @@ export class VaultClient {
|
|
|
513
820
|
* Backed by `GET /membership/me` (see hq-pro ADR-0002).
|
|
514
821
|
*/
|
|
515
822
|
async listMyMemberships(): Promise<Membership[]> {
|
|
516
|
-
const data = await this.get
|
|
823
|
+
const data = await this.get("/membership/me", membershipsResponseSchema);
|
|
517
824
|
return data.memberships;
|
|
518
825
|
}
|
|
519
826
|
|
|
@@ -527,8 +834,9 @@ export class VaultClient {
|
|
|
527
834
|
* person exists.
|
|
528
835
|
*/
|
|
529
836
|
async listMyPendingInvitesByEmail(): Promise<PendingInviteByEmail[]> {
|
|
530
|
-
const data = await this.get
|
|
837
|
+
const data = await this.get(
|
|
531
838
|
"/membership/pending-by-email",
|
|
839
|
+
pendingInvitesByEmailResponseSchema,
|
|
532
840
|
);
|
|
533
841
|
return data.invites ?? [];
|
|
534
842
|
}
|
|
@@ -539,27 +847,34 @@ export class VaultClient {
|
|
|
539
847
|
* have no pending invites. The caller's email is inferred from the JWT.
|
|
540
848
|
*/
|
|
541
849
|
async claimPendingInvitesByEmail(personUid: string): Promise<void> {
|
|
542
|
-
await this.post(
|
|
850
|
+
await this.post(
|
|
851
|
+
"/membership/claim-by-email",
|
|
852
|
+
{ personUid },
|
|
853
|
+
emptyObjectResponseSchema,
|
|
854
|
+
);
|
|
543
855
|
}
|
|
544
856
|
|
|
545
857
|
async listMembersOfCompany(companyUid: string): Promise<Membership[]> {
|
|
546
|
-
const data = await this.get
|
|
858
|
+
const data = await this.get(
|
|
547
859
|
`/membership/company/${encodeURIComponent(companyUid)}`,
|
|
860
|
+
membersResponseSchema,
|
|
548
861
|
);
|
|
549
862
|
return data.members;
|
|
550
863
|
}
|
|
551
864
|
|
|
552
865
|
async updateRole(input: UpdateRoleInput): Promise<Membership> {
|
|
553
|
-
const data = await this.post
|
|
866
|
+
const data = await this.post(
|
|
554
867
|
"/membership/role",
|
|
555
868
|
input,
|
|
869
|
+
membershipResponseSchema,
|
|
556
870
|
);
|
|
557
871
|
return data.membership;
|
|
558
872
|
}
|
|
559
873
|
|
|
560
874
|
async listPendingInvites(companyUid: string): Promise<Membership[]> {
|
|
561
|
-
const data = await this.get
|
|
875
|
+
const data = await this.get(
|
|
562
876
|
`/membership/company/${encodeURIComponent(companyUid)}/pending`,
|
|
877
|
+
invitesResponseSchema,
|
|
563
878
|
);
|
|
564
879
|
return data.invites;
|
|
565
880
|
}
|
|
@@ -581,8 +896,9 @@ export class VaultClient {
|
|
|
581
896
|
* state without catching errors.
|
|
582
897
|
*/
|
|
583
898
|
async listMyExplicitGrants(companyUid: string): Promise<ExplicitGrant[]> {
|
|
584
|
-
const data = await this.get
|
|
899
|
+
const data = await this.get(
|
|
585
900
|
`/v1/files/grants?company=${encodeURIComponent(companyUid)}`,
|
|
901
|
+
explicitGrantsResponseSchema,
|
|
586
902
|
);
|
|
587
903
|
return data.grants ?? [];
|
|
588
904
|
}
|
|
@@ -608,15 +924,14 @@ export class VaultClient {
|
|
|
608
924
|
const qs = new URLSearchParams({ company: companyUid });
|
|
609
925
|
if (prefix) qs.set("prefix", prefix);
|
|
610
926
|
if (cursor) qs.set("cursor", cursor);
|
|
611
|
-
const data = await this.get
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
}>(`/v1/files/list?${qs.toString()}`);
|
|
927
|
+
const data = await this.get(
|
|
928
|
+
`/v1/files/list?${qs.toString()}`,
|
|
929
|
+
listFilesResponseSchema,
|
|
930
|
+
);
|
|
616
931
|
return {
|
|
617
|
-
objects: data.objects
|
|
618
|
-
cursor: data.cursor
|
|
619
|
-
truncated: data.truncated
|
|
932
|
+
objects: data.objects,
|
|
933
|
+
cursor: data.cursor,
|
|
934
|
+
truncated: data.truncated,
|
|
620
935
|
};
|
|
621
936
|
}
|
|
622
937
|
|
|
@@ -632,7 +947,7 @@ export class VaultClient {
|
|
|
632
947
|
expiresIn?: number;
|
|
633
948
|
keys: PresignKeyInput[];
|
|
634
949
|
}): Promise<{ results: PresignResultRow[]; expiresAt: string }> {
|
|
635
|
-
return this.post
|
|
950
|
+
return this.post(
|
|
636
951
|
`/v1/files/presign`,
|
|
637
952
|
{
|
|
638
953
|
company: input.companyUid,
|
|
@@ -640,6 +955,7 @@ export class VaultClient {
|
|
|
640
955
|
...(input.expiresIn ? { expiresIn: input.expiresIn } : {}),
|
|
641
956
|
keys: input.keys,
|
|
642
957
|
},
|
|
958
|
+
presignResponseSchema,
|
|
643
959
|
);
|
|
644
960
|
}
|
|
645
961
|
|
|
@@ -659,8 +975,9 @@ export class VaultClient {
|
|
|
659
975
|
async getMembershipSyncConfig(
|
|
660
976
|
membershipId: string,
|
|
661
977
|
): Promise<MembershipSyncConfig> {
|
|
662
|
-
return this.get
|
|
978
|
+
return this.get(
|
|
663
979
|
`/v1/memberships/${encodeURIComponent(membershipId)}/sync-config`,
|
|
980
|
+
membershipSyncConfigSchema,
|
|
664
981
|
);
|
|
665
982
|
}
|
|
666
983
|
|
|
@@ -678,10 +995,11 @@ export class VaultClient {
|
|
|
678
995
|
membershipId: string,
|
|
679
996
|
partial: SetMembershipSyncConfigInput,
|
|
680
997
|
): Promise<MembershipSyncConfig> {
|
|
681
|
-
return this.request
|
|
998
|
+
return this.request(
|
|
682
999
|
"PUT",
|
|
683
1000
|
`/v1/memberships/${encodeURIComponent(membershipId)}/sync-config`,
|
|
684
1001
|
partial,
|
|
1002
|
+
membershipSyncConfigSchema,
|
|
685
1003
|
);
|
|
686
1004
|
}
|
|
687
1005
|
|
|
@@ -689,7 +1007,10 @@ export class VaultClient {
|
|
|
689
1007
|
|
|
690
1008
|
readonly entity = {
|
|
691
1009
|
get: async (uid: string): Promise<EntityInfo> => {
|
|
692
|
-
const data = await this.get
|
|
1010
|
+
const data = await this.get(
|
|
1011
|
+
`/entity/${encodeURIComponent(uid)}`,
|
|
1012
|
+
entityResponseSchema,
|
|
1013
|
+
);
|
|
693
1014
|
return data.entity;
|
|
694
1015
|
},
|
|
695
1016
|
|
|
@@ -705,8 +1026,9 @@ export class VaultClient {
|
|
|
705
1026
|
* global lookup (admin tooling) should still use this method.
|
|
706
1027
|
*/
|
|
707
1028
|
findBySlug: async (type: string, slug: string): Promise<EntityInfo> => {
|
|
708
|
-
const data = await this.get
|
|
1029
|
+
const data = await this.get(
|
|
709
1030
|
`/entity/by-slug/${encodeURIComponent(type)}/${encodeURIComponent(slug)}`,
|
|
1031
|
+
entityResponseSchema,
|
|
710
1032
|
);
|
|
711
1033
|
return data.entity;
|
|
712
1034
|
},
|
|
@@ -727,25 +1049,24 @@ export class VaultClient {
|
|
|
727
1049
|
type: string,
|
|
728
1050
|
slug: string,
|
|
729
1051
|
): Promise<EntityInfo | null> => {
|
|
730
|
-
const check = await this.get
|
|
731
|
-
available: boolean;
|
|
732
|
-
conflictingCompanyUid?: string;
|
|
733
|
-
}>(
|
|
1052
|
+
const check = await this.get(
|
|
734
1053
|
`/entity/check-slug/me?type=${encodeURIComponent(type)}&slug=${encodeURIComponent(slug)}`,
|
|
1054
|
+
checkSlugMeResponseSchema,
|
|
735
1055
|
);
|
|
736
1056
|
if (check.available || !check.conflictingCompanyUid) return null;
|
|
737
1057
|
return this.entity.get(check.conflictingCompanyUid);
|
|
738
1058
|
},
|
|
739
1059
|
|
|
740
1060
|
create: async (input: CreateEntityInput): Promise<EntityInfo> => {
|
|
741
|
-
const data = await this.post
|
|
1061
|
+
const data = await this.post("/entity", input, createEntityResponseSchema);
|
|
742
1062
|
return data.entity;
|
|
743
1063
|
},
|
|
744
1064
|
|
|
745
1065
|
/** Return every entity of `type` owned by the caller (scoped by JWT). */
|
|
746
1066
|
listByType: async (type: string): Promise<EntityInfo[]> => {
|
|
747
|
-
const data = await this.get
|
|
1067
|
+
const data = await this.get(
|
|
748
1068
|
`/entity/by-type/${encodeURIComponent(type)}`,
|
|
1069
|
+
entitiesResponseSchema,
|
|
749
1070
|
);
|
|
750
1071
|
return data.entities ?? [];
|
|
751
1072
|
},
|
|
@@ -789,9 +1110,10 @@ export class VaultClient {
|
|
|
789
1110
|
// -- Provisioning operations (VLT-2) -----------------------------------------
|
|
790
1111
|
|
|
791
1112
|
async provisionBucket(companyUid: string): Promise<{ bucketName: string; kmsKeyId: string }> {
|
|
792
|
-
const data = await this.post
|
|
1113
|
+
const data = await this.post(
|
|
793
1114
|
"/provision/bucket",
|
|
794
1115
|
{ companyUid },
|
|
1116
|
+
provisionBucketResponseSchema,
|
|
795
1117
|
);
|
|
796
1118
|
return data;
|
|
797
1119
|
}
|
|
@@ -820,7 +1142,7 @@ export class VaultClient {
|
|
|
820
1142
|
* objects without ever materialising them under `companies/{co}/`.
|
|
821
1143
|
*/
|
|
822
1144
|
async vend(input: VendInput): Promise<VendResult> {
|
|
823
|
-
return this.post
|
|
1145
|
+
return this.post("/vend", input, vendResponseSchema);
|
|
824
1146
|
}
|
|
825
1147
|
|
|
826
1148
|
// -- STS operations (VLT-8) -----------------------------------------------
|
|
@@ -848,7 +1170,7 @@ export class VaultClient {
|
|
|
848
1170
|
};
|
|
849
1171
|
expiresAt: string;
|
|
850
1172
|
}> => {
|
|
851
|
-
return this.post("/sts/vend", input);
|
|
1173
|
+
return this.post("/sts/vend", input, stsVendResponseSchema);
|
|
852
1174
|
},
|
|
853
1175
|
/**
|
|
854
1176
|
* Vend task-scoped child credentials strictly narrower than the caller's
|
|
@@ -864,14 +1186,14 @@ export class VaultClient {
|
|
|
864
1186
|
* the parent task for incident response.
|
|
865
1187
|
*/
|
|
866
1188
|
vendChild: async (input: VendChildInput): Promise<VendChildResult> => {
|
|
867
|
-
const data = await this.post
|
|
1189
|
+
const data = await this.post("/sts/vend-child", input, vendChildResponseSchema);
|
|
868
1190
|
return data;
|
|
869
1191
|
},
|
|
870
1192
|
vendSelf: async (input: { personUid: string; durationSeconds?: number }): Promise<{
|
|
871
1193
|
credentials: { accessKeyId: string; secretAccessKey: string; sessionToken: string };
|
|
872
1194
|
expiresAt: string;
|
|
873
1195
|
}> => {
|
|
874
|
-
return this.post("/sts/vend-self", input);
|
|
1196
|
+
return this.post("/sts/vend-self", input, stsVendResponseSchema);
|
|
875
1197
|
},
|
|
876
1198
|
};
|
|
877
1199
|
|
|
@@ -891,7 +1213,7 @@ export class VaultClient {
|
|
|
891
1213
|
* either yes or no; see `./telemetry.ts::collectAndSendTelemetry`.
|
|
892
1214
|
*/
|
|
893
1215
|
async getTelemetryOptIn(): Promise<TelemetryOptInResponse> {
|
|
894
|
-
return this.get
|
|
1216
|
+
return this.get("/v1/usage/opt-in", telemetryOptInResponseSchema);
|
|
895
1217
|
}
|
|
896
1218
|
|
|
897
1219
|
/**
|
|
@@ -903,7 +1225,7 @@ export class VaultClient {
|
|
|
903
1225
|
* 1 MiB pre-flush cap which is the binding limit in practice.
|
|
904
1226
|
*/
|
|
905
1227
|
async postUsage(batch: UsageBatch): Promise<UsageIngestResult> {
|
|
906
|
-
return this.post
|
|
1228
|
+
return this.post("/v1/usage", batch, usageIngestResultSchema);
|
|
907
1229
|
}
|
|
908
1230
|
|
|
909
1231
|
/**
|
|
@@ -916,20 +1238,29 @@ export class VaultClient {
|
|
|
916
1238
|
async postSkillInvocations(
|
|
917
1239
|
batch: SkillInvocationBatch,
|
|
918
1240
|
): Promise<SkillInvocationIngestResult> {
|
|
919
|
-
return this.post
|
|
1241
|
+
return this.post("/v1/skill-invocations", batch, usageIngestResultSchema);
|
|
920
1242
|
}
|
|
921
1243
|
|
|
922
1244
|
// -- HTTP primitives with retry -------------------------------------------
|
|
923
1245
|
|
|
924
|
-
private async get<T>(path: string): Promise<T> {
|
|
925
|
-
return this.request
|
|
1246
|
+
private async get<T>(path: string, schema: VaultResponseSchema<T>): Promise<T> {
|
|
1247
|
+
return this.request("GET", path, undefined, schema);
|
|
926
1248
|
}
|
|
927
1249
|
|
|
928
|
-
private async post<T>(
|
|
929
|
-
|
|
1250
|
+
private async post<T>(
|
|
1251
|
+
path: string,
|
|
1252
|
+
body: unknown | undefined,
|
|
1253
|
+
schema: VaultResponseSchema<T>,
|
|
1254
|
+
): Promise<T> {
|
|
1255
|
+
return this.request("POST", path, body, schema);
|
|
930
1256
|
}
|
|
931
1257
|
|
|
932
|
-
private async request<T>(
|
|
1258
|
+
private async request<T>(
|
|
1259
|
+
method: string,
|
|
1260
|
+
path: string,
|
|
1261
|
+
body: unknown,
|
|
1262
|
+
schema: VaultResponseSchema<T>,
|
|
1263
|
+
): Promise<T> {
|
|
933
1264
|
let lastError: Error | undefined;
|
|
934
1265
|
|
|
935
1266
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
@@ -962,7 +1293,28 @@ export class VaultClient {
|
|
|
962
1293
|
|
|
963
1294
|
if (res.ok) {
|
|
964
1295
|
if (res.status === 204) return undefined as T;
|
|
965
|
-
|
|
1296
|
+
const responseBody = await res.text();
|
|
1297
|
+
let decoded: unknown;
|
|
1298
|
+
try {
|
|
1299
|
+
decoded = JSON.parse(responseBody);
|
|
1300
|
+
} catch (err) {
|
|
1301
|
+
throw new VaultClientError(
|
|
1302
|
+
`Invalid JSON response from vault-service for ${method} ${path}`,
|
|
1303
|
+
502,
|
|
1304
|
+
err instanceof Error ? err.message : responseBody,
|
|
1305
|
+
);
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
const parsed = schema.safeParse(decoded);
|
|
1309
|
+
if (!parsed.success) {
|
|
1310
|
+
throw new VaultClientError(
|
|
1311
|
+
`Invalid response from vault-service for ${method} ${path}: ${summarizeZodIssues(parsed.error.issues)}`,
|
|
1312
|
+
502,
|
|
1313
|
+
responseBody,
|
|
1314
|
+
);
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
return parsed.data;
|
|
966
1318
|
}
|
|
967
1319
|
|
|
968
1320
|
const responseBody = await res.text();
|