@kya-os/cli 1.7.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/build.js +2 -2
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/check.js +3 -3
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/checkpoint-init.d.ts +32 -0
- package/dist/commands/checkpoint-init.d.ts.map +1 -0
- package/dist/commands/checkpoint-init.js +521 -0
- package/dist/commands/checkpoint-init.js.map +1 -0
- package/dist/commands/claim.js +2 -2
- package/dist/commands/claim.js.map +1 -1
- package/dist/commands/dco.d.ts +38 -1
- package/dist/commands/dco.d.ts.map +1 -1
- package/dist/commands/dco.js +180 -7
- package/dist/commands/dco.js.map +1 -1
- package/dist/commands/dev.js +1 -1
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +18 -24
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/env.js +6 -6
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/identity.js +3 -3
- package/dist/commands/identity.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +103 -65
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/register.d.ts +1 -1
- package/dist/commands/register.d.ts.map +1 -1
- package/dist/commands/register.js +35 -7
- package/dist/commands/register.js.map +1 -1
- package/dist/commands/rotate.js +4 -4
- package/dist/commands/rotate.js.map +1 -1
- package/dist/commands/start.js +3 -3
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/status.js +1 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/verify.js +6 -6
- package/dist/commands/verify.js.map +1 -1
- package/dist/dco.d.ts +4 -0
- package/dist/dco.d.ts.map +1 -0
- package/dist/dco.js +21 -0
- package/dist/dco.js.map +1 -0
- package/dist/index.js +18 -15
- package/dist/utils/checkpoint-api.d.ts +86 -0
- package/dist/utils/checkpoint-api.d.ts.map +1 -0
- package/dist/utils/checkpoint-api.js +196 -0
- package/dist/utils/checkpoint-api.js.map +1 -0
- package/dist/utils/checkpoint-env.d.ts +23 -0
- package/dist/utils/checkpoint-env.d.ts.map +1 -0
- package/dist/utils/checkpoint-env.js +59 -0
- package/dist/utils/checkpoint-env.js.map +1 -0
- package/dist/utils/checkpoint-scaffold.d.ts +61 -0
- package/dist/utils/checkpoint-scaffold.d.ts.map +1 -0
- package/dist/utils/checkpoint-scaffold.js +268 -0
- package/dist/utils/checkpoint-scaffold.js.map +1 -0
- package/dist/utils/cli-kit/browser.d.ts +24 -0
- package/dist/utils/cli-kit/browser.d.ts.map +1 -0
- package/dist/utils/cli-kit/browser.js +58 -0
- package/dist/utils/cli-kit/browser.js.map +1 -0
- package/dist/utils/cli-kit/claim-polling.d.ts +18 -0
- package/dist/utils/cli-kit/claim-polling.d.ts.map +1 -0
- package/dist/utils/{claim-polling.js → cli-kit/claim-polling.js} +19 -26
- package/dist/utils/cli-kit/claim-polling.js.map +1 -0
- package/dist/utils/cli-kit/diagnostics.d.ts +9 -0
- package/dist/utils/cli-kit/diagnostics.d.ts.map +1 -0
- package/dist/utils/cli-kit/diagnostics.js +11 -0
- package/dist/utils/cli-kit/diagnostics.js.map +1 -0
- package/dist/utils/cli-kit/fs-safe.d.ts +14 -0
- package/dist/utils/cli-kit/fs-safe.d.ts.map +1 -0
- package/dist/utils/cli-kit/fs-safe.js +20 -0
- package/dist/utils/cli-kit/fs-safe.js.map +1 -0
- package/dist/utils/cli-kit/index.d.ts +15 -0
- package/dist/utils/cli-kit/index.d.ts.map +1 -0
- package/dist/utils/cli-kit/index.js +10 -0
- package/dist/utils/cli-kit/index.js.map +1 -0
- package/dist/utils/cli-kit/json-file.d.ts +21 -0
- package/dist/utils/cli-kit/json-file.d.ts.map +1 -0
- package/dist/utils/cli-kit/json-file.js +51 -0
- package/dist/utils/cli-kit/json-file.js.map +1 -0
- package/dist/utils/cli-kit/marker-block.d.ts +26 -0
- package/dist/utils/cli-kit/marker-block.d.ts.map +1 -0
- package/dist/utils/cli-kit/marker-block.js +61 -0
- package/dist/utils/cli-kit/marker-block.js.map +1 -0
- package/dist/utils/cli-kit/paths.d.ts +15 -0
- package/dist/utils/cli-kit/paths.d.ts.map +1 -0
- package/dist/utils/cli-kit/paths.js +21 -0
- package/dist/utils/cli-kit/paths.js.map +1 -0
- package/dist/utils/cli-kit/secure-storage.d.ts +14 -0
- package/dist/utils/cli-kit/secure-storage.d.ts.map +1 -0
- package/dist/utils/cli-kit/secure-storage.js +20 -0
- package/dist/utils/cli-kit/secure-storage.js.map +1 -0
- package/dist/utils/cli-kit/step-report.d.ts +16 -0
- package/dist/utils/cli-kit/step-report.d.ts.map +1 -0
- package/dist/utils/cli-kit/step-report.js +36 -0
- package/dist/utils/cli-kit/step-report.js.map +1 -0
- package/dist/utils/dco/agent-metadata.d.ts +1 -1
- package/dist/utils/dco/agent-metadata.js +1 -1
- package/dist/utils/dco/agent-metadata.js.map +1 -1
- package/dist/utils/dco/claude-config.d.ts +18 -8
- package/dist/utils/dco/claude-config.d.ts.map +1 -1
- package/dist/utils/dco/claude-config.js +33 -79
- package/dist/utils/dco/claude-config.js.map +1 -1
- package/dist/utils/dco/dispatch.d.ts +59 -0
- package/dist/utils/dco/dispatch.d.ts.map +1 -0
- package/dist/utils/dco/dispatch.js +332 -0
- package/dist/utils/dco/dispatch.js.map +1 -0
- package/dist/utils/dco/git-config.d.ts.map +1 -1
- package/dist/utils/dco/git-config.js +5 -3
- package/dist/utils/dco/git-config.js.map +1 -1
- package/dist/utils/dco/github.d.ts +8 -0
- package/dist/utils/dco/github.d.ts.map +1 -1
- package/dist/utils/dco/github.js +11 -0
- package/dist/utils/dco/github.js.map +1 -1
- package/dist/utils/dco/paths.d.ts +1 -8
- package/dist/utils/dco/paths.d.ts.map +1 -1
- package/dist/utils/dco/paths.js +3 -12
- package/dist/utils/dco/paths.js.map +1 -1
- package/dist/utils/dco/render.d.ts +1 -1
- package/dist/utils/dco/render.d.ts.map +1 -1
- package/dist/utils/dco/render.js +4 -21
- package/dist/utils/dco/render.js.map +1 -1
- package/dist/utils/dco/resolve-agent.d.ts +54 -0
- package/dist/utils/dco/resolve-agent.d.ts.map +1 -0
- package/dist/utils/dco/resolve-agent.js +164 -0
- package/dist/utils/dco/resolve-agent.js.map +1 -0
- package/dist/utils/dco/setup.d.ts +10 -7
- package/dist/utils/dco/setup.d.ts.map +1 -1
- package/dist/utils/dco/setup.js +304 -202
- package/dist/utils/dco/setup.js.map +1 -1
- package/dist/utils/dco/ssh-key.d.ts +13 -0
- package/dist/utils/dco/ssh-key.d.ts.map +1 -1
- package/dist/utils/dco/ssh-key.js +21 -0
- package/dist/utils/dco/ssh-key.js.map +1 -1
- package/dist/utils/dco/status.d.ts +1 -1
- package/dist/utils/dco/status.d.ts.map +1 -1
- package/dist/utils/dco/status.js +3 -3
- package/dist/utils/dco/status.js.map +1 -1
- package/dist/utils/dco/verify.d.ts +114 -0
- package/dist/utils/dco/verify.d.ts.map +1 -0
- package/dist/utils/dco/verify.js +383 -0
- package/dist/utils/dco/verify.js.map +1 -0
- package/dist/utils/gitignore.d.ts +17 -0
- package/dist/utils/gitignore.d.ts.map +1 -0
- package/dist/utils/gitignore.js +40 -0
- package/dist/utils/gitignore.js.map +1 -0
- package/dist/utils/identity-heal.d.ts +16 -0
- package/dist/utils/identity-heal.d.ts.map +1 -0
- package/dist/utils/identity-heal.js +37 -0
- package/dist/utils/identity-heal.js.map +1 -0
- package/dist/utils/poll.d.ts +50 -0
- package/dist/utils/poll.d.ts.map +1 -0
- package/dist/utils/poll.js +73 -0
- package/dist/utils/poll.js.map +1 -0
- package/package.json +4 -3
- package/dist/utils/claim-polling.d.ts +0 -21
- package/dist/utils/claim-polling.d.ts.map +0 -1
- package/dist/utils/claim-polling.js.map +0 -1
- package/dist/utils/dco/fs-safe.d.ts +0 -14
- package/dist/utils/dco/fs-safe.d.ts.map +0 -1
- package/dist/utils/dco/fs-safe.js +0 -20
- package/dist/utils/dco/fs-safe.js.map +0 -1
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client for the `kya-os checkpoint init` claim-token flow (KYA-1037).
|
|
3
|
+
*
|
|
4
|
+
* Talks to the three public Checkpoint dashboard endpoints added for this
|
|
5
|
+
* flow: register a claim token, poll its status, and exchange a claimed
|
|
6
|
+
* token for a project API key. Base URL is `CHECKPOINT_API_URL` when set,
|
|
7
|
+
* else the production dashboard origin, mirroring the `KTA_API_URL` /
|
|
8
|
+
* `KTA_BASE_URL` override pattern already used by `register.ts`/`claim.ts`
|
|
9
|
+
* for the sibling knowthat.ai claim flow.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Reconstructs the claim URL from a token alone, same shape the register
|
|
13
|
+
* endpoint itself builds (`/cli/claim?token=...` off the same base). Used
|
|
14
|
+
* only as a fallback for a marker written before this CLI persisted the
|
|
15
|
+
* server-issued `claimUrl` directly; a current run always reprints the
|
|
16
|
+
* value the server returned at register time.
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildCheckpointClaimUrl(claimToken: string): string;
|
|
19
|
+
/** The configured Checkpoint origin (protocol + host), to host-match a server-returned URL before acting on it. */
|
|
20
|
+
export declare function checkpointOrigin(): string;
|
|
21
|
+
/**
|
|
22
|
+
* True when CHECKPOINT_API_URL resolves to plain http on a non-localhost
|
|
23
|
+
* host: the claim token, and later the minted API key, cross that
|
|
24
|
+
* connection in the clear.
|
|
25
|
+
*/
|
|
26
|
+
export declare function isInsecureCheckpointOrigin(): boolean;
|
|
27
|
+
export interface CheckpointRegisterHints {
|
|
28
|
+
domainHint?: string;
|
|
29
|
+
repoName?: string;
|
|
30
|
+
framework?: "nextjs" | "express" | "static" | "unknown";
|
|
31
|
+
}
|
|
32
|
+
export interface CheckpointRegisterResult {
|
|
33
|
+
registrationId: string;
|
|
34
|
+
claimToken: string;
|
|
35
|
+
claimUrl: string;
|
|
36
|
+
/**
|
|
37
|
+
* Short human-checkable code (`XXX-XXX`) derived from the registration
|
|
38
|
+
* id. The claim URL is first-claimer-wins with nothing binding it to
|
|
39
|
+
* the person who ran `checkpoint init`: if it leaks pre-claim (echoed
|
|
40
|
+
* into CI logs, shoulder-surfed), whoever opens it first claims it into
|
|
41
|
+
* THEIR org, and the real caller's CLI would otherwise proceed to
|
|
42
|
+
* install telemetry into the attacker's project. The claim page shows
|
|
43
|
+
* the same code so the human can cross-check terminal against browser
|
|
44
|
+
* before trusting a "claimed" status.
|
|
45
|
+
*/
|
|
46
|
+
confirmationCode: string;
|
|
47
|
+
expiresAt: string;
|
|
48
|
+
}
|
|
49
|
+
export type CheckpointClaimStatus = "pending" | "claimed" | "expired";
|
|
50
|
+
export interface CheckpointExchangeResult {
|
|
51
|
+
projectId: string;
|
|
52
|
+
friendlyId: string | null;
|
|
53
|
+
organizationId: string;
|
|
54
|
+
apiKey: string;
|
|
55
|
+
dashboardUrl: string;
|
|
56
|
+
}
|
|
57
|
+
/** True for an http(s) URL only -- never file:, vscode:, or any other scheme an OS handler might act on unexpectedly. */
|
|
58
|
+
export declare function isHttpUrl(value: string): boolean;
|
|
59
|
+
export declare const CONFIRMATION_CODE_RE: RegExp;
|
|
60
|
+
export declare const API_KEY_RE: RegExp;
|
|
61
|
+
export declare const PROJECT_ID_RE: RegExp;
|
|
62
|
+
/**
|
|
63
|
+
* True only for an http(s) URL whose origin matches the configured
|
|
64
|
+
* Checkpoint origin. A same-shape check gated ONLY the open() call in
|
|
65
|
+
* checkpoint-init.ts (Bugbot, PR #658): announceClaim, the marker, and
|
|
66
|
+
* the --json payload still trusted and displayed any http(s) URL, so a
|
|
67
|
+
* compromised or misconfigured register response could still get a
|
|
68
|
+
* cross-origin, token-bearing link printed and persisted even though it
|
|
69
|
+
* was already judged unsafe to open. Validating at the source means
|
|
70
|
+
* every consumer of a parsed CheckpointRegisterResult gets the guarantee
|
|
71
|
+
* for free.
|
|
72
|
+
*/
|
|
73
|
+
export declare function isTrustedClaimUrl(value: string): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* `POST /api/cli/register`: mints a 24h claim token for this repo. The
|
|
76
|
+
* plaintext token is returned here and persisted (alongside
|
|
77
|
+
* `registrationId`) to `.checkpoint/registration.json` (0600, gitignored)
|
|
78
|
+
* by checkpoint-init.ts: a resumed run needs the token itself, not just
|
|
79
|
+
* the id, since the token IS the exchange credential.
|
|
80
|
+
*/
|
|
81
|
+
export declare function registerCheckpointProject(hints: CheckpointRegisterHints, signal?: AbortSignal): Promise<CheckpointRegisterResult>;
|
|
82
|
+
/** `GET /api/cli/registrations/:id/status`: the poll target while waiting for the browser claim. */
|
|
83
|
+
export declare function fetchCheckpointClaimStatus(registrationId: string, signal?: AbortSignal): Promise<CheckpointClaimStatus>;
|
|
84
|
+
/** `POST /api/cli/exchange`: trades a claimed token for a project API key exactly once. */
|
|
85
|
+
export declare function exchangeCheckpointClaim(claimToken: string, signal?: AbortSignal): Promise<CheckpointExchangeResult>;
|
|
86
|
+
//# sourceMappingURL=checkpoint-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkpoint-api.d.ts","sourceRoot":"","sources":["../../src/utils/checkpoint-api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAkBH;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAIlE;AAED,mHAAmH;AACnH,wBAAgB,gBAAgB,IAAI,MAAM,CAGzC;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,OAAO,CAiBpD;AAOD,MAAM,WAAW,uBAAuB;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;CACzD;AAED,MAAM,WAAW,wBAAwB;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;;;OASG;IACH,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAEtE,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;AAyBD,yHAAyH;AACzH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAOhD;AAUD,eAAO,MAAM,oBAAoB,QAA8B,CAAC;AAGhE,eAAO,MAAM,UAAU,QAA8B,CAAC;AACtD,eAAO,MAAM,aAAa,QAAsB,CAAC;AAEjD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAOxD;AAoDD;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,uBAAuB,EAC9B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,wBAAwB,CAAC,CAUnC;AAED,oGAAoG;AACpG,wBAAsB,0BAA0B,CAC9C,cAAc,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,qBAAqB,CAAC,CAUhC;AAED,2FAA2F;AAC3F,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,wBAAwB,CAAC,CAUnC"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client for the `kya-os checkpoint init` claim-token flow (KYA-1037).
|
|
3
|
+
*
|
|
4
|
+
* Talks to the three public Checkpoint dashboard endpoints added for this
|
|
5
|
+
* flow: register a claim token, poll its status, and exchange a claimed
|
|
6
|
+
* token for a project API key. Base URL is `CHECKPOINT_API_URL` when set,
|
|
7
|
+
* else the production dashboard origin, mirroring the `KTA_API_URL` /
|
|
8
|
+
* `KTA_BASE_URL` override pattern already used by `register.ts`/`claim.ts`
|
|
9
|
+
* for the sibling knowthat.ai claim flow.
|
|
10
|
+
*/
|
|
11
|
+
const DEFAULT_CHECKPOINT_ORIGIN = "https://kya.vouched.id";
|
|
12
|
+
function checkpointApiUrl(path) {
|
|
13
|
+
const base = process.env.CHECKPOINT_API_URL || DEFAULT_CHECKPOINT_ORIGIN;
|
|
14
|
+
const url = new URL(base);
|
|
15
|
+
// new URL(path, base) would silently drop any path prefix already on
|
|
16
|
+
// `base` (e.g. a preview deploy served at http://localhost:3000/preview-x)
|
|
17
|
+
// because an absolute path like "/api/cli/register" overrides the
|
|
18
|
+
// base's own path entirely. Join onto the base's pathname instead so a
|
|
19
|
+
// prefix survives.
|
|
20
|
+
const prefix = url.pathname === "/" ? "" : url.pathname.replace(/\/$/, "");
|
|
21
|
+
const suffix = path.startsWith("/") ? path : `/${path}`;
|
|
22
|
+
url.pathname = `${prefix}${suffix}`;
|
|
23
|
+
return url.toString();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Reconstructs the claim URL from a token alone, same shape the register
|
|
27
|
+
* endpoint itself builds (`/cli/claim?token=...` off the same base). Used
|
|
28
|
+
* only as a fallback for a marker written before this CLI persisted the
|
|
29
|
+
* server-issued `claimUrl` directly; a current run always reprints the
|
|
30
|
+
* value the server returned at register time.
|
|
31
|
+
*/
|
|
32
|
+
export function buildCheckpointClaimUrl(claimToken) {
|
|
33
|
+
const url = new URL(checkpointApiUrl("/cli/claim"));
|
|
34
|
+
url.searchParams.set("token", claimToken);
|
|
35
|
+
return url.toString();
|
|
36
|
+
}
|
|
37
|
+
/** The configured Checkpoint origin (protocol + host), to host-match a server-returned URL before acting on it. */
|
|
38
|
+
export function checkpointOrigin() {
|
|
39
|
+
const base = process.env.CHECKPOINT_API_URL || DEFAULT_CHECKPOINT_ORIGIN;
|
|
40
|
+
return new URL(base).origin;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* True when CHECKPOINT_API_URL resolves to plain http on a non-localhost
|
|
44
|
+
* host: the claim token, and later the minted API key, cross that
|
|
45
|
+
* connection in the clear.
|
|
46
|
+
*/
|
|
47
|
+
export function isInsecureCheckpointOrigin() {
|
|
48
|
+
const base = process.env.CHECKPOINT_API_URL || DEFAULT_CHECKPOINT_ORIGIN;
|
|
49
|
+
try {
|
|
50
|
+
const url = new URL(base);
|
|
51
|
+
if (url.protocol !== "http:")
|
|
52
|
+
return false;
|
|
53
|
+
// WHATWG URL keeps the brackets on an IPv6 literal ("[::1]", not
|
|
54
|
+
// "::1"), so the un-bracketed form here was dead code and IPv6
|
|
55
|
+
// loopback (http://[::1]:PORT, real for local dev) incorrectly
|
|
56
|
+
// tripped the insecure-origin warning (bestbrian, PR #658 follow-up).
|
|
57
|
+
return (url.hostname !== "localhost" &&
|
|
58
|
+
url.hostname !== "127.0.0.1" &&
|
|
59
|
+
url.hostname !== "[::1]");
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async function parseEnvelope(res) {
|
|
66
|
+
const body = (await res.json().catch(() => null));
|
|
67
|
+
if (!res.ok || !body?.success || !body.data) {
|
|
68
|
+
const message = body?.error?.message || `Request failed with status ${res.status}`;
|
|
69
|
+
const error = new Error(message);
|
|
70
|
+
error.code = body?.error?.code;
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
return body.data;
|
|
74
|
+
}
|
|
75
|
+
function isNonEmptyString(value) {
|
|
76
|
+
return typeof value === "string" && value.length > 0;
|
|
77
|
+
}
|
|
78
|
+
/** True for an http(s) URL only -- never file:, vscode:, or any other scheme an OS handler might act on unexpectedly. */
|
|
79
|
+
export function isHttpUrl(value) {
|
|
80
|
+
try {
|
|
81
|
+
const protocol = new URL(value).protocol;
|
|
82
|
+
return protocol === "http:" || protocol === "https:";
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Exported so checkpoint-init.ts's isValidMarker can apply the SAME
|
|
89
|
+
// shape checks to a marker read off disk, not just a fresh API response
|
|
90
|
+
// (bestbrian, PR #658 follow-up review): a marker's apiKey/projectId/
|
|
91
|
+
// claimUrl otherwise reached writeCheckpointEnv/the Beacon snippet/
|
|
92
|
+
// announceClaim unchecked on the resume-after-exchange path, a gap a
|
|
93
|
+
// hostile committed `.checkpoint/` directory could exploit even though
|
|
94
|
+
// nothing here opens a new trust boundary a malicious repo doesn't
|
|
95
|
+
// already have some other way in.
|
|
96
|
+
export const CONFIRMATION_CODE_RE = /^[0-9A-F]{3}-[0-9A-F]{3}$/;
|
|
97
|
+
// The two live formats the server mints (credentials.mdx): sk_... for
|
|
98
|
+
// current keys, as_... as a real legacy format some paths still generate.
|
|
99
|
+
export const API_KEY_RE = /^(sk|as)_[A-Za-z0-9._-]+$/;
|
|
100
|
+
export const PROJECT_ID_RE = /^[A-Za-z0-9._-]+$/;
|
|
101
|
+
/**
|
|
102
|
+
* True only for an http(s) URL whose origin matches the configured
|
|
103
|
+
* Checkpoint origin. A same-shape check gated ONLY the open() call in
|
|
104
|
+
* checkpoint-init.ts (Bugbot, PR #658): announceClaim, the marker, and
|
|
105
|
+
* the --json payload still trusted and displayed any http(s) URL, so a
|
|
106
|
+
* compromised or misconfigured register response could still get a
|
|
107
|
+
* cross-origin, token-bearing link printed and persisted even though it
|
|
108
|
+
* was already judged unsafe to open. Validating at the source means
|
|
109
|
+
* every consumer of a parsed CheckpointRegisterResult gets the guarantee
|
|
110
|
+
* for free.
|
|
111
|
+
*/
|
|
112
|
+
export function isTrustedClaimUrl(value) {
|
|
113
|
+
if (!isHttpUrl(value))
|
|
114
|
+
return false;
|
|
115
|
+
try {
|
|
116
|
+
return new URL(value).origin === checkpointOrigin();
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/** Validates only the fields checkpoint-init.ts actually reads, not the whole declared shape. */
|
|
123
|
+
function assertRegisterResult(data) {
|
|
124
|
+
const d = data;
|
|
125
|
+
if (!d ||
|
|
126
|
+
!isNonEmptyString(d.registrationId) ||
|
|
127
|
+
!isNonEmptyString(d.claimToken) ||
|
|
128
|
+
!isNonEmptyString(d.claimUrl) ||
|
|
129
|
+
!isTrustedClaimUrl(d.claimUrl) ||
|
|
130
|
+
!isNonEmptyString(d.confirmationCode) ||
|
|
131
|
+
!CONFIRMATION_CODE_RE.test(d.confirmationCode)) {
|
|
132
|
+
throw new Error("Malformed response from Checkpoint (register)");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function assertStatusResult(data) {
|
|
136
|
+
const status = data?.status;
|
|
137
|
+
if (status !== "pending" && status !== "claimed" && status !== "expired") {
|
|
138
|
+
throw new Error("Malformed response from Checkpoint (status)");
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function assertExchangeResult(data) {
|
|
142
|
+
const d = data;
|
|
143
|
+
if (!d ||
|
|
144
|
+
// projectId and apiKey are format-checked, not just non-empty: both
|
|
145
|
+
// land in a sink an unvalidated newline could corrupt -- projectId
|
|
146
|
+
// into the Beacon snippet's JS string literal, apiKey into a raw
|
|
147
|
+
// .env.local line (a value containing "\nINJECTED=evil" would write
|
|
148
|
+
// a rogue env var into the user's app).
|
|
149
|
+
!isNonEmptyString(d.projectId) ||
|
|
150
|
+
!PROJECT_ID_RE.test(d.projectId) ||
|
|
151
|
+
!isNonEmptyString(d.apiKey) ||
|
|
152
|
+
!API_KEY_RE.test(d.apiKey) ||
|
|
153
|
+
!isNonEmptyString(d.dashboardUrl) ||
|
|
154
|
+
!isHttpUrl(d.dashboardUrl) ||
|
|
155
|
+
!isNonEmptyString(d.organizationId)) {
|
|
156
|
+
throw new Error("Malformed response from Checkpoint (exchange)");
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* `POST /api/cli/register`: mints a 24h claim token for this repo. The
|
|
161
|
+
* plaintext token is returned here and persisted (alongside
|
|
162
|
+
* `registrationId`) to `.checkpoint/registration.json` (0600, gitignored)
|
|
163
|
+
* by checkpoint-init.ts: a resumed run needs the token itself, not just
|
|
164
|
+
* the id, since the token IS the exchange credential.
|
|
165
|
+
*/
|
|
166
|
+
export async function registerCheckpointProject(hints, signal) {
|
|
167
|
+
const res = await fetch(checkpointApiUrl("/api/cli/register"), {
|
|
168
|
+
method: "POST",
|
|
169
|
+
headers: { "content-type": "application/json" },
|
|
170
|
+
body: JSON.stringify(hints),
|
|
171
|
+
signal,
|
|
172
|
+
});
|
|
173
|
+
const data = await parseEnvelope(res);
|
|
174
|
+
assertRegisterResult(data);
|
|
175
|
+
return data;
|
|
176
|
+
}
|
|
177
|
+
/** `GET /api/cli/registrations/:id/status`: the poll target while waiting for the browser claim. */
|
|
178
|
+
export async function fetchCheckpointClaimStatus(registrationId, signal) {
|
|
179
|
+
const res = await fetch(checkpointApiUrl(`/api/cli/registrations/${encodeURIComponent(registrationId)}/status`), { signal });
|
|
180
|
+
const data = await parseEnvelope(res);
|
|
181
|
+
assertStatusResult(data);
|
|
182
|
+
return data.status;
|
|
183
|
+
}
|
|
184
|
+
/** `POST /api/cli/exchange`: trades a claimed token for a project API key exactly once. */
|
|
185
|
+
export async function exchangeCheckpointClaim(claimToken, signal) {
|
|
186
|
+
const res = await fetch(checkpointApiUrl("/api/cli/exchange"), {
|
|
187
|
+
method: "POST",
|
|
188
|
+
headers: { "content-type": "application/json" },
|
|
189
|
+
body: JSON.stringify({ claimToken }),
|
|
190
|
+
signal,
|
|
191
|
+
});
|
|
192
|
+
const data = await parseEnvelope(res);
|
|
193
|
+
assertExchangeResult(data);
|
|
194
|
+
return data;
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=checkpoint-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkpoint-api.js","sourceRoot":"","sources":["../../src/utils/checkpoint-api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,yBAAyB,GAAG,wBAAwB,CAAC;AAE3D,SAAS,gBAAgB,CAAC,IAAY;IACpC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,yBAAyB,CAAC;IACzE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;IAC1B,qEAAqE;IACrE,2EAA2E;IAC3E,kEAAkE;IAClE,uEAAuE;IACvE,mBAAmB;IACnB,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC3E,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;IACxD,GAAG,CAAC,QAAQ,GAAG,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;IACpC,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CAAC,UAAkB;IACxD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC,CAAC;IACpD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC1C,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC;AAED,mHAAmH;AACnH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,yBAAyB,CAAC;IACzE,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;AAC9B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,0BAA0B;IACxC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,yBAAyB,CAAC;IACzE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO;YAAE,OAAO,KAAK,CAAC;QAC3C,iEAAiE;QACjE,+DAA+D;QAC/D,+DAA+D;QAC/D,sEAAsE;QACtE,OAAO,CACL,GAAG,CAAC,QAAQ,KAAK,WAAW;YAC5B,GAAG,CAAC,QAAQ,KAAK,WAAW;YAC5B,GAAG,CAAC,QAAQ,KAAK,OAAO,CACzB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAgDD,KAAK,UAAU,aAAa,CAAI,GAAa;IAC3C,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAA0B,CAAC;IAC3E,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5C,MAAM,OAAO,GACX,IAAI,EAAE,KAAK,EAAE,OAAO,IAAI,8BAA8B,GAAG,CAAC,MAAM,EAAE,CAAC;QACrE,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;QAChC,KAAmC,CAAC,IAAI,GAAG,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC;QAC9D,MAAM,KAAK,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC;AACnB,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc;IACtC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;AACvD,CAAC;AAED,yHAAyH;AACzH,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC;QACzC,OAAO,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,QAAQ,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,oEAAoE;AACpE,wEAAwE;AACxE,sEAAsE;AACtE,oEAAoE;AACpE,qEAAqE;AACrE,uEAAuE;AACvE,mEAAmE;AACnE,kCAAkC;AAClC,MAAM,CAAC,MAAM,oBAAoB,GAAG,2BAA2B,CAAC;AAChE,sEAAsE;AACtE,0EAA0E;AAC1E,MAAM,CAAC,MAAM,UAAU,GAAG,2BAA2B,CAAC;AACtD,MAAM,CAAC,MAAM,aAAa,GAAG,mBAAmB,CAAC;AAEjD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,gBAAgB,EAAE,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,iGAAiG;AACjG,SAAS,oBAAoB,CAC3B,IAAa;IAEb,MAAM,CAAC,GAAG,IAAgD,CAAC;IAC3D,IACE,CAAC,CAAC;QACF,CAAC,gBAAgB,CAAC,CAAC,CAAC,cAAc,CAAC;QACnC,CAAC,gBAAgB,CAAC,CAAC,CAAC,UAAU,CAAC;QAC/B,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC7B,CAAC,iBAAiB,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC9B,CAAC,gBAAgB,CAAC,CAAC,CAAC,gBAAgB,CAAC;QACrC,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,EAC9C,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CACzB,IAAa;IAEb,MAAM,MAAM,GAAI,IAAoC,EAAE,MAAM,CAAC;IAC7D,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAC3B,IAAa;IAEb,MAAM,CAAC,GAAG,IAAgD,CAAC;IAC3D,IACE,CAAC,CAAC;QACF,oEAAoE;QACpE,mEAAmE;QACnE,iEAAiE;QACjE,oEAAoE;QACpE,wCAAwC;QACxC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC;QAC9B,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QAChC,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC;QAC3B,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;QAC1B,CAAC,gBAAgB,CAAC,CAAC,CAAC,YAAY,CAAC;QACjC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC;QAC1B,CAAC,gBAAgB,CAAC,CAAC,CAAC,cAAc,CAAC,EACnC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,KAA8B,EAC9B,MAAoB;IAEpB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,EAAE;QAC7D,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;QAC3B,MAAM;KACP,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,aAAa,CAA2B,GAAG,CAAC,CAAC;IAChE,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAC3B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,oGAAoG;AACpG,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,cAAsB,EACtB,MAAoB;IAEpB,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,gBAAgB,CACd,0BAA0B,kBAAkB,CAAC,cAAc,CAAC,SAAS,CACtE,EACD,EAAE,MAAM,EAAE,CACX,CAAC;IACF,MAAM,IAAI,GAAG,MAAM,aAAa,CAAoC,GAAG,CAAC,CAAC;IACzE,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACzB,OAAO,IAAI,CAAC,MAAM,CAAC;AACrB,CAAC;AAED,2FAA2F;AAC3F,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,UAAkB,EAClB,MAAoB;IAEpB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,EAAE;QAC7D,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,CAAC;QACpC,MAAM;KACP,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,aAAa,CAA2B,GAAG,CAAC,CAAC;IAChE,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAC3B,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal, dedicated `.env.local` writer for `kya-os checkpoint init`'s two
|
|
3
|
+
* variables.
|
|
4
|
+
*
|
|
5
|
+
* `EnvManager` (env-manager.ts) is intentionally NOT reused here: its
|
|
6
|
+
* `EnvVariables` interface and every parsing/regex path inside it are
|
|
7
|
+
* hardcoded to the MCP-I identity variable set (`AGENT_DID`,
|
|
8
|
+
* `AGENT_KEY_ID`, `KYA_VOUCHED_API_KEY`, ...). Feeding it
|
|
9
|
+
* `CHECKPOINT_API_KEY`/`CHECKPOINT_PROJECT_ID` would silently fall
|
|
10
|
+
* through its "unrecognized variable" branches and duplicate the lines on
|
|
11
|
+
* every re-run instead of updating them in place. This mirrors
|
|
12
|
+
* EnvManager's SAFE behaviors (prefer updating existing lines, append a
|
|
13
|
+
* clearly-labeled new section otherwise, never touch unrelated lines)
|
|
14
|
+
* scoped to just the two keys this command owns.
|
|
15
|
+
*/
|
|
16
|
+
export interface CheckpointEnvVars {
|
|
17
|
+
CHECKPOINT_API_KEY: string;
|
|
18
|
+
CHECKPOINT_PROJECT_ID: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function writeCheckpointEnv(projectRoot: string, vars: CheckpointEnvVars): {
|
|
21
|
+
file: string;
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=checkpoint-env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkpoint-env.d.ts","sourceRoot":"","sources":["../../src/utils/checkpoint-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,MAAM,WAAW,iBAAiB;IAChC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAOD,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,iBAAiB,GACtB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAyClB"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal, dedicated `.env.local` writer for `kya-os checkpoint init`'s two
|
|
3
|
+
* variables.
|
|
4
|
+
*
|
|
5
|
+
* `EnvManager` (env-manager.ts) is intentionally NOT reused here: its
|
|
6
|
+
* `EnvVariables` interface and every parsing/regex path inside it are
|
|
7
|
+
* hardcoded to the MCP-I identity variable set (`AGENT_DID`,
|
|
8
|
+
* `AGENT_KEY_ID`, `KYA_VOUCHED_API_KEY`, ...). Feeding it
|
|
9
|
+
* `CHECKPOINT_API_KEY`/`CHECKPOINT_PROJECT_ID` would silently fall
|
|
10
|
+
* through its "unrecognized variable" branches and duplicate the lines on
|
|
11
|
+
* every re-run instead of updating them in place. This mirrors
|
|
12
|
+
* EnvManager's SAFE behaviors (prefer updating existing lines, append a
|
|
13
|
+
* clearly-labeled new section otherwise, never touch unrelated lines)
|
|
14
|
+
* scoped to just the two keys this command owns.
|
|
15
|
+
*/
|
|
16
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
17
|
+
import { join } from "path";
|
|
18
|
+
const ENV_KEYS = [
|
|
19
|
+
"CHECKPOINT_API_KEY",
|
|
20
|
+
"CHECKPOINT_PROJECT_ID",
|
|
21
|
+
];
|
|
22
|
+
export function writeCheckpointEnv(projectRoot, vars) {
|
|
23
|
+
const filePath = join(projectRoot, ".env.local");
|
|
24
|
+
const existing = existsSync(filePath) ? readFileSync(filePath, "utf-8") : "";
|
|
25
|
+
const lines = existing.length > 0 ? existing.split("\n") : [];
|
|
26
|
+
const seen = new Set();
|
|
27
|
+
const updatedLines = lines.map((line) => {
|
|
28
|
+
// Optional leading `export ` so a shell-sourced .env.local
|
|
29
|
+
// (`export CHECKPOINT_API_KEY=...`) gets updated in place too, rather
|
|
30
|
+
// than falling through to the "missing" branch and appending a
|
|
31
|
+
// duplicate line alongside it. The prefix (captured separately) is
|
|
32
|
+
// preserved on update, not silently dropped, so an exported var
|
|
33
|
+
// doesn't quietly become unexported.
|
|
34
|
+
const match = line.match(/^(export\s+)?([A-Z_][A-Z0-9_]*)\s*=/);
|
|
35
|
+
const exportPrefix = match?.[1] ?? "";
|
|
36
|
+
const key = match?.[2];
|
|
37
|
+
if (key && ENV_KEYS.includes(key)) {
|
|
38
|
+
seen.add(key);
|
|
39
|
+
return `${exportPrefix}${key}=${vars[key]}`;
|
|
40
|
+
}
|
|
41
|
+
return line;
|
|
42
|
+
});
|
|
43
|
+
const missing = ENV_KEYS.filter((key) => !seen.has(key));
|
|
44
|
+
if (missing.length > 0) {
|
|
45
|
+
if (updatedLines.length > 0 &&
|
|
46
|
+
updatedLines[updatedLines.length - 1] !== "") {
|
|
47
|
+
updatedLines.push("");
|
|
48
|
+
}
|
|
49
|
+
updatedLines.push("# Added by `kya-os checkpoint init`");
|
|
50
|
+
for (const key of missing) {
|
|
51
|
+
updatedLines.push(`${key}=${vars[key]}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Exactly one trailing newline, regardless of what was there before.
|
|
55
|
+
const content = `${updatedLines.join("\n").replace(/\n+$/, "")}\n`;
|
|
56
|
+
writeFileSync(filePath, content, "utf-8");
|
|
57
|
+
return { file: ".env.local" };
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=checkpoint-env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkpoint-env.js","sourceRoot":"","sources":["../../src/utils/checkpoint-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAO5B,MAAM,QAAQ,GAAgC;IAC5C,oBAAoB;IACpB,uBAAuB;CACxB,CAAC;AAEF,MAAM,UAAU,kBAAkB,CAChC,WAAmB,EACnB,IAAuB;IAEvB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7E,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,MAAM,YAAY,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACtC,2DAA2D;QAC3D,sEAAsE;QACtE,+DAA+D;QAC/D,mEAAmE;QACnE,gEAAgE;QAChE,qCAAqC;QACrC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAChE,MAAM,YAAY,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,KAAK,EAAE,CAAC,CAAC,CAAwC,CAAC;QAC9D,IAAI,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAClC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,OAAO,GAAG,YAAY,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACzD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,IACE,YAAY,CAAC,MAAM,GAAG,CAAC;YACvB,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,EAC5C,CAAC;YACD,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxB,CAAC;QACD,YAAY,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;QACzD,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,YAAY,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,qEAAqE;IACrE,MAAM,OAAO,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC;IACnE,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect-layer scaffolding for `kya-os checkpoint init` (KYA-1037).
|
|
3
|
+
*
|
|
4
|
+
* Maps the repo's detected platform onto one of the three Detect layers
|
|
5
|
+
* Checkpoint ships (Next.js middleware, Express snippet, the keyless
|
|
6
|
+
* Beacon), and, for Next.js, installs the SDK and writes middleware.ts
|
|
7
|
+
* directly (no shelling out to another package's setup script, see the
|
|
8
|
+
* comment on scaffoldNextjs for why). Every install/write step is behind
|
|
9
|
+
* an injectable ScaffoldRunner, so tests never spawn a real process or
|
|
10
|
+
* touch the real filesystem.
|
|
11
|
+
*/
|
|
12
|
+
import { type PlatformInfo } from "./platform-detector.js";
|
|
13
|
+
export type CheckpointFramework = "nextjs" | "express" | "static" | "unknown";
|
|
14
|
+
/**
|
|
15
|
+
* Maps `detectPlatform()`'s general-purpose platform/framework detection
|
|
16
|
+
* onto the three layers Checkpoint's `init` can scaffold. A repo with no
|
|
17
|
+
* `package.json` at all (a plain HTML/CSS/JS site) maps to `static`; one
|
|
18
|
+
* with a `package.json` but no recognized framework maps to `unknown`,
|
|
19
|
+
* both get the same keyless Beacon snippet, but the distinction is kept
|
|
20
|
+
* server-side as a hint for future support triage.
|
|
21
|
+
*
|
|
22
|
+
* Checks package.json's own `next` dependency directly, not just
|
|
23
|
+
* platformInfo's derived platform/framework fields: detectPlatform()
|
|
24
|
+
* unconditionally overwrites both to 'cloudflare'/'cloudflare-workers'
|
|
25
|
+
* whenever wrangler.toml/json exists, even for a Next.js repo deployed
|
|
26
|
+
* there, silently losing the nextjs detection underneath it.
|
|
27
|
+
*/
|
|
28
|
+
export declare function detectCheckpointFramework(projectRoot?: string, platformInfo?: PlatformInfo): CheckpointFramework;
|
|
29
|
+
export declare function checkpointFrameworkLabel(framework: CheckpointFramework): string;
|
|
30
|
+
/** Best-effort repo name: git remote slug, else the directory name. */
|
|
31
|
+
export declare function detectRepoName(projectRoot?: string): string | undefined;
|
|
32
|
+
/** Best-effort domain hint from `package.json`'s `homepage` field. */
|
|
33
|
+
export declare function detectDomainHint(projectRoot?: string): string | undefined;
|
|
34
|
+
export interface ScaffoldRunner {
|
|
35
|
+
/** Runs `command` with `args` in `cwd`; returns the exit status (0 = success). Never throws. */
|
|
36
|
+
run(command: string, args: string[], cwd: string): {
|
|
37
|
+
status: number;
|
|
38
|
+
};
|
|
39
|
+
/** Writes `content` to `path`. Throws on failure, so the caller can decide how to degrade. */
|
|
40
|
+
writeFile(path: string, content: string): void;
|
|
41
|
+
/** True if `path` exists. */
|
|
42
|
+
fileExists(path: string): boolean;
|
|
43
|
+
}
|
|
44
|
+
/** The real runner: shells out via execFileSync (swallowing spawn errors into a non-zero status) and touches the real filesystem. */
|
|
45
|
+
export declare const defaultScaffoldRunner: ScaffoldRunner;
|
|
46
|
+
export declare const NEXTJS_MANUAL_SNIPPET = "import { createMiddleware } from '@kya-os/checkpoint-nextjs';\n\nexport default createMiddleware({\n apiKey: process.env.CHECKPOINT_API_KEY!,\n projectId: process.env.CHECKPOINT_PROJECT_ID!,\n // The SDK default is 'enforce', which is inert without a deployed\n // policy, spelled out explicitly so flipping it later is a one-word diff.\n enforcementMode: 'observe',\n});\n\nexport const config = { matcher: '/((?!_next/static|_next/image|favicon.ico).*)' };\n";
|
|
47
|
+
export declare const EXPRESS_SNIPPET = "import { withCheckpoint } from '@kya-os/checkpoint-express';\n\napp.use(withCheckpoint({\n apiKey: process.env.CHECKPOINT_API_KEY!,\n projectId: process.env.CHECKPOINT_PROJECT_ID!,\n}));\n";
|
|
48
|
+
export declare function beaconSnippet(projectId: string): string;
|
|
49
|
+
export interface ScaffoldResult {
|
|
50
|
+
framework: CheckpointFramework;
|
|
51
|
+
/** True once the SDK package install succeeded (Next.js/Express only). */
|
|
52
|
+
installed: boolean;
|
|
53
|
+
/** True once the framework's own setup step (writing middleware.ts, printing the snippet) actually ran. */
|
|
54
|
+
setupRan: boolean;
|
|
55
|
+
/** Human-readable next step: either a success line or the manual wiring snippet + docs link. */
|
|
56
|
+
message: string;
|
|
57
|
+
}
|
|
58
|
+
export declare function scaffoldNextjs(projectRoot: string, packageManager: PlatformInfo["packageManager"], runner?: ScaffoldRunner): ScaffoldResult;
|
|
59
|
+
export declare function scaffoldExpress(projectRoot: string, packageManager: PlatformInfo["packageManager"], runner?: ScaffoldRunner): ScaffoldResult;
|
|
60
|
+
export declare function scaffoldBeacon(projectId: string, framework: CheckpointFramework): ScaffoldResult;
|
|
61
|
+
//# sourceMappingURL=checkpoint-scaffold.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkpoint-scaffold.d.ts","sourceRoot":"","sources":["../../src/utils/checkpoint-scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3E,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAiB9E;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,GAAE,MAAsB,EACnC,YAAY,GAAE,YAA0C,GACvD,mBAAmB,CAarB;AAED,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,mBAAmB,GAC7B,MAAM,CAYR;AAED,uEAAuE;AACvE,wBAAgB,cAAc,CAC5B,WAAW,GAAE,MAAsB,GAClC,MAAM,GAAG,SAAS,CAkBpB;AAED,sEAAsE;AACtE,wBAAgB,gBAAgB,CAC9B,WAAW,GAAE,MAAsB,GAClC,MAAM,GAAG,SAAS,CAkBpB;AAED,MAAM,WAAW,cAAc;IAC7B,gGAAgG;IAChG,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE,8FAA8F;IAC9F,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,6BAA6B;IAC7B,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CACnC;AAED,qIAAqI;AACrI,eAAO,MAAM,qBAAqB,EAAE,cAwBnC,CAAC;AAiBF,eAAO,MAAM,qBAAqB,sdAWjC,CAAC;AAEF,eAAO,MAAM,eAAe,mMAM3B,CAAC;AAEF,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAWvD;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,mBAAmB,CAAC;IAC/B,0EAA0E;IAC1E,SAAS,EAAE,OAAO,CAAC;IACnB,2GAA2G;IAC3G,QAAQ,EAAE,OAAO,CAAC;IAClB,gGAAgG;IAChG,OAAO,EAAE,MAAM,CAAC;CACjB;AA+BD,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,YAAY,CAAC,gBAAgB,CAAC,EAC9C,MAAM,GAAE,cAAsC,GAC7C,cAAc,CAiDhB;AAED,wBAAgB,eAAe,CAC7B,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,YAAY,CAAC,gBAAgB,CAAC,EAC9C,MAAM,GAAE,cAAsC,GAC7C,cAAc,CAgBhB;AAED,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,mBAAmB,GAC7B,cAAc,CAOhB"}
|