sleev 0.0.11 → 0.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/README.md +19 -39
  2. package/dist/auth/browser.d.ts +12 -0
  3. package/dist/auth/browser.js +33 -24
  4. package/dist/auth/browser.js.map +1 -0
  5. package/dist/auth/firebase-tokens.d.ts +39 -0
  6. package/dist/auth/firebase-tokens.js +173 -0
  7. package/dist/auth/firebase-tokens.js.map +1 -0
  8. package/dist/auth/firebase.d.ts +17 -0
  9. package/dist/auth/firebase.js +55 -0
  10. package/dist/auth/firebase.js.map +1 -0
  11. package/dist/auth/login.d.ts +22 -0
  12. package/dist/auth/login.js +31 -28
  13. package/dist/auth/login.js.map +1 -0
  14. package/dist/auth/loopback.d.ts +19 -0
  15. package/dist/auth/loopback.js +114 -44
  16. package/dist/auth/loopback.js.map +1 -0
  17. package/dist/auth/schema.d.ts +26 -0
  18. package/dist/auth/schema.js +59 -17
  19. package/dist/auth/schema.js.map +1 -0
  20. package/dist/auth/token.d.ts +19 -0
  21. package/dist/auth/token.js +53 -0
  22. package/dist/auth/token.js.map +1 -0
  23. package/dist/auth/verify.d.ts +6 -0
  24. package/dist/auth/verify.js +22 -0
  25. package/dist/auth/verify.js.map +1 -0
  26. package/dist/cli.d.ts +8 -0
  27. package/dist/cli.js +245 -59
  28. package/dist/cli.js.map +1 -0
  29. package/dist/config/paths.d.ts +12 -0
  30. package/dist/config/paths.js +34 -0
  31. package/dist/config/paths.js.map +1 -0
  32. package/dist/config/store.d.ts +63 -0
  33. package/dist/config/store.js +270 -0
  34. package/dist/config/store.js.map +1 -0
  35. package/dist/control/local-installations.d.ts +13 -0
  36. package/dist/control/local-installations.js +37 -0
  37. package/dist/control/local-installations.js.map +1 -0
  38. package/dist/daemon/config.d.ts +10 -0
  39. package/dist/daemon/config.js +52 -0
  40. package/dist/daemon/config.js.map +1 -0
  41. package/dist/daemon/controller.d.ts +29 -0
  42. package/dist/daemon/controller.js +34 -0
  43. package/dist/daemon/controller.js.map +1 -0
  44. package/dist/daemon/health.d.ts +8 -0
  45. package/dist/daemon/health.js +47 -0
  46. package/dist/daemon/health.js.map +1 -0
  47. package/dist/daemon/start.d.ts +5 -0
  48. package/dist/daemon/start.js +24 -0
  49. package/dist/daemon/start.js.map +1 -0
  50. package/dist/daemon/systemd.d.ts +35 -0
  51. package/dist/daemon/systemd.js +181 -0
  52. package/dist/daemon/systemd.js.map +1 -0
  53. package/dist/gateway/acquire.d.ts +14 -0
  54. package/dist/gateway/acquire.js +112 -0
  55. package/dist/gateway/acquire.js.map +1 -0
  56. package/dist/gateway/manifest.d.ts +26 -0
  57. package/dist/gateway/manifest.js +98 -0
  58. package/dist/gateway/manifest.js.map +1 -0
  59. package/dist/gateway/platform.d.ts +5 -0
  60. package/dist/gateway/platform.js +27 -0
  61. package/dist/gateway/platform.js.map +1 -0
  62. package/dist/harness/claude.d.ts +8 -0
  63. package/dist/{apps → harness}/claude.js +28 -28
  64. package/dist/harness/claude.js.map +1 -0
  65. package/dist/harness/codex.d.ts +10 -0
  66. package/dist/harness/codex.js +213 -0
  67. package/dist/harness/codex.js.map +1 -0
  68. package/dist/harness/index.d.ts +13 -0
  69. package/dist/harness/index.js +63 -0
  70. package/dist/harness/index.js.map +1 -0
  71. package/dist/harness/opencode-config.d.ts +8 -0
  72. package/dist/{apps → harness}/opencode-config.js +116 -83
  73. package/dist/harness/opencode-config.js.map +1 -0
  74. package/dist/harness/opencode.d.ts +14 -0
  75. package/dist/harness/opencode.js +50 -0
  76. package/dist/harness/opencode.js.map +1 -0
  77. package/dist/harness/providers.d.ts +8 -0
  78. package/dist/harness/providers.js +30 -0
  79. package/dist/harness/providers.js.map +1 -0
  80. package/dist/harness/types.d.ts +14 -0
  81. package/dist/harness/types.js +2 -0
  82. package/dist/harness/types.js.map +1 -0
  83. package/dist/product.d.ts +12 -0
  84. package/dist/product.js +53 -10
  85. package/dist/product.js.map +1 -0
  86. package/dist/tui/clipboard.d.ts +1 -0
  87. package/dist/tui/clipboard.js +48 -0
  88. package/dist/tui/clipboard.js.map +1 -0
  89. package/dist/tui/openTuiApp.d.ts +1 -0
  90. package/dist/tui/openTuiApp.js +1436 -0
  91. package/dist/tui/openTuiApp.js.map +1 -0
  92. package/dist/tui/pages/flow-screen.d.ts +50 -0
  93. package/dist/tui/pages/flow-screen.js +435 -0
  94. package/dist/tui/pages/flow-screen.js.map +1 -0
  95. package/dist/tui/pages/footer.d.ts +7 -0
  96. package/dist/tui/pages/footer.js +14 -0
  97. package/dist/tui/pages/footer.js.map +1 -0
  98. package/dist/tui/pages/home-screen.d.ts +19 -0
  99. package/dist/tui/pages/home-screen.js +89 -0
  100. package/dist/tui/pages/home-screen.js.map +1 -0
  101. package/dist/tui/pages/index.d.ts +17 -0
  102. package/dist/tui/pages/index.js +11 -0
  103. package/dist/tui/pages/index.js.map +1 -0
  104. package/dist/tui/pages/local-setup-screen.d.ts +23 -0
  105. package/dist/tui/pages/local-setup-screen.js +134 -0
  106. package/dist/tui/pages/local-setup-screen.js.map +1 -0
  107. package/dist/tui/pages/location-card.d.ts +19 -0
  108. package/dist/tui/pages/location-card.js +116 -0
  109. package/dist/tui/pages/location-card.js.map +1 -0
  110. package/dist/tui/pages/menu-screen.d.ts +24 -0
  111. package/dist/tui/pages/menu-screen.js +117 -0
  112. package/dist/tui/pages/menu-screen.js.map +1 -0
  113. package/dist/tui/pages/session-grid.d.ts +23 -0
  114. package/dist/tui/pages/session-grid.js +552 -0
  115. package/dist/tui/pages/session-grid.js.map +1 -0
  116. package/dist/tui/pages/setup-screen.d.ts +15 -0
  117. package/dist/tui/pages/setup-screen.js +80 -0
  118. package/dist/tui/pages/setup-screen.js.map +1 -0
  119. package/dist/tui/pages/terminal-log.d.ts +14 -0
  120. package/dist/tui/pages/terminal-log.js +104 -0
  121. package/dist/tui/pages/terminal-log.js.map +1 -0
  122. package/dist/tui/pages/welcome-screen.d.ts +16 -0
  123. package/dist/tui/pages/welcome-screen.js +80 -0
  124. package/dist/tui/pages/welcome-screen.js.map +1 -0
  125. package/dist/tui/saved-tokens.d.ts +10 -0
  126. package/dist/tui/saved-tokens.js +104 -0
  127. package/dist/tui/saved-tokens.js.map +1 -0
  128. package/dist/tui/theme.d.ts +25 -0
  129. package/dist/tui/theme.js +27 -0
  130. package/dist/tui/theme.js.map +1 -0
  131. package/package.json +55 -38
  132. package/dist/apps/codex.js +0 -184
  133. package/dist/apps/opencode.js +0 -158
  134. package/dist/apps.js +0 -148
  135. package/dist/auth/command.js +0 -109
  136. package/dist/auth/index.js +0 -2
  137. package/dist/auth/validation.js +0 -27
  138. package/dist/credentials/index.js +0 -3
  139. package/dist/credentials/schema.js +0 -63
  140. package/dist/credentials/store.js +0 -52
  141. package/dist/harnesses.js +0 -66
  142. package/dist/index.js +0 -3
  143. package/dist/providers.js +0 -30
  144. package/dist/terminal.js +0 -55
@@ -1,8 +1,19 @@
1
- // Temporary loopback server that receives the browser login handoff.
2
- import { createServer } from 'node:http';
3
- import { parseHandoff } from './schema.js';
1
+ import { createServer, } from "node:http";
2
+ import { parseFirebaseHandoff, parseHandoff, parseTokenHandoff, } from "./schema.js";
4
3
  const MAX_BODY_BYTES = 16 * 1024;
5
4
  export async function startLoopback(options) {
5
+ return start(options, {
6
+ parse: parseHandoff,
7
+ verify: (payload) => accountMismatch(options.expectedAccount, payload),
8
+ });
9
+ }
10
+ export async function startTokenLoopback(options) {
11
+ return start(options, { parse: parseTokenHandoff });
12
+ }
13
+ export async function startFirebaseLoopback(options) {
14
+ return start(options, { parse: parseFirebaseHandoff });
15
+ }
16
+ async function start(options, runtime) {
6
17
  let settled = false;
7
18
  let finish = () => undefined;
8
19
  let fail = () => undefined;
@@ -10,69 +21,125 @@ export async function startLoopback(options) {
10
21
  finish = resolve;
11
22
  fail = reject;
12
23
  });
13
- const server = createServer(async (req, res) => {
14
- try {
15
- await handleRequest(req, res, options, (payload) => {
16
- if (settled)
17
- return;
18
- settled = true;
19
- finish(payload);
20
- }, (err) => {
21
- if (settled)
22
- return;
23
- settled = true;
24
- fail(err);
25
- });
26
- }
27
- catch (err) {
28
- sendJson(res, 400, { error: err instanceof Error ? err.message : 'Invalid request.' }, options.webOrigin);
29
- }
24
+ const server = createServer((req, res) => {
25
+ void (async () => {
26
+ try {
27
+ await handleRequest(req, res, options, runtime, (payload) => {
28
+ if (settled)
29
+ return;
30
+ settled = true;
31
+ finish(payload);
32
+ }, (err) => {
33
+ if (settled)
34
+ return;
35
+ settled = true;
36
+ fail(err);
37
+ });
38
+ }
39
+ catch (err) {
40
+ sendJson(res, 400, {
41
+ error: err instanceof Error
42
+ ? err.message
43
+ : "Invalid request.",
44
+ }, options.webOrigin);
45
+ }
46
+ })();
30
47
  });
31
48
  await listen(server);
32
49
  const address = server.address();
33
- if (!address || typeof address === 'string') {
50
+ if (!address || typeof address === "string") {
34
51
  await closeServer(server);
35
- throw new Error('Could not bind local login callback server.');
52
+ throw new Error("Could not bind local login callback server.");
36
53
  }
37
54
  const timeout = setTimeout(() => {
38
55
  if (settled)
39
56
  return;
40
57
  settled = true;
41
- fail(new Error('Timed out waiting for browser login.'));
58
+ fail(new Error("Timed out waiting for browser login."));
42
59
  void closeServer(server);
43
60
  }, options.timeoutMs);
44
- wait.finally(() => clearTimeout(timeout)).catch(() => undefined);
61
+ const abort = () => {
62
+ if (settled)
63
+ return;
64
+ settled = true;
65
+ fail(new Error("Sign in cancelled."));
66
+ void closeServer(server);
67
+ };
68
+ if (options.signal?.aborted) {
69
+ abort();
70
+ }
71
+ else {
72
+ options.signal?.addEventListener("abort", abort, { once: true });
73
+ }
74
+ wait.finally(() => {
75
+ clearTimeout(timeout);
76
+ options.signal?.removeEventListener("abort", abort);
77
+ }).catch(() => undefined);
45
78
  return {
46
79
  callback: `http://127.0.0.1:${address.port}/callback`,
47
80
  wait,
48
81
  close: () => closeServer(server),
49
82
  };
50
83
  }
51
- async function handleRequest(req, res, options, accept, reject) {
52
- if (req.method === 'OPTIONS') {
84
+ async function handleRequest(req, res, options, runtime, accept, reject) {
85
+ if (req.method === "OPTIONS") {
53
86
  handleOptions(req, res, options.webOrigin);
54
87
  return;
55
88
  }
56
- if (req.method !== 'POST' || req.url !== '/callback') {
57
- sendJson(res, 404, { error: 'Not found.' }, options.webOrigin);
89
+ if (req.method !== "POST" || req.url !== "/callback") {
90
+ sendJson(res, 404, { error: "Not found." }, options.webOrigin);
58
91
  return;
59
92
  }
60
93
  if (!hasAllowedOrigin(req, options.webOrigin)) {
61
- sendJson(res, 403, { error: 'Origin is not allowed.' }, options.webOrigin);
94
+ sendJson(res, 403, { error: "Origin is not allowed." }, options.webOrigin);
62
95
  return;
63
96
  }
64
97
  const body = await readBody(req);
65
- const payload = parseHandoff(JSON.parse(body));
66
- if (payload.state !== options.state) {
67
- sendJson(res, 403, { error: 'Login state did not match.' }, options.webOrigin);
98
+ const payload = runtime.parse(JSON.parse(body));
99
+ if (stateOf(payload) !== options.state) {
100
+ sendJson(res, 403, { error: "Login state did not match." }, options.webOrigin);
101
+ return;
102
+ }
103
+ const mismatch = runtime.verify?.(payload) ?? null;
104
+ if (mismatch) {
105
+ reject(new Error(mismatch));
106
+ sendJson(res, 403, { error: mismatch }, options.webOrigin);
68
107
  return;
69
108
  }
70
109
  accept(payload);
71
110
  sendJson(res, 200, { ok: true }, options.webOrigin);
72
111
  }
112
+ function stateOf(payload) {
113
+ if (typeof payload !== "object" || payload === null)
114
+ return undefined;
115
+ const state = payload.state;
116
+ if (typeof state !== "string")
117
+ return undefined;
118
+ return state;
119
+ }
120
+ function accountMismatch(expected, payload) {
121
+ if (!expected)
122
+ return null;
123
+ if (expected.accountId) {
124
+ if (!payload.accountId)
125
+ return "Could not verify browser account. Run `sleeved auth login` again.";
126
+ if (expected.accountId !== payload.accountId) {
127
+ return "Browser is signed into a different Sleev account. Run `sleeved auth login` to switch accounts.";
128
+ }
129
+ return null;
130
+ }
131
+ if (expected.email) {
132
+ if (!payload.email)
133
+ return "Could not verify browser email. Run `sleeved auth login` again.";
134
+ if (expected.email !== payload.email) {
135
+ return "Browser is signed into a different Sleev email. Run `sleeved auth login` to switch accounts.";
136
+ }
137
+ }
138
+ return null;
139
+ }
73
140
  function handleOptions(req, res, origin) {
74
141
  if (!hasAllowedOrigin(req, origin)) {
75
- sendJson(res, 403, { error: 'Origin is not allowed.' }, origin);
142
+ sendJson(res, 403, { error: "Origin is not allowed." }, origin);
76
143
  return;
77
144
  }
78
145
  writeCors(res, origin);
@@ -87,36 +154,38 @@ function readBody(req) {
87
154
  return new Promise((resolve, reject) => {
88
155
  const chunks = [];
89
156
  let size = 0;
90
- req.on('data', (chunk) => {
157
+ req.on("data", (chunk) => {
91
158
  size += chunk.length;
92
159
  if (size > MAX_BODY_BYTES) {
93
- reject(new Error('Login callback body is too large.'));
160
+ reject(new Error("Login callback body is too large."));
94
161
  req.destroy();
95
162
  return;
96
163
  }
97
164
  chunks.push(chunk);
98
165
  });
99
- req.once('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
100
- req.once('error', () => reject(new Error('Could not read login callback.')));
166
+ req.once("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
167
+ req.once("error", () => reject(new Error("Could not read login callback.")));
101
168
  });
102
169
  }
103
170
  function sendJson(res, status, body, origin) {
104
171
  if (res.writableEnded)
105
172
  return;
106
173
  writeCors(res, origin);
107
- res.writeHead(status, { 'content-type': 'application/json; charset=utf-8' });
174
+ res.writeHead(status, {
175
+ "content-type": "application/json; charset=utf-8",
176
+ });
108
177
  res.end(JSON.stringify(body));
109
178
  }
110
179
  function writeCors(res, origin) {
111
- res.setHeader('access-control-allow-origin', origin);
112
- res.setHeader('access-control-allow-methods', 'POST, OPTIONS');
113
- res.setHeader('access-control-allow-headers', 'content-type');
180
+ res.setHeader("access-control-allow-origin", origin);
181
+ res.setHeader("access-control-allow-methods", "POST, OPTIONS");
182
+ res.setHeader("access-control-allow-headers", "content-type");
114
183
  }
115
184
  function listen(server) {
116
185
  return new Promise((resolve, reject) => {
117
- server.once('error', reject);
118
- server.listen(0, '127.0.0.1', () => {
119
- server.removeListener('error', reject);
186
+ server.once("error", reject);
187
+ server.listen(0, "127.0.0.1", () => {
188
+ server.removeListener("error", reject);
120
189
  resolve();
121
190
  });
122
191
  });
@@ -132,3 +201,4 @@ function closeServer(server) {
132
201
  });
133
202
  });
134
203
  }
204
+ //# sourceMappingURL=loopback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopback.js","sourceRoot":"","sources":["../../src/auth/loopback.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ export type LoginHandoff = {
2
+ state: string;
3
+ label: string | null;
4
+ accountId: string;
5
+ email: string | null;
6
+ };
7
+ export type TokenHandoff = {
8
+ state: string;
9
+ token: string;
10
+ label: string | null;
11
+ proxyUrl: string;
12
+ };
13
+ export type FirebaseHandoff = {
14
+ state: string;
15
+ refreshToken: string;
16
+ accountId: string;
17
+ email: string | null;
18
+ label: string | null;
19
+ };
20
+ export type AccountIdentity = {
21
+ accountId: string | null;
22
+ email: string | null;
23
+ };
24
+ export declare function parseHandoff(input: unknown): LoginHandoff;
25
+ export declare function parseTokenHandoff(input: unknown): TokenHandoff;
26
+ export declare function parseFirebaseHandoff(input: unknown): FirebaseHandoff;
@@ -1,35 +1,76 @@
1
- // Validation for the browser-to-CLI auth handoff payload.
2
1
  export function parseHandoff(input) {
3
- if (!isRecord(input))
4
- throw new Error('Login callback payload must be an object.');
5
- const state = stringField(input, 'state');
6
- const token = stringField(input, 'token');
7
- const label = nullableStringField(input, 'label');
8
- const proxyUrl = stringField(input, 'proxyUrl');
2
+ if (!isRecord(input)) {
3
+ throw new Error("Login callback payload must be an object.");
4
+ }
5
+ const state = stringField(input, "state");
6
+ const label = nullableStringField(input, "label");
7
+ const accountId = stringField(input, "accountId");
8
+ const email = nullableStringField(input, "email");
9
+ if (!state)
10
+ throw new Error("Login callback state is missing.");
11
+ if (!accountId)
12
+ throw new Error("Login callback account ID is missing.");
13
+ return {
14
+ state,
15
+ label,
16
+ accountId,
17
+ email,
18
+ };
19
+ }
20
+ export function parseTokenHandoff(input) {
21
+ if (!isRecord(input)) {
22
+ throw new Error("Token callback payload must be an object.");
23
+ }
24
+ const state = stringField(input, "state");
25
+ const token = stringField(input, "token");
26
+ const label = nullableStringField(input, "label");
27
+ const proxyUrl = stringField(input, "proxyUrl");
28
+ if (!state)
29
+ throw new Error("Token callback state is missing.");
30
+ if (!token.startsWith("slv_live_"))
31
+ throw new Error("Token callback token is invalid.");
32
+ validateUrl(proxyUrl, "Token callback proxy URL");
33
+ return {
34
+ state,
35
+ token,
36
+ label,
37
+ proxyUrl,
38
+ };
39
+ }
40
+ export function parseFirebaseHandoff(input) {
41
+ if (!isRecord(input)) {
42
+ throw new Error("Firebase callback payload must be an object.");
43
+ }
44
+ const state = stringField(input, "state");
45
+ const refreshToken = stringField(input, "refreshToken");
46
+ const accountId = stringField(input, "accountId");
47
+ const email = nullableStringField(input, "email");
48
+ const label = nullableStringField(input, "label");
9
49
  if (!state)
10
- throw new Error('Login callback state is missing.');
11
- if (!token.startsWith('slv_live_'))
12
- throw new Error('Login callback token is invalid.');
13
- validateUrl(proxyUrl, 'Login callback proxy URL');
14
- return { state, token, label, proxyUrl };
50
+ throw new Error("Firebase callback state is missing.");
51
+ if (!refreshToken)
52
+ throw new Error("Firebase callback refresh token is missing.");
53
+ if (!accountId)
54
+ throw new Error("Firebase callback account ID is missing.");
55
+ return { state, refreshToken, accountId, email, label };
15
56
  }
16
57
  function stringField(input, key) {
17
58
  const value = input[key];
18
- if (typeof value !== 'string')
59
+ if (typeof value !== "string")
19
60
  throw new Error(`${key} must be a string.`);
20
61
  return value;
21
62
  }
22
63
  function nullableStringField(input, key) {
23
64
  const value = input[key];
24
- if (value === null || typeof value === 'undefined')
65
+ if (value === null || typeof value === "undefined")
25
66
  return null;
26
- if (typeof value !== 'string')
67
+ if (typeof value !== "string")
27
68
  throw new Error(`${key} must be a string or null.`);
28
69
  return value;
29
70
  }
30
71
  function validateUrl(raw, name) {
31
72
  const url = parseUrl(raw, name);
32
- if (url.protocol !== 'https:' && url.protocol !== 'http:') {
73
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
33
74
  throw new Error(`${name} must use http or https.`);
34
75
  }
35
76
  }
@@ -42,5 +83,6 @@ function parseUrl(raw, name) {
42
83
  }
43
84
  }
44
85
  function isRecord(input) {
45
- return typeof input === 'object' && input !== null && !Array.isArray(input);
86
+ return typeof input === "object" && input !== null && !Array.isArray(input);
46
87
  }
88
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/auth/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { Writable } from "node:stream";
2
+ export type TokenResult = {
3
+ id: string;
4
+ token: string;
5
+ label: string | null;
6
+ proxyUrl: string;
7
+ createdAt: string;
8
+ };
9
+ export type TokenOptions = {
10
+ webOrigin?: string;
11
+ label?: string;
12
+ output?: Writable;
13
+ opener?: (url: string) => Promise<boolean>;
14
+ onUrl?: (url: string) => void;
15
+ timeoutMs?: number;
16
+ signal?: AbortSignal;
17
+ now?: () => Date;
18
+ };
19
+ export declare function createToken(options?: TokenOptions): Promise<TokenResult>;
@@ -0,0 +1,53 @@
1
+ // Creates live Sleev tokens through the browser callback used by the legacy CLI.
2
+ import { randomBytes, randomUUID } from "node:crypto";
3
+ import { hostname } from "node:os";
4
+ import { webOrigin as defaultWebOrigin } from "../product.js";
5
+ import { openBrowser } from "./browser.js";
6
+ import { startTokenLoopback } from "./loopback.js";
7
+ const TOKEN_TIMEOUT_MS = 10 * 60 * 1000;
8
+ export async function createToken(options = {}) {
9
+ const output = options.output ?? process.stdout;
10
+ const origin = options.webOrigin ?? defaultWebOrigin();
11
+ const opener = options.opener ?? openBrowser;
12
+ const state = randomBytes(32).toString("base64url");
13
+ const loopback = await startTokenLoopback({
14
+ state,
15
+ webOrigin: origin,
16
+ timeoutMs: options.timeoutMs ?? TOKEN_TIMEOUT_MS,
17
+ ...(options.signal ? { signal: options.signal } : {}),
18
+ });
19
+ const url = tokenUrl(origin, state, loopback.callback, options.label);
20
+ options.onUrl?.(url);
21
+ output.write(`Opening ${origin} to create a Sleev token.\n`);
22
+ try {
23
+ const opened = await opener(url);
24
+ if (!opened) {
25
+ output.write("Could not open a browser automatically. Open this URL instead:\n");
26
+ output.write(`${url}\n`);
27
+ }
28
+ output.write("Waiting for browser token confirmation...\n");
29
+ const payload = await loopback.wait;
30
+ output.write("Browser token confirmed.\n");
31
+ return {
32
+ id: randomUUID(),
33
+ token: payload.token,
34
+ label: payload.label,
35
+ proxyUrl: payload.proxyUrl,
36
+ createdAt: (options.now ?? (() => new Date()))().toISOString(),
37
+ };
38
+ }
39
+ finally {
40
+ await loopback.close();
41
+ }
42
+ }
43
+ function tokenUrl(origin, state, callback, label) {
44
+ const url = new URL("/cli/login", origin);
45
+ url.searchParams.set("mode", "signup");
46
+ url.searchParams.set("state", state);
47
+ url.searchParams.set("callback", callback);
48
+ url.searchParams.set("device", hostname().slice(0, 80));
49
+ if (label)
50
+ url.searchParams.set("label", label);
51
+ return url.toString();
52
+ }
53
+ //# sourceMappingURL=token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/auth/token.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { FirebaseTokenManager } from "./firebase-tokens.js";
2
+ export type VerifyResult = {
3
+ accountId: string;
4
+ email: string | null;
5
+ };
6
+ export declare function verifyFirebaseAuth(manager?: FirebaseTokenManager, fetchImpl?: typeof fetch): Promise<VerifyResult>;
@@ -0,0 +1,22 @@
1
+ // Proves the Firebase chain end to end: stored refresh token -> minted ID
2
+ // token -> authenticated control-server call.
3
+ import { apiOrigin } from "../product.js";
4
+ import { FirebaseTokenManager } from "./firebase-tokens.js";
5
+ export async function verifyFirebaseAuth(manager = new FirebaseTokenManager(), fetchImpl = fetch) {
6
+ const idToken = await manager.getIdToken();
7
+ const response = await fetchImpl(`${apiOrigin()}/api/users/me`, {
8
+ headers: { authorization: `Bearer ${idToken}` },
9
+ });
10
+ if (!response.ok) {
11
+ throw new Error(`Control rejected the Firebase token (HTTP ${response.status}).`);
12
+ }
13
+ const body = (await response.json().catch(() => null));
14
+ if (!body || typeof body.id !== "string") {
15
+ throw new Error("Control returned an unexpected /api/users/me body.");
16
+ }
17
+ return {
18
+ accountId: body.id,
19
+ email: typeof body.email === "string" ? body.email : null,
20
+ };
21
+ }
22
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/auth/verify.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,8CAA8C;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAO5D,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACpC,OAAO,GAAG,IAAI,oBAAoB,EAAE,EACpC,YAA0B,KAAK;IAE/B,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;IAC3C,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,SAAS,EAAE,eAAe,EAAE;QAC5D,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,OAAO,EAAE,EAAE;KAClD,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACX,6CAA6C,QAAQ,CAAC,MAAM,IAAI,CACnE,CAAC;IACN,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAG7C,CAAC;IAET,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IAC1E,CAAC;IAED,OAAO;QACH,SAAS,EAAE,IAAI,CAAC,EAAE;QAClB,KAAK,EAAE,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;KAC5D,CAAC;AACN,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ type CommandResult = {
3
+ exitCode: number;
4
+ output?: string;
5
+ error?: string;
6
+ };
7
+ export declare function runCli(argv: string[]): Promise<CommandResult>;
8
+ export {};