@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.
- package/dist/auth.d.ts +21 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +116 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli/accept.d.ts +29 -0
- package/dist/cli/accept.d.ts.map +1 -0
- package/dist/cli/accept.js +67 -0
- package/dist/cli/accept.js.map +1 -0
- package/dist/cli/conflict.d.ts +33 -0
- package/dist/cli/conflict.d.ts.map +1 -0
- package/dist/cli/conflict.js +91 -0
- package/dist/cli/conflict.js.map +1 -0
- package/dist/cli/index.d.ts +19 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +14 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/invite.d.ts +51 -0
- package/dist/cli/invite.d.ts.map +1 -0
- package/dist/cli/invite.js +120 -0
- package/dist/cli/invite.js.map +1 -0
- package/dist/cli/invite.test.d.ts +5 -0
- package/dist/cli/invite.test.d.ts.map +1 -0
- package/dist/cli/invite.test.js +175 -0
- package/dist/cli/invite.test.js.map +1 -0
- package/dist/cli/promote.d.ts +30 -0
- package/dist/cli/promote.d.ts.map +1 -0
- package/dist/cli/promote.js +79 -0
- package/dist/cli/promote.js.map +1 -0
- package/dist/cli/share.d.ts +33 -0
- package/dist/cli/share.d.ts.map +1 -0
- package/dist/cli/share.js +153 -0
- package/dist/cli/share.js.map +1 -0
- package/dist/cli/share.test.d.ts +5 -0
- package/dist/cli/share.test.d.ts.map +1 -0
- package/dist/cli/share.test.js +121 -0
- package/dist/cli/share.test.js.map +1 -0
- package/dist/cli/sync.d.ts +30 -0
- package/dist/cli/sync.d.ts.map +1 -0
- package/dist/cli/sync.js +138 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/cli/sync.test.d.ts +5 -0
- package/dist/cli/sync.test.d.ts.map +1 -0
- package/dist/cli/sync.test.js +172 -0
- package/dist/cli/sync.test.js.map +1 -0
- package/dist/cognito-auth.d.ts +70 -0
- package/dist/cognito-auth.d.ts.map +1 -0
- package/dist/cognito-auth.js +280 -0
- package/dist/cognito-auth.js.map +1 -0
- package/dist/context.d.ts +30 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +117 -0
- package/dist/context.js.map +1 -0
- package/dist/context.test.d.ts +7 -0
- package/dist/context.test.d.ts.map +1 -0
- package/dist/context.test.js +148 -0
- package/dist/context.test.js.map +1 -0
- package/dist/daemon-worker.d.ts +6 -0
- package/dist/daemon-worker.d.ts.map +1 -0
- package/dist/daemon-worker.js +26 -0
- package/dist/daemon-worker.js.map +1 -0
- package/dist/daemon.d.ts +10 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +88 -0
- package/dist/daemon.js.map +1 -0
- package/dist/ignore.d.ts +10 -0
- package/dist/ignore.d.ts.map +1 -0
- package/dist/ignore.js +54 -0
- package/dist/ignore.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +138 -0
- package/dist/index.js.map +1 -0
- package/dist/journal.d.ts +12 -0
- package/dist/journal.d.ts.map +1 -0
- package/dist/journal.js +42 -0
- package/dist/journal.js.map +1 -0
- package/dist/s3.d.ts +15 -0
- package/dist/s3.d.ts.map +1 -0
- package/dist/s3.js +129 -0
- package/dist/s3.js.map +1 -0
- package/dist/types.d.ts +52 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/vault-client.d.ts +164 -0
- package/dist/vault-client.d.ts.map +1 -0
- package/dist/vault-client.js +209 -0
- package/dist/vault-client.js.map +1 -0
- package/dist/vault-client.test.d.ts +7 -0
- package/dist/vault-client.test.d.ts.map +1 -0
- package/dist/vault-client.test.js +257 -0
- package/dist/vault-client.test.js.map +1 -0
- package/dist/watcher.d.ts +18 -0
- package/dist/watcher.d.ts.map +1 -0
- package/dist/watcher.js +106 -0
- package/dist/watcher.js.map +1 -0
- package/package.json +32 -0
- package/src/auth.ts +146 -0
- package/src/cognito-auth.ts +375 -0
- package/src/daemon-worker.ts +32 -0
- package/src/daemon.ts +97 -0
- package/src/ignore.ts +61 -0
- package/src/index.ts +182 -0
- package/src/journal.ts +63 -0
- package/src/s3.ts +178 -0
- package/src/types.ts +59 -0
- package/src/watcher.ts +130 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cognito browser-OAuth helper (VLT-9).
|
|
3
|
+
*
|
|
4
|
+
* Drives the Cognito Hosted UI authorization-code + PKCE flow for the
|
|
5
|
+
* vault-service User Pool. Used by the CLI (`hq login`, `create-hq`) to
|
|
6
|
+
* obtain a JWT that is then passed to the vault-service API as
|
|
7
|
+
* `Authorization: Bearer <accessToken>`.
|
|
8
|
+
*
|
|
9
|
+
* Why PKCE: the CLI is a public client (no secret), so we use PKCE per
|
|
10
|
+
* RFC 7636 to prove that the same process that started the auth request
|
|
11
|
+
* is the one exchanging the code for tokens.
|
|
12
|
+
*
|
|
13
|
+
* Why a localhost callback: Cognito allows `http://localhost:*` as a
|
|
14
|
+
* redirect URI specifically for native/CLI apps (RFC 8252 §7). We spin
|
|
15
|
+
* up a one-shot HTTP server on the chosen port, capture exactly one
|
|
16
|
+
* callback, then close it.
|
|
17
|
+
*/
|
|
18
|
+
import * as crypto from "crypto";
|
|
19
|
+
import * as fs from "fs";
|
|
20
|
+
import * as http from "http";
|
|
21
|
+
import * as path from "path";
|
|
22
|
+
import * as os from "os";
|
|
23
|
+
import open from "open";
|
|
24
|
+
/** Returned when an interactive login is needed but stdin/browser is unavailable. */
|
|
25
|
+
export class CognitoAuthError extends Error {
|
|
26
|
+
constructor(message) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.name = "CognitoAuthError";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Token cache (~/.hq/cognito-tokens.json)
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
const HQ_DIR = path.join(os.homedir(), ".hq");
|
|
35
|
+
const TOKEN_FILE = path.join(HQ_DIR, "cognito-tokens.json");
|
|
36
|
+
export function loadCachedTokens() {
|
|
37
|
+
if (!fs.existsSync(TOKEN_FILE))
|
|
38
|
+
return null;
|
|
39
|
+
try {
|
|
40
|
+
const raw = fs.readFileSync(TOKEN_FILE, "utf-8");
|
|
41
|
+
return JSON.parse(raw);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export function saveCachedTokens(tokens) {
|
|
48
|
+
if (!fs.existsSync(HQ_DIR)) {
|
|
49
|
+
fs.mkdirSync(HQ_DIR, { recursive: true, mode: 0o700 });
|
|
50
|
+
}
|
|
51
|
+
fs.writeFileSync(TOKEN_FILE, JSON.stringify(tokens, null, 2), { mode: 0o600 });
|
|
52
|
+
}
|
|
53
|
+
export function clearCachedTokens() {
|
|
54
|
+
if (fs.existsSync(TOKEN_FILE))
|
|
55
|
+
fs.unlinkSync(TOKEN_FILE);
|
|
56
|
+
}
|
|
57
|
+
/** True when the token expires within the given buffer (default 60s). */
|
|
58
|
+
export function isExpiring(tokens, bufferSeconds = 60) {
|
|
59
|
+
const expiresAt = new Date(tokens.expiresAt).getTime();
|
|
60
|
+
return expiresAt - Date.now() < bufferSeconds * 1000;
|
|
61
|
+
}
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
// PKCE
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
function base64UrlEncode(buf) {
|
|
66
|
+
return buf
|
|
67
|
+
.toString("base64")
|
|
68
|
+
.replace(/\+/g, "-")
|
|
69
|
+
.replace(/\//g, "_")
|
|
70
|
+
.replace(/=+$/, "");
|
|
71
|
+
}
|
|
72
|
+
function generatePkce() {
|
|
73
|
+
const verifier = base64UrlEncode(crypto.randomBytes(32));
|
|
74
|
+
const challenge = base64UrlEncode(crypto.createHash("sha256").update(verifier).digest());
|
|
75
|
+
return { verifier, challenge };
|
|
76
|
+
}
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
// Endpoint helpers
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
function authBaseUrl(config) {
|
|
81
|
+
return `https://${config.userPoolDomain}.auth.${config.region}.amazoncognito.com`;
|
|
82
|
+
}
|
|
83
|
+
function redirectUri(port) {
|
|
84
|
+
return `http://localhost:${port}/callback`;
|
|
85
|
+
}
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
// Browser login
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
/**
|
|
90
|
+
* Open the Cognito Hosted UI in the user's browser, wait for the redirect
|
|
91
|
+
* back to localhost, and exchange the auth code for tokens.
|
|
92
|
+
*
|
|
93
|
+
* Times out after 5 minutes if the user doesn't complete the flow.
|
|
94
|
+
*/
|
|
95
|
+
export async function browserLogin(config) {
|
|
96
|
+
const port = config.port ?? 3000;
|
|
97
|
+
const scopes = (config.scopes ?? ["openid", "email", "profile"]).join(" ");
|
|
98
|
+
const { verifier, challenge } = generatePkce();
|
|
99
|
+
const state = base64UrlEncode(crypto.randomBytes(16));
|
|
100
|
+
const authUrl = new URL(`${authBaseUrl(config)}/login`);
|
|
101
|
+
authUrl.searchParams.set("client_id", config.clientId);
|
|
102
|
+
authUrl.searchParams.set("response_type", "code");
|
|
103
|
+
authUrl.searchParams.set("scope", scopes);
|
|
104
|
+
authUrl.searchParams.set("redirect_uri", redirectUri(port));
|
|
105
|
+
authUrl.searchParams.set("code_challenge", challenge);
|
|
106
|
+
authUrl.searchParams.set("code_challenge_method", "S256");
|
|
107
|
+
authUrl.searchParams.set("state", state);
|
|
108
|
+
const code = await waitForAuthCode(port, state);
|
|
109
|
+
const tokens = await exchangeCodeForTokens(config, code, verifier, port);
|
|
110
|
+
saveCachedTokens(tokens);
|
|
111
|
+
return tokens;
|
|
112
|
+
// -- inner: spin up loopback server and open browser ---------------------
|
|
113
|
+
function waitForAuthCode(port, expectedState) {
|
|
114
|
+
return new Promise((resolve, reject) => {
|
|
115
|
+
// cleanup() is a function declaration so it can be referenced from the
|
|
116
|
+
// server callbacks and the timeout closure below before its source
|
|
117
|
+
// position. It clears the 15-min login timer + closes the loopback
|
|
118
|
+
// server — without this both keep Node's event loop alive after the
|
|
119
|
+
// calling script "completes", making it look hung.
|
|
120
|
+
const server = http.createServer((req, res) => {
|
|
121
|
+
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
122
|
+
if (url.pathname !== "/callback") {
|
|
123
|
+
res.writeHead(404);
|
|
124
|
+
res.end("Not found");
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const code = url.searchParams.get("code");
|
|
128
|
+
const state = url.searchParams.get("state");
|
|
129
|
+
const error = url.searchParams.get("error");
|
|
130
|
+
if (error) {
|
|
131
|
+
res.writeHead(400, { "Content-Type": "text/html" });
|
|
132
|
+
res.end(`<h1>Authentication failed</h1><p>${escapeHtml(error)}</p>`);
|
|
133
|
+
cleanup();
|
|
134
|
+
reject(new CognitoAuthError(`Cognito returned error: ${error}`));
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (state !== expectedState) {
|
|
138
|
+
res.writeHead(400, { "Content-Type": "text/html" });
|
|
139
|
+
res.end("<h1>State mismatch</h1><p>Possible CSRF — try again.</p>");
|
|
140
|
+
cleanup();
|
|
141
|
+
reject(new CognitoAuthError("Cognito state parameter mismatch"));
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
if (!code) {
|
|
145
|
+
res.writeHead(400, { "Content-Type": "text/html" });
|
|
146
|
+
res.end("<h1>Missing code</h1>");
|
|
147
|
+
cleanup();
|
|
148
|
+
reject(new CognitoAuthError("Cognito callback missing code"));
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
152
|
+
res.end(`<!doctype html><html><body style="font-family:system-ui;text-align:center;padding:48px;">
|
|
153
|
+
<h1>Signed in to HQ by Indigo</h1>
|
|
154
|
+
<p>You can close this tab and return to your terminal.</p>
|
|
155
|
+
<script>setTimeout(()=>window.close(),1500)</script>
|
|
156
|
+
</body></html>`);
|
|
157
|
+
cleanup();
|
|
158
|
+
resolve(code);
|
|
159
|
+
});
|
|
160
|
+
server.on("error", (err) => {
|
|
161
|
+
cleanup();
|
|
162
|
+
reject(err);
|
|
163
|
+
});
|
|
164
|
+
server.listen(port, "127.0.0.1", () => {
|
|
165
|
+
console.log(`\n Opening browser for HQ sign-in...`);
|
|
166
|
+
console.log(` If your browser doesn't open, visit:\n ${authUrl.toString()}\n`);
|
|
167
|
+
open(authUrl.toString()).catch(() => {
|
|
168
|
+
/* user can paste the URL manually */
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
const loginTimer = setTimeout(() => {
|
|
172
|
+
cleanup();
|
|
173
|
+
reject(new CognitoAuthError("Login timed out after 15 minutes"));
|
|
174
|
+
}, 15 * 60 * 1000);
|
|
175
|
+
function cleanup() {
|
|
176
|
+
clearTimeout(loginTimer);
|
|
177
|
+
server.close();
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
async function exchangeCodeForTokens(config, code, verifier, port) {
|
|
183
|
+
const body = new URLSearchParams({
|
|
184
|
+
grant_type: "authorization_code",
|
|
185
|
+
client_id: config.clientId,
|
|
186
|
+
code,
|
|
187
|
+
code_verifier: verifier,
|
|
188
|
+
redirect_uri: redirectUri(port),
|
|
189
|
+
});
|
|
190
|
+
const res = await fetch(`${authBaseUrl(config)}/oauth2/token`, {
|
|
191
|
+
method: "POST",
|
|
192
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
193
|
+
body: body.toString(),
|
|
194
|
+
});
|
|
195
|
+
if (!res.ok) {
|
|
196
|
+
const text = await res.text();
|
|
197
|
+
throw new CognitoAuthError(`Token exchange failed (${res.status}): ${text}`);
|
|
198
|
+
}
|
|
199
|
+
const data = (await res.json());
|
|
200
|
+
if (!data.refresh_token) {
|
|
201
|
+
throw new CognitoAuthError("Cognito did not return a refresh token — check OAuth scopes include offline_access semantics");
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
accessToken: data.access_token,
|
|
205
|
+
idToken: data.id_token,
|
|
206
|
+
refreshToken: data.refresh_token,
|
|
207
|
+
expiresAt: new Date(Date.now() + data.expires_in * 1000).toISOString(),
|
|
208
|
+
tokenType: "Bearer",
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Use the refresh token to obtain a fresh access token without user interaction.
|
|
213
|
+
* The refresh token itself is NOT rotated by Cognito on the refresh grant, so
|
|
214
|
+
* we preserve the existing one in the result.
|
|
215
|
+
*/
|
|
216
|
+
export async function refreshTokens(config, currentRefreshToken) {
|
|
217
|
+
const body = new URLSearchParams({
|
|
218
|
+
grant_type: "refresh_token",
|
|
219
|
+
client_id: config.clientId,
|
|
220
|
+
refresh_token: currentRefreshToken,
|
|
221
|
+
});
|
|
222
|
+
const res = await fetch(`${authBaseUrl(config)}/oauth2/token`, {
|
|
223
|
+
method: "POST",
|
|
224
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
225
|
+
body: body.toString(),
|
|
226
|
+
});
|
|
227
|
+
if (!res.ok) {
|
|
228
|
+
const text = await res.text();
|
|
229
|
+
throw new CognitoAuthError(`Refresh failed (${res.status}): ${text}`);
|
|
230
|
+
}
|
|
231
|
+
const data = (await res.json());
|
|
232
|
+
const tokens = {
|
|
233
|
+
accessToken: data.access_token,
|
|
234
|
+
idToken: data.id_token,
|
|
235
|
+
refreshToken: data.refresh_token ?? currentRefreshToken,
|
|
236
|
+
expiresAt: new Date(Date.now() + data.expires_in * 1000).toISOString(),
|
|
237
|
+
tokenType: "Bearer",
|
|
238
|
+
};
|
|
239
|
+
saveCachedTokens(tokens);
|
|
240
|
+
return tokens;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* High-level helper: return a non-expired access token, refreshing or
|
|
244
|
+
* launching browser login as needed.
|
|
245
|
+
*
|
|
246
|
+
* Pass `interactive: false` from automated contexts where you would rather
|
|
247
|
+
* fail fast than open a browser.
|
|
248
|
+
*/
|
|
249
|
+
export async function getValidAccessToken(config, options = {}) {
|
|
250
|
+
const interactive = options.interactive ?? true;
|
|
251
|
+
const cached = loadCachedTokens();
|
|
252
|
+
if (cached && !isExpiring(cached))
|
|
253
|
+
return cached.accessToken;
|
|
254
|
+
if (cached) {
|
|
255
|
+
try {
|
|
256
|
+
const refreshed = await refreshTokens(config, cached.refreshToken);
|
|
257
|
+
return refreshed.accessToken;
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
// fall through to interactive login
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (!interactive) {
|
|
264
|
+
throw new CognitoAuthError("No valid HQ session and interactive login is disabled. Run `hq login` first.");
|
|
265
|
+
}
|
|
266
|
+
const fresh = await browserLogin(config);
|
|
267
|
+
return fresh.accessToken;
|
|
268
|
+
}
|
|
269
|
+
// ---------------------------------------------------------------------------
|
|
270
|
+
// Helpers
|
|
271
|
+
// ---------------------------------------------------------------------------
|
|
272
|
+
function escapeHtml(s) {
|
|
273
|
+
return s
|
|
274
|
+
.replace(/&/g, "&")
|
|
275
|
+
.replace(/</g, "<")
|
|
276
|
+
.replace(/>/g, ">")
|
|
277
|
+
.replace(/"/g, """)
|
|
278
|
+
.replace(/'/g, "'");
|
|
279
|
+
}
|
|
280
|
+
//# sourceMappingURL=cognito-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cognito-auth.js","sourceRoot":"","sources":["../src/cognito-auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entity context resolution (VLT-5 US-001).
|
|
3
|
+
*
|
|
4
|
+
* Resolves an entity (company) via vault-service, vends STS-scoped credentials,
|
|
5
|
+
* and returns an EntityContext for S3 operations. Handles auto-refresh when
|
|
6
|
+
* credentials are within 2 minutes of expiry.
|
|
7
|
+
*/
|
|
8
|
+
import type { EntityContext, VaultServiceConfig } from "./types.js";
|
|
9
|
+
/**
|
|
10
|
+
* Look up an entity by slug or UID via vault-service, then vend STS-scoped
|
|
11
|
+
* credentials for that entity. Returns an EntityContext ready for S3 ops.
|
|
12
|
+
*
|
|
13
|
+
* Caches the result and auto-refreshes when the credentials are within
|
|
14
|
+
* 2 minutes of expiry.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveEntityContext(companyUidOrSlug: string, config: VaultServiceConfig): Promise<EntityContext>;
|
|
17
|
+
/**
|
|
18
|
+
* Check if credentials are expiring within the refresh threshold.
|
|
19
|
+
*/
|
|
20
|
+
export declare function isExpiringSoon(expiresAt: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Force-refresh a cached context. Useful when an S3 operation fails with
|
|
23
|
+
* an expired credentials error.
|
|
24
|
+
*/
|
|
25
|
+
export declare function refreshEntityContext(companyUidOrSlug: string, config: VaultServiceConfig): Promise<EntityContext>;
|
|
26
|
+
/**
|
|
27
|
+
* Clear the entire context cache. Useful for tests.
|
|
28
|
+
*/
|
|
29
|
+
export declare function clearContextCache(): void;
|
|
30
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAWpE;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,gBAAgB,EAAE,MAAM,EACxB,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,aAAa,CAAC,CAwCxB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAIzD;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,gBAAgB,EAAE,MAAM,EACxB,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,aAAa,CAAC,CAIxB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entity context resolution (VLT-5 US-001).
|
|
3
|
+
*
|
|
4
|
+
* Resolves an entity (company) via vault-service, vends STS-scoped credentials,
|
|
5
|
+
* and returns an EntityContext for S3 operations. Handles auto-refresh when
|
|
6
|
+
* credentials are within 2 minutes of expiry.
|
|
7
|
+
*/
|
|
8
|
+
/** Minimum remaining TTL before auto-refresh triggers (2 minutes). */
|
|
9
|
+
const REFRESH_THRESHOLD_MS = 2 * 60 * 1000;
|
|
10
|
+
/** STS session duration requested from vault-service (15 minutes). */
|
|
11
|
+
const DEFAULT_SESSION_DURATION_SECONDS = 900;
|
|
12
|
+
/** Cached contexts keyed by entity UID. */
|
|
13
|
+
const contextCache = new Map();
|
|
14
|
+
/**
|
|
15
|
+
* Look up an entity by slug or UID via vault-service, then vend STS-scoped
|
|
16
|
+
* credentials for that entity. Returns an EntityContext ready for S3 ops.
|
|
17
|
+
*
|
|
18
|
+
* Caches the result and auto-refreshes when the credentials are within
|
|
19
|
+
* 2 minutes of expiry.
|
|
20
|
+
*/
|
|
21
|
+
export async function resolveEntityContext(companyUidOrSlug, config) {
|
|
22
|
+
// Check cache — return if credentials still fresh
|
|
23
|
+
const cached = contextCache.get(companyUidOrSlug);
|
|
24
|
+
if (cached && !isExpiringSoon(cached.expiresAt)) {
|
|
25
|
+
return cached;
|
|
26
|
+
}
|
|
27
|
+
// Step 1: Resolve entity — if it looks like a UID (cmp_*), fetch directly;
|
|
28
|
+
// otherwise look up by slug
|
|
29
|
+
const entity = companyUidOrSlug.startsWith("cmp_")
|
|
30
|
+
? await fetchEntity(companyUidOrSlug, config)
|
|
31
|
+
: await fetchEntityBySlug("company", companyUidOrSlug, config);
|
|
32
|
+
if (!entity.bucketName) {
|
|
33
|
+
throw new Error(`Entity ${entity.uid} (${entity.slug}) has no bucket provisioned. ` +
|
|
34
|
+
`Run VLT-2 bucket provisioning first.`);
|
|
35
|
+
}
|
|
36
|
+
// Step 2: Vend STS-scoped credentials
|
|
37
|
+
const vendResult = await vendCredentials(entity.uid, config);
|
|
38
|
+
const ctx = {
|
|
39
|
+
uid: entity.uid,
|
|
40
|
+
bucketName: entity.bucketName,
|
|
41
|
+
region: config.region ?? "us-east-1",
|
|
42
|
+
credentials: {
|
|
43
|
+
accessKeyId: vendResult.credentials.accessKeyId,
|
|
44
|
+
secretAccessKey: vendResult.credentials.secretAccessKey,
|
|
45
|
+
sessionToken: vendResult.credentials.sessionToken,
|
|
46
|
+
},
|
|
47
|
+
expiresAt: vendResult.expiresAt,
|
|
48
|
+
};
|
|
49
|
+
// Cache by both UID and slug for fast lookups
|
|
50
|
+
contextCache.set(entity.uid, ctx);
|
|
51
|
+
contextCache.set(entity.slug, ctx);
|
|
52
|
+
return ctx;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Check if credentials are expiring within the refresh threshold.
|
|
56
|
+
*/
|
|
57
|
+
export function isExpiringSoon(expiresAt) {
|
|
58
|
+
const expiryMs = new Date(expiresAt).getTime();
|
|
59
|
+
const nowMs = Date.now();
|
|
60
|
+
return expiryMs - nowMs < REFRESH_THRESHOLD_MS;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Force-refresh a cached context. Useful when an S3 operation fails with
|
|
64
|
+
* an expired credentials error.
|
|
65
|
+
*/
|
|
66
|
+
export async function refreshEntityContext(companyUidOrSlug, config) {
|
|
67
|
+
// Evict cache entry to force fresh resolution
|
|
68
|
+
contextCache.delete(companyUidOrSlug);
|
|
69
|
+
return resolveEntityContext(companyUidOrSlug, config);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Clear the entire context cache. Useful for tests.
|
|
73
|
+
*/
|
|
74
|
+
export function clearContextCache() {
|
|
75
|
+
contextCache.clear();
|
|
76
|
+
}
|
|
77
|
+
async function fetchEntity(uid, config) {
|
|
78
|
+
const res = await fetch(`${config.apiUrl}/entity/${uid}`, {
|
|
79
|
+
headers: { Authorization: `Bearer ${config.authToken}` },
|
|
80
|
+
});
|
|
81
|
+
if (!res.ok) {
|
|
82
|
+
const body = await res.text();
|
|
83
|
+
throw new Error(`Failed to fetch entity ${uid}: ${res.status} ${body}`);
|
|
84
|
+
}
|
|
85
|
+
const data = (await res.json());
|
|
86
|
+
return data.entity;
|
|
87
|
+
}
|
|
88
|
+
async function fetchEntityBySlug(type, slug, config) {
|
|
89
|
+
const res = await fetch(`${config.apiUrl}/entity/by-slug/${type}/${slug}`, {
|
|
90
|
+
headers: { Authorization: `Bearer ${config.authToken}` },
|
|
91
|
+
});
|
|
92
|
+
if (!res.ok) {
|
|
93
|
+
const body = await res.text();
|
|
94
|
+
throw new Error(`Failed to find entity by slug ${type}/${slug}: ${res.status} ${body}`);
|
|
95
|
+
}
|
|
96
|
+
const data = (await res.json());
|
|
97
|
+
return data.entity;
|
|
98
|
+
}
|
|
99
|
+
async function vendCredentials(companyUid, config) {
|
|
100
|
+
const res = await fetch(`${config.apiUrl}/sts/vend`, {
|
|
101
|
+
method: "POST",
|
|
102
|
+
headers: {
|
|
103
|
+
"Content-Type": "application/json",
|
|
104
|
+
Authorization: `Bearer ${config.authToken}`,
|
|
105
|
+
},
|
|
106
|
+
body: JSON.stringify({
|
|
107
|
+
companyUid,
|
|
108
|
+
durationSeconds: DEFAULT_SESSION_DURATION_SECONDS,
|
|
109
|
+
}),
|
|
110
|
+
});
|
|
111
|
+
if (!res.ok) {
|
|
112
|
+
const body = await res.text();
|
|
113
|
+
throw new Error(`STS vend failed for ${companyUid}: ${res.status} ${body}`);
|
|
114
|
+
}
|
|
115
|
+
return (await res.json());
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.test.d.ts","sourceRoot":"","sources":["../src/context.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for context.ts — entity context resolution (VLT-5 US-001).
|
|
3
|
+
*
|
|
4
|
+
* Uses a mock fetch to simulate vault-service API responses.
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, beforeEach, vi } from "vitest";
|
|
7
|
+
import { resolveEntityContext, refreshEntityContext, clearContextCache, isExpiringSoon, } from "./context.js";
|
|
8
|
+
const mockConfig = {
|
|
9
|
+
apiUrl: "https://vault-api.test",
|
|
10
|
+
authToken: "test-jwt-token",
|
|
11
|
+
region: "us-east-1",
|
|
12
|
+
};
|
|
13
|
+
const mockEntity = {
|
|
14
|
+
uid: "cmp_01ABCDEF",
|
|
15
|
+
slug: "acme",
|
|
16
|
+
bucketName: "hq-vault-acme-123",
|
|
17
|
+
status: "active",
|
|
18
|
+
};
|
|
19
|
+
const mockVendResponse = {
|
|
20
|
+
credentials: {
|
|
21
|
+
accessKeyId: "ASIA_TEST_KEY",
|
|
22
|
+
secretAccessKey: "test-secret",
|
|
23
|
+
sessionToken: "test-session-token",
|
|
24
|
+
expiration: new Date(Date.now() + 15 * 60 * 1000).toISOString(),
|
|
25
|
+
},
|
|
26
|
+
expiresAt: new Date(Date.now() + 15 * 60 * 1000).toISOString(),
|
|
27
|
+
};
|
|
28
|
+
function setupFetchMock(overrides) {
|
|
29
|
+
const fetchMock = vi.fn();
|
|
30
|
+
fetchMock.mockImplementation(async (url) => {
|
|
31
|
+
const urlStr = String(url);
|
|
32
|
+
if (urlStr.includes("/entity/by-slug/")) {
|
|
33
|
+
return {
|
|
34
|
+
ok: (overrides?.entityStatus ?? 200) < 400,
|
|
35
|
+
status: overrides?.entityStatus ?? 200,
|
|
36
|
+
json: async () => overrides?.entityBody ?? { entity: mockEntity },
|
|
37
|
+
text: async () => JSON.stringify(overrides?.entityBody ?? { entity: mockEntity }),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
if (urlStr.includes("/entity/cmp_")) {
|
|
41
|
+
return {
|
|
42
|
+
ok: (overrides?.entityStatus ?? 200) < 400,
|
|
43
|
+
status: overrides?.entityStatus ?? 200,
|
|
44
|
+
json: async () => overrides?.entityBody ?? { entity: mockEntity },
|
|
45
|
+
text: async () => JSON.stringify(overrides?.entityBody ?? { entity: mockEntity }),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (urlStr.includes("/sts/vend")) {
|
|
49
|
+
return {
|
|
50
|
+
ok: (overrides?.vendStatus ?? 200) < 400,
|
|
51
|
+
status: overrides?.vendStatus ?? 200,
|
|
52
|
+
json: async () => overrides?.vendBody ?? mockVendResponse,
|
|
53
|
+
text: async () => JSON.stringify(overrides?.vendBody ?? mockVendResponse),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return { ok: false, status: 404, text: async () => "Not found" };
|
|
57
|
+
});
|
|
58
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
59
|
+
return fetchMock;
|
|
60
|
+
}
|
|
61
|
+
describe("resolveEntityContext", () => {
|
|
62
|
+
beforeEach(() => {
|
|
63
|
+
clearContextCache();
|
|
64
|
+
vi.restoreAllMocks();
|
|
65
|
+
});
|
|
66
|
+
it("resolves context by slug", async () => {
|
|
67
|
+
const fetchMock = setupFetchMock();
|
|
68
|
+
const ctx = await resolveEntityContext("acme", mockConfig);
|
|
69
|
+
expect(ctx.uid).toBe("cmp_01ABCDEF");
|
|
70
|
+
expect(ctx.bucketName).toBe("hq-vault-acme-123");
|
|
71
|
+
expect(ctx.credentials.accessKeyId).toBe("ASIA_TEST_KEY");
|
|
72
|
+
expect(ctx.region).toBe("us-east-1");
|
|
73
|
+
// Verify entity lookup used by-slug endpoint
|
|
74
|
+
expect(fetchMock).toHaveBeenCalledTimes(2);
|
|
75
|
+
expect(String(fetchMock.mock.calls[0][0])).toContain("/entity/by-slug/company/acme");
|
|
76
|
+
expect(String(fetchMock.mock.calls[1][0])).toContain("/sts/vend");
|
|
77
|
+
});
|
|
78
|
+
it("resolves context by UID directly", async () => {
|
|
79
|
+
const fetchMock = setupFetchMock();
|
|
80
|
+
const ctx = await resolveEntityContext("cmp_01ABCDEF", mockConfig);
|
|
81
|
+
expect(ctx.uid).toBe("cmp_01ABCDEF");
|
|
82
|
+
// Verify entity lookup used direct UID endpoint
|
|
83
|
+
expect(String(fetchMock.mock.calls[0][0])).toContain("/entity/cmp_01ABCDEF");
|
|
84
|
+
});
|
|
85
|
+
it("returns cached context when credentials are fresh", async () => {
|
|
86
|
+
const fetchMock = setupFetchMock();
|
|
87
|
+
const ctx1 = await resolveEntityContext("acme", mockConfig);
|
|
88
|
+
const ctx2 = await resolveEntityContext("acme", mockConfig);
|
|
89
|
+
expect(ctx1).toBe(ctx2); // Same reference
|
|
90
|
+
expect(fetchMock).toHaveBeenCalledTimes(2); // Only 1 entity + 1 vend call
|
|
91
|
+
});
|
|
92
|
+
it("auto-refreshes when credentials expire soon", async () => {
|
|
93
|
+
const almostExpired = new Date(Date.now() + 60 * 1000).toISOString(); // 1 min left
|
|
94
|
+
const fetchMock = setupFetchMock({
|
|
95
|
+
vendBody: {
|
|
96
|
+
credentials: mockVendResponse.credentials,
|
|
97
|
+
expiresAt: almostExpired,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
const ctx1 = await resolveEntityContext("acme", mockConfig);
|
|
101
|
+
// Second call should refresh because <2 min remaining
|
|
102
|
+
const ctx2 = await resolveEntityContext("acme", mockConfig);
|
|
103
|
+
expect(ctx2).not.toBe(ctx1);
|
|
104
|
+
expect(fetchMock).toHaveBeenCalledTimes(4); // 2 entity + 2 vend calls
|
|
105
|
+
});
|
|
106
|
+
it("throws when entity has no bucket", async () => {
|
|
107
|
+
setupFetchMock({
|
|
108
|
+
entityBody: { entity: { ...mockEntity, bucketName: undefined } },
|
|
109
|
+
});
|
|
110
|
+
await expect(resolveEntityContext("acme", mockConfig)).rejects.toThrow(/no bucket provisioned/);
|
|
111
|
+
});
|
|
112
|
+
it("throws on entity lookup failure", async () => {
|
|
113
|
+
setupFetchMock({ entityStatus: 404 });
|
|
114
|
+
await expect(resolveEntityContext("nonexistent", mockConfig)).rejects.toThrow(/Failed to find entity/);
|
|
115
|
+
});
|
|
116
|
+
it("throws on STS vend failure", async () => {
|
|
117
|
+
setupFetchMock({ vendStatus: 403 });
|
|
118
|
+
await expect(resolveEntityContext("acme", mockConfig)).rejects.toThrow(/STS vend failed/);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
describe("refreshEntityContext", () => {
|
|
122
|
+
beforeEach(() => {
|
|
123
|
+
clearContextCache();
|
|
124
|
+
vi.restoreAllMocks();
|
|
125
|
+
});
|
|
126
|
+
it("evicts cache and fetches fresh credentials", async () => {
|
|
127
|
+
const fetchMock = setupFetchMock();
|
|
128
|
+
const ctx1 = await resolveEntityContext("acme", mockConfig);
|
|
129
|
+
const ctx2 = await refreshEntityContext("acme", mockConfig);
|
|
130
|
+
expect(ctx2).not.toBe(ctx1);
|
|
131
|
+
expect(fetchMock).toHaveBeenCalledTimes(4); // 2 initial + 2 refresh
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
describe("isExpiringSoon", () => {
|
|
135
|
+
it("returns false when well within TTL", () => {
|
|
136
|
+
const future = new Date(Date.now() + 10 * 60 * 1000).toISOString();
|
|
137
|
+
expect(isExpiringSoon(future)).toBe(false);
|
|
138
|
+
});
|
|
139
|
+
it("returns true when within 2 minutes", () => {
|
|
140
|
+
const soon = new Date(Date.now() + 90 * 1000).toISOString();
|
|
141
|
+
expect(isExpiringSoon(soon)).toBe(true);
|
|
142
|
+
});
|
|
143
|
+
it("returns true when already expired", () => {
|
|
144
|
+
const past = new Date(Date.now() - 1000).toISOString();
|
|
145
|
+
expect(isExpiringSoon(past)).toBe(true);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
//# sourceMappingURL=context.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.test.js","sourceRoot":"","sources":["../src/context.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon-worker.d.ts","sourceRoot":"","sources":["../src/daemon-worker.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|