@learning-with-court/cli 0.1.0 → 0.2.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/README.md CHANGED
@@ -4,17 +4,14 @@ CLI for the learning-with-court platform. Two modes:
4
4
 
5
5
  1. **Stdio MCP proxy** (default): forwards tool calls from a local agent to
6
6
  the hosted MCP server at `mcp.workshop.institute`. Auth resolves via env
7
- var (`LWC_TOKEN`) → cached `~/.lwc/token.json` → browser OAuth (PKCE).
7
+ var (`LWC_TOKEN`) → cached `~/.lwc/token.json` → browser sign-in.
8
8
  2. **Subcommands** for one-shot operations:
9
9
  - `setup <workshop-id> [--dir <path>]` — clone a workshop project
10
- repo (default: `~/learning-with-court/<workshop-id>/`) after Clerk
11
- sign-in. Pass `--dir` to install somewhere else; the CLI auto-creates
12
- parent directories.
10
+ repo (default: `~/learning-with-court/<workshop-id>/`). Pass `--dir`
11
+ to install somewhere else; the CLI auto-creates parent directories.
13
12
  - `refresh <workshop-id>` — refresh the clone token and `git pull`.
14
13
  - `auth login` / `auth logout` — manual control of the cached token.
15
14
 
16
- Modeled on `mixcraft-app/packages/mcp-proxy`.
17
-
18
15
  ## Usage
19
16
 
20
17
  ```sh
@@ -28,8 +25,34 @@ npx -y @learning-with-court/cli@latest setup mcp-workshop --dir ~/workshops/mcp-
28
25
  npx -y @learning-with-court/cli@latest
29
26
  ```
30
27
 
28
+ ## Auth flow
29
+
30
+ `lwc auth login` (and any subcommand that needs a token) runs an
31
+ authorization-code + PKCE flow against `workshop.institute`:
32
+
33
+ 1. The CLI starts a loopback server on an ephemeral localhost port and
34
+ opens `https://workshop.institute/cli-auth?...` with a PKCE challenge
35
+ and random state.
36
+ 2. You sign in (if needed) and click **Authorize**.
37
+ 3. The browser redirects to `http://localhost:<port>/callback?code=...`,
38
+ the CLI exchanges the code at `mcp.workshop.institute/cli/token`,
39
+ and caches the resulting JWT.
40
+
41
+ Tokens are RS256 JWTs signed by an AWS KMS key; the public key is
42
+ published at `https://mcp.workshop.institute/.well-known/jwks.json`.
43
+ Lifetime: 90 days. After expiry, re-run `lwc auth login`.
44
+
45
+ ### Environment overrides
46
+
47
+ - `LWC_TOKEN` — bypass the cache and use this token directly.
48
+ - `LWC_API_URL` — point at a different MCP API origin (default
49
+ `https://mcp.workshop.institute`).
50
+ - `LWC_LANDING_URL` — override the browser-side landing origin (default
51
+ is derived from `LWC_API_URL`: `mcp.` and `mcp-` prefixes are
52
+ stripped, so `mcp-dev.workshop.institute` → `dev.workshop.institute`).
53
+
31
54
  ## Token storage
32
55
 
33
- `~/.lwc/token.json`, mode `0600`. Contains the Clerk OAuth access token,
34
- refresh token, and expiry. Delete the file or run `lwc auth logout` to
56
+ `~/.lwc/token.json`, mode `0600`. Contains the JWT, expiry, and the
57
+ opaque user identifier. Delete the file or run `lwc auth logout` to
35
58
  revoke locally.
@@ -1,6 +1,7 @@
1
1
  export interface CallbackResult {
2
2
  type: 'callback';
3
- code: string;
3
+ /** The Clerk-templated JWT minted by the cli-auth page. */
4
+ token: string;
4
5
  state: string;
5
6
  }
6
7
  export interface CancelResult {
@@ -15,7 +16,7 @@ export interface LocalServerHandle {
15
16
  }
16
17
  /**
17
18
  * Start a local HTTP server on an OS-assigned ephemeral port. Resolves
18
- * `done` when the browser hits `/callback?code=...&state=...` or
19
+ * `done` when the browser hits `/callback?token=...&state=...` or
19
20
  * `/cancel?state=...`. The caller is responsible for validating that the
20
21
  * returned `state` matches what they generated.
21
22
  *
@@ -10,7 +10,7 @@ const CANCEL_HTML = `<!doctype html>
10
10
  const NOT_FOUND_HTML = '<h1>Not found</h1>';
11
11
  /**
12
12
  * Start a local HTTP server on an OS-assigned ephemeral port. Resolves
13
- * `done` when the browser hits `/callback?code=...&state=...` or
13
+ * `done` when the browser hits `/callback?token=...&state=...` or
14
14
  * `/cancel?state=...`. The caller is responsible for validating that the
15
15
  * returned `state` matches what they generated.
16
16
  *
@@ -30,16 +30,16 @@ export function startLocalCallbackServer(opts = {}) {
30
30
  const host = req.headers.host ?? 'localhost';
31
31
  const reqUrl = new URL(req.url ?? '/', `http://${host}`);
32
32
  if (reqUrl.pathname === '/callback') {
33
- const code = reqUrl.searchParams.get('code');
33
+ const token = reqUrl.searchParams.get('token');
34
34
  const state = reqUrl.searchParams.get('state');
35
- if (!code || !state) {
35
+ if (!token || !state) {
36
36
  res.writeHead(400, { 'Content-Type': 'text/html' });
37
- res.end('<h1>Missing code or state</h1>');
37
+ res.end('<h1>Missing token or state</h1>');
38
38
  return;
39
39
  }
40
40
  res.writeHead(200, { 'Content-Type': 'text/html' });
41
41
  res.end(SUCCESS_HTML);
42
- resolveDone({ type: 'callback', code, state });
42
+ resolveDone({ type: 'callback', token, state });
43
43
  return;
44
44
  }
45
45
  if (reqUrl.pathname === '/cancel') {
@@ -1 +1 @@
1
- {"version":3,"file":"local-server.js","sourceRoot":"","sources":["../../src/auth/local-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"local-server.js","sourceRoot":"","sources":["../../src/auth/local-server.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,16 @@
1
1
  import { type CachedToken } from './token-cache.js';
2
2
  /**
3
- * Drive the full browser-based login flow. Opens the user's browser to
4
- * `<landing>/cli-auth?...`, waits for them to complete the authorize
5
- * dance, exchanges the resulting code for a JWT, and returns it. Does
6
- * NOT cache the token caller is responsible for that.
3
+ * Drive the browser-based sign-in flow. Opens
4
+ * `<landing>/cli-auth?...&port=<loopback-port>[&refresh=1]`, waits for
5
+ * the user to complete the consent (or for the page to auto-mint when
6
+ * `refresh=true` and they have an active Clerk session), and returns
7
+ * the resulting Clerk-templated JWT. Caller is responsible for caching.
8
+ *
9
+ * `refresh=true` puts the cli-auth page into auto-mint mode: it skips
10
+ * the consent card render and mints the JWT immediately if the user is
11
+ * still signed into Clerk. If their Clerk session is gone, they fall
12
+ * back to the normal sign-in path. Use this for re-auth after expiry.
7
13
  */
8
- export declare function loginViaBrowser(): Promise<CachedToken>;
14
+ export declare function loginViaBrowser(opts?: {
15
+ refresh?: boolean;
16
+ }): Promise<CachedToken>;
@@ -1,6 +1,6 @@
1
1
  import { spawn } from 'node:child_process';
2
- import { cliAuthPageUrl, tokenExchangeUrl } from '../config.js';
3
- import { generatePkcePair, generateState } from './pkce.js';
2
+ import { randomBytes } from 'node:crypto';
3
+ import { cliAuthPageUrl } from '../config.js';
4
4
  import { startLocalCallbackServer } from './local-server.js';
5
5
  import { decodeJwtPayload } from './token-cache.js';
6
6
  function openBrowser(url) {
@@ -13,53 +13,64 @@ function openBrowser(url) {
13
13
  const child = spawn(cmd, args, { stdio: 'ignore', detached: true, shell: process.platform === 'win32' });
14
14
  child.unref();
15
15
  }
16
+ function generateState() {
17
+ return randomBytes(16).toString('hex');
18
+ }
16
19
  function buildAuthorizeUrl(params) {
17
20
  const url = new URL(cliAuthPageUrl());
18
21
  url.searchParams.set('state', params.state);
19
- url.searchParams.set('code_challenge', params.codeChallenge);
20
- url.searchParams.set('code_challenge_method', 'S256');
21
22
  url.searchParams.set('port', String(params.port));
23
+ if (params.refresh) {
24
+ url.searchParams.set('refresh', '1');
25
+ }
22
26
  return url.toString();
23
27
  }
24
- async function exchangeCodeForToken(params) {
25
- const response = await fetch(tokenExchangeUrl(), {
26
- method: 'POST',
27
- headers: { 'Content-Type': 'application/json' },
28
- body: JSON.stringify({ code: params.code, code_verifier: params.codeVerifier }),
29
- });
30
- if (!response.ok) {
31
- const text = await response.text().catch(() => '');
32
- throw new Error(`Token exchange failed (${response.status}): ${text}`);
28
+ function parseCachedToken(jwt) {
29
+ const claims = decodeJwtPayload(jwt);
30
+ if (!claims) {
31
+ throw new Error('Invalid JWT received from cli-auth callback (could not decode).');
32
+ }
33
+ const sub = typeof claims.sub === 'string' ? claims.sub : '';
34
+ const expFromJwt = typeof claims.exp === 'number' ? claims.exp * 1000 : null;
35
+ if (!expFromJwt) {
36
+ throw new Error('JWT is missing an exp claim.');
33
37
  }
34
- const data = (await response.json());
35
- const claims = decodeJwtPayload(data.access_token);
36
- const sub = typeof claims?.sub === 'string' ? claims.sub : '';
37
- const expFromJwt = typeof claims?.exp === 'number' ? claims.exp * 1000 : null;
38
- const expFromExpiresIn = Date.now() + data.expires_in * 1000;
38
+ const scope = typeof claims.scope === 'string' ? claims.scope : '';
39
39
  return {
40
- accessToken: data.access_token,
41
- tokenType: data.token_type ?? 'Bearer',
42
- expiresAt: expFromJwt ?? expFromExpiresIn,
43
- scope: data.scope ?? '',
40
+ accessToken: jwt,
41
+ tokenType: 'Bearer',
42
+ expiresAt: expFromJwt,
43
+ scope,
44
44
  sub,
45
45
  };
46
46
  }
47
47
  /**
48
- * Drive the full browser-based login flow. Opens the user's browser to
49
- * `<landing>/cli-auth?...`, waits for them to complete the authorize
50
- * dance, exchanges the resulting code for a JWT, and returns it. Does
51
- * NOT cache the token caller is responsible for that.
48
+ * Drive the browser-based sign-in flow. Opens
49
+ * `<landing>/cli-auth?...&port=<loopback-port>[&refresh=1]`, waits for
50
+ * the user to complete the consent (or for the page to auto-mint when
51
+ * `refresh=true` and they have an active Clerk session), and returns
52
+ * the resulting Clerk-templated JWT. Caller is responsible for caching.
53
+ *
54
+ * `refresh=true` puts the cli-auth page into auto-mint mode: it skips
55
+ * the consent card render and mints the JWT immediately if the user is
56
+ * still signed into Clerk. If their Clerk session is gone, they fall
57
+ * back to the normal sign-in path. Use this for re-auth after expiry.
52
58
  */
53
- export async function loginViaBrowser() {
59
+ export async function loginViaBrowser(opts = {}) {
60
+ const refresh = opts.refresh ?? false;
54
61
  const state = generateState();
55
- const { codeVerifier, codeChallenge } = generatePkcePair();
56
62
  const server = await startLocalCallbackServer();
57
63
  const authorizeUrl = buildAuthorizeUrl({
58
64
  state,
59
- codeChallenge,
60
65
  port: server.port,
66
+ refresh,
61
67
  });
62
- console.error('Opening browser to sign in...');
68
+ if (refresh) {
69
+ console.error('Refreshing your sign-in...');
70
+ }
71
+ else {
72
+ console.error('Opening browser to sign in...');
73
+ }
63
74
  console.error(`If your browser doesn't open, visit:\n ${authorizeUrl}`);
64
75
  openBrowser(authorizeUrl);
65
76
  let result;
@@ -76,9 +87,6 @@ export async function loginViaBrowser() {
76
87
  if (result.type === 'cancel') {
77
88
  throw new Error('Sign-in cancelled. Run `lwc auth login` to retry.');
78
89
  }
79
- return exchangeCodeForToken({
80
- code: result.code,
81
- codeVerifier,
82
- });
90
+ return parseCachedToken(result.token);
83
91
  }
84
92
  //# sourceMappingURL=login.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/auth/login.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/auth/login.ts"],"names":[],"mappings":"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"}
@@ -8,10 +8,12 @@ export async function resolveBearerToken() {
8
8
  if (cached && !isTokenExpired(cached)) {
9
9
  return cached.accessToken;
10
10
  }
11
- // No cached token, or it expired. Drive the browser flow. The new CLI
12
- // tokens are 90-day JWTs with no refresh token — re-auth is the
13
- // recovery path on expiry.
14
- const fresh = await loginViaBrowser();
11
+ // Cache is missing or expired. Drive the browser flow:
12
+ // - cached + expired refresh mode (cli-auth auto-mints if Clerk
13
+ // session is alive; user sees a brief browser flash)
14
+ // - no cached token → first-time consent flow
15
+ const refresh = cached !== null;
16
+ const fresh = await loginViaBrowser({ refresh });
15
17
  saveCachedToken(fresh);
16
18
  return fresh.accessToken;
17
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-token.js","sourceRoot":"","sources":["../../src/auth/resolve-token.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,eAAe,EACf,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;IACvC,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,IAAI,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,OAAO,MAAM,CAAC,WAAW,CAAC;IAC5B,CAAC;IAED,sEAAsE;IACtE,gEAAgE;IAChE,2BAA2B;IAC3B,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAC;IACtC,eAAe,CAAC,KAAK,CAAC,CAAC;IACvB,OAAO,KAAK,CAAC,WAAW,CAAC;AAC3B,CAAC"}
1
+ {"version":3,"file":"resolve-token.js","sourceRoot":"","sources":["../../src/auth/resolve-token.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,eAAe,EACf,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;IACvC,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,IAAI,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,OAAO,MAAM,CAAC,WAAW,CAAC;IAC5B,CAAC;IAED,uDAAuD;IACvD,mEAAmE;IACnE,wDAAwD;IACxD,+CAA+C;IAC/C,MAAM,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC;IAChC,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IACjD,eAAe,CAAC,KAAK,CAAC,CAAC;IACvB,OAAO,KAAK,CAAC,WAAW,CAAC;AAC3B,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import * as fs from 'node:fs';
2
2
  import * as path from 'node:path';
3
+ import { spawnSync } from 'node:child_process';
3
4
  import { resolveBearerToken } from '../auth/resolve-token.js';
4
5
  import { callRemoteTool, parseStructured } from '../proxy/call-tool.js';
5
6
  import { ensureGitInstalled, git, cleanRemoteUrl } from '../git.js';
@@ -48,11 +49,52 @@ export async function runSetup(opts) {
48
49
  path: dest,
49
50
  installedAt: new Date().toISOString(),
50
51
  });
52
+ installDeps(dest);
51
53
  console.error('');
52
54
  console.error(`Done. Open the workshop:`);
53
55
  console.error(` cd ${dest}`);
54
56
  console.error(`Then start your coding agent (Claude Code, Cursor, Codex, etc.).`);
55
57
  }
58
+ /**
59
+ * Run the workshop's package install if a package.json is present, so the
60
+ * learner can run verify scripts immediately without a "node_modules is
61
+ * missing" prompt on first session start. Picks pnpm/npm/yarn from the
62
+ * lockfile present at the dest. If no lockfile, defaults to pnpm. If the
63
+ * required package manager isn't installed, surfaces a hint and continues
64
+ * — clone is still useful, the learner can install themselves.
65
+ */
66
+ function installDeps(dest) {
67
+ if (!fs.existsSync(path.join(dest, 'package.json'))) {
68
+ return;
69
+ }
70
+ const has = (f) => fs.existsSync(path.join(dest, f));
71
+ const tool = has('pnpm-lock.yaml')
72
+ ? 'pnpm'
73
+ : has('yarn.lock')
74
+ ? 'yarn'
75
+ : has('package-lock.json')
76
+ ? 'npm'
77
+ : 'pnpm';
78
+ step(`Installing dependencies (${tool} install)`);
79
+ const proc = spawnSync(tool, ['install'], {
80
+ cwd: dest,
81
+ stdio: 'inherit',
82
+ shell: process.platform === 'win32',
83
+ });
84
+ if (proc.error) {
85
+ if (proc.error.code === 'ENOENT') {
86
+ console.error(` Note: ${tool} is not installed; skipped dependency install. ` +
87
+ `Run '${tool} install' in ${dest} before starting the workshop.`);
88
+ return;
89
+ }
90
+ console.error(` Note: ${tool} install errored — ${proc.error.message}`);
91
+ return;
92
+ }
93
+ if (proc.status !== 0) {
94
+ console.error(` Note: ${tool} install exited ${proc.status}. ` +
95
+ `Re-run it manually in ${dest} if needed.`);
96
+ }
97
+ }
56
98
  /**
57
99
  * Per-phase progress line. Plain ASCII so it renders identically in TTY,
58
100
  * piped output, log files, and CI capture — no spinner, no Unicode, no
@@ -1 +1 @@
1
- {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -2,5 +2,4 @@ export declare const DEFAULT_API_URL = "https://mcp.workshop.institute";
2
2
  export declare function apiUrl(): string;
3
3
  export declare function mcpEndpoint(): string;
4
4
  export declare function landingUrl(): string;
5
- export declare function tokenExchangeUrl(): string;
6
5
  export declare function cliAuthPageUrl(): string;
package/dist/config.js CHANGED
@@ -18,9 +18,6 @@ export function landingUrl() {
18
18
  const host = api.host.replace(/^mcp[.-]/, '');
19
19
  return `${api.protocol}//${host}`;
20
20
  }
21
- export function tokenExchangeUrl() {
22
- return `${apiUrl()}/cli/token`;
23
- }
24
21
  export function cliAuthPageUrl() {
25
22
  return `${landingUrl()}/cli-auth`;
26
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,gCAAgC,CAAC;AAEhE,MAAM,UAAU,MAAM;IACpB,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,eAAe,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,GAAG,MAAM,EAAE,MAAM,CAAC;AAC3B,CAAC;AAED,wEAAwE;AACxE,oEAAoE;AACpE,4DAA4D;AAC5D,gEAAgE;AAChE,wDAAwD;AACxD,MAAM,UAAU,UAAU;IACxB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IAC7C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC9C,OAAO,GAAG,GAAG,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,GAAG,MAAM,EAAE,YAAY,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,GAAG,UAAU,EAAE,WAAW,CAAC;AACpC,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,gCAAgC,CAAC;AAEhE,MAAM,UAAU,MAAM;IACpB,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,eAAe,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,GAAG,MAAM,EAAE,MAAM,CAAC;AAC3B,CAAC;AAED,wEAAwE;AACxE,oEAAoE;AACpE,4DAA4D;AAC5D,gEAAgE;AAChE,wDAAwD;AACxD,MAAM,UAAU,UAAU;IACxB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IAC7C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC9C,OAAO,GAAG,GAAG,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,GAAG,UAAU,EAAE,WAAW,CAAC;AACpC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@learning-with-court/cli",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "CLI for learning-with-court — proxies MCP and bootstraps workshop projects.",
5
5
  "type": "module",
6
6
  "main": "dist/cli.js",
@@ -1,6 +0,0 @@
1
- export declare function generateState(): string;
2
- export interface PkcePair {
3
- codeVerifier: string;
4
- codeChallenge: string;
5
- }
6
- export declare function generatePkcePair(): PkcePair;
package/dist/auth/pkce.js DELETED
@@ -1,13 +0,0 @@
1
- import { createHash, randomBytes } from 'node:crypto';
2
- // 32 random bytes → 43-char base64url string. Matches the inputs the
3
- // platform's /cli/authorize and /cli/token endpoints validate against
4
- // (see docs/features/own-cli-auth-flow/plan.md, Phase 1).
5
- export function generateState() {
6
- return randomBytes(32).toString('base64url');
7
- }
8
- export function generatePkcePair() {
9
- const codeVerifier = randomBytes(32).toString('base64url');
10
- const codeChallenge = createHash('sha256').update(codeVerifier).digest('base64url');
11
- return { codeVerifier, codeChallenge };
12
- }
13
- //# sourceMappingURL=pkce.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pkce.js","sourceRoot":"","sources":["../../src/auth/pkce.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEtD,qEAAqE;AACrE,sEAAsE;AACtE,0DAA0D;AAE1D,MAAM,UAAU,aAAa;IAC3B,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC/C,CAAC;AAOD,MAAM,UAAU,gBAAgB;IAC9B,MAAM,YAAY,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC3D,MAAM,aAAa,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACpF,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC;AACzC,CAAC"}