@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
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication — OAuth flow with IndigoAI
|
|
3
|
+
* Opens browser for sign-in, receives tokens via localhost callback
|
|
4
|
+
*/
|
|
5
|
+
import type { Credentials } from "./types.js";
|
|
6
|
+
export declare function hasCredentials(): boolean;
|
|
7
|
+
export declare function readCredentials(): Credentials | null;
|
|
8
|
+
export declare function writeCredentials(creds: Credentials): void;
|
|
9
|
+
export declare function clearCredentials(): void;
|
|
10
|
+
/**
|
|
11
|
+
* Start OAuth flow:
|
|
12
|
+
* 1. Open browser to AUTH_URL with callback port
|
|
13
|
+
* 2. Start localhost server to receive tokens
|
|
14
|
+
* 3. Store credentials
|
|
15
|
+
*/
|
|
16
|
+
export declare function authenticate(): Promise<Credentials>;
|
|
17
|
+
/**
|
|
18
|
+
* Refresh temporary AWS credentials using refresh token
|
|
19
|
+
*/
|
|
20
|
+
export declare function refreshAwsCredentials(creds: Credentials): Promise<Credentials>;
|
|
21
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAU9C,wBAAgB,cAAc,IAAI,OAAO,CAExC;AAED,wBAAgB,eAAe,IAAI,WAAW,GAAG,IAAI,CAQpD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAKzD;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAIvC;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,WAAW,CAAC,CA0DzD;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,WAAW,GACjB,OAAO,CAAC,WAAW,CAAC,CA4BtB"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication — OAuth flow with IndigoAI
|
|
3
|
+
* Opens browser for sign-in, receives tokens via localhost callback
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from "fs";
|
|
6
|
+
import * as path from "path";
|
|
7
|
+
import * as http from "http";
|
|
8
|
+
import open from "open";
|
|
9
|
+
const AUTH_URL = "https://hq.indigoai.com/auth";
|
|
10
|
+
const CALLBACK_PORT = 19847;
|
|
11
|
+
const CREDS_DIR = path.join(process.env.HOME || process.env.USERPROFILE || "~", ".hq");
|
|
12
|
+
const CREDS_FILE = path.join(CREDS_DIR, "credentials.json");
|
|
13
|
+
export function hasCredentials() {
|
|
14
|
+
return fs.existsSync(CREDS_FILE);
|
|
15
|
+
}
|
|
16
|
+
export function readCredentials() {
|
|
17
|
+
if (!fs.existsSync(CREDS_FILE))
|
|
18
|
+
return null;
|
|
19
|
+
try {
|
|
20
|
+
const content = fs.readFileSync(CREDS_FILE, "utf-8");
|
|
21
|
+
return JSON.parse(content);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export function writeCredentials(creds) {
|
|
28
|
+
if (!fs.existsSync(CREDS_DIR)) {
|
|
29
|
+
fs.mkdirSync(CREDS_DIR, { recursive: true });
|
|
30
|
+
}
|
|
31
|
+
fs.writeFileSync(CREDS_FILE, JSON.stringify(creds, null, 2), { mode: 0o600 });
|
|
32
|
+
}
|
|
33
|
+
export function clearCredentials() {
|
|
34
|
+
if (fs.existsSync(CREDS_FILE)) {
|
|
35
|
+
fs.unlinkSync(CREDS_FILE);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Start OAuth flow:
|
|
40
|
+
* 1. Open browser to AUTH_URL with callback port
|
|
41
|
+
* 2. Start localhost server to receive tokens
|
|
42
|
+
* 3. Store credentials
|
|
43
|
+
*/
|
|
44
|
+
export async function authenticate() {
|
|
45
|
+
return new Promise((resolve, reject) => {
|
|
46
|
+
const server = http.createServer((req, res) => {
|
|
47
|
+
const url = new URL(req.url || "", `http://localhost:${CALLBACK_PORT}`);
|
|
48
|
+
if (url.pathname === "/callback") {
|
|
49
|
+
const token = url.searchParams.get("token");
|
|
50
|
+
const refreshToken = url.searchParams.get("refresh_token");
|
|
51
|
+
const userId = url.searchParams.get("user_id");
|
|
52
|
+
const bucket = url.searchParams.get("bucket");
|
|
53
|
+
const region = url.searchParams.get("region") || "us-east-1";
|
|
54
|
+
const teamId = url.searchParams.get("team_id");
|
|
55
|
+
if (!token || !refreshToken || !userId || !bucket) {
|
|
56
|
+
res.writeHead(400, { "Content-Type": "text/html" });
|
|
57
|
+
res.end("<h1>Authentication failed</h1><p>Missing required parameters. Please try again.</p>");
|
|
58
|
+
server.close();
|
|
59
|
+
reject(new Error("Authentication failed: missing parameters"));
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const creds = {
|
|
63
|
+
accessKeyId: "", // Will be populated via STS
|
|
64
|
+
secretAccessKey: "",
|
|
65
|
+
refreshToken,
|
|
66
|
+
userId,
|
|
67
|
+
bucket,
|
|
68
|
+
region,
|
|
69
|
+
...(teamId ? { teamId } : {}),
|
|
70
|
+
};
|
|
71
|
+
writeCredentials(creds);
|
|
72
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
73
|
+
res.end("<h1>Authenticated!</h1><p>You can close this window and return to your terminal.</p>");
|
|
74
|
+
server.close();
|
|
75
|
+
resolve(creds);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
server.listen(CALLBACK_PORT, () => {
|
|
79
|
+
const authUrl = `${AUTH_URL}?callback=http://localhost:${CALLBACK_PORT}/callback`;
|
|
80
|
+
console.log(` Opening browser for authentication...`);
|
|
81
|
+
console.log(` If browser doesn't open, visit: ${authUrl}`);
|
|
82
|
+
open(authUrl).catch(() => {
|
|
83
|
+
// If open fails, user can manually visit the URL
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
// Timeout after 5 minutes
|
|
87
|
+
setTimeout(() => {
|
|
88
|
+
server.close();
|
|
89
|
+
reject(new Error("Authentication timed out after 5 minutes"));
|
|
90
|
+
}, 5 * 60 * 1000);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Refresh temporary AWS credentials using refresh token
|
|
95
|
+
*/
|
|
96
|
+
export async function refreshAwsCredentials(creds) {
|
|
97
|
+
const response = await fetch("https://hq.indigoai.com/api/auth/refresh", {
|
|
98
|
+
method: "POST",
|
|
99
|
+
headers: { "Content-Type": "application/json" },
|
|
100
|
+
body: JSON.stringify({ refreshToken: creds.refreshToken }),
|
|
101
|
+
});
|
|
102
|
+
if (!response.ok) {
|
|
103
|
+
throw new Error(`Failed to refresh credentials: ${response.statusText}`);
|
|
104
|
+
}
|
|
105
|
+
const data = (await response.json());
|
|
106
|
+
const updated = {
|
|
107
|
+
...creds,
|
|
108
|
+
accessKeyId: data.accessKeyId,
|
|
109
|
+
secretAccessKey: data.secretAccessKey,
|
|
110
|
+
sessionToken: data.sessionToken,
|
|
111
|
+
expiration: data.expiration,
|
|
112
|
+
};
|
|
113
|
+
writeCredentials(updated);
|
|
114
|
+
return updated;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB,MAAM,QAAQ,GAAG,8BAA8B,CAAC;AAChD,MAAM,aAAa,GAAG,KAAK,CAAC;AAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CACzB,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,EAClD,KAAK,CACN,CAAC;AACF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;AAE5D,MAAM,UAAU,cAAc;IAC5B,OAAO,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAgB,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAkB;IACjD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IACD,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAChF,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IAC5B,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YAC5C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,oBAAoB,aAAa,EAAE,CAAC,CAAC;YAExE,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;gBACjC,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAC5C,MAAM,YAAY,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;gBAC3D,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAC/C,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBAC9C,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,WAAW,CAAC;gBAC7D,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAE/C,IAAI,CAAC,KAAK,IAAI,CAAC,YAAY,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;oBAClD,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;oBACpD,GAAG,CAAC,GAAG,CAAC,qFAAqF,CAAC,CAAC;oBAC/F,MAAM,CAAC,KAAK,EAAE,CAAC;oBACf,MAAM,CAAC,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC,CAAC;oBAC/D,OAAO;gBACT,CAAC;gBAED,MAAM,KAAK,GAAgB;oBACzB,WAAW,EAAE,EAAE,EAAE,4BAA4B;oBAC7C,eAAe,EAAE,EAAE;oBACnB,YAAY;oBACZ,MAAM;oBACN,MAAM;oBACN,MAAM;oBACN,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC9B,CAAC;gBAEF,gBAAgB,CAAC,KAAK,CAAC,CAAC;gBAExB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;gBACpD,GAAG,CAAC,GAAG,CACL,sFAAsF,CACvF,CAAC;gBAEF,MAAM,CAAC,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,GAAG,EAAE;YAChC,MAAM,OAAO,GAAG,GAAG,QAAQ,8BAA8B,aAAa,WAAW,CAAC;YAClF,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,qCAAqC,OAAO,EAAE,CAAC,CAAC;YAC5D,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;gBACvB,iDAAiD;YACnD,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,0BAA0B;QAC1B,UAAU,CAAC,GAAG,EAAE;YACd,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC,CAAC;QAChE,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,KAAkB;IAElB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,0CAA0C,EAAE;QACvE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE,CAAC;KAC3D,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,kCAAkC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAKlC,CAAC;IAEF,MAAM,OAAO,GAAgB;QAC3B,GAAG,KAAK;QACR,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,eAAe,EAAE,IAAI,CAAC,eAAe;QACrC,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,UAAU,EAAE,IAAI,CAAC,UAAU;KAC5B,CAAC;IAEF,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC1B,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `hq accept` command — accept a membership invite (VLT-7 US-003).
|
|
3
|
+
*
|
|
4
|
+
* Parses magic links (hq://accept/<token> or raw tokens), resolves the
|
|
5
|
+
* caller's identity from Cognito, and calls VaultClient.acceptInvite().
|
|
6
|
+
*/
|
|
7
|
+
import type { VaultServiceConfig } from "../types.js";
|
|
8
|
+
import type { Membership } from "../vault-client.js";
|
|
9
|
+
export interface AcceptOptions {
|
|
10
|
+
/** Raw token or magic link (hq://accept/<token>) */
|
|
11
|
+
tokenOrLink: string;
|
|
12
|
+
/** Caller's person UID (from Cognito) */
|
|
13
|
+
callerUid: string;
|
|
14
|
+
/** Vault service config */
|
|
15
|
+
vaultConfig: VaultServiceConfig;
|
|
16
|
+
}
|
|
17
|
+
export interface AcceptResult {
|
|
18
|
+
membership: Membership;
|
|
19
|
+
companySlug?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Parse a magic link or raw token into the raw invite token.
|
|
23
|
+
*/
|
|
24
|
+
export declare function parseToken(tokenOrLink: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Accept a membership invite.
|
|
27
|
+
*/
|
|
28
|
+
export declare function accept(options: AcceptOptions): Promise<AcceptResult>;
|
|
29
|
+
//# sourceMappingURL=accept.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accept.d.ts","sourceRoot":"","sources":["../../src/cli/accept.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAQtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,WAAW,aAAa;IAC5B,oDAAoD;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,yCAAyC;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,2BAA2B;IAC3B,WAAW,EAAE,kBAAkB,CAAC;CACjC;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAgBtD;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAyC1E"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `hq accept` command — accept a membership invite (VLT-7 US-003).
|
|
3
|
+
*
|
|
4
|
+
* Parses magic links (hq://accept/<token> or raw tokens), resolves the
|
|
5
|
+
* caller's identity from Cognito, and calls VaultClient.acceptInvite().
|
|
6
|
+
*/
|
|
7
|
+
import { VaultClient, VaultAuthError, VaultNotFoundError, VaultConflictError, VaultPermissionDeniedError, } from "../vault-client.js";
|
|
8
|
+
/**
|
|
9
|
+
* Parse a magic link or raw token into the raw invite token.
|
|
10
|
+
*/
|
|
11
|
+
export function parseToken(tokenOrLink) {
|
|
12
|
+
const trimmed = tokenOrLink.trim();
|
|
13
|
+
// hq://accept/<token>
|
|
14
|
+
if (trimmed.startsWith("hq://accept/")) {
|
|
15
|
+
return trimmed.slice("hq://accept/".length);
|
|
16
|
+
}
|
|
17
|
+
// https://hq.indigoai.com/accept/<token> (future web route)
|
|
18
|
+
const httpsPrefix = "https://hq.indigoai.com/accept/";
|
|
19
|
+
if (trimmed.startsWith(httpsPrefix)) {
|
|
20
|
+
return trimmed.slice(httpsPrefix.length);
|
|
21
|
+
}
|
|
22
|
+
// Raw token
|
|
23
|
+
return trimmed;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Accept a membership invite.
|
|
27
|
+
*/
|
|
28
|
+
export async function accept(options) {
|
|
29
|
+
const { tokenOrLink, callerUid, vaultConfig } = options;
|
|
30
|
+
const token = parseToken(tokenOrLink);
|
|
31
|
+
if (!token) {
|
|
32
|
+
throw new Error("No invite token provided. Usage: /accept <token-or-magic-link>");
|
|
33
|
+
}
|
|
34
|
+
const client = new VaultClient(vaultConfig);
|
|
35
|
+
try {
|
|
36
|
+
const result = await client.acceptInvite(token, callerUid);
|
|
37
|
+
const membership = result.membership;
|
|
38
|
+
// Try to resolve company slug for display
|
|
39
|
+
let companySlug;
|
|
40
|
+
if (membership.companyUid) {
|
|
41
|
+
try {
|
|
42
|
+
const entity = await client.entity.get(membership.companyUid);
|
|
43
|
+
companySlug = entity.slug;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// Non-critical — just display UID instead
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { membership, companySlug };
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
if (err instanceof VaultAuthError) {
|
|
53
|
+
throw new Error("Authentication failed — run `hq auth` to refresh your session");
|
|
54
|
+
}
|
|
55
|
+
if (err instanceof VaultConflictError) {
|
|
56
|
+
throw new Error("This invite was already accepted");
|
|
57
|
+
}
|
|
58
|
+
if (err instanceof VaultNotFoundError) {
|
|
59
|
+
throw new Error("Invite not found or expired");
|
|
60
|
+
}
|
|
61
|
+
if (err instanceof VaultPermissionDeniedError) {
|
|
62
|
+
throw new Error("This invite was for a different person");
|
|
63
|
+
}
|
|
64
|
+
throw err;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=accept.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accept.js","sourceRoot":"","sources":["../../src/cli/accept.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,0BAA0B,GAC3B,MAAM,oBAAoB,CAAC;AAiB5B;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,WAAmB;IAC5C,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;IAEnC,sBAAsB;IACtB,IAAI,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QACvC,OAAO,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IAC9C,CAAC;IAED,4DAA4D;IAC5D,MAAM,WAAW,GAAG,iCAAiC,CAAC;IACtD,IAAI,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QACpC,OAAO,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC;IAED,YAAY;IACZ,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,OAAsB;IACjD,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IACxD,MAAM,KAAK,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IAEtC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;IACpF,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,WAAW,CAAC,CAAC;IAE5C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAC3D,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QAErC,0CAA0C;QAC1C,IAAI,WAA+B,CAAC;QACpC,IAAI,UAAU,CAAC,UAAU,EAAE,CAAC;YAC1B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;gBAC9D,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC;YAC5B,CAAC;YAAC,MAAM,CAAC;gBACP,0CAA0C;YAC5C,CAAC;QACH,CAAC;QAED,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;IACrC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,cAAc,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,GAAG,YAAY,kBAAkB,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,GAAG,YAAY,kBAAkB,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjD,CAAC;QACD,IAAI,GAAG,YAAY,0BAA0B,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC5D,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conflict resolution for hq share/sync (VLT-5 US-002).
|
|
3
|
+
*
|
|
4
|
+
* Interactive prompts in terminal mode; deterministic resolution via
|
|
5
|
+
* --on-conflict flag for worker/skill callers.
|
|
6
|
+
*/
|
|
7
|
+
export type ConflictStrategy = "overwrite" | "keep" | "abort";
|
|
8
|
+
export interface ConflictInfo {
|
|
9
|
+
path: string;
|
|
10
|
+
localHash?: string;
|
|
11
|
+
remoteHash?: string;
|
|
12
|
+
localModified?: Date;
|
|
13
|
+
remoteModified?: Date;
|
|
14
|
+
direction: "push" | "pull";
|
|
15
|
+
}
|
|
16
|
+
export type ConflictResolution = "overwrite" | "keep" | "skip" | "diff" | "abort";
|
|
17
|
+
/**
|
|
18
|
+
* Resolve a conflict interactively or via strategy flag.
|
|
19
|
+
*
|
|
20
|
+
* In non-interactive mode (strategy provided), returns deterministically:
|
|
21
|
+
* overwrite → "overwrite"
|
|
22
|
+
* keep → "keep"
|
|
23
|
+
* abort → "abort"
|
|
24
|
+
*
|
|
25
|
+
* In interactive mode (strategy undefined), prompts the user.
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveConflict(conflict: ConflictInfo, strategy?: ConflictStrategy): Promise<ConflictResolution>;
|
|
28
|
+
/**
|
|
29
|
+
* Show a simple diff between local and remote content.
|
|
30
|
+
* Returns the content strings for display.
|
|
31
|
+
*/
|
|
32
|
+
export declare function showDiff(localPath: string, remoteContent: Buffer): void;
|
|
33
|
+
//# sourceMappingURL=conflict.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflict.d.ts","sourceRoot":"","sources":["../../src/cli/conflict.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,MAAM,GAAG,OAAO,CAAC;AAE9D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,IAAI,CAAC;IACrB,cAAc,CAAC,EAAE,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAElF;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,YAAY,EACtB,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,OAAO,CAAC,kBAAkB,CAAC,CAM7B;AAuDD;;;GAGG;AACH,wBAAgB,QAAQ,CACtB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,GACpB,IAAI,CAcN"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conflict resolution for hq share/sync (VLT-5 US-002).
|
|
3
|
+
*
|
|
4
|
+
* Interactive prompts in terminal mode; deterministic resolution via
|
|
5
|
+
* --on-conflict flag for worker/skill callers.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from "fs";
|
|
8
|
+
import * as readline from "readline";
|
|
9
|
+
/**
|
|
10
|
+
* Resolve a conflict interactively or via strategy flag.
|
|
11
|
+
*
|
|
12
|
+
* In non-interactive mode (strategy provided), returns deterministically:
|
|
13
|
+
* overwrite → "overwrite"
|
|
14
|
+
* keep → "keep"
|
|
15
|
+
* abort → "abort"
|
|
16
|
+
*
|
|
17
|
+
* In interactive mode (strategy undefined), prompts the user.
|
|
18
|
+
*/
|
|
19
|
+
export async function resolveConflict(conflict, strategy) {
|
|
20
|
+
if (strategy) {
|
|
21
|
+
return strategy === "abort" ? "abort" : strategy;
|
|
22
|
+
}
|
|
23
|
+
return promptConflict(conflict);
|
|
24
|
+
}
|
|
25
|
+
async function promptConflict(conflict) {
|
|
26
|
+
const rl = readline.createInterface({
|
|
27
|
+
input: process.stdin,
|
|
28
|
+
output: process.stderr,
|
|
29
|
+
});
|
|
30
|
+
const direction = conflict.direction === "push"
|
|
31
|
+
? "Remote has a newer version"
|
|
32
|
+
: "Local file has uncommitted edits";
|
|
33
|
+
console.error(`\n Conflict: ${conflict.path}`);
|
|
34
|
+
console.error(` ${direction}`);
|
|
35
|
+
if (conflict.localModified) {
|
|
36
|
+
console.error(` Local modified: ${conflict.localModified.toISOString()}`);
|
|
37
|
+
}
|
|
38
|
+
if (conflict.remoteModified) {
|
|
39
|
+
console.error(` Remote modified: ${conflict.remoteModified.toISOString()}`);
|
|
40
|
+
}
|
|
41
|
+
const options = conflict.direction === "push"
|
|
42
|
+
? "[o]verwrite remote / [k]eep remote / [d]iff / [a]bort"
|
|
43
|
+
: "[o]verwrite local / [k]eep local / [d]iff / [s]kip";
|
|
44
|
+
const answer = await new Promise((resolve) => {
|
|
45
|
+
rl.question(` ${options}: `, (ans) => {
|
|
46
|
+
rl.close();
|
|
47
|
+
resolve(ans.trim().toLowerCase());
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
switch (answer) {
|
|
51
|
+
case "o":
|
|
52
|
+
case "overwrite":
|
|
53
|
+
return "overwrite";
|
|
54
|
+
case "k":
|
|
55
|
+
case "keep":
|
|
56
|
+
return "keep";
|
|
57
|
+
case "d":
|
|
58
|
+
case "diff":
|
|
59
|
+
return "diff";
|
|
60
|
+
case "s":
|
|
61
|
+
case "skip":
|
|
62
|
+
return "skip";
|
|
63
|
+
case "a":
|
|
64
|
+
case "abort":
|
|
65
|
+
return "abort";
|
|
66
|
+
default:
|
|
67
|
+
// Default to keep (safe option)
|
|
68
|
+
console.error(" Unrecognized choice, keeping current version.");
|
|
69
|
+
return "keep";
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Show a simple diff between local and remote content.
|
|
74
|
+
* Returns the content strings for display.
|
|
75
|
+
*/
|
|
76
|
+
export function showDiff(localPath, remoteContent) {
|
|
77
|
+
const localContent = fs.existsSync(localPath)
|
|
78
|
+
? fs.readFileSync(localPath, "utf-8")
|
|
79
|
+
: "(file does not exist locally)";
|
|
80
|
+
const remoteStr = remoteContent.toString("utf-8");
|
|
81
|
+
console.error("\n--- LOCAL ---");
|
|
82
|
+
console.error(localContent.slice(0, 2000));
|
|
83
|
+
if (localContent.length > 2000)
|
|
84
|
+
console.error("... (truncated)");
|
|
85
|
+
console.error("\n--- REMOTE ---");
|
|
86
|
+
console.error(remoteStr.slice(0, 2000));
|
|
87
|
+
if (remoteStr.length > 2000)
|
|
88
|
+
console.error("... (truncated)");
|
|
89
|
+
console.error("");
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=conflict.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflict.js","sourceRoot":"","sources":["../../src/cli/conflict.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hq-cloud CLI entry points.
|
|
3
|
+
*
|
|
4
|
+
* Registers `hq share`, `hq sync`, and membership commands.
|
|
5
|
+
* These are consumed by @indigoai-us/hq-cli or invoked directly.
|
|
6
|
+
*/
|
|
7
|
+
export { share } from "./share.js";
|
|
8
|
+
export type { ShareOptions, ShareResult } from "./share.js";
|
|
9
|
+
export { sync } from "./sync.js";
|
|
10
|
+
export type { SyncOptions, SyncResult } from "./sync.js";
|
|
11
|
+
export { resolveConflict, showDiff } from "./conflict.js";
|
|
12
|
+
export type { ConflictStrategy, ConflictInfo, ConflictResolution } from "./conflict.js";
|
|
13
|
+
export { invite, listInvites, revokeInvite } from "./invite.js";
|
|
14
|
+
export type { InviteOptions, InviteResult, InviteListOptions, InviteRevokeOptions } from "./invite.js";
|
|
15
|
+
export { accept, parseToken } from "./accept.js";
|
|
16
|
+
export type { AcceptOptions, AcceptResult } from "./accept.js";
|
|
17
|
+
export { promote } from "./promote.js";
|
|
18
|
+
export type { PromoteOptions, PromoteResult } from "./promote.js";
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEzD,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC1D,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAGxF,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvG,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE/D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hq-cloud CLI entry points.
|
|
3
|
+
*
|
|
4
|
+
* Registers `hq share`, `hq sync`, and membership commands.
|
|
5
|
+
* These are consumed by @indigoai-us/hq-cli or invoked directly.
|
|
6
|
+
*/
|
|
7
|
+
export { share } from "./share.js";
|
|
8
|
+
export { sync } from "./sync.js";
|
|
9
|
+
export { resolveConflict, showDiff } from "./conflict.js";
|
|
10
|
+
// Membership commands (VLT-7)
|
|
11
|
+
export { invite, listInvites, revokeInvite } from "./invite.js";
|
|
12
|
+
export { accept, parseToken } from "./accept.js";
|
|
13
|
+
export { promote } from "./promote.js";
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG1D,8BAA8B;AAC9B,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGjD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `hq invite` command — create pending membership + magic link (VLT-7 US-002).
|
|
3
|
+
*
|
|
4
|
+
* Thin UX layer over VaultClient.createInvite(). Handles arg parsing,
|
|
5
|
+
* validation (paths only with guest role), and formats the magic link output.
|
|
6
|
+
*/
|
|
7
|
+
import type { VaultServiceConfig } from "../types.js";
|
|
8
|
+
import type { MembershipRole, Membership } from "../vault-client.js";
|
|
9
|
+
export interface InviteOptions {
|
|
10
|
+
/** Target — email address or person slug/uid */
|
|
11
|
+
target: string;
|
|
12
|
+
/** Role for the invitee (default: member) */
|
|
13
|
+
role?: MembershipRole;
|
|
14
|
+
/** Comma-separated allowed prefixes (only valid with role=guest) */
|
|
15
|
+
paths?: string;
|
|
16
|
+
/** Company slug or UID (defaults to active company) */
|
|
17
|
+
company?: string;
|
|
18
|
+
/** Vault service config */
|
|
19
|
+
vaultConfig: VaultServiceConfig;
|
|
20
|
+
/** Caller's person UID */
|
|
21
|
+
callerUid: string;
|
|
22
|
+
}
|
|
23
|
+
export interface InviteResult {
|
|
24
|
+
inviteToken: string;
|
|
25
|
+
magicLink: string;
|
|
26
|
+
membership: Membership;
|
|
27
|
+
}
|
|
28
|
+
export interface InviteListOptions {
|
|
29
|
+
company?: string;
|
|
30
|
+
vaultConfig: VaultServiceConfig;
|
|
31
|
+
callerUid: string;
|
|
32
|
+
}
|
|
33
|
+
export interface InviteRevokeOptions {
|
|
34
|
+
tokenOrKey: string;
|
|
35
|
+
/** Company slug or UID — required so the server can authorize the caller */
|
|
36
|
+
company: string;
|
|
37
|
+
vaultConfig: VaultServiceConfig;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Create a pending membership invite and return a magic link.
|
|
41
|
+
*/
|
|
42
|
+
export declare function invite(options: InviteOptions): Promise<InviteResult>;
|
|
43
|
+
/**
|
|
44
|
+
* List pending invites for a company.
|
|
45
|
+
*/
|
|
46
|
+
export declare function listInvites(options: InviteListOptions): Promise<Membership[]>;
|
|
47
|
+
/**
|
|
48
|
+
* Revoke a pending invite.
|
|
49
|
+
*/
|
|
50
|
+
export declare function revokeInvite(options: InviteRevokeOptions): Promise<void>;
|
|
51
|
+
//# sourceMappingURL=invite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invite.d.ts","sourceRoot":"","sources":["../../src/cli/invite.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAQtD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErE,MAAM,WAAW,aAAa;IAC5B,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,WAAW,EAAE,kBAAkB,CAAC;IAChC,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,kBAAkB,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,kBAAkB,CAAC;CACjC;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAiD1E;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAgBnF;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB9E"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `hq invite` command — create pending membership + magic link (VLT-7 US-002).
|
|
3
|
+
*
|
|
4
|
+
* Thin UX layer over VaultClient.createInvite(). Handles arg parsing,
|
|
5
|
+
* validation (paths only with guest role), and formats the magic link output.
|
|
6
|
+
*/
|
|
7
|
+
import { VaultClient, VaultAuthError, VaultPermissionDeniedError, VaultNotFoundError, VaultConflictError, } from "../vault-client.js";
|
|
8
|
+
/**
|
|
9
|
+
* Create a pending membership invite and return a magic link.
|
|
10
|
+
*/
|
|
11
|
+
export async function invite(options) {
|
|
12
|
+
const { target, role = "member", paths, company, vaultConfig, callerUid } = options;
|
|
13
|
+
// Validate: --paths only with --role guest
|
|
14
|
+
if (paths && role !== "guest") {
|
|
15
|
+
throw new Error("--paths is only valid with --role guest (allowedPrefixes are only meaningful for the guest role)");
|
|
16
|
+
}
|
|
17
|
+
const client = new VaultClient(vaultConfig);
|
|
18
|
+
// Resolve company UID
|
|
19
|
+
const companyUid = await resolveCompanyUid(client, company);
|
|
20
|
+
// Parse paths
|
|
21
|
+
const allowedPrefixes = paths
|
|
22
|
+
? paths.split(",").map((p) => p.trim()).filter(Boolean)
|
|
23
|
+
: undefined;
|
|
24
|
+
// Determine if target is email or person identifier
|
|
25
|
+
const isEmail = target.includes("@");
|
|
26
|
+
try {
|
|
27
|
+
const result = await client.createInvite({
|
|
28
|
+
...(isEmail ? { inviteeEmail: target } : { personUid: target }),
|
|
29
|
+
companyUid,
|
|
30
|
+
role,
|
|
31
|
+
allowedPrefixes,
|
|
32
|
+
invitedBy: callerUid,
|
|
33
|
+
});
|
|
34
|
+
const magicLink = `hq://accept/${result.inviteToken}`;
|
|
35
|
+
return {
|
|
36
|
+
inviteToken: result.inviteToken,
|
|
37
|
+
magicLink,
|
|
38
|
+
membership: result.membership,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
if (err instanceof VaultAuthError) {
|
|
43
|
+
throw new Error("Authentication failed — run `hq auth` to refresh your session");
|
|
44
|
+
}
|
|
45
|
+
if (err instanceof VaultPermissionDeniedError) {
|
|
46
|
+
throw new Error("Permission denied — only admins and owners can invite members");
|
|
47
|
+
}
|
|
48
|
+
if (err instanceof VaultConflictError) {
|
|
49
|
+
throw new Error("This person already has a membership or pending invite for this company");
|
|
50
|
+
}
|
|
51
|
+
throw err;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* List pending invites for a company.
|
|
56
|
+
*/
|
|
57
|
+
export async function listInvites(options) {
|
|
58
|
+
const { company, vaultConfig } = options;
|
|
59
|
+
const client = new VaultClient(vaultConfig);
|
|
60
|
+
const companyUid = await resolveCompanyUid(client, company);
|
|
61
|
+
try {
|
|
62
|
+
return await client.listPendingInvites(companyUid);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
if (err instanceof VaultAuthError) {
|
|
66
|
+
throw new Error("Authentication failed — run `hq auth` to refresh your session");
|
|
67
|
+
}
|
|
68
|
+
if (err instanceof VaultPermissionDeniedError) {
|
|
69
|
+
throw new Error("Permission denied — only admins and owners can list invites");
|
|
70
|
+
}
|
|
71
|
+
throw err;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Revoke a pending invite.
|
|
76
|
+
*/
|
|
77
|
+
export async function revokeInvite(options) {
|
|
78
|
+
const { tokenOrKey, company, vaultConfig } = options;
|
|
79
|
+
const client = new VaultClient(vaultConfig);
|
|
80
|
+
const companyUid = await resolveCompanyUid(client, company);
|
|
81
|
+
try {
|
|
82
|
+
await client.revokeMembership(tokenOrKey, companyUid);
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
if (err instanceof VaultAuthError) {
|
|
86
|
+
throw new Error("Authentication failed — run `hq auth` to refresh your session");
|
|
87
|
+
}
|
|
88
|
+
if (err instanceof VaultPermissionDeniedError) {
|
|
89
|
+
throw new Error("Permission denied — only admins and owners can revoke invites");
|
|
90
|
+
}
|
|
91
|
+
if (err instanceof VaultNotFoundError) {
|
|
92
|
+
throw new Error("Invite not found — it may have already been accepted or revoked");
|
|
93
|
+
}
|
|
94
|
+
throw err;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
// Helpers
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
async function resolveCompanyUid(client, companyRef) {
|
|
101
|
+
if (!companyRef) {
|
|
102
|
+
throw new Error("No company specified. Use --company <slug> or set up .hq/config.json");
|
|
103
|
+
}
|
|
104
|
+
// If already a UID, return it
|
|
105
|
+
if (companyRef.startsWith("cmp_")) {
|
|
106
|
+
return companyRef;
|
|
107
|
+
}
|
|
108
|
+
// Resolve slug → UID via entity registry
|
|
109
|
+
try {
|
|
110
|
+
const entity = await client.entity.findBySlug("company", companyRef);
|
|
111
|
+
return entity.uid;
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
if (err instanceof VaultNotFoundError) {
|
|
115
|
+
throw new Error(`Company "${companyRef}" not found in the vault registry`);
|
|
116
|
+
}
|
|
117
|
+
throw err;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=invite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invite.js","sourceRoot":"","sources":["../../src/cli/invite.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,WAAW,EACX,cAAc,EACd,0BAA0B,EAC1B,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAqC5B;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,OAAsB;IACjD,MAAM,EAAE,MAAM,EAAE,IAAI,GAAG,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAEpF,2CAA2C;IAC3C,IAAI,KAAK,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,kGAAkG,CAAC,CAAC;IACtH,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,WAAW,CAAC,CAAC;IAE5C,sBAAsB;IACtB,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE5D,cAAc;IACd,MAAM,eAAe,GAAG,KAAK;QAC3B,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;QACvD,CAAC,CAAC,SAAS,CAAC;IAEd,oDAAoD;IACpD,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAErC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC;YACvC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;YAC/D,UAAU;YACV,IAAI;YACJ,eAAe;YACf,SAAS,EAAE,SAAS;SACrB,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,eAAe,MAAM,CAAC,WAAW,EAAE,CAAC;QAEtD,OAAO;YACL,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,SAAS;YACT,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,cAAc,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,GAAG,YAAY,0BAA0B,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,GAAG,YAAY,kBAAkB,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAC;QAC7F,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAA0B;IAC1D,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,WAAW,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE5D,IAAI,CAAC;QACH,OAAO,MAAM,MAAM,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC;IACrD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,cAAc,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,GAAG,YAAY,0BAA0B,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;QACjF,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA4B;IAC7D,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IACrD,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,WAAW,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE5D,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IACxD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,cAAc,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,GAAG,YAAY,0BAA0B,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,GAAG,YAAY,kBAAkB,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;QACrF,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,KAAK,UAAU,iBAAiB,CAC9B,MAAmB,EACnB,UAAmB;IAEnB,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACb,sEAAsE,CACvE,CAAC;IACJ,CAAC;IAED,8BAA8B;IAC9B,IAAI,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAClC,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,yCAAyC;IACzC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QACrE,OAAO,MAAM,CAAC,GAAG,CAAC;IACpB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,kBAAkB,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CAAC,YAAY,UAAU,mCAAmC,CAAC,CAAC;QAC7E,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invite.test.d.ts","sourceRoot":"","sources":["../../src/cli/invite.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|