crosscheck-cli 0.0.62 → 0.0.64
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/activate.d.ts +55 -0
- package/dist/activate.js +8 -2
- package/dist/activate.js.map +1 -1
- package/dist/cli-enterprise.d.ts +11 -0
- package/dist/cli.d.ts +8 -0
- package/dist/config.d.ts +55 -0
- package/dist/config.js +1 -1
- package/dist/doctor.d.ts +13 -0
- package/dist/engine-version.d.ts +27 -0
- package/dist/enterprise/compliance.d.ts +20 -0
- package/dist/enterprise/doctor.d.ts +17 -0
- package/dist/enterprise/install.d.ts +13 -0
- package/dist/enterprise/keys-setup.d.ts +8 -0
- package/dist/enterprise/login.d.ts +8 -0
- package/dist/enterprise/policy.d.ts +26 -0
- package/dist/explain.d.ts +38 -0
- package/dist/fingerprint.d.ts +31 -0
- package/dist/heartbeat.d.ts +32 -0
- package/dist/http.d.ts +33 -0
- package/dist/install.d.ts +19 -0
- package/dist/jwt.d.ts +35 -0
- package/dist/key-format.d.ts +40 -0
- package/dist/key-status-signing.d.ts +25 -0
- package/dist/key-status.d.ts +61 -0
- package/dist/key-verify.d.ts +31 -0
- package/dist/key-verify.js +7 -3
- package/dist/key-verify.js.map +1 -1
- package/dist/keychain.d.ts +120 -0
- package/dist/keys-browser-flow.d.ts +68 -0
- package/dist/keys-manage-cli.d.ts +11 -0
- package/dist/keys-session.d.ts +89 -0
- package/dist/keys-setup.d.ts +38 -0
- package/dist/lib.d.ts +45 -0
- package/dist/lib.js +57 -0
- package/dist/lib.js.map +1 -0
- package/dist/mcp-register.d.ts +49 -0
- package/dist/mcp.d.ts +24 -0
- package/dist/model-policy.d.ts +44 -0
- package/dist/model-prefs.d.ts +104 -0
- package/dist/model-resolve.d.ts +61 -0
- package/dist/models-cli.d.ts +11 -0
- package/dist/onepassword/browser-flow.d.ts +35 -0
- package/dist/onepassword/config.d.ts +53 -0
- package/dist/onepassword/op.d.ts +54 -0
- package/dist/onepassword/reference.d.ts +29 -0
- package/dist/onepassword/setup.d.ts +54 -0
- package/dist/open-browser.d.ts +6 -0
- package/dist/otel-setup.d.ts +69 -0
- package/dist/pref-conflicts.d.ts +36 -0
- package/dist/reconcile.d.ts +59 -0
- package/dist/signing.d.ts +48 -0
- package/dist/single-instance.d.ts +97 -0
- package/dist/telemetry.d.ts +25 -0
- package/dist/update-check.d.ts +17 -0
- package/package.json +14 -3
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Activation. Two paths:
|
|
3
|
+
*
|
|
4
|
+
* 1. Device-authorization grant (RFC 8628) — new default. Run with no
|
|
5
|
+
* argument: `crosscheck activate`
|
|
6
|
+
* Prints a URL + short user-code; polls /api/crosscheck/cli/token
|
|
7
|
+
* until the user authorizes in their browser; stores the resulting
|
|
8
|
+
* JWT + signing keys in the OS keychain. This is what `gh auth
|
|
9
|
+
* login` / `vercel login` do; eliminates the "paste a 256-char
|
|
10
|
+
* base64 token into your terminal" friction wall.
|
|
11
|
+
*
|
|
12
|
+
* 2. Legacy single-use token paste — kept alive for backwards
|
|
13
|
+
* compatibility with the old install flow:
|
|
14
|
+
* `crosscheck activate <TOKEN>`
|
|
15
|
+
* Will be removed in a future release.
|
|
16
|
+
*
|
|
17
|
+
* Both paths end with the same artifacts in the keychain:
|
|
18
|
+
* - jwt (Ed25519-signed activation JWT)
|
|
19
|
+
* - jwtJti (revocation handle)
|
|
20
|
+
* - jwtPublicKey (key used to verify the JWT — comes from server)
|
|
21
|
+
* - hmacSigningKey (per-seat key for signing telemetry events)
|
|
22
|
+
*/
|
|
23
|
+
/** Public entry point. With no token, runs the device flow. */
|
|
24
|
+
export declare function activate(token?: string): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Device-flow activation. Prints a URL + user-code, polls until the user
|
|
27
|
+
* authorizes in their browser, then stores artifacts in the keychain.
|
|
28
|
+
*
|
|
29
|
+
* Polling resilience (per Matt's panel review): network errors retry with
|
|
30
|
+
* backoff and don't terminate the flow. Only `expired`, `denied`, and
|
|
31
|
+
* `already_consumed` are terminal.
|
|
32
|
+
*/
|
|
33
|
+
export declare function activateDeviceFlow(opts?: {
|
|
34
|
+
/** Extra query params appended to the /cli/start verification URL — used by
|
|
35
|
+
* `install` to pass a loopback callback + state + provider list so the same
|
|
36
|
+
* browser session also collects provider keys (one visit, not two). */
|
|
37
|
+
extraVerifyParams?: Record<string, string>;
|
|
38
|
+
/** crosscheck-enterprise only: point the browser step at
|
|
39
|
+
* /enterprise/sso/start instead of the server-provided /cli/start. The
|
|
40
|
+
* device-code/poll/JWT mechanics underneath are completely unchanged —
|
|
41
|
+
* only which page confirms the code differs. */
|
|
42
|
+
verificationUrlOverride?: string;
|
|
43
|
+
/** Called once the device code exists, instead of printing to the console.
|
|
44
|
+
* A GUI host (Crosscheck Desktop) renders the code and URL in its own
|
|
45
|
+
* window; a terminal is not the only place this flow can happen. When
|
|
46
|
+
* omitted, the console output below is unchanged. */
|
|
47
|
+
onPrompt?: (info: {
|
|
48
|
+
verifyUrl: string;
|
|
49
|
+
userCode: string;
|
|
50
|
+
expiresIn: number;
|
|
51
|
+
}) => void;
|
|
52
|
+
/** Set false to suppress the automatic browser launch — a GUI host may want
|
|
53
|
+
* to show the code first and let the user press a button. */
|
|
54
|
+
autoOpenBrowser?: boolean;
|
|
55
|
+
}): Promise<void>;
|
package/dist/activate.js
CHANGED
|
@@ -93,8 +93,14 @@ export async function activateDeviceFlow(opts) {
|
|
|
93
93
|
parts.push(`${encodeURIComponent(k)}=${encodeURIComponent(v)}`);
|
|
94
94
|
}
|
|
95
95
|
const verifyUrl = `${opts?.verificationUrlOverride ?? start.verificationUrl}?${parts.join("&")}`;
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
if (opts?.onPrompt) {
|
|
97
|
+
opts.onPrompt({ verifyUrl, userCode: start.userCode, expiresIn: start.expiresIn });
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
printActivationPrompt(verifyUrl, start.userCode, start.expiresIn);
|
|
101
|
+
}
|
|
102
|
+
if (opts?.autoOpenBrowser !== false)
|
|
103
|
+
openBrowser(verifyUrl);
|
|
98
104
|
// Compute the machine fingerprint once and send it on every poll so the
|
|
99
105
|
// device-flow activation carries the same identity as the legacy flow
|
|
100
106
|
// (enables revocation + the server's seat-in-use guard).
|
package/dist/activate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activate.js","sourceRoot":"","sources":["../src/activate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAgC1B,2DAA2D;AAC3D,KAAK,UAAU,iBAAiB,CAAC,CAAkB;IACjD,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,SAAS,CAAC,gBAAgB,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC;IACpD,MAAM,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,CAAC,CAAC,YAAY,EAAE,CAAC;QACnB,MAAM,SAAS,CAAC,cAAc,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;IAClD,CAAC;AACH,CAAC;AAED,+DAA+D;AAC/D,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,KAAc;IAC3C,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QAChC,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,kBAAkB,EAAE,CAAC;AAC9B,CAAC;AAED,sEAAsE;AACtE,KAAK,UAAU,cAAc,CAAC,KAAa;IACzC,MAAM,eAAe,GAAG,MAAM,sBAAsB,EAAE,CAAC;IACvD,MAAM,WAAW,GAAG,MAAM,sBAAsB,EAAE,CAAC;IACnD,MAAM,UAAU,GAAG,cAAc,EAAE,CAAC;IAEpC,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,UAAU,0BAA0B,EAAE;QACjE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,eAAe,EAAE,KAAK;YACtB,eAAe;YACf,WAAW;YACX,UAAU;SACX,CAAC;KACH,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAmB,CAAC;IACvD,IAAI,GAAG,CAAC,UAAU,KAAK,GAAG,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QAC1D,MAAM,KAAK,GACT,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE;YACtB,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAC1D,CAAC,CAAC,QAAQ,GAAG,CAAC,UAAU,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,sBAAsB,KAAK,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC9B,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC,4BAA4B,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;AACxF,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,
|
|
1
|
+
{"version":3,"file":"activate.js","sourceRoot":"","sources":["../src/activate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* crosscheck-enterprise CLI entry point. Deliberately a much smaller command
|
|
4
|
+
* surface than the standard crosscheck-cli's cli.ts — no `keys store`
|
|
5
|
+
* (file/keychain), no `keys add|remove` free-for-all, no `--backend`
|
|
6
|
+
* choice, no Google-OAuth activate/login. Every one of those omissions is
|
|
7
|
+
* the point, not an oversight: this bin only ever signs in via the org's
|
|
8
|
+
* SSO and only ever stores keys in 1Password, restricted to whatever the
|
|
9
|
+
* org admin has currently allowed (see /account/enterprise).
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Crosscheck (XC) CLI entry point. Minimal argument parser — subcommand and
|
|
4
|
+
* positional/named args. We don't pull in a heavyweight CLI library in the
|
|
5
|
+
* skeleton; if richer help text or interactive flows are needed later,
|
|
6
|
+
* commander or yargs slots in here.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile-time constants. Override the server base URL via the
|
|
3
|
+
* CROSSCHECK_SERVER environment variable for local development against a
|
|
4
|
+
* preview deployment. The Ed25519 public key is embedded at build time so
|
|
5
|
+
* the CLI can verify JWTs offline.
|
|
6
|
+
*/
|
|
7
|
+
export declare const SERVER_URL: string;
|
|
8
|
+
/** npm package name of this CLI — used when self-registering the MCP server. */
|
|
9
|
+
export declare const CLI_PACKAGE = "crosscheck-cli";
|
|
10
|
+
/** This CLI's own version, read from package.json at runtime. Used by the
|
|
11
|
+
* serve-time update check to compare against the npm `latest` dist-tag. */
|
|
12
|
+
export declare const CLI_VERSION: string;
|
|
13
|
+
/**
|
|
14
|
+
* npm package name of the TypeScript MCP engine the CLI runs. The CLI is the
|
|
15
|
+
* license/onboarding wrapper; crosscheck-mcp is the engine (formerly a bundled
|
|
16
|
+
* Python server — now pure TypeScript, shipped as a normal npm dependency).
|
|
17
|
+
*/
|
|
18
|
+
export declare const ENGINE_PACKAGE = "crosscheck-mcp";
|
|
19
|
+
/**
|
|
20
|
+
* Engine version the npx fallback pins to. We never float the fallback to
|
|
21
|
+
* `@latest`: that drifts past the version this CLI was built/tested against
|
|
22
|
+
* and triggers a fresh native rebuild in a throwaway npx cache (the failure
|
|
23
|
+
* mode behind "MCP error -32000: Connection closed" on some machines). Keep
|
|
24
|
+
* this in lockstep with the `crosscheck-mcp` dependency in package.json.
|
|
25
|
+
*/
|
|
26
|
+
export declare const ENGINE_FALLBACK_VERSION = "0.2.25";
|
|
27
|
+
/**
|
|
28
|
+
* Ed25519 public key (PEM, SPKI) used to verify activation JWTs. This is
|
|
29
|
+
* replaced at build time by the publish pipeline with the public half of
|
|
30
|
+
* the keypair produced by scripts/generate-cb-secrets.ts on the server.
|
|
31
|
+
*
|
|
32
|
+
* For local dev: set CROSSCHECK_JWT_PUBLIC_KEY in the environment.
|
|
33
|
+
*/
|
|
34
|
+
export declare const EMBEDDED_PUBLIC_KEY_PEM: string;
|
|
35
|
+
/**
|
|
36
|
+
* OS keychain service identifier. Stored entries:
|
|
37
|
+
* - "jwt" → the activation JWT (rotates ~weekly)
|
|
38
|
+
* - "hmacSigningKey" → per-seat HMAC key from /activate
|
|
39
|
+
* - "key:anthropic" / "key:openai" / "key:gemini" / "key:grok"
|
|
40
|
+
* → user-supplied upstream LLM keys
|
|
41
|
+
* - "installUuid" → stable UUID generated at first run
|
|
42
|
+
*/
|
|
43
|
+
export declare const KEYCHAIN_SERVICE = "crosscheck";
|
|
44
|
+
/**
|
|
45
|
+
* Heartbeat cadence. Matches the server's 24h refreshAt / 7d exp / 72h
|
|
46
|
+
* fail-open grace. Configurable for tests.
|
|
47
|
+
*/
|
|
48
|
+
export declare const HEARTBEAT_INTERVAL_MS: number;
|
|
49
|
+
export declare const HEARTBEAT_FAIL_OPEN_MS: number;
|
|
50
|
+
/**
|
|
51
|
+
* Telemetry batch flush. Events accumulate in memory and POST in batches
|
|
52
|
+
* up to 100 events or 30 seconds, whichever comes first.
|
|
53
|
+
*/
|
|
54
|
+
export declare const TELEMETRY_BATCH_SIZE = 50;
|
|
55
|
+
export declare const TELEMETRY_FLUSH_MS = 30000;
|
package/dist/config.js
CHANGED
|
@@ -31,7 +31,7 @@ export const ENGINE_PACKAGE = "crosscheck-mcp";
|
|
|
31
31
|
* mode behind "MCP error -32000: Connection closed" on some machines). Keep
|
|
32
32
|
* this in lockstep with the `crosscheck-mcp` dependency in package.json.
|
|
33
33
|
*/
|
|
34
|
-
export const ENGINE_FALLBACK_VERSION = "0.2.
|
|
34
|
+
export const ENGINE_FALLBACK_VERSION = "0.2.25";
|
|
35
35
|
/**
|
|
36
36
|
* Ed25519 public key (PEM, SPKI) used to verify activation JWTs. This is
|
|
37
37
|
* replaced at build time by the publish pipeline with the public half of
|
package/dist/doctor.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `crosscheck doctor` — diagnose a broken install without guessing.
|
|
3
|
+
*
|
|
4
|
+
* Prints a checklist and exits non-zero if a CRITICAL check fails, so users
|
|
5
|
+
* (and support) get an actionable cause instead of Claude Code's bare
|
|
6
|
+
* "-32000: Connection closed". Each check is independent and never throws —
|
|
7
|
+
* a thrown check is reported as a failure, not a crash.
|
|
8
|
+
*/
|
|
9
|
+
export type Level = "ok" | "warn" | "fail";
|
|
10
|
+
export declare function line(level: Level, msg: string): void;
|
|
11
|
+
export declare function runDoctor(): Promise<{
|
|
12
|
+
critical: number;
|
|
13
|
+
}>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the crosscheck-mcp engine version this process is actually RUNNING
|
|
3
|
+
* — for diagnostics (heartbeat reporting) only, never for launch decisions
|
|
4
|
+
* (mcp.ts's resolveEngineLauncher is the source of truth there).
|
|
5
|
+
*
|
|
6
|
+
* MEMOIZED, AND THAT IS THE POINT. `serve` is a long-lived process that
|
|
7
|
+
* loaded the engine once at startup, but the file it loaded from is an npx
|
|
8
|
+
* cache directory that a later `npx crosscheck-cli@latest` overwrites in
|
|
9
|
+
* place. Re-reading package.json on every heartbeat therefore reported the
|
|
10
|
+
* version on DISK while the process kept executing the code it had already
|
|
11
|
+
* loaded — so a server running a five-day-old engine cheerfully reported
|
|
12
|
+
* itself as current.
|
|
13
|
+
*
|
|
14
|
+
* That is not a cosmetic reporting bug. It is why a GPT-6 Astra failure went
|
|
15
|
+
* unexplained for days: the dashboard said the engine was new enough to have
|
|
16
|
+
* the fix, the process was not, and nothing anywhere could see the gap.
|
|
17
|
+
* Reading once, at startup, means the reported version is the version whose
|
|
18
|
+
* code is running.
|
|
19
|
+
*
|
|
20
|
+
* Can't `require.resolve(`${ENGINE_PACKAGE}/package.json`)` directly — the
|
|
21
|
+
* engine's "exports" map only exposes ".", so that subpath throws on Node
|
|
22
|
+
* ≥18 (see mcp.ts). Instead resolve the main entry (dist/<entry>.cjs) and
|
|
23
|
+
* walk up two directories to the package root.
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveEngineVersion(): string;
|
|
26
|
+
/** Test seam only — lets a test observe that the value is pinned. */
|
|
27
|
+
export declare function __resetEngineVersionCache(): void;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared compliance check: is this machine actually doing what its org's
|
|
3
|
+
* enterprise policy requires? Used by both `doctor` (human-readable report)
|
|
4
|
+
* and the heartbeat self-report (the one signal that can trigger a
|
|
5
|
+
* server-side revocation — see crosscheck-site's decidePolicyCompliance).
|
|
6
|
+
*
|
|
7
|
+
* Compliant means BOTH:
|
|
8
|
+
* 1. The secret backend is 1password-only (no local file/keychain keys).
|
|
9
|
+
* 2. Every locally-configured provider key is on the org's current
|
|
10
|
+
* allowlist (no leftover key for a provider the admin has since
|
|
11
|
+
* disabled).
|
|
12
|
+
*/
|
|
13
|
+
import { type ProviderPolicy } from "./policy.js";
|
|
14
|
+
export type ComplianceReport = {
|
|
15
|
+
compliant: boolean;
|
|
16
|
+
policy: ProviderPolicy | null;
|
|
17
|
+
backendOk: boolean;
|
|
18
|
+
outOfPolicyProviders: string[];
|
|
19
|
+
};
|
|
20
|
+
export declare function checkCompliance(jwt: string): Promise<ComplianceReport>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* crosscheck-enterprise-only doctor checks, run in addition to the shared
|
|
3
|
+
* runDoctor() checks (Node version, secret store, activation, etc.). Two
|
|
4
|
+
* things the standard CLI has no concept of, both computed by the shared
|
|
5
|
+
* checkCompliance() helper (also used by the heartbeat self-report):
|
|
6
|
+
*
|
|
7
|
+
* 1. Is the 1Password-only backend actually active? (Not just configured
|
|
8
|
+
* — actually the CURRENT backend. A user who somehow ran the legacy
|
|
9
|
+
* `--backend 1password` flow is caught here, not silently accepted.)
|
|
10
|
+
* 2. Are locally-configured provider keys a subset of the org's current
|
|
11
|
+
* allowlist? A key left over from before an admin disabled a provider
|
|
12
|
+
* would otherwise sit there unnoticed until the next `serve` filters
|
|
13
|
+
* it out anyway — this surfaces it explicitly.
|
|
14
|
+
*/
|
|
15
|
+
export declare function runEnterpriseDoctorChecks(): Promise<{
|
|
16
|
+
critical: number;
|
|
17
|
+
}>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `crosscheck-enterprise install` — the enterprise analog of install.ts's
|
|
3
|
+
* runInstall(): activate/sign-in, set up keys, register the MCP server.
|
|
4
|
+
* Idempotent, same as the standard install (safe to re-run).
|
|
5
|
+
*
|
|
6
|
+
* Differences from the standard flow, by design (see the org bootstrap
|
|
7
|
+
* model in schema.ts): sign-in is always SSO (enterpriseLogin, never
|
|
8
|
+
* Google), and keys setup is always the restricted 1Password-only wizard
|
|
9
|
+
* scoped to the org's current provider allowlist — there is no "skip keys,
|
|
10
|
+
* add later" shortcut here the way the standard flow has, because without
|
|
11
|
+
* at least one allowed provider mapped there's nothing this bin can do.
|
|
12
|
+
*/
|
|
13
|
+
export declare function runEnterpriseInstall(): Promise<void>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `crosscheck-enterprise keys setup` — 1Password-only, restricted to the
|
|
3
|
+
* org's currently-allowed providers. Unlike the standard CLI's `keys setup`,
|
|
4
|
+
* there is no file/keychain option to fall back to, and no `--backend`
|
|
5
|
+
* choice: this bin only ever wires 1Password, and only ever offers
|
|
6
|
+
* providers the org admin has enabled (see /account/enterprise).
|
|
7
|
+
*/
|
|
8
|
+
export declare function runEnterpriseOnePasswordKeysSetup(): Promise<void>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `crosscheck-enterprise login` — same device-code/poll/JWT mechanics as
|
|
3
|
+
* the standard CLI's activate flow (activateDeviceFlow), just pointed at
|
|
4
|
+
* /enterprise/sso/start instead of the server-provided /cli/start. That
|
|
5
|
+
* page collects the work email and routes to the org's own Okta/Entra —
|
|
6
|
+
* there is no Google OAuth path in this bin at all.
|
|
7
|
+
*/
|
|
8
|
+
export declare function enterpriseLogin(): Promise<void>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider-policy fetch + cache for crosscheck-enterprise. Deliberately
|
|
3
|
+
* fails RESTRICTIVE (last-known-good cached policy, or an empty allowlist
|
|
4
|
+
* if there's no cache at all) rather than fail-open — the opposite
|
|
5
|
+
* fail-direction from heartbeat's entitlement grace window, on purpose:
|
|
6
|
+
* staying open is safe for "are you still a paying customer," staying
|
|
7
|
+
* restricted is safe for "which providers is this org allowed to use."
|
|
8
|
+
*/
|
|
9
|
+
import type { ModelPolicy } from "../model-policy.js";
|
|
10
|
+
export type ProviderPolicy = {
|
|
11
|
+
version: number;
|
|
12
|
+
allowedProviders: readonly string[];
|
|
13
|
+
/** Per-provider model allow/deny, additive on top of allowedProviders.
|
|
14
|
+
* Absent (undefined) or missing a given provider means no model-level
|
|
15
|
+
* restriction for that provider — only the provider-level allowlist
|
|
16
|
+
* above applies. Optional so an older cached policy.json (pre-model-
|
|
17
|
+
* policy) still parses. */
|
|
18
|
+
modelPolicy?: ModelPolicy;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Fetch the current policy from the server, falling back to the cached
|
|
22
|
+
* last-known-good policy on any failure (network, non-200, malformed body).
|
|
23
|
+
* Returns null only when there's neither a live fetch NOR a cache — the
|
|
24
|
+
* caller should treat that as "no providers allowed" (see mcp.ts).
|
|
25
|
+
*/
|
|
26
|
+
export declare function fetchProviderPolicy(jwt: string): Promise<ProviderPolicy | null>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `crosscheck explain` — verify a cost figure on your own machine.
|
|
3
|
+
*
|
|
4
|
+
* The server stores opaque fingerprints; the laptop stores the mapping from
|
|
5
|
+
* fingerprint to branch name. This command is where the two meet, and it is
|
|
6
|
+
* the whole answer to "how do I know that number is real?" — a developer can
|
|
7
|
+
* check every dollar attributed to them without the server ever having learned
|
|
8
|
+
* what they were building.
|
|
9
|
+
*
|
|
10
|
+
* It prints only what it can actually stand behind: buckets the server has
|
|
11
|
+
* numbers for, joined to local labels where the local map has them, and an
|
|
12
|
+
* explicit note where it doesn't. No estimating, no filling in gaps.
|
|
13
|
+
*/
|
|
14
|
+
type LocalEntry = {
|
|
15
|
+
label: string;
|
|
16
|
+
lastSeen: string;
|
|
17
|
+
};
|
|
18
|
+
type LocalMap = Record<string, LocalEntry>;
|
|
19
|
+
export type ServerBucket = {
|
|
20
|
+
fingerprint: string;
|
|
21
|
+
kind: "feature" | "maintenance";
|
|
22
|
+
label: string | null;
|
|
23
|
+
panelRuns: number;
|
|
24
|
+
panelCostUsd: number;
|
|
25
|
+
hostTokens: number;
|
|
26
|
+
hostCostUsd: number;
|
|
27
|
+
totalCostUsd: number;
|
|
28
|
+
sharedCostUsd?: number;
|
|
29
|
+
};
|
|
30
|
+
export declare function localFeatureMap(dir?: string): LocalMap;
|
|
31
|
+
/**
|
|
32
|
+
* Render the joined view. Pure, so the formatting is testable without a
|
|
33
|
+
* network or a home directory.
|
|
34
|
+
*/
|
|
35
|
+
export declare function renderExplain(buckets: ServerBucket[], local: LocalMap): string;
|
|
36
|
+
/** Fetch buckets for this seat and print the joined view. */
|
|
37
|
+
export declare function explain(): Promise<number>;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Privacy-preserving machine fingerprint. Hashed with scrypt (Node built-in):
|
|
3
|
+
*
|
|
4
|
+
* fingerprint = scrypt(machine-id || install-uuid || os-platform, fixedSalt)
|
|
5
|
+
*
|
|
6
|
+
* The same inputs always produce the same hash (fixed salt). The hash is not
|
|
7
|
+
* reversible to PII — it's only useful as a stable identifier for
|
|
8
|
+
* re-activation flows. NEVER raw MAC address, serial number, or hardware UUID
|
|
9
|
+
* — those are PII and unstable across OS updates.
|
|
10
|
+
*
|
|
11
|
+
* Uses Node's built-in crypto (no native dependency) — the fingerprint is a
|
|
12
|
+
* stable, non-secret identifier the server simply stores, so a slow password
|
|
13
|
+
* KDF (argon2) was unnecessary and added a node-gyp build step.
|
|
14
|
+
*
|
|
15
|
+
* The `installUuid` is generated once at first run and stored in the OS
|
|
16
|
+
* keychain so subsequent invocations on the same install yield the same
|
|
17
|
+
* fingerprint even if the machine-id rotates.
|
|
18
|
+
*/
|
|
19
|
+
export type OsPlatform = "darwin" | "linux" | "win32" | "other";
|
|
20
|
+
export declare function detectPlatform(): OsPlatform;
|
|
21
|
+
export declare function getOrCreateInstallUuid(): Promise<string>;
|
|
22
|
+
/**
|
|
23
|
+
* Best-effort machine identifier. Falls back to a stable hash of OS +
|
|
24
|
+
* hostname if a true machine-id is unavailable.
|
|
25
|
+
*/
|
|
26
|
+
export declare function getMachineId(): string;
|
|
27
|
+
/**
|
|
28
|
+
* Compute the fingerprint hash. scrypt with the fixed salt so the result is
|
|
29
|
+
* deterministic for the same machine and the server can just store the string.
|
|
30
|
+
*/
|
|
31
|
+
export declare function computeFingerprintHash(): Promise<string>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heartbeat scheduler. Runs every 24h from a long-lived `crosscheck serve`
|
|
3
|
+
* process; tolerates up to 72h of network failure before locking the CLI
|
|
4
|
+
* out (matches the server's grace window).
|
|
5
|
+
*
|
|
6
|
+
* On `status: "revoked"` the CLI must refuse to make further calls and
|
|
7
|
+
* surface the reason ("your subscription was canceled", "this machine was
|
|
8
|
+
* deactivated from the dashboard", etc.) — heartbeat is the only way the
|
|
9
|
+
* server gets to revoke a seat that's already activated.
|
|
10
|
+
*/
|
|
11
|
+
type HeartbeatResponse = {
|
|
12
|
+
status: "ok" | "revoked" | "past_due";
|
|
13
|
+
reason?: string;
|
|
14
|
+
refreshJwt?: string;
|
|
15
|
+
refreshAt?: string;
|
|
16
|
+
expiresAt?: string;
|
|
17
|
+
};
|
|
18
|
+
export type HeartbeatState = {
|
|
19
|
+
lastOkAt: number | null;
|
|
20
|
+
status: "ok" | "revoked" | "past_due";
|
|
21
|
+
message: string | null;
|
|
22
|
+
};
|
|
23
|
+
export declare function currentState(): HeartbeatState;
|
|
24
|
+
export declare function isAllowedToRun(now?: number): boolean;
|
|
25
|
+
export declare function runHeartbeat(opts?: {
|
|
26
|
+
checkPolicyCompliance?: boolean;
|
|
27
|
+
}): Promise<HeartbeatResponse>;
|
|
28
|
+
/** Long-running scheduler. Returns a stop fn. */
|
|
29
|
+
export declare function startScheduler(opts?: {
|
|
30
|
+
checkPolicyCompliance?: boolean;
|
|
31
|
+
}): () => void;
|
|
32
|
+
export {};
|
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal HTTP helper built on Node's global `fetch` (stable in Node 18+).
|
|
3
|
+
*
|
|
4
|
+
* Why not undici: undici@7 hard-requires Node >= 20.18.1 and crashes on import
|
|
5
|
+
* on slightly older Node 20.x — and its `request()` does NOT follow 3xx
|
|
6
|
+
* redirects on POST, so an apex→www 308 made every activation call read a
|
|
7
|
+
* "Redirecting…" HTML body and fail to parse as JSON. Global `fetch` is built
|
|
8
|
+
* in (no dependency, works on Node 18+) and follows redirects by default.
|
|
9
|
+
*
|
|
10
|
+
* The returned shape intentionally mirrors the slice of undici's `request`
|
|
11
|
+
* response this CLI used (`statusCode`, `body.json()`, `body.text()`) so call
|
|
12
|
+
* sites didn't have to change.
|
|
13
|
+
*/
|
|
14
|
+
type RequestOpts = {
|
|
15
|
+
method?: string;
|
|
16
|
+
headers?: Record<string, string>;
|
|
17
|
+
body?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Abort after this many ms. Opt-in, because most calls here are user-
|
|
20
|
+
* initiated and would rather wait than fail. Startup-path calls are the
|
|
21
|
+
* exception: on that path a hanging server must not hold up an MCP
|
|
22
|
+
* connection, so those pass a bound.
|
|
23
|
+
*/
|
|
24
|
+
timeoutMs?: number;
|
|
25
|
+
};
|
|
26
|
+
export declare function request(url: string, opts?: RequestOpts): Promise<{
|
|
27
|
+
statusCode: number;
|
|
28
|
+
body: {
|
|
29
|
+
json: () => Promise<unknown>;
|
|
30
|
+
text: () => Promise<string>;
|
|
31
|
+
};
|
|
32
|
+
}>;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One-command install orchestrator — the path documented for Claude Code in
|
|
3
|
+
* VS Code. Run as `npx -y crosscheck-cli@latest install` (Claude Code will
|
|
4
|
+
* run this for you when you ask it to "Install Crosscheck").
|
|
5
|
+
*
|
|
6
|
+
* Steps:
|
|
7
|
+
* 1. Node version sanity check.
|
|
8
|
+
* 2. Activate + add provider keys. For a first-time install this is ONE
|
|
9
|
+
* browser session: the keys loopback is started, device-auth opens
|
|
10
|
+
* /cli/start with the loopback params, and after authorization the same
|
|
11
|
+
* page collects all provider keys. Env-present keys are imported first;
|
|
12
|
+
* already-activated machines just top up missing keys.
|
|
13
|
+
* 3. Register the MCP server with Claude Code (user scope), then next steps.
|
|
14
|
+
*
|
|
15
|
+
* Fully non-interactive (never reads stdin) and idempotent — re-running
|
|
16
|
+
* `crosscheck install` is safe, and a skipped/timed-out keys step still leaves
|
|
17
|
+
* activation intact (run `crosscheck keys setup` later).
|
|
18
|
+
*/
|
|
19
|
+
export declare function runInstall(): Promise<void>;
|
package/dist/jwt.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local Ed25519 JWT verification. The activation flow stores the JWT in the
|
|
3
|
+
* keychain along with the public key that signed it; every subsequent CLI
|
|
4
|
+
* invocation parses + verifies it locally with the keychain-stored public
|
|
5
|
+
* key before making any privileged decision (e.g., whether to keep running,
|
|
6
|
+
* whether to refresh on heartbeat).
|
|
7
|
+
*
|
|
8
|
+
* No network round-trip on the hot path — heartbeats are scheduled, not
|
|
9
|
+
* per-call. This is the offline-tolerance the design depends on.
|
|
10
|
+
*
|
|
11
|
+
* Public-key source precedence:
|
|
12
|
+
* 1. Keychain entry "jwtPublicKey" (set by activate.ts on first activation)
|
|
13
|
+
* 2. CROSSCHECK_JWT_PUBLIC_KEY env var (dev override)
|
|
14
|
+
* 3. Fall back to bundled config.ts constant (empty by default; deprecated)
|
|
15
|
+
*
|
|
16
|
+
* verifyJwt is async because it reads from the OS keychain. Callers must
|
|
17
|
+
* await it. The first call caches the resolved KeyObject in memory.
|
|
18
|
+
*/
|
|
19
|
+
export type CodybuildJwtPayload = {
|
|
20
|
+
sub: string;
|
|
21
|
+
seatId: string;
|
|
22
|
+
orgId: string;
|
|
23
|
+
fp: string;
|
|
24
|
+
iat: number;
|
|
25
|
+
exp: number;
|
|
26
|
+
refreshAt: number;
|
|
27
|
+
jti: string;
|
|
28
|
+
};
|
|
29
|
+
export declare function verifyJwt(jwt: string): Promise<{
|
|
30
|
+
ok: true;
|
|
31
|
+
payload: CodybuildJwtPayload;
|
|
32
|
+
} | {
|
|
33
|
+
ok: false;
|
|
34
|
+
reason: string;
|
|
35
|
+
}>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider key-format helpers — used to (a) catch obvious paste mistakes
|
|
3
|
+
* (someone pasting an org id, an email, a truncated key, or the wrong
|
|
4
|
+
* provider's key) before we store a dud, and (b) map intuitive provider
|
|
5
|
+
* aliases (e.g. `xai`) to the canonical internal id (`grok`).
|
|
6
|
+
*
|
|
7
|
+
* Patterns are deliberately loose (prefix + min length) so a provider tweaking
|
|
8
|
+
* the tail of their key format doesn't lock users out — they're a sanity check,
|
|
9
|
+
* not a cryptographic gate. Keep in lockstep with the site's provider-fields.ts.
|
|
10
|
+
*/
|
|
11
|
+
/** Canonical internal provider ids (what the keychain + engine use). */
|
|
12
|
+
export declare const CANONICAL_PROVIDERS: readonly ["anthropic", "openai", "gemini", "grok", "groq", "deepseek", "mistral", "kimi", "qwen"];
|
|
13
|
+
/** Resolve an alias (or canonical id) to the canonical provider id, or null
|
|
14
|
+
* if it's neither. */
|
|
15
|
+
export declare function resolveProvider(input: string): string | null;
|
|
16
|
+
/** Per-provider key shape: a loose validation regex + a human hint. */
|
|
17
|
+
export declare const KEY_FORMATS: Record<string, {
|
|
18
|
+
pattern: RegExp;
|
|
19
|
+
hint: string;
|
|
20
|
+
}>;
|
|
21
|
+
/** Generic "is this even an API key?" check: no whitespace, not an email,
|
|
22
|
+
* not a URL, reasonable length. Catches the most common paste mistakes
|
|
23
|
+
* regardless of provider. */
|
|
24
|
+
export declare function looksLikeApiKey(value: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* HARD validation. Only rejects things that clearly aren't an API key at all
|
|
27
|
+
* (whitespace, email, URL, far too short). Returns a message, or null when the
|
|
28
|
+
* value is plausibly a key. Deliberately does NOT enforce a provider-specific
|
|
29
|
+
* prefix — providers change their key formats over time, and we must never
|
|
30
|
+
* hard-block a key the user says is correct. Prefix/shape mismatches are
|
|
31
|
+
* surfaced as a non-blocking warning via `formatWarning` instead.
|
|
32
|
+
*/
|
|
33
|
+
export declare function validateKey(provider: string, value: string): string | null;
|
|
34
|
+
/**
|
|
35
|
+
* SOFT check: the value passes hard validation but doesn't match the provider's
|
|
36
|
+
* usual key shape (e.g. an xAI key that doesn't start with `xai-`). Returns a
|
|
37
|
+
* non-blocking warning string, or null. Callers should print it and proceed —
|
|
38
|
+
* never block on it.
|
|
39
|
+
*/
|
|
40
|
+
export declare function formatWarning(provider: string, value: string): string | null;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical signing form for key status reports.
|
|
3
|
+
*
|
|
4
|
+
* MUST stay byte-identical to src/lib/crosscheck/key-status-crypto.ts in
|
|
5
|
+
* crosscheck-site. Drift fails verification server-side, and a rejected
|
|
6
|
+
* report is indistinguishable in the UI from "this machine has no keys" —
|
|
7
|
+
* the most misleading failure this feature could have.
|
|
8
|
+
*
|
|
9
|
+
* Providers are sorted before joining: a report is a set, not a sequence, and
|
|
10
|
+
* signing it as a sequence would make verification depend on the order the
|
|
11
|
+
* key store happened to enumerate in.
|
|
12
|
+
*/
|
|
13
|
+
export type SignableKeyStatusItem = {
|
|
14
|
+
provider: string;
|
|
15
|
+
present: boolean;
|
|
16
|
+
suffix?: string;
|
|
17
|
+
lastResult?: string;
|
|
18
|
+
lastCheckedAt?: string;
|
|
19
|
+
};
|
|
20
|
+
export declare function canonicalKeyStatusBody(r: {
|
|
21
|
+
seatId: string;
|
|
22
|
+
orgId: string;
|
|
23
|
+
reportedAt: string;
|
|
24
|
+
providers: readonly SignableKeyStatusItem[];
|
|
25
|
+
}): string;
|