@kya-os/cli 1.6.3 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +1 -1
  2. package/dist/commands/checkpoint-init.d.ts +32 -0
  3. package/dist/commands/checkpoint-init.d.ts.map +1 -0
  4. package/dist/commands/checkpoint-init.js +554 -0
  5. package/dist/commands/checkpoint-init.js.map +1 -0
  6. package/dist/commands/receipts.d.ts +11 -0
  7. package/dist/commands/receipts.d.ts.map +1 -1
  8. package/dist/commands/receipts.js +24 -19
  9. package/dist/commands/receipts.js.map +1 -1
  10. package/dist/index.js +10 -2
  11. package/dist/utils/checkpoint-api.d.ts +86 -0
  12. package/dist/utils/checkpoint-api.d.ts.map +1 -0
  13. package/dist/utils/checkpoint-api.js +196 -0
  14. package/dist/utils/checkpoint-api.js.map +1 -0
  15. package/dist/utils/checkpoint-env.d.ts +23 -0
  16. package/dist/utils/checkpoint-env.d.ts.map +1 -0
  17. package/dist/utils/checkpoint-env.js +59 -0
  18. package/dist/utils/checkpoint-env.js.map +1 -0
  19. package/dist/utils/checkpoint-scaffold.d.ts +61 -0
  20. package/dist/utils/checkpoint-scaffold.d.ts.map +1 -0
  21. package/dist/utils/checkpoint-scaffold.js +268 -0
  22. package/dist/utils/checkpoint-scaffold.js.map +1 -0
  23. package/dist/utils/dco/claude-config.d.ts +6 -0
  24. package/dist/utils/dco/claude-config.d.ts.map +1 -1
  25. package/dist/utils/dco/claude-config.js +22 -2
  26. package/dist/utils/dco/claude-config.js.map +1 -1
  27. package/dist/utils/dco/setup.d.ts.map +1 -1
  28. package/dist/utils/dco/setup.js +1 -0
  29. package/dist/utils/dco/setup.js.map +1 -1
  30. package/dist/utils/poll.d.ts +50 -0
  31. package/dist/utils/poll.d.ts.map +1 -0
  32. package/dist/utils/poll.js +73 -0
  33. package/dist/utils/poll.js.map +1 -0
  34. package/package.json +4 -4
package/README.md CHANGED
@@ -166,7 +166,7 @@ Options:
166
166
 
167
167
  - `--json` - Output in JSON format for automation
168
168
  - `--path <path>` - Custom path for receipt storage
169
- - `--verify` - Verify receipts against KTA log
169
+ - `--verify` - Request cryptographic verification (legacy registry receipts report unsupported)
170
170
 
171
171
  ### `doctor`
172
172
 
@@ -0,0 +1,32 @@
1
+ /**
2
+ * `mcpi checkpoint init`, KYA-1037, the one-command Detect install.
3
+ *
4
+ * A NEW command group (`checkpoint init`), not an overload of the
5
+ * existing top-level `init` (MCP-I agent identity init, unrelated and
6
+ * untouched). Since `package.json` exposes only the `mcpi` bin,
7
+ * `npx @kya-os/cli checkpoint init` resolves it, satisfying the
8
+ * one-command story without a second `kya` bin.
9
+ *
10
+ * Flow: register a claim token, print + open the claim URL, poll for the
11
+ * browser claim, exchange the claimed token for a project API key, write
12
+ * env + scaffold the right Detect layer, print the dashboard link.
13
+ * `.checkpoint/registration.json` (machine-local, 0600, gitignored)
14
+ * tracks progress through three states, so a re-run always resumes
15
+ * rather than starting over or losing the (single-use) exchange:
16
+ *
17
+ * 1. pending (registrationId + claimToken + claimUrl, no exchange yet)
18
+ * 2. exchanged (also projectId/apiKey/dashboardUrl/organizationId; the
19
+ * finish step, env write + scaffold, hasn't run)
20
+ * 3. setupComplete (the finish step ran; claimToken is dropped, spent,
21
+ * no further use, and the marker only proves "done")
22
+ */
23
+ import { Command } from "commander";
24
+ export declare const MAX_POLL_ATTEMPTS: number;
25
+ export interface CheckpointInitOptions {
26
+ json?: boolean;
27
+ /** Include the live, token-bearing claim URL in --json output. Ignored in normal (non --json) mode, which always prints the URL. */
28
+ revealClaimUrl?: boolean;
29
+ }
30
+ export declare function checkpointInit(options?: CheckpointInitOptions): Promise<void>;
31
+ export declare function createCheckpointCommand(): Command;
32
+ //# sourceMappingURL=checkpoint-init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpoint-init.d.ts","sourceRoot":"","sources":["../../src/commands/checkpoint-init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAKH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+CpC,eAAO,MAAM,iBAAiB,QAAiD,CAAC;AAwChF,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,oIAAoI;IACpI,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAsYD,wBAAsB,cAAc,CAClC,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,IAAI,CAAC,CAqQf;AAED,wBAAgB,uBAAuB,IAAI,OAAO,CAkBjD"}
@@ -0,0 +1,554 @@
1
+ /**
2
+ * `mcpi checkpoint init`, KYA-1037, the one-command Detect install.
3
+ *
4
+ * A NEW command group (`checkpoint init`), not an overload of the
5
+ * existing top-level `init` (MCP-I agent identity init, unrelated and
6
+ * untouched). Since `package.json` exposes only the `mcpi` bin,
7
+ * `npx @kya-os/cli checkpoint init` resolves it, satisfying the
8
+ * one-command story without a second `kya` bin.
9
+ *
10
+ * Flow: register a claim token, print + open the claim URL, poll for the
11
+ * browser claim, exchange the claimed token for a project API key, write
12
+ * env + scaffold the right Detect layer, print the dashboard link.
13
+ * `.checkpoint/registration.json` (machine-local, 0600, gitignored)
14
+ * tracks progress through three states, so a re-run always resumes
15
+ * rather than starting over or losing the (single-use) exchange:
16
+ *
17
+ * 1. pending (registrationId + claimToken + claimUrl, no exchange yet)
18
+ * 2. exchanged (also projectId/apiKey/dashboardUrl/organizationId; the
19
+ * finish step, env write + scaffold, hasn't run)
20
+ * 3. setupComplete (the finish step ran; claimToken is dropped, spent,
21
+ * no further use, and the marker only proves "done")
22
+ */
23
+ import chalk from "chalk";
24
+ import ora from "ora";
25
+ import open from "open";
26
+ import { Command } from "commander";
27
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync, unlinkSync, } from "fs";
28
+ import { join } from "path";
29
+ import { showInfo } from "../utils/prompts.js";
30
+ import { detectPlatform, } from "../utils/platform-detector.js";
31
+ import { detectCheckpointFramework, detectDomainHint, detectRepoName, checkpointFrameworkLabel, scaffoldNextjs, scaffoldExpress, scaffoldBeacon, } from "../utils/checkpoint-scaffold.js";
32
+ import { registerCheckpointProject, fetchCheckpointClaimStatus, exchangeCheckpointClaim, buildCheckpointClaimUrl, checkpointOrigin, isInsecureCheckpointOrigin, isHttpUrl, isTrustedClaimUrl, CONFIRMATION_CODE_RE, API_KEY_RE, PROJECT_ID_RE, } from "../utils/checkpoint-api.js";
33
+ import { writeCheckpointEnv } from "../utils/checkpoint-env.js";
34
+ import { pollWithDeadline } from "../utils/poll.js";
35
+ const MARKER_DIR = ".checkpoint";
36
+ const MARKER_FILE = "registration.json";
37
+ const POLL_INTERVAL_MS = 5000;
38
+ const POLL_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes, per the plan's foreground cap
39
+ export const MAX_POLL_ATTEMPTS = Math.floor(POLL_TIMEOUT_MS / POLL_INTERVAL_MS);
40
+ function markerPath(projectRoot) {
41
+ return join(projectRoot, MARKER_DIR, MARKER_FILE);
42
+ }
43
+ function isOptionalString(value) {
44
+ return value === undefined || typeof value === "string";
45
+ }
46
+ /** Undefined is fine (the field is optional); if present, it must be a string matching the given shape check. */
47
+ function isOptionalMatch(value, matches) {
48
+ return value === undefined || (typeof value === "string" && matches(value));
49
+ }
50
+ /**
51
+ * A marker read off disk could be hand-edited, truncated, written by a
52
+ * different CLI version, or (bestbrian, PR #658 follow-up) come from a
53
+ * hostile committed `.checkpoint/` directory: on the resume-after-exchange
54
+ * path these values reach writeCheckpointEnv, the Beacon snippet, and
55
+ * announceClaim directly, without ever passing through
56
+ * assertExchangeResult/assertRegisterResult, those only validate a FRESH
57
+ * API response, not a marker read off disk. Apply the SAME shape checks
58
+ * here, so a malformed value is treated as no marker at all rather than
59
+ * flowing through unchecked.
60
+ */
61
+ function isValidMarker(value) {
62
+ if (!value || typeof value !== "object")
63
+ return false;
64
+ const v = value;
65
+ if (typeof v.registrationId !== "string" || v.registrationId.length === 0) {
66
+ return false;
67
+ }
68
+ // The origin check only matters while the claim is still pending and
69
+ // unclaimed: that's the window a hostile committed marker could exploit
70
+ // by luring the user into approving a cross-origin claim. Once past
71
+ // that (matches checkpointInit's OWN resume-after-exchange condition
72
+ // exactly, not just "apiKey is present": a marker missing projectId or
73
+ // dashboardUrl still falls into the pending-resume branch below, and a
74
+ // looser check here previously let its claimUrl through unchecked,
75
+ // Bugbot, PR #658 follow-up) or finished (setupComplete), claimUrl is
76
+ // dead, it's never opened, announced, or acted on again from either of
77
+ // those two states, only ever passed through unread. Origin-validating
78
+ // it there serves no protective purpose while risking exactly what it's
79
+ // meant to prevent: a later CHECKPOINT_API_URL change would reject the
80
+ // WHOLE marker, silently losing the one, unrecoverable copy of a minted
81
+ // apiKey, or making an already-complete setup re-register.
82
+ const pastPendingClaim = (v.projectId !== undefined &&
83
+ v.apiKey !== undefined &&
84
+ v.dashboardUrl !== undefined) ||
85
+ v.setupComplete === true;
86
+ const claimUrlIsValid = pastPendingClaim ? isHttpUrl : isTrustedClaimUrl;
87
+ if (!isOptionalString(v.claimToken) ||
88
+ !isOptionalString(v.organizationId) ||
89
+ !isOptionalMatch(v.claimUrl, claimUrlIsValid) ||
90
+ !isOptionalMatch(v.confirmationCode, (s) => CONFIRMATION_CODE_RE.test(s)) ||
91
+ !isOptionalMatch(v.projectId, (s) => PROJECT_ID_RE.test(s)) ||
92
+ !isOptionalMatch(v.apiKey, (s) => API_KEY_RE.test(s)) ||
93
+ !isOptionalMatch(v.dashboardUrl, isHttpUrl)) {
94
+ return false;
95
+ }
96
+ return v.setupComplete === undefined || typeof v.setupComplete === "boolean";
97
+ }
98
+ function readMarker(projectRoot) {
99
+ const filePath = markerPath(projectRoot);
100
+ if (!existsSync(filePath))
101
+ return null;
102
+ try {
103
+ const parsed = JSON.parse(readFileSync(filePath, "utf-8"));
104
+ return isValidMarker(parsed) ? parsed : null;
105
+ }
106
+ catch {
107
+ return null;
108
+ }
109
+ }
110
+ function writeMarker(projectRoot, marker) {
111
+ const dir = join(projectRoot, MARKER_DIR);
112
+ if (!existsSync(dir))
113
+ mkdirSync(dir, { recursive: true });
114
+ const filePath = markerPath(projectRoot);
115
+ writeFileSync(filePath, JSON.stringify(marker, null, 2), "utf-8");
116
+ try {
117
+ // Machine-local state holding a live claim/exchange credential until
118
+ // it's consumed, same 0600 posture register.ts uses for identity.json.
119
+ chmodSync(filePath, 0o600);
120
+ }
121
+ catch {
122
+ // Windows chmod semantics differ; best-effort, never fatal.
123
+ }
124
+ }
125
+ /**
126
+ * Drops the marker once its registration is dead (expired, never claimed
127
+ * in time, or the server has confirmed it no longer exists). Without
128
+ * this, a later run's "does a marker with a registrationId exist?" resume
129
+ * check keeps finding the SAME dead registration forever.
130
+ */
131
+ function clearMarker(projectRoot) {
132
+ const filePath = markerPath(projectRoot);
133
+ try {
134
+ if (existsSync(filePath))
135
+ unlinkSync(filePath);
136
+ }
137
+ catch {
138
+ // Best-effort, worst case the next run's register overwrites it anyway.
139
+ }
140
+ }
141
+ /**
142
+ * Adds `entry` to .gitignore if no existing pattern already covers it,
143
+ * including a trailing-`*` wildcard pattern (e.g. `.env*`, create-next-app's
144
+ * own default), the same glob EnvManager.checkGitignore() already honors,
145
+ * so this doesn't append a redundant, already-covered line. Used for BOTH
146
+ * credential-bearing paths this command writes: `.checkpoint/` (holds a
147
+ * pending claim token) and `.env.local` (holds the live, minted API key).
148
+ * Neither write is safe to leave ungitignored, a repo whose `.gitignore`
149
+ * doesn't already cover it (hand-rolled Express apps, a pruned/custom
150
+ * .gitignore) would otherwise let `git add .` stage a real credential
151
+ * straight into history.
152
+ */
153
+ function ensureGitignored(projectRoot, entry, label) {
154
+ const gitignorePath = join(projectRoot, ".gitignore");
155
+ const bare = entry.replace(/\/$/, "");
156
+ let content = existsSync(gitignorePath)
157
+ ? readFileSync(gitignorePath, "utf-8")
158
+ : "";
159
+ const alreadyIgnored = content
160
+ .split("\n")
161
+ .map((line) => line.trim())
162
+ .filter((line) => line && !line.startsWith("#"))
163
+ .some((line) => line === entry ||
164
+ line === bare ||
165
+ line === `/${bare}` ||
166
+ line === `/${entry}` ||
167
+ (line.endsWith("*") && bare.startsWith(line.slice(0, -1))));
168
+ if (alreadyIgnored)
169
+ return;
170
+ if (content && !content.endsWith("\n"))
171
+ content += "\n";
172
+ content += `${content ? "\n" : ""}# ${label}\n${entry}\n`;
173
+ writeFileSync(gitignorePath, content, "utf-8");
174
+ }
175
+ function scaffoldByFramework(framework, projectRoot, packageManager, projectId) {
176
+ if (framework === "nextjs")
177
+ return scaffoldNextjs(projectRoot, packageManager);
178
+ if (framework === "express")
179
+ return scaffoldExpress(projectRoot, packageManager);
180
+ return scaffoldBeacon(projectId, framework);
181
+ }
182
+ /** Poll the status endpoint roughly every 5s for up to 5 minutes (wall clock). */
183
+ async function pollForClaim(registrationId, json) {
184
+ const spinner = json ? null : ora("Waiting for you to claim...").start();
185
+ const outcome = await pollWithDeadline(async (signal) => {
186
+ try {
187
+ const status = await fetchCheckpointClaimStatus(registrationId, signal);
188
+ if (status === "claimed" || status === "expired") {
189
+ return { kind: "done", value: status };
190
+ }
191
+ return { kind: "continue" };
192
+ }
193
+ catch (error) {
194
+ // A definitive "no such registration" is fatal, the server has
195
+ // confirmed the row is gone, so retrying can never succeed. Any
196
+ // other failure (network hiccup, 5xx, our own abort) is
197
+ // transient, same tolerance `pollForClaimStatus`
198
+ // (claim-polling.ts) uses for the sibling knowthat.ai flow.
199
+ if (error?.code === "NOT_FOUND") {
200
+ return { kind: "fatal", error };
201
+ }
202
+ return { kind: "continue" };
203
+ }
204
+ }, { intervalMs: POLL_INTERVAL_MS, timeoutMs: POLL_TIMEOUT_MS });
205
+ if (outcome.outcome === "done") {
206
+ if (outcome.value === "claimed")
207
+ spinner?.succeed("Claimed!");
208
+ else
209
+ spinner?.fail("Claim link expired.");
210
+ return outcome.value;
211
+ }
212
+ if (outcome.outcome === "fatal") {
213
+ spinner?.fail("This registration no longer exists.");
214
+ return "not-found";
215
+ }
216
+ if (outcome.outcome === "interrupted") {
217
+ spinner?.warn("Skipped waiting for you to claim.");
218
+ return "pending";
219
+ }
220
+ spinner?.warn("Still waiting for you to claim.");
221
+ return "pending";
222
+ }
223
+ function printOrJson(json, humanLine, jsonPayload) {
224
+ if (json) {
225
+ console.log(JSON.stringify(jsonPayload, null, 2));
226
+ }
227
+ else {
228
+ console.log(humanLine);
229
+ }
230
+ }
231
+ /**
232
+ * Announces the claim URL (+ confirmation code, when known) on both the
233
+ * fresh-register and resume paths.
234
+ *
235
+ * In --json mode, claimUrl is included ONLY when `revealClaimUrl` is set:
236
+ * the URL carries a live, one-time claim token, and --json output is the
237
+ * shape most likely to end up piped into a log or another tool. Without
238
+ * the flag, --json prints registrationId + confirmationCode, enough for
239
+ * a human watching the SAME terminal to cross-check the claim page, but
240
+ * nothing an automated log-scraper could use to steal the claim.
241
+ * Non-json (human) mode always prints the URL either way: a human has to
242
+ * literally click it, and that's the terminal they're already watching.
243
+ *
244
+ * The warning lines go to stderr, not through printOrJson: they must
245
+ * stay visible in --json mode too (a leaked pre-claim URL is exactly the
246
+ * failure this exists to catch, silence there defeats the point) without
247
+ * corrupting the JSON-per-line stream automation parses from stdout.
248
+ */
249
+ function announceClaim(json, revealClaimUrl, registrationId, claimUrl, confirmationCode) {
250
+ const jsonPayload = {
251
+ status: "pending",
252
+ registrationId,
253
+ confirmationCode,
254
+ };
255
+ if (revealClaimUrl) {
256
+ jsonPayload.claimUrl = claimUrl;
257
+ }
258
+ printOrJson(json, `Claim your project: ${chalk.cyan(claimUrl)}`, jsonPayload);
259
+ // The URL itself is shown either in the human line above (always) or in
260
+ // the JSON payload (only with --reveal-claim-url). When neither holds
261
+ // (--json without the flag), no link reached the user anywhere, so the
262
+ // "this link" warning below would refer to something they never saw.
263
+ const urlWasShown = !json || revealClaimUrl;
264
+ if (json && !urlWasShown) {
265
+ console.error(chalk.gray("The claim URL is left out of --json output by default (it carries a live claim token). Re-run with --reveal-claim-url to include it."));
266
+ }
267
+ if (confirmationCode) {
268
+ console.error(chalk.yellow(`Confirmation code: ${confirmationCode}. Check this matches the claim page before approving.`));
269
+ }
270
+ if (urlWasShown) {
271
+ console.error(chalk.gray("This link contains a live claim token. Don't share it or paste it into a public log."));
272
+ }
273
+ }
274
+ /**
275
+ * Reports a failure uniformly: the human/JSON message plus a non-zero
276
+ * exit code. Never calls `process.exit()` directly, that would race
277
+ * pending stdout writes, setting `exitCode` lets Node exit naturally
278
+ * once the event loop drains, and needs no NODE_ENV/VITEST special-casing
279
+ * to stay testable.
280
+ */
281
+ function reportFailure(json, error, fallbackMessage, guidance) {
282
+ const baseMessage = error instanceof Error ? error.message : fallbackMessage;
283
+ const humanLine = guidance ? `${baseMessage} ${guidance}` : baseMessage;
284
+ printOrJson(json, chalk.red(humanLine), {
285
+ success: false,
286
+ error: baseMessage,
287
+ });
288
+ process.exitCode = 1;
289
+ }
290
+ /**
291
+ * Writes .env.local (every framework, the key is minted either way, so
292
+ * discarding it for the keyless Beacon path would be the only record of
293
+ * it ever existing outside the dashboard) and scaffolds the Detect layer,
294
+ * then flips the marker to `setupComplete`, the ONLY signal the
295
+ * top-of-function idempotency check trusts. Split out of `checkpointInit`
296
+ * so it can run from two call sites: right after a fresh exchange, or on
297
+ * a resumed run that already has a persisted `apiKey` because a prior
298
+ * run's finish step never completed.
299
+ */
300
+ async function finishSetup(projectRoot, framework, platformInfo, marker, json) {
301
+ let scaffold;
302
+ try {
303
+ // .env.local is about to hold a live, usable project API key, make
304
+ // sure it can't land in git BEFORE writing the secret into it, same
305
+ // as the .checkpoint/ guard for the claim token.
306
+ ensureGitignored(projectRoot, ".env.local", "Local environment variables");
307
+ writeCheckpointEnv(projectRoot, {
308
+ CHECKPOINT_API_KEY: marker.apiKey,
309
+ CHECKPOINT_PROJECT_ID: marker.projectId,
310
+ });
311
+ scaffold = scaffoldByFramework(framework, projectRoot, platformInfo.packageManager, marker.projectId);
312
+ if (!json) {
313
+ console.log(`\n${scaffold.message}`);
314
+ }
315
+ // Fully done: the key is safely in .env.local, drop it from the
316
+ // marker along with the now-spent claimToken, and flip setupComplete,
317
+ // the signal the top-of-function idempotency check looks for.
318
+ // Re-writing (not appending) keeps exactly one on-disk copy.
319
+ writeMarker(projectRoot, {
320
+ registrationId: marker.registrationId,
321
+ claimUrl: marker.claimUrl,
322
+ projectId: marker.projectId,
323
+ dashboardUrl: marker.dashboardUrl,
324
+ organizationId: marker.organizationId,
325
+ setupComplete: true,
326
+ });
327
+ }
328
+ catch (error) {
329
+ // The marker written right after exchange (holding apiKey) is still
330
+ // on disk, untouched, at this point, a re-run resumes straight back
331
+ // into this same finish step instead of losing the key or
332
+ // re-exchanging an already-spent token.
333
+ reportFailure(json, error, "Failed to finish setup.", "Run `mcpi checkpoint init` again to retry.");
334
+ return;
335
+ }
336
+ printOrJson(json, chalk.bold.green(`\nDone. Your project: ${marker.dashboardUrl}`), {
337
+ success: true,
338
+ projectId: marker.projectId,
339
+ organizationId: marker.organizationId,
340
+ dashboardUrl: marker.dashboardUrl,
341
+ scaffold: {
342
+ framework: scaffold.framework,
343
+ installed: scaffold.installed,
344
+ setupRan: scaffold.setupRan,
345
+ },
346
+ });
347
+ }
348
+ export async function checkpointInit(options = {}) {
349
+ const { json = false, revealClaimUrl = false } = options;
350
+ const projectRoot = process.cwd();
351
+ const existing = readMarker(projectRoot);
352
+ // Idempotency: already fully set up (env written + scaffold ran).
353
+ if (existing?.setupComplete) {
354
+ printOrJson(json, chalk.green(`Already set up. Your project: ${existing.dashboardUrl ?? ""}`), {
355
+ success: true,
356
+ alreadySetUp: true,
357
+ projectId: existing.projectId,
358
+ dashboardUrl: existing.dashboardUrl,
359
+ });
360
+ return;
361
+ }
362
+ // To stderr, not stdout: this must stay visible whether or not --json is
363
+ // set, without corrupting the JSON stream automation parses from stdout.
364
+ if (isInsecureCheckpointOrigin()) {
365
+ console.error(chalk.yellow("Warning: CHECKPOINT_API_URL is plain http on a non-localhost host. " +
366
+ "The claim token and, once claimed, your API key cross that connection in the clear."));
367
+ }
368
+ const platformInfo = detectPlatform(projectRoot);
369
+ const framework = detectCheckpointFramework(projectRoot, platformInfo);
370
+ if (!json) {
371
+ console.log(chalk.cyan(`\nDetected: ${checkpointFrameworkLabel(framework)}`));
372
+ }
373
+ // Resume after a successful exchange whose finish step (env write +
374
+ // scaffold) never completed, a crash, a full disk, the process getting
375
+ // killed. The claim token is already spent (the server accepts an
376
+ // exchange exactly once), so finish with the persisted credential
377
+ // instead of registering fresh or re-exchanging, which would 409.
378
+ if (existing?.projectId && existing?.apiKey && existing?.dashboardUrl) {
379
+ await finishSetup(projectRoot, framework, platformInfo, {
380
+ registrationId: existing.registrationId,
381
+ claimUrl: existing.claimUrl,
382
+ projectId: existing.projectId,
383
+ dashboardUrl: existing.dashboardUrl,
384
+ organizationId: existing.organizationId,
385
+ apiKey: existing.apiKey,
386
+ }, json);
387
+ return;
388
+ }
389
+ let registrationId;
390
+ let claimToken;
391
+ let claimUrl;
392
+ let confirmationCode;
393
+ if (existing?.registrationId && existing.claimToken) {
394
+ // Resume: skip register, reuse the persisted token, reprint the URL
395
+ // (the user may have lost the terminal output from the first run).
396
+ // Reprints the SERVER-ISSUED claimUrl persisted at register time, not
397
+ // a client-side reconstruction off the current CHECKPOINT_API_URL --
398
+ // if that env var differs from what it was at register time (a
399
+ // different machine, a flipped endpoint), a rebuilt URL would point
400
+ // at the wrong place while the original is still the valid one.
401
+ // Falls back to reconstructing only for a marker written before this
402
+ // CLI persisted claimUrl.
403
+ registrationId = existing.registrationId;
404
+ claimToken = existing.claimToken;
405
+ claimUrl = existing.claimUrl ?? buildCheckpointClaimUrl(claimToken);
406
+ // Undefined only for a marker written before this CLI persisted the
407
+ // code -- announceClaim degrades gracefully and just omits the line.
408
+ confirmationCode = existing.confirmationCode;
409
+ if (!json) {
410
+ showInfo("Resuming a previous `checkpoint init` run.");
411
+ }
412
+ announceClaim(json, revealClaimUrl, registrationId, claimUrl, confirmationCode);
413
+ }
414
+ else {
415
+ const spinner = json ? null : ora("Registering with Checkpoint...").start();
416
+ let registered;
417
+ try {
418
+ registered = await registerCheckpointProject({
419
+ domainHint: detectDomainHint(projectRoot),
420
+ repoName: detectRepoName(projectRoot),
421
+ framework,
422
+ });
423
+ }
424
+ catch (error) {
425
+ spinner?.fail("Registration failed.");
426
+ reportFailure(json, error, "Failed to register with Checkpoint.");
427
+ return;
428
+ }
429
+ spinner?.succeed("Registered with Checkpoint.");
430
+ registrationId = registered.registrationId;
431
+ claimToken = registered.claimToken;
432
+ claimUrl = registered.claimUrl;
433
+ confirmationCode = registered.confirmationCode;
434
+ // Gitignore BEFORE the write, same ordering as the .env.local guard
435
+ // below, the marker is about to hold a live claim token, so it must
436
+ // never be writable-then-gitignored (a window where `git add .` could
437
+ // pick it up).
438
+ ensureGitignored(projectRoot, `${MARKER_DIR}/`, "Checkpoint CLI local state");
439
+ writeMarker(projectRoot, {
440
+ registrationId,
441
+ claimToken,
442
+ claimUrl,
443
+ confirmationCode,
444
+ });
445
+ // In --json mode this is the ONLY line naming the claim URL: with no
446
+ // other announcement, automation polling the JSON stream would have
447
+ // no way to open/surface the link and could only wait out the poll
448
+ // cap and fail.
449
+ announceClaim(json, revealClaimUrl, registrationId, claimUrl, confirmationCode);
450
+ if (!json) {
451
+ // Only ever hand the OS's default-protocol-handler a URL that's
452
+ // both http(s) and actually points at the configured Checkpoint
453
+ // origin -- assertRegisterResult already rejects a non-http(s)
454
+ // claimUrl outright, but a scheme/host check right here, at the
455
+ // one place this value reaches a system-level open() call, is
456
+ // cheap defense in depth against a compromised or misconfigured
457
+ // origin returning something like a file:/vscode: URI.
458
+ const opensSafely = isHttpUrl(claimUrl) && new URL(claimUrl).origin === checkpointOrigin();
459
+ if (opensSafely) {
460
+ try {
461
+ await open(claimUrl);
462
+ }
463
+ catch {
464
+ // Best-effort, the printed URL above is the fallback.
465
+ }
466
+ }
467
+ }
468
+ }
469
+ const status = await pollForClaim(registrationId, json);
470
+ if (status === "not-found") {
471
+ // The server confirmed this registration no longer exists, resuming
472
+ // would just poll (or exchange) the same dead id forever.
473
+ clearMarker(projectRoot);
474
+ reportFailure(json, new Error("This registration no longer exists on Checkpoint."), "This registration no longer exists on Checkpoint.", "Run `mcpi checkpoint init` again to start fresh.");
475
+ return;
476
+ }
477
+ if (status !== "claimed") {
478
+ if (status === "expired") {
479
+ // Drop the marker so re-running actually registers fresh instead of
480
+ // resuming (and re-polling) this same dead registration forever,
481
+ // the message below promises a NEW link, so the next run must
482
+ // deliver one.
483
+ clearMarker(projectRoot);
484
+ }
485
+ const message = status === "expired"
486
+ ? "This claim link expired. Run `mcpi checkpoint init` again to get a new one."
487
+ : "Run `mcpi checkpoint init` again after claiming to finish setup.";
488
+ printOrJson(json, chalk.yellow(message), {
489
+ success: false,
490
+ status,
491
+ message,
492
+ // Expired means the link is dead, the message above already
493
+ // promises a fresh one on re-run, so don't hand back a stale URL.
494
+ // Otherwise, same --reveal-claim-url gating as announceClaim: a
495
+ // live claim token doesn't belong in --json output by default.
496
+ claimUrl: status === "expired" || !revealClaimUrl ? undefined : claimUrl,
497
+ });
498
+ return; // exit 0 -- the resume path above makes re-running the fix.
499
+ }
500
+ const spinner = json ? null : ora("Finishing setup...").start();
501
+ let exchanged;
502
+ try {
503
+ exchanged = await exchangeCheckpointClaim(claimToken);
504
+ }
505
+ catch (error) {
506
+ spinner?.fail("Could not finish setup.");
507
+ const code = error?.code;
508
+ // A definitive rejection (unknown token, already spent, expired)
509
+ // means retrying with the SAME token can never succeed, the server
510
+ // has permanently closed this door. Clear the marker so a re-run
511
+ // registers fresh instead of retrying the same dead exchange forever.
512
+ // Anything else (network-shaped, 5xx) is transient: keep the marker
513
+ // so a re-run resumes and simply retries the exchange.
514
+ const definitive = code === "NOT_FOUND" ||
515
+ code === "ALREADY_EXCHANGED" ||
516
+ code === "EXPIRED";
517
+ if (definitive) {
518
+ clearMarker(projectRoot);
519
+ }
520
+ reportFailure(json, error, "Failed to exchange claim token.", definitive
521
+ ? "Run `mcpi checkpoint init` again to start fresh."
522
+ : "Run `mcpi checkpoint init` again to retry.");
523
+ return;
524
+ }
525
+ // Not "Set up complete" -- finishSetup (env write + scaffold) hasn't
526
+ // run yet and can still fail, which would leave a contradictory green
527
+ // checkmark on screen right above the error it then reports.
528
+ spinner?.succeed("Claim exchanged.");
529
+ // Persist immediately: exchange succeeds exactly once, so this is the
530
+ // only moment the API key exists. If the finish step below fails or the
531
+ // process dies before it completes, a re-run must resume from here
532
+ // rather than re-exchanging (which the server would reject with 409).
533
+ const exchangedMarker = {
534
+ registrationId,
535
+ claimUrl,
536
+ projectId: exchanged.projectId,
537
+ dashboardUrl: exchanged.dashboardUrl,
538
+ organizationId: exchanged.organizationId,
539
+ apiKey: exchanged.apiKey,
540
+ };
541
+ writeMarker(projectRoot, exchangedMarker);
542
+ await finishSetup(projectRoot, framework, platformInfo, exchangedMarker, json);
543
+ }
544
+ export function createCheckpointCommand() {
545
+ const checkpoint = new Command("checkpoint").description("Set up Checkpoint Detect for this repo");
546
+ checkpoint
547
+ .command("init")
548
+ .description("Register this repo with Checkpoint, claim it in your browser, and scaffold detection")
549
+ .option("--json", "Output in JSON format for automation")
550
+ .option("--reveal-claim-url", "Include the live claim URL in --json output. Off by default: the URL carries a one-time claim token, and --json output is the shape most likely to end up piped into a log.")
551
+ .action((options) => checkpointInit(options));
552
+ return checkpoint;
553
+ }
554
+ //# sourceMappingURL=checkpoint-init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpoint-init.js","sourceRoot":"","sources":["../../src/commands/checkpoint-init.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import type { Receipt } from "@kya-os/contracts/registry";
1
2
  interface ReceiptsOptions {
2
3
  json?: boolean;
3
4
  path?: string;
@@ -7,5 +8,15 @@ interface ReceiptsOptions {
7
8
  * List and manage stored receipts
8
9
  */
9
10
  export declare function receipts(options?: ReceiptsOptions): Promise<void>;
11
+ /**
12
+ * Legacy registry receipts do not carry the signed KYA-OS audit envelopes
13
+ * required by the core verifier. Never promote structural well-formedness to
14
+ * cryptographic verification.
15
+ */
16
+ export declare function verifyReceipt(receipt: Receipt): Promise<{
17
+ status: "invalid" | "unsupported";
18
+ valid: false;
19
+ error: string;
20
+ }>;
10
21
  export {};
11
22
  //# sourceMappingURL=receipts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"receipts.d.ts","sourceRoot":"","sources":["../../src/commands/receipts.ts"],"names":[],"mappings":"AAOA,UAAU,eAAe;IACvB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,OAAO,GAAE,eAAoB,iBAgM3D"}
1
+ {"version":3,"file":"receipts.d.ts","sourceRoot":"","sources":["../../src/commands/receipts.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAE1D,UAAU,eAAe;IACvB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,OAAO,GAAE,eAAoB,iBAqM3D;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,OAAO,GACf,OAAO,CAAC;IACT,MAAM,EAAE,SAAS,GAAG,aAAa,CAAC;IAClC,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CA0BD"}