@detergent-software/atk 7.10.1-dev.1 → 7.11.0-dev.2
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/README.md +44 -12
- package/build/commands/_app.d.ts.map +1 -1
- package/build/commands/_app.js +6 -1
- package/build/commands/_app.js.map +1 -1
- package/build/commands/index.d.ts.map +1 -1
- package/build/commands/index.js +5 -2
- package/build/commands/index.js.map +1 -1
- package/build/commands/login.d.ts +15 -0
- package/build/commands/login.d.ts.map +1 -0
- package/build/commands/login.js +148 -0
- package/build/commands/login.js.map +1 -0
- package/build/commands/logout.d.ts +11 -0
- package/build/commands/logout.d.ts.map +1 -0
- package/build/commands/logout.js +49 -0
- package/build/commands/logout.js.map +1 -0
- package/build/commands/schema.d.ts +1 -1
- package/build/commands/uninstall.js +1 -1
- package/build/commands/uninstall.js.map +1 -1
- package/build/commands/whoami.d.ts +11 -0
- package/build/commands/whoami.d.ts.map +1 -0
- package/build/commands/whoami.js +70 -0
- package/build/commands/whoami.js.map +1 -0
- package/build/components/NoticeBanner.d.ts +12 -0
- package/build/components/NoticeBanner.d.ts.map +1 -0
- package/build/components/NoticeBanner.js +21 -0
- package/build/components/NoticeBanner.js.map +1 -0
- package/build/components/index.d.ts +1 -0
- package/build/components/index.d.ts.map +1 -1
- package/build/components/index.js +1 -0
- package/build/components/index.js.map +1 -1
- package/build/hooks/usePublishState.js +2 -2
- package/build/hooks/usePublishState.js.map +1 -1
- package/build/lib/api/sdk.gen.d.ts +3 -3
- package/build/lib/api/sdk.gen.js +3 -3
- package/build/lib/api/types.gen.d.ts +101 -29
- package/build/lib/api/types.gen.d.ts.map +1 -1
- package/build/lib/api-client.d.ts +3 -3
- package/build/lib/api-client.d.ts.map +1 -1
- package/build/lib/api-client.js +38 -11
- package/build/lib/api-client.js.map +1 -1
- package/build/lib/auth.d.ts +43 -11
- package/build/lib/auth.d.ts.map +1 -1
- package/build/lib/auth.js +106 -39
- package/build/lib/auth.js.map +1 -1
- package/build/lib/diagnostics.d.ts.map +1 -1
- package/build/lib/diagnostics.js +75 -31
- package/build/lib/diagnostics.js.map +1 -1
- package/build/lib/entra.d.ts +86 -0
- package/build/lib/entra.d.ts.map +1 -0
- package/build/lib/entra.js +209 -0
- package/build/lib/entra.js.map +1 -0
- package/build/lib/notices.d.ts +33 -0
- package/build/lib/notices.d.ts.map +1 -0
- package/build/lib/notices.js +43 -0
- package/build/lib/notices.js.map +1 -0
- package/package.json +2 -1
package/build/lib/auth.d.ts
CHANGED
|
@@ -1,37 +1,69 @@
|
|
|
1
|
+
import type { Principal } from './api/types.gen.js';
|
|
2
|
+
import { type EntraSession } from './entra.js';
|
|
1
3
|
import { type ErrorHintOptions } from './errors.js';
|
|
2
4
|
export declare class AuthError extends Error {
|
|
3
5
|
command?: string;
|
|
4
6
|
hint?: string;
|
|
5
7
|
constructor(message: string, options?: ErrorHintOptions);
|
|
6
8
|
}
|
|
9
|
+
/** Environment variable holding a raw bearer token (GitHub or Entra) for CI and agents. */
|
|
10
|
+
export declare const ATK_TOKEN_ENV_VAR = "ATK_TOKEN";
|
|
11
|
+
export interface Credential {
|
|
12
|
+
source: CredentialSource;
|
|
13
|
+
token: string;
|
|
14
|
+
}
|
|
15
|
+
/** Where a credential came from, in chain order. */
|
|
16
|
+
export type CredentialSource = 'ATK_TOKEN' | 'config' | 'entra' | 'gh' | 'GITHUB_TOKEN';
|
|
7
17
|
/**
|
|
8
|
-
* Clear the cached GitHub token. Useful for testing
|
|
18
|
+
* Clear the cached credential and GitHub token. Useful for testing, and for
|
|
19
|
+
* `atk login` / `atk logout`, which change what the chain would return.
|
|
9
20
|
*/
|
|
10
21
|
export declare function clearTokenCache(): void;
|
|
11
22
|
/**
|
|
12
|
-
*
|
|
23
|
+
* Resolve the bearer token to send to the ATK API, and where it came from.
|
|
24
|
+
*
|
|
25
|
+
* Resolution order (the first hit wins and is cached for the process):
|
|
26
|
+
* 1. `ATK_TOKEN` environment variable (either kind of token, for CI and agents)
|
|
27
|
+
* 2. The cached Entra session, refreshed silently (`atk login`)
|
|
28
|
+
* 3. `githubToken` in `~/.atkrc.json`
|
|
29
|
+
* 4. `GITHUB_TOKEN` environment variable
|
|
30
|
+
* 5. `gh auth token`
|
|
13
31
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
32
|
+
* An expired Entra session falls through; if a GitHub token is then found it
|
|
33
|
+
* is used and an `entra-expired` notice is recorded once. When nothing is
|
|
34
|
+
* found the {@link AuthError} names `atk login` as the fix. Commands never
|
|
35
|
+
* start the device-code flow themselves.
|
|
36
|
+
*/
|
|
37
|
+
export declare function getCredential(): Promise<Credential>;
|
|
38
|
+
/**
|
|
39
|
+
* Get a GitHub token specifically (never an Entra token).
|
|
18
40
|
*
|
|
19
|
-
*
|
|
41
|
+
* Resolution order: `githubToken` config → `GITHUB_TOKEN` → `gh auth token`.
|
|
42
|
+
* Only for operations that talk to GitHub directly (`atk unpublish`,
|
|
43
|
+
* `atk promote`, `atk release-notes`); everything that talks to the ATK API
|
|
44
|
+
* goes through {@link getCredential}.
|
|
20
45
|
*/
|
|
21
46
|
export declare function getGitHubToken(): Promise<string>;
|
|
47
|
+
/**
|
|
48
|
+
* The Entra session outcome seen by the last credential resolution, or
|
|
49
|
+
* `undefined` if the chain has not run (or stopped at `ATK_TOKEN`).
|
|
50
|
+
*/
|
|
51
|
+
export declare function getLastEntraSession(): EntraSession | undefined;
|
|
22
52
|
/**
|
|
23
53
|
* Check if the gh CLI is installed and available.
|
|
24
54
|
*/
|
|
25
55
|
export declare function isGhCliAvailable(): Promise<boolean>;
|
|
26
56
|
/**
|
|
27
|
-
* Validate that a
|
|
28
|
-
*
|
|
29
|
-
*
|
|
57
|
+
* Validate that a token is accepted by the ATK API by calling `GET /me` with
|
|
58
|
+
* exactly that token — never the process-cached one. Works for GitHub and
|
|
59
|
+
* Entra tokens alike; the API picks the scheme.
|
|
30
60
|
*
|
|
31
61
|
* A 401/403 is an expected outcome and returns `{ valid: false }` quietly;
|
|
32
|
-
* only a network failure logs a warning.
|
|
62
|
+
* only a network failure logs a warning. `principal` is the `/me` payload on
|
|
63
|
+
* success; `username` is its `login`, kept for callers that only need a name.
|
|
33
64
|
*/
|
|
34
65
|
export declare function validateToken(token: string): Promise<{
|
|
66
|
+
principal?: Principal;
|
|
35
67
|
username?: string;
|
|
36
68
|
valid: boolean;
|
|
37
69
|
}>;
|
package/build/lib/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAKpD,OAAO,EAAE,KAAK,YAAY,EAAmB,MAAM,YAAY,CAAC;AAChE,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGpD,qBAAa,SAAU,SAAQ,KAAK;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;gBAEF,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB;CAM5D;AAED,2FAA2F;AAC3F,eAAO,MAAM,iBAAiB,cAAc,CAAC;AAE7C,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,gBAAgB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,oDAAoD;AACpD,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,GAAG,IAAI,GAAG,cAAc,CAAC;AAcxF;;;GAGG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAItC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC,CAMnD;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAQhD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,YAAY,GAAG,SAAS,CAE9D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CAMnD;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,SAAS,CAAC,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,CAqBvE"}
|
package/build/lib/auth.js
CHANGED
|
@@ -2,7 +2,9 @@ import { execFile } from 'node:child_process';
|
|
|
2
2
|
import { createApiClientForToken, resolveApiUrl } from './api-client.js';
|
|
3
3
|
import { me } from './api/sdk.gen.js';
|
|
4
4
|
import { loadConfig } from './config.js';
|
|
5
|
+
import { getEntraSession } from './entra.js';
|
|
5
6
|
import {} from './errors.js';
|
|
7
|
+
import { addNotice } from './notices.js';
|
|
6
8
|
export class AuthError extends Error {
|
|
7
9
|
command;
|
|
8
10
|
hint;
|
|
@@ -13,43 +15,70 @@ export class AuthError extends Error {
|
|
|
13
15
|
this.command = options.command;
|
|
14
16
|
}
|
|
15
17
|
}
|
|
16
|
-
/**
|
|
17
|
-
|
|
18
|
+
/** Environment variable holding a raw bearer token (GitHub or Entra) for CI and agents. */
|
|
19
|
+
export const ATK_TOKEN_ENV_VAR = 'ATK_TOKEN';
|
|
20
|
+
const NOT_SIGNED_IN_MESSAGE = 'Not signed in. Run `atk login` to sign in with your Emergent account, or `gh auth login` / `GITHUB_TOKEN` for GitHub.';
|
|
21
|
+
const SESSION_EXPIRED_MESSAGE = 'Your Emergent sign-in has expired. Run `atk login` to renew it, or use `gh auth login` / `GITHUB_TOKEN` for GitHub.';
|
|
22
|
+
const GITHUB_HINT = 'Run `gh auth login`, or set the GITHUB_TOKEN environment variable.';
|
|
23
|
+
/** Cached results so a process resolves each chain at most once. */
|
|
24
|
+
let cachedCredential;
|
|
25
|
+
let cachedGitHubToken;
|
|
26
|
+
/** The Entra outcome the last {@link getCredential} run observed, for `atk doctor`. */
|
|
27
|
+
let lastEntraSession;
|
|
18
28
|
/**
|
|
19
|
-
* Clear the cached GitHub token. Useful for testing
|
|
29
|
+
* Clear the cached credential and GitHub token. Useful for testing, and for
|
|
30
|
+
* `atk login` / `atk logout`, which change what the chain would return.
|
|
20
31
|
*/
|
|
21
32
|
export function clearTokenCache() {
|
|
22
|
-
|
|
33
|
+
cachedCredential = undefined;
|
|
34
|
+
cachedGitHubToken = undefined;
|
|
35
|
+
lastEntraSession = undefined;
|
|
23
36
|
}
|
|
24
37
|
/**
|
|
25
|
-
*
|
|
38
|
+
* Resolve the bearer token to send to the ATK API, and where it came from.
|
|
26
39
|
*
|
|
27
|
-
* Resolution order:
|
|
28
|
-
* 1.
|
|
29
|
-
* 2.
|
|
30
|
-
* 3. `
|
|
40
|
+
* Resolution order (the first hit wins and is cached for the process):
|
|
41
|
+
* 1. `ATK_TOKEN` environment variable (either kind of token, for CI and agents)
|
|
42
|
+
* 2. The cached Entra session, refreshed silently (`atk login`)
|
|
43
|
+
* 3. `githubToken` in `~/.atkrc.json`
|
|
44
|
+
* 4. `GITHUB_TOKEN` environment variable
|
|
45
|
+
* 5. `gh auth token`
|
|
31
46
|
*
|
|
32
|
-
*
|
|
47
|
+
* An expired Entra session falls through; if a GitHub token is then found it
|
|
48
|
+
* is used and an `entra-expired` notice is recorded once. When nothing is
|
|
49
|
+
* found the {@link AuthError} names `atk login` as the fix. Commands never
|
|
50
|
+
* start the device-code flow themselves.
|
|
33
51
|
*/
|
|
34
|
-
export
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
export function getCredential() {
|
|
53
|
+
cachedCredential ??= resolveCredential().catch((err) => {
|
|
54
|
+
cachedCredential = undefined;
|
|
55
|
+
throw err;
|
|
56
|
+
});
|
|
57
|
+
return cachedCredential;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get a GitHub token specifically (never an Entra token).
|
|
61
|
+
*
|
|
62
|
+
* Resolution order: `githubToken` config → `GITHUB_TOKEN` → `gh auth token`.
|
|
63
|
+
* Only for operations that talk to GitHub directly (`atk unpublish`,
|
|
64
|
+
* `atk promote`, `atk release-notes`); everything that talks to the ATK API
|
|
65
|
+
* goes through {@link getCredential}.
|
|
66
|
+
*/
|
|
67
|
+
export function getGitHubToken() {
|
|
68
|
+
cachedGitHubToken ??= resolveGitHubToken()
|
|
69
|
+
.then((found) => found.token)
|
|
70
|
+
.catch((err) => {
|
|
71
|
+
cachedGitHubToken = undefined;
|
|
72
|
+
throw err;
|
|
73
|
+
});
|
|
74
|
+
return cachedGitHubToken;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The Entra session outcome seen by the last credential resolution, or
|
|
78
|
+
* `undefined` if the chain has not run (or stopped at `ATK_TOKEN`).
|
|
79
|
+
*/
|
|
80
|
+
export function getLastEntraSession() {
|
|
81
|
+
return lastEntraSession;
|
|
53
82
|
}
|
|
54
83
|
/**
|
|
55
84
|
* Check if the gh CLI is installed and available.
|
|
@@ -62,12 +91,13 @@ export function isGhCliAvailable() {
|
|
|
62
91
|
});
|
|
63
92
|
}
|
|
64
93
|
/**
|
|
65
|
-
* Validate that a
|
|
66
|
-
*
|
|
67
|
-
*
|
|
94
|
+
* Validate that a token is accepted by the ATK API by calling `GET /me` with
|
|
95
|
+
* exactly that token — never the process-cached one. Works for GitHub and
|
|
96
|
+
* Entra tokens alike; the API picks the scheme.
|
|
68
97
|
*
|
|
69
98
|
* A 401/403 is an expected outcome and returns `{ valid: false }` quietly;
|
|
70
|
-
* only a network failure logs a warning.
|
|
99
|
+
* only a network failure logs a warning. `principal` is the `/me` payload on
|
|
100
|
+
* success; `username` is its `login`, kept for callers that only need a name.
|
|
71
101
|
*/
|
|
72
102
|
export async function validateToken(token) {
|
|
73
103
|
try {
|
|
@@ -82,7 +112,7 @@ export async function validateToken(token) {
|
|
|
82
112
|
if (!result.response.ok || !result.data) {
|
|
83
113
|
return { valid: false };
|
|
84
114
|
}
|
|
85
|
-
return { username: result.data.login, valid: true };
|
|
115
|
+
return { principal: result.data, username: result.data.login, valid: true };
|
|
86
116
|
}
|
|
87
117
|
catch (error) {
|
|
88
118
|
console.warn(`Warning: Token validation failed — ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -99,17 +129,14 @@ function getTokenFromGhCli() {
|
|
|
99
129
|
const msg = stderr.includes('not logged in')
|
|
100
130
|
? 'GitHub CLI is not authenticated. Run `gh auth login` first.'
|
|
101
131
|
: `Failed to get token from GitHub CLI: ${stderr || error.message}`;
|
|
102
|
-
reject(new AuthError(msg, {
|
|
103
|
-
command: 'gh auth login',
|
|
104
|
-
hint: 'Run `gh auth login`, or set the GITHUB_TOKEN environment variable.',
|
|
105
|
-
}));
|
|
132
|
+
reject(new AuthError(msg, { command: 'gh auth login', hint: GITHUB_HINT }));
|
|
106
133
|
return;
|
|
107
134
|
}
|
|
108
135
|
const token = stdout.trim();
|
|
109
136
|
if (!token) {
|
|
110
137
|
reject(new AuthError('GitHub CLI returned an empty token. Run `gh auth login` first.', {
|
|
111
138
|
command: 'gh auth login',
|
|
112
|
-
hint:
|
|
139
|
+
hint: GITHUB_HINT,
|
|
113
140
|
}));
|
|
114
141
|
return;
|
|
115
142
|
}
|
|
@@ -117,4 +144,44 @@ function getTokenFromGhCli() {
|
|
|
117
144
|
});
|
|
118
145
|
});
|
|
119
146
|
}
|
|
147
|
+
async function resolveCredential() {
|
|
148
|
+
// 1. ATK_TOKEN: a raw bearer of either kind
|
|
149
|
+
const atkToken = process.env[ATK_TOKEN_ENV_VAR]?.trim();
|
|
150
|
+
if (atkToken) {
|
|
151
|
+
return { source: 'ATK_TOKEN', token: atkToken };
|
|
152
|
+
}
|
|
153
|
+
// 2. Cached Entra session, refreshed silently
|
|
154
|
+
const entra = await getEntraSession();
|
|
155
|
+
lastEntraSession = entra;
|
|
156
|
+
if (entra.ok) {
|
|
157
|
+
return { source: 'entra', token: entra.token };
|
|
158
|
+
}
|
|
159
|
+
// 3–5. GitHub token sources
|
|
160
|
+
let github;
|
|
161
|
+
try {
|
|
162
|
+
github = await resolveGitHubToken();
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
const ghDetail = err instanceof Error ? err.message : String(err);
|
|
166
|
+
throw new AuthError(entra.reason === 'expired' ? SESSION_EXPIRED_MESSAGE : NOT_SIGNED_IN_MESSAGE, {
|
|
167
|
+
command: 'atk login',
|
|
168
|
+
hint: `No GitHub token was found either (${ghDetail})`,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
if (entra.reason === 'expired') {
|
|
172
|
+
addNotice({ kind: 'entra-expired' });
|
|
173
|
+
}
|
|
174
|
+
return github;
|
|
175
|
+
}
|
|
176
|
+
async function resolveGitHubToken() {
|
|
177
|
+
const config = await loadConfig();
|
|
178
|
+
if (config.githubToken) {
|
|
179
|
+
return { source: 'config', token: config.githubToken };
|
|
180
|
+
}
|
|
181
|
+
const envToken = process.env['GITHUB_TOKEN'];
|
|
182
|
+
if (envToken) {
|
|
183
|
+
return { source: 'GITHUB_TOKEN', token: envToken };
|
|
184
|
+
}
|
|
185
|
+
return { source: 'gh', token: await getTokenFromGhCli() };
|
|
186
|
+
}
|
|
120
187
|
//# sourceMappingURL=auth.js.map
|
package/build/lib/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/lib/diagnostics.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/lib/diagnostics.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAW9D;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAqBjE;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,EACnC,mBAAmB,CAAC,EAAE,MAAM,GAC3B,OAAO,CAAC,eAAe,EAAE,CAAC,CAmL5B"}
|
package/build/lib/diagnostics.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
1
2
|
import { resolveApiUrl } from './api-client.js';
|
|
2
|
-
import {
|
|
3
|
+
import { getCredential, getLastEntraSession, isGhCliAvailable, validateToken } from './auth.js';
|
|
3
4
|
import { loadConfig, loadProjectConfig } from './config.js';
|
|
4
5
|
import { detectTools, getAdapterDiagnostics } from './detector.js';
|
|
6
|
+
import { getEntraCachePath } from './entra.js';
|
|
5
7
|
import { lockfileExists, readLockfile } from './lockfile.js';
|
|
6
8
|
import { findProjectRoot } from './paths.js';
|
|
7
9
|
import { fetchRegistry } from './registry.js';
|
|
@@ -60,8 +62,8 @@ export async function runDiagnostics(progress, projectRootOverride) {
|
|
|
60
62
|
}
|
|
61
63
|
else {
|
|
62
64
|
checks.push({
|
|
63
|
-
detail: 'Install from https://cli.github.com, or set githubToken in config / GITHUB_TOKEN.',
|
|
64
|
-
message: 'Not found — used as a token source and for `atk unpublish`/`atk promote`',
|
|
65
|
+
detail: 'Install from https://cli.github.com, or set githubToken in config / GITHUB_TOKEN. Not needed when signed in with `atk login`, except for those two commands.',
|
|
66
|
+
message: 'Not found — used as a GitHub token source and for `atk unpublish`/`atk promote`',
|
|
65
67
|
name: 'GitHub CLI (gh)',
|
|
66
68
|
status: 'warn',
|
|
67
69
|
});
|
|
@@ -93,34 +95,9 @@ export async function runDiagnostics(progress, projectRootOverride) {
|
|
|
93
95
|
name: 'ATK API',
|
|
94
96
|
status: 'pass',
|
|
95
97
|
});
|
|
96
|
-
// Check
|
|
97
|
-
progress('Checking
|
|
98
|
-
|
|
99
|
-
const token = await getGitHubToken();
|
|
100
|
-
const validation = await validateToken(token);
|
|
101
|
-
if (validation.valid) {
|
|
102
|
-
checks.push({
|
|
103
|
-
message: `Authenticated as ${validation.username ?? 'unknown'}`,
|
|
104
|
-
name: 'GitHub auth',
|
|
105
|
-
status: 'pass',
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
checks.push({
|
|
110
|
-
detail: 'Run `gh auth login` or update githubToken in config. The token must belong to an active EmergentSoftware member.',
|
|
111
|
-
message: 'Token was rejected by the ATK API (invalid, expired, or not an org member)',
|
|
112
|
-
name: 'GitHub auth',
|
|
113
|
-
status: 'fail',
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
catch (err) {
|
|
118
|
-
checks.push({
|
|
119
|
-
message: err instanceof Error ? err.message : 'Failed to get token',
|
|
120
|
-
name: 'GitHub auth',
|
|
121
|
-
status: 'fail',
|
|
122
|
-
});
|
|
123
|
-
}
|
|
98
|
+
// Check authentication against the ATK API
|
|
99
|
+
progress('Checking authentication...');
|
|
100
|
+
checks.push(await checkAuthentication());
|
|
124
101
|
// Check registry access
|
|
125
102
|
progress('Checking registry access...');
|
|
126
103
|
try {
|
|
@@ -244,4 +221,71 @@ export async function runDiagnostics(progress, projectRootOverride) {
|
|
|
244
221
|
}
|
|
245
222
|
return checks;
|
|
246
223
|
}
|
|
224
|
+
const SOURCE_LABELS = {
|
|
225
|
+
ATK_TOKEN: 'ATK_TOKEN',
|
|
226
|
+
config: 'githubToken in config',
|
|
227
|
+
entra: 'atk login session',
|
|
228
|
+
gh: 'gh auth token',
|
|
229
|
+
GITHUB_TOKEN: 'GITHUB_TOKEN',
|
|
230
|
+
};
|
|
231
|
+
/**
|
|
232
|
+
* Resolve the credential chain and validate the result against `GET /me`.
|
|
233
|
+
* When an Entra session file exists but did not supply the credential, the
|
|
234
|
+
* detail says so, since that usually means `atk login` is needed again.
|
|
235
|
+
*/
|
|
236
|
+
async function checkAuthentication() {
|
|
237
|
+
const name = 'Authentication';
|
|
238
|
+
let credential;
|
|
239
|
+
try {
|
|
240
|
+
credential = await getCredential();
|
|
241
|
+
}
|
|
242
|
+
catch (err) {
|
|
243
|
+
return {
|
|
244
|
+
detail: staleEntraSessionNote(),
|
|
245
|
+
message: err instanceof Error ? err.message : 'Failed to resolve a credential',
|
|
246
|
+
name,
|
|
247
|
+
status: 'fail',
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
const validation = await validateToken(credential.token);
|
|
251
|
+
const source = SOURCE_LABELS[credential.source];
|
|
252
|
+
if (!validation.valid) {
|
|
253
|
+
return {
|
|
254
|
+
detail: credential.source === 'entra'
|
|
255
|
+
? 'Run `atk login --force` to sign in again.'
|
|
256
|
+
: `Run \`atk login\`, or refresh the GitHub token (${source}). GitHub tokens must belong to an active EmergentSoftware member.`,
|
|
257
|
+
message: `Credential from ${source} was rejected by the ATK API`,
|
|
258
|
+
name,
|
|
259
|
+
status: 'fail',
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
const principal = validation.principal;
|
|
263
|
+
const who = principal?.login ?? validation.username ?? 'unknown';
|
|
264
|
+
const scheme = principal?.scheme ?? 'unknown';
|
|
265
|
+
const sunset = principal?.githubAuthSunset
|
|
266
|
+
? `GitHub sign-in to ATK ends on ${principal.githubAuthSunset.slice(0, 10)}; run \`atk login\` to switch to your Emergent account.`
|
|
267
|
+
: undefined;
|
|
268
|
+
return {
|
|
269
|
+
detail: sunset ?? (credential.source === 'entra' ? undefined : staleEntraSessionNote()),
|
|
270
|
+
message: `Signed in as ${who} via ${scheme} (from ${source})`,
|
|
271
|
+
name,
|
|
272
|
+
status: 'pass',
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
/** A note when `~/.atk/auth/msal-cache.json` exists but yielded no session. */
|
|
276
|
+
function staleEntraSessionNote() {
|
|
277
|
+
if (!existsSync(getEntraCachePath())) {
|
|
278
|
+
return undefined;
|
|
279
|
+
}
|
|
280
|
+
const session = getLastEntraSession();
|
|
281
|
+
if (!session || session.ok) {
|
|
282
|
+
return undefined;
|
|
283
|
+
}
|
|
284
|
+
const why = session.reason === 'expired'
|
|
285
|
+
? 'the session has expired'
|
|
286
|
+
: session.reason === 'none'
|
|
287
|
+
? 'it holds no account'
|
|
288
|
+
: `it could not be read: ${session.detail ?? 'unknown error'}`;
|
|
289
|
+
return `An Emergent session file exists at ${getEntraCachePath()} but ${why}. Run \`atk login\` to renew it or \`atk logout\` to remove it.`;
|
|
290
|
+
}
|
|
247
291
|
//# sourceMappingURL=diagnostics.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/lib/diagnostics.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/lib/diagnostics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Microsoft Entra ID sign-in for the ATK CLI (`atk login` / `atk logout`).
|
|
3
|
+
*
|
|
4
|
+
* Wraps `@azure/msal-node`'s public-client device-code flow against the
|
|
5
|
+
* `ES ATK CLI` app registration and persists MSAL's token cache to
|
|
6
|
+
* `~/.atk/auth/msal-cache.json` through an `ICachePlugin`. The file holds a
|
|
7
|
+
* refresh token, so it is created with mode 0600 (best effort on Windows) and
|
|
8
|
+
* lives outside `~/.atk/cache/`, which `atk cache clear` deletes wholesale.
|
|
9
|
+
*
|
|
10
|
+
* MSAL is imported lazily, and only once a cache file exists or a sign-in is
|
|
11
|
+
* requested, so GitHub-token users pay no startup cost for it.
|
|
12
|
+
*
|
|
13
|
+
* The tenant, client id and scope are constants: one set of registrations
|
|
14
|
+
* serves dev and prod, so a single sign-in works against both APIs.
|
|
15
|
+
*/
|
|
16
|
+
/** The Emergent Software tenant. */
|
|
17
|
+
export declare const ENTRA_TENANT_ID = "25ee13ae-a8a5-4bc2-bb23-aea90536fb0c";
|
|
18
|
+
export declare const ENTRA_AUTHORITY = "https://login.microsoftonline.com/25ee13ae-a8a5-4bc2-bb23-aea90536fb0c";
|
|
19
|
+
/** `ES ATK CLI`: a public client allowed to use the device-code flow. */
|
|
20
|
+
export declare const ENTRA_CLIENT_ID = "488be9fb-eb4d-464c-8045-a5e4783658c6";
|
|
21
|
+
/** The `ES ATK API` scope every ATK access token must carry. MSAL adds `openid profile offline_access` itself. */
|
|
22
|
+
export declare const ENTRA_SCOPES: string[];
|
|
23
|
+
/** What the CLI shows the user while the device-code flow waits for them. */
|
|
24
|
+
export interface DeviceCodePrompt {
|
|
25
|
+
/** Seconds until the code expires. */
|
|
26
|
+
expiresIn: number;
|
|
27
|
+
/** Microsoft's own instruction text, e.g. "To sign in, use a web browser to open ...". */
|
|
28
|
+
message: string;
|
|
29
|
+
userCode: string;
|
|
30
|
+
verificationUri: string;
|
|
31
|
+
}
|
|
32
|
+
/** The signed-in account, reduced to what the CLI needs. */
|
|
33
|
+
export interface EntraAccount {
|
|
34
|
+
homeAccountId: string;
|
|
35
|
+
name?: string;
|
|
36
|
+
/** The user principal name, e.g. `jasonp@emergentsoftware.net`. */
|
|
37
|
+
username: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Result of {@link getEntraSession}.
|
|
41
|
+
*
|
|
42
|
+
* - `none`: no cache file, or a cache with no account (never signed in, or signed out).
|
|
43
|
+
* - `expired`: an account exists but the refresh token was rejected; the user must run `atk login`.
|
|
44
|
+
* - `error`: MSAL failed for another reason (network, corrupt cache); `detail` says why.
|
|
45
|
+
*/
|
|
46
|
+
export type EntraSession = {
|
|
47
|
+
account: EntraAccount;
|
|
48
|
+
ok: true;
|
|
49
|
+
token: string;
|
|
50
|
+
} | {
|
|
51
|
+
detail?: string;
|
|
52
|
+
ok: false;
|
|
53
|
+
reason: 'error' | 'expired' | 'none';
|
|
54
|
+
};
|
|
55
|
+
/** Path of the persisted MSAL cache: `~/.atk/auth/msal-cache.json`. */
|
|
56
|
+
export declare function getEntraCachePath(): string;
|
|
57
|
+
/**
|
|
58
|
+
* Silently obtain an access token for the cached Entra account.
|
|
59
|
+
*
|
|
60
|
+
* Short-circuits without importing MSAL when no cache file exists. An
|
|
61
|
+
* interaction-required or invalid-grant failure means the session has expired.
|
|
62
|
+
*/
|
|
63
|
+
export declare function getEntraSession(): Promise<EntraSession>;
|
|
64
|
+
/**
|
|
65
|
+
* Run the device-code flow. `onCode` receives the verification URL and user
|
|
66
|
+
* code as soon as Entra issues them; the promise resolves once the user has
|
|
67
|
+
* completed sign-in in their browser.
|
|
68
|
+
*/
|
|
69
|
+
export declare function loginWithDeviceCode(onCode: (prompt: DeviceCodePrompt) => void): Promise<{
|
|
70
|
+
account: EntraAccount;
|
|
71
|
+
token: string;
|
|
72
|
+
}>;
|
|
73
|
+
/**
|
|
74
|
+
* Remove every account from the MSAL cache and delete the cache file.
|
|
75
|
+
* Returns whether a signed-in account was actually removed.
|
|
76
|
+
*/
|
|
77
|
+
export declare function logoutEntra(): Promise<boolean>;
|
|
78
|
+
/**
|
|
79
|
+
* Remove one account (and its tokens) from the cache. Used by `atk login`
|
|
80
|
+
* when the API refuses a freshly acquired token (e.g. a guest account) so a
|
|
81
|
+
* useless session is not left behind.
|
|
82
|
+
*/
|
|
83
|
+
export declare function removeEntraAccount(account: EntraAccount): Promise<void>;
|
|
84
|
+
/** Forget the memoised MSAL client. Intended for tests. */
|
|
85
|
+
export declare function resetEntraClient(): void;
|
|
86
|
+
//# sourceMappingURL=entra.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entra.d.ts","sourceRoot":"","sources":["../../src/lib/entra.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AASH,oCAAoC;AACpC,eAAO,MAAM,eAAe,yCAAyC,CAAC;AACtE,eAAO,MAAM,eAAe,2EAAyD,CAAC;AACtF,yEAAyE;AACzE,eAAO,MAAM,eAAe,yCAAyC,CAAC;AACtE,kHAAkH;AAClH,eAAO,MAAM,YAAY,UAAgE,CAAC;AAE1F,6EAA6E;AAC7E,MAAM,WAAW,gBAAgB;IAC/B,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,0FAA0F;IAC1F,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,4DAA4D;AAC5D,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GACpB;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAA;CAAE,CAAC;AAIzE,uEAAuE;AACvE,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC,CAmB7D;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,GACzC,OAAO,CAAC;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAyBnD;AAED;;;GAGG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAsBpD;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAO7E;AAED,2DAA2D;AAC3D,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
|