@indigoai-us/hq-cloud 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/dist/auth.d.ts +21 -0
  2. package/dist/auth.d.ts.map +1 -0
  3. package/dist/auth.js +116 -0
  4. package/dist/auth.js.map +1 -0
  5. package/dist/cli/accept.d.ts +29 -0
  6. package/dist/cli/accept.d.ts.map +1 -0
  7. package/dist/cli/accept.js +67 -0
  8. package/dist/cli/accept.js.map +1 -0
  9. package/dist/cli/conflict.d.ts +33 -0
  10. package/dist/cli/conflict.d.ts.map +1 -0
  11. package/dist/cli/conflict.js +91 -0
  12. package/dist/cli/conflict.js.map +1 -0
  13. package/dist/cli/index.d.ts +19 -0
  14. package/dist/cli/index.d.ts.map +1 -0
  15. package/dist/cli/index.js +14 -0
  16. package/dist/cli/index.js.map +1 -0
  17. package/dist/cli/invite.d.ts +51 -0
  18. package/dist/cli/invite.d.ts.map +1 -0
  19. package/dist/cli/invite.js +120 -0
  20. package/dist/cli/invite.js.map +1 -0
  21. package/dist/cli/invite.test.d.ts +5 -0
  22. package/dist/cli/invite.test.d.ts.map +1 -0
  23. package/dist/cli/invite.test.js +175 -0
  24. package/dist/cli/invite.test.js.map +1 -0
  25. package/dist/cli/promote.d.ts +30 -0
  26. package/dist/cli/promote.d.ts.map +1 -0
  27. package/dist/cli/promote.js +79 -0
  28. package/dist/cli/promote.js.map +1 -0
  29. package/dist/cli/share.d.ts +33 -0
  30. package/dist/cli/share.d.ts.map +1 -0
  31. package/dist/cli/share.js +153 -0
  32. package/dist/cli/share.js.map +1 -0
  33. package/dist/cli/share.test.d.ts +5 -0
  34. package/dist/cli/share.test.d.ts.map +1 -0
  35. package/dist/cli/share.test.js +121 -0
  36. package/dist/cli/share.test.js.map +1 -0
  37. package/dist/cli/sync.d.ts +30 -0
  38. package/dist/cli/sync.d.ts.map +1 -0
  39. package/dist/cli/sync.js +138 -0
  40. package/dist/cli/sync.js.map +1 -0
  41. package/dist/cli/sync.test.d.ts +5 -0
  42. package/dist/cli/sync.test.d.ts.map +1 -0
  43. package/dist/cli/sync.test.js +172 -0
  44. package/dist/cli/sync.test.js.map +1 -0
  45. package/dist/cognito-auth.d.ts +70 -0
  46. package/dist/cognito-auth.d.ts.map +1 -0
  47. package/dist/cognito-auth.js +280 -0
  48. package/dist/cognito-auth.js.map +1 -0
  49. package/dist/context.d.ts +30 -0
  50. package/dist/context.d.ts.map +1 -0
  51. package/dist/context.js +117 -0
  52. package/dist/context.js.map +1 -0
  53. package/dist/context.test.d.ts +7 -0
  54. package/dist/context.test.d.ts.map +1 -0
  55. package/dist/context.test.js +148 -0
  56. package/dist/context.test.js.map +1 -0
  57. package/dist/daemon-worker.d.ts +6 -0
  58. package/dist/daemon-worker.d.ts.map +1 -0
  59. package/dist/daemon-worker.js +26 -0
  60. package/dist/daemon-worker.js.map +1 -0
  61. package/dist/daemon.d.ts +10 -0
  62. package/dist/daemon.d.ts.map +1 -0
  63. package/dist/daemon.js +88 -0
  64. package/dist/daemon.js.map +1 -0
  65. package/dist/ignore.d.ts +10 -0
  66. package/dist/ignore.d.ts.map +1 -0
  67. package/dist/ignore.js +54 -0
  68. package/dist/ignore.js.map +1 -0
  69. package/dist/index.d.ts +33 -0
  70. package/dist/index.d.ts.map +1 -0
  71. package/dist/index.js +138 -0
  72. package/dist/index.js.map +1 -0
  73. package/dist/journal.d.ts +12 -0
  74. package/dist/journal.d.ts.map +1 -0
  75. package/dist/journal.js +42 -0
  76. package/dist/journal.js.map +1 -0
  77. package/dist/s3.d.ts +15 -0
  78. package/dist/s3.d.ts.map +1 -0
  79. package/dist/s3.js +129 -0
  80. package/dist/s3.js.map +1 -0
  81. package/dist/types.d.ts +52 -0
  82. package/dist/types.d.ts.map +1 -0
  83. package/dist/types.js +5 -0
  84. package/dist/types.js.map +1 -0
  85. package/dist/vault-client.d.ts +164 -0
  86. package/dist/vault-client.d.ts.map +1 -0
  87. package/dist/vault-client.js +209 -0
  88. package/dist/vault-client.js.map +1 -0
  89. package/dist/vault-client.test.d.ts +7 -0
  90. package/dist/vault-client.test.d.ts.map +1 -0
  91. package/dist/vault-client.test.js +257 -0
  92. package/dist/vault-client.test.js.map +1 -0
  93. package/dist/watcher.d.ts +18 -0
  94. package/dist/watcher.d.ts.map +1 -0
  95. package/dist/watcher.js +106 -0
  96. package/dist/watcher.js.map +1 -0
  97. package/package.json +32 -0
  98. package/src/auth.ts +146 -0
  99. package/src/cognito-auth.ts +375 -0
  100. package/src/daemon-worker.ts +32 -0
  101. package/src/daemon.ts +97 -0
  102. package/src/ignore.ts +61 -0
  103. package/src/index.ts +182 -0
  104. package/src/journal.ts +63 -0
  105. package/src/s3.ts +178 -0
  106. package/src/types.ts +59 -0
  107. package/src/watcher.ts +130 -0
  108. package/tsconfig.json +8 -0
@@ -0,0 +1,52 @@
1
+ /**
2
+ * HQ Cloud Sync Types
3
+ */
4
+ export interface SyncConfig {
5
+ bucket: string;
6
+ region: string;
7
+ userId: string;
8
+ prefix: string;
9
+ }
10
+ export interface Credentials {
11
+ accessKeyId: string;
12
+ secretAccessKey: string;
13
+ sessionToken?: string;
14
+ expiration?: string;
15
+ refreshToken: string;
16
+ userId: string;
17
+ bucket: string;
18
+ region: string;
19
+ teamId?: string;
20
+ }
21
+ export interface JournalEntry {
22
+ hash: string;
23
+ size: number;
24
+ syncedAt: string;
25
+ direction: "up" | "down";
26
+ }
27
+ export interface SyncJournal {
28
+ version: "1";
29
+ lastSync: string;
30
+ files: Record<string, JournalEntry>;
31
+ }
32
+ export interface SyncStatus {
33
+ running: boolean;
34
+ lastSync: string | null;
35
+ fileCount: number;
36
+ bucket: string | null;
37
+ errors: string[];
38
+ }
39
+ export interface PushResult {
40
+ filesUploaded: number;
41
+ bytesUploaded: number;
42
+ }
43
+ export interface PullResult {
44
+ filesDownloaded: number;
45
+ bytesDownloaded: number;
46
+ }
47
+ export interface DaemonState {
48
+ pid: number;
49
+ startedAt: string;
50
+ hqRoot: string;
51
+ }
52
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,IAAI,GAAG,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,GAAG,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * HQ Cloud Sync Types
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,164 @@
1
+ /**
2
+ * VaultClient — typed SDK for vault-service membership operations (VLT-7 US-001).
3
+ *
4
+ * Wraps vault-service HTTP API with shared auth, retry, and typed errors.
5
+ * Colocated with hq-cloud so /invite, /promote, /accept and future commands
6
+ * share one client instead of each rolling its own HTTP layer.
7
+ */
8
+ import type { VaultServiceConfig } from "./types.js";
9
+ export declare class VaultClientError extends Error {
10
+ readonly statusCode: number;
11
+ readonly body?: string | undefined;
12
+ constructor(message: string, statusCode: number, body?: string | undefined);
13
+ }
14
+ export declare class VaultAuthError extends VaultClientError {
15
+ constructor(message?: string);
16
+ }
17
+ export declare class VaultPermissionDeniedError extends VaultClientError {
18
+ constructor(message?: string);
19
+ }
20
+ export declare class VaultNotFoundError extends VaultClientError {
21
+ constructor(message?: string);
22
+ }
23
+ export declare class VaultConflictError extends VaultClientError {
24
+ constructor(message?: string);
25
+ }
26
+ export type MembershipRole = "owner" | "admin" | "member" | "guest";
27
+ export type MembershipStatus = "pending" | "active" | "revoked";
28
+ export interface Membership {
29
+ membershipKey: string;
30
+ personUid: string;
31
+ companyUid: string;
32
+ role: MembershipRole;
33
+ status: MembershipStatus;
34
+ allowedPrefixes?: string[];
35
+ inviteToken?: string;
36
+ invitedBy: string;
37
+ invitedAt: string;
38
+ acceptedAt?: string;
39
+ revokedAt?: string;
40
+ createdAt: string;
41
+ updatedAt: string;
42
+ }
43
+ export interface CreateInviteInput {
44
+ personUid?: string;
45
+ inviteeEmail?: string;
46
+ companyUid: string;
47
+ role: MembershipRole;
48
+ allowedPrefixes?: string[];
49
+ invitedBy: string;
50
+ }
51
+ export interface CreateInviteResult {
52
+ membership: Membership;
53
+ inviteToken: string;
54
+ }
55
+ export interface AcceptInviteResult {
56
+ membership: Membership;
57
+ }
58
+ export interface UpdateRoleInput {
59
+ membershipKey: string;
60
+ newRole: MembershipRole;
61
+ allowedPrefixes?: string[];
62
+ updaterUid: string;
63
+ /** Required so the server can authorize the caller as admin/owner of the company. */
64
+ companyUid: string;
65
+ }
66
+ export interface EntityInfo {
67
+ uid: string;
68
+ slug: string;
69
+ type: string;
70
+ bucketName?: string;
71
+ status: string;
72
+ }
73
+ export interface CreateEntityInput {
74
+ type: "person" | "company";
75
+ slug: string;
76
+ name: string;
77
+ email?: string;
78
+ ownerUid?: string;
79
+ }
80
+ export interface CreateEntityResult {
81
+ entity: EntityInfo;
82
+ }
83
+ export type TaskAction = "read" | "write";
84
+ export interface TaskScope {
85
+ /** S3 key prefixes the child may access (e.g. ["drafts/"]). */
86
+ allowedPrefixes: string[];
87
+ /** Defaults to ["read", "write"]. Use ["read"] for read-only children. */
88
+ allowedActions?: TaskAction[];
89
+ }
90
+ export interface VendChildInput {
91
+ companyUid: string;
92
+ /** ULID generated by the parent task. Flows into STS session name for audit. */
93
+ taskId: string;
94
+ /** Short human-readable description (<256 chars). Logged alongside the session. */
95
+ taskDescription: string;
96
+ taskScope: TaskScope;
97
+ /**
98
+ * Child session duration in seconds. Defaults to 900 on the server — AWS STS
99
+ * AssumeRole enforces a 900s floor. The task-scoped policy is the security
100
+ * boundary, not the duration.
101
+ */
102
+ durationSeconds?: number;
103
+ }
104
+ export interface StsChildCredentials {
105
+ accessKeyId: string;
106
+ secretAccessKey: string;
107
+ sessionToken: string;
108
+ }
109
+ export interface VendChildResult {
110
+ credentials: StsChildCredentials;
111
+ /** STS session name: `${parentPersonUid}--task--${taskId}` — used in CloudTrail.
112
+ * (Dash-separated because AWS STS `roleSessionName` disallows colons.) */
113
+ sessionName: string;
114
+ /** ISO-8601 session expiration. */
115
+ expiresAt: string;
116
+ }
117
+ export declare class VaultClient {
118
+ private readonly apiUrl;
119
+ private readonly authToken;
120
+ constructor(config: VaultServiceConfig);
121
+ createInvite(input: CreateInviteInput): Promise<CreateInviteResult>;
122
+ acceptInvite(token: string, personUid: string): Promise<AcceptInviteResult>;
123
+ /**
124
+ * Revoke a membership. The handler needs both the membershipKey AND the
125
+ * companyUid so it can authorize the caller as admin/owner of the company
126
+ * before performing the revoke. (We can't infer companyUid from the key
127
+ * alone without an extra DDB read, and the caller already knows it.)
128
+ */
129
+ revokeMembership(membershipKey: string, companyUid: string): Promise<void>;
130
+ listMembersOfCompany(companyUid: string): Promise<Membership[]>;
131
+ updateRole(input: UpdateRoleInput): Promise<Membership>;
132
+ listPendingInvites(companyUid: string): Promise<Membership[]>;
133
+ readonly entity: {
134
+ get: (uid: string) => Promise<EntityInfo>;
135
+ findBySlug: (type: string, slug: string) => Promise<EntityInfo>;
136
+ create: (input: CreateEntityInput) => Promise<EntityInfo>;
137
+ };
138
+ provisionBucket(companyUid: string): Promise<{
139
+ bucketName: string;
140
+ kmsKeyId: string;
141
+ }>;
142
+ readonly sts: {
143
+ /**
144
+ * Vend task-scoped child credentials strictly narrower than the caller's
145
+ * own membership. Backed by the vault-service `POST /sts/vend-child`
146
+ * route (kebab-case to match the rest of the vault-service API).
147
+ *
148
+ * The child policy is intersected with the caller's membership on the
149
+ * server — if `taskScope.allowedPrefixes` requests anything the parent
150
+ * can't see, the server throws ScopeExceedsParentError before calling STS.
151
+ *
152
+ * Session name format: `${parentPersonUid}--task--${taskId}` — this lands
153
+ * in CloudTrail verbatim, so every child S3 action can be traced back to
154
+ * the parent task for incident response.
155
+ */
156
+ vendChild: (input: VendChildInput) => Promise<VendChildResult>;
157
+ };
158
+ private get;
159
+ private post;
160
+ private request;
161
+ private mapError;
162
+ private extractMessage;
163
+ }
164
+ //# sourceMappingURL=vault-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault-client.d.ts","sourceRoot":"","sources":["../src/vault-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,209 @@
1
+ /**
2
+ * VaultClient — typed SDK for vault-service membership operations (VLT-7 US-001).
3
+ *
4
+ * Wraps vault-service HTTP API with shared auth, retry, and typed errors.
5
+ * Colocated with hq-cloud so /invite, /promote, /accept and future commands
6
+ * share one client instead of each rolling its own HTTP layer.
7
+ */
8
+ // ---------------------------------------------------------------------------
9
+ // Error classes
10
+ // ---------------------------------------------------------------------------
11
+ export class VaultClientError extends Error {
12
+ statusCode;
13
+ body;
14
+ constructor(message, statusCode, body) {
15
+ super(message);
16
+ this.statusCode = statusCode;
17
+ this.body = body;
18
+ this.name = "VaultClientError";
19
+ }
20
+ }
21
+ export class VaultAuthError extends VaultClientError {
22
+ constructor(message = "Authentication failed — session expired or invalid") {
23
+ super(message, 401);
24
+ this.name = "VaultAuthError";
25
+ }
26
+ }
27
+ export class VaultPermissionDeniedError extends VaultClientError {
28
+ constructor(message = "Permission denied — admin role required") {
29
+ super(message, 403);
30
+ this.name = "VaultPermissionDeniedError";
31
+ }
32
+ }
33
+ export class VaultNotFoundError extends VaultClientError {
34
+ constructor(message = "Resource not found") {
35
+ super(message, 404);
36
+ this.name = "VaultNotFoundError";
37
+ }
38
+ }
39
+ export class VaultConflictError extends VaultClientError {
40
+ constructor(message = "Conflict — resource already exists or was already accepted") {
41
+ super(message, 409);
42
+ this.name = "VaultConflictError";
43
+ }
44
+ }
45
+ // ---------------------------------------------------------------------------
46
+ // Retry config
47
+ // ---------------------------------------------------------------------------
48
+ const MAX_RETRIES = 3;
49
+ const BASE_DELAY_MS = 500;
50
+ function isTransient(status) {
51
+ return status === 429 || status >= 500;
52
+ }
53
+ async function sleep(ms) {
54
+ return new Promise((resolve) => setTimeout(resolve, ms));
55
+ }
56
+ // ---------------------------------------------------------------------------
57
+ // VaultClient
58
+ // ---------------------------------------------------------------------------
59
+ export class VaultClient {
60
+ apiUrl;
61
+ authToken;
62
+ constructor(config) {
63
+ this.apiUrl = config.apiUrl.replace(/\/+$/, "");
64
+ this.authToken = config.authToken;
65
+ }
66
+ // -- Membership operations ------------------------------------------------
67
+ async createInvite(input) {
68
+ const data = await this.post("/membership/invite", input);
69
+ return data;
70
+ }
71
+ async acceptInvite(token, personUid) {
72
+ const data = await this.post("/membership/accept", { token, personUid });
73
+ return data;
74
+ }
75
+ /**
76
+ * Revoke a membership. The handler needs both the membershipKey AND the
77
+ * companyUid so it can authorize the caller as admin/owner of the company
78
+ * before performing the revoke. (We can't infer companyUid from the key
79
+ * alone without an extra DDB read, and the caller already knows it.)
80
+ */
81
+ async revokeMembership(membershipKey, companyUid) {
82
+ await this.post("/membership/revoke", { membershipKey, companyUid });
83
+ }
84
+ async listMembersOfCompany(companyUid) {
85
+ const data = await this.get(`/membership/company/${encodeURIComponent(companyUid)}`);
86
+ return data.members;
87
+ }
88
+ async updateRole(input) {
89
+ const data = await this.post("/membership/role", input);
90
+ return data.membership;
91
+ }
92
+ async listPendingInvites(companyUid) {
93
+ const data = await this.get(`/membership/company/${encodeURIComponent(companyUid)}/pending`);
94
+ return data.invites;
95
+ }
96
+ // -- Entity operations ----------------------------------------------------
97
+ entity = {
98
+ get: async (uid) => {
99
+ const data = await this.get(`/entity/${encodeURIComponent(uid)}`);
100
+ return data.entity;
101
+ },
102
+ findBySlug: async (type, slug) => {
103
+ const data = await this.get(`/entity/by-slug/${encodeURIComponent(type)}/${encodeURIComponent(slug)}`);
104
+ return data.entity;
105
+ },
106
+ create: async (input) => {
107
+ const data = await this.post("/entity", input);
108
+ return data.entity;
109
+ },
110
+ };
111
+ // -- Provisioning operations (VLT-2) -----------------------------------------
112
+ async provisionBucket(companyUid) {
113
+ const data = await this.post("/provision/bucket", { companyUid });
114
+ return data;
115
+ }
116
+ // -- STS operations (VLT-8) -----------------------------------------------
117
+ sts = {
118
+ /**
119
+ * Vend task-scoped child credentials strictly narrower than the caller's
120
+ * own membership. Backed by the vault-service `POST /sts/vend-child`
121
+ * route (kebab-case to match the rest of the vault-service API).
122
+ *
123
+ * The child policy is intersected with the caller's membership on the
124
+ * server — if `taskScope.allowedPrefixes` requests anything the parent
125
+ * can't see, the server throws ScopeExceedsParentError before calling STS.
126
+ *
127
+ * Session name format: `${parentPersonUid}--task--${taskId}` — this lands
128
+ * in CloudTrail verbatim, so every child S3 action can be traced back to
129
+ * the parent task for incident response.
130
+ */
131
+ vendChild: async (input) => {
132
+ const data = await this.post("/sts/vend-child", input);
133
+ return data;
134
+ },
135
+ };
136
+ // -- HTTP primitives with retry -------------------------------------------
137
+ async get(path) {
138
+ return this.request("GET", path);
139
+ }
140
+ async post(path, body) {
141
+ return this.request("POST", path, body);
142
+ }
143
+ async request(method, path, body) {
144
+ let lastError;
145
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
146
+ if (attempt > 0) {
147
+ const delay = BASE_DELAY_MS * Math.pow(2, attempt - 1);
148
+ await sleep(delay);
149
+ }
150
+ const headers = {
151
+ Authorization: `Bearer ${this.authToken}`,
152
+ Accept: "application/json",
153
+ };
154
+ const init = { method, headers };
155
+ if (body !== undefined) {
156
+ headers["Content-Type"] = "application/json";
157
+ init.body = JSON.stringify(body);
158
+ }
159
+ let res;
160
+ try {
161
+ res = await fetch(`${this.apiUrl}${path}`, init);
162
+ }
163
+ catch (err) {
164
+ lastError = err instanceof Error ? err : new Error(String(err));
165
+ if (attempt < MAX_RETRIES)
166
+ continue;
167
+ throw lastError;
168
+ }
169
+ if (res.ok) {
170
+ if (res.status === 204)
171
+ return undefined;
172
+ return (await res.json());
173
+ }
174
+ const responseBody = await res.text();
175
+ // Non-retryable errors → throw immediately
176
+ if (!isTransient(res.status)) {
177
+ throw this.mapError(res.status, responseBody);
178
+ }
179
+ // Retryable — store and loop
180
+ lastError = this.mapError(res.status, responseBody);
181
+ }
182
+ throw lastError ?? new VaultClientError("Request failed after retries", 500);
183
+ }
184
+ mapError(status, body) {
185
+ const message = this.extractMessage(body);
186
+ switch (status) {
187
+ case 401:
188
+ return new VaultAuthError(message);
189
+ case 403:
190
+ return new VaultPermissionDeniedError(message);
191
+ case 404:
192
+ return new VaultNotFoundError(message);
193
+ case 409:
194
+ return new VaultConflictError(message);
195
+ default:
196
+ return new VaultClientError(message || `Request failed with status ${status}`, status, body);
197
+ }
198
+ }
199
+ extractMessage(body) {
200
+ try {
201
+ const parsed = JSON.parse(body);
202
+ return parsed.message ?? parsed.error ?? body;
203
+ }
204
+ catch {
205
+ return body;
206
+ }
207
+ }
208
+ }
209
+ //# sourceMappingURL=vault-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault-client.js","sourceRoot":"","sources":["../src/vault-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * VaultClient unit tests (VLT-7 US-001).
3
+ *
4
+ * Uses mocked fetch to assert retry behavior, error mapping, and auth header injection.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=vault-client.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault-client.test.d.ts","sourceRoot":"","sources":["../src/vault-client.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}