codequill 0.8.1-beta.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.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +121 -0
  3. package/dist/commands/attest.js +442 -0
  4. package/dist/commands/attest.js.map +1 -0
  5. package/dist/commands/backup.js +370 -0
  6. package/dist/commands/backup.js.map +1 -0
  7. package/dist/commands/claim.js +104 -0
  8. package/dist/commands/claim.js.map +1 -0
  9. package/dist/commands/log.js +188 -0
  10. package/dist/commands/log.js.map +1 -0
  11. package/dist/commands/login.js +147 -0
  12. package/dist/commands/login.js.map +1 -0
  13. package/dist/commands/prove.js +244 -0
  14. package/dist/commands/prove.js.map +1 -0
  15. package/dist/commands/publish.js +243 -0
  16. package/dist/commands/publish.js.map +1 -0
  17. package/dist/commands/pull.js +174 -0
  18. package/dist/commands/pull.js.map +1 -0
  19. package/dist/commands/quota.js +94 -0
  20. package/dist/commands/quota.js.map +1 -0
  21. package/dist/commands/revoke.js +97 -0
  22. package/dist/commands/revoke.js.map +1 -0
  23. package/dist/commands/snapshot.js +128 -0
  24. package/dist/commands/snapshot.js.map +1 -0
  25. package/dist/commands/status.js +234 -0
  26. package/dist/commands/status.js.map +1 -0
  27. package/dist/commands/verifyAttestation.js +212 -0
  28. package/dist/commands/verifyAttestation.js.map +1 -0
  29. package/dist/commands/verifyProof.js +145 -0
  30. package/dist/commands/verifyProof.js.map +1 -0
  31. package/dist/commands/wait.js +36 -0
  32. package/dist/commands/wait.js.map +1 -0
  33. package/dist/commands/who.js +55 -0
  34. package/dist/commands/who.js.map +1 -0
  35. package/dist/commands/why.js +412 -0
  36. package/dist/commands/why.js.map +1 -0
  37. package/dist/index.js +50 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/launcher.js +69 -0
  40. package/dist/launcher.js.map +1 -0
  41. package/dist/services/api.js +51 -0
  42. package/dist/services/api.js.map +1 -0
  43. package/dist/services/apiClient.js +166 -0
  44. package/dist/services/apiClient.js.map +1 -0
  45. package/dist/services/authStore.js +84 -0
  46. package/dist/services/authStore.js.map +1 -0
  47. package/dist/services/config.js +19 -0
  48. package/dist/services/config.js.map +1 -0
  49. package/dist/services/confirm.js +58 -0
  50. package/dist/services/confirm.js.map +1 -0
  51. package/dist/services/crypto.js +38 -0
  52. package/dist/services/crypto.js.map +1 -0
  53. package/dist/services/errors.js +17 -0
  54. package/dist/services/errors.js.map +1 -0
  55. package/dist/services/fs.js +25 -0
  56. package/dist/services/fs.js.map +1 -0
  57. package/dist/services/git.js +121 -0
  58. package/dist/services/git.js.map +1 -0
  59. package/dist/services/manifests/attestationManifest.js +35 -0
  60. package/dist/services/manifests/attestationManifest.js.map +1 -0
  61. package/dist/services/manifests/proofManifest.js +151 -0
  62. package/dist/services/manifests/proofManifest.js.map +1 -0
  63. package/dist/services/manifests/snapshotManifest.js +214 -0
  64. package/dist/services/manifests/snapshotManifest.js.map +1 -0
  65. package/dist/services/merkle.js +92 -0
  66. package/dist/services/merkle.js.map +1 -0
  67. package/dist/services/paths.js +16 -0
  68. package/dist/services/paths.js.map +1 -0
  69. package/dist/services/snapshotIndex.js +401 -0
  70. package/dist/services/snapshotIndex.js.map +1 -0
  71. package/dist/services/txWaiter.js +84 -0
  72. package/dist/services/txWaiter.js.map +1 -0
  73. package/dist/services/ui.js +98 -0
  74. package/dist/services/ui.js.map +1 -0
  75. package/dist/services/utilities.js +45 -0
  76. package/dist/services/utilities.js.map +1 -0
  77. package/dist/services/zip.js +24 -0
  78. package/dist/services/zip.js.map +1 -0
  79. package/dist/types/api.js +2 -0
  80. package/dist/types/api.js.map +1 -0
  81. package/dist/version.js +7 -0
  82. package/dist/version.js.map +1 -0
  83. package/package.json +52 -0
@@ -0,0 +1,188 @@
1
+ import { colors, relativeTime, shortCommit, shortHash, spinner } from '../services/ui.js';
2
+ import { apiClient } from '../services/apiClient.js';
3
+ import { loadTokens, isExpired } from '../services/authStore.js';
4
+ import { ApiError } from '../services/errors.js';
5
+ import { detectGitRepo, deriveRepoName } from '../services/git.js';
6
+ import { SnapshotIndex } from '../services/snapshotIndex.js';
7
+ function logSortTs(it) {
8
+ return (typeof it.timestamp === 'number' && Number.isFinite(it.timestamp)) ? it.timestamp : 0;
9
+ }
10
+ function canTryBackend() {
11
+ const tokens = loadTokens();
12
+ if (!tokens)
13
+ return false;
14
+ if (isExpired(tokens) && !tokens.refresh_token)
15
+ return false;
16
+ return true;
17
+ }
18
+ async function fetchPublishedSnapshots(repoName) {
19
+ const res = await apiClient.get(`/v1/cli/snapshots?repo_name=${encodeURIComponent(repoName)}`);
20
+ const list = Array.isArray(res?.snapshots) ? res.snapshots : [];
21
+ return list.map((p) => ({
22
+ snapshot_id: p.snapshot_id,
23
+ merkle_root: p.merkle_root,
24
+ commit_hash: p.commit_hash,
25
+ published_at: p.published_at,
26
+ tx_hash: p.tx_hash,
27
+ chain_id: p.chain_id,
28
+ manifest_cid: p.manifest_cid,
29
+ wallet_address: p.wallet_address,
30
+ }));
31
+ }
32
+ export async function handleLog(opts) {
33
+ // Must run inside repo (no --path)
34
+ const git = detectGitRepo(process.cwd());
35
+ if (!git.isRepo || !git.root) {
36
+ console.error(colors.error('Not a git repository. Run this command inside a git repository.'));
37
+ process.exitCode = 1;
38
+ return;
39
+ }
40
+ const repoName = deriveRepoName(git.root, git.remote);
41
+ if (!repoName) {
42
+ console.error(colors.error('Unable to determine repo name from git remote.'));
43
+ console.error(colors.dim('Hint: add a GitHub origin remote, or ensure `origin` is configured.'));
44
+ process.exitCode = 1;
45
+ return;
46
+ }
47
+ // Load index (self-heals / rebuilds from disk if missing/corrupt)
48
+ const sIdx = spinner('Loading snapshot index ...');
49
+ const index = new SnapshotIndex({ repoRoot: git.root, repoName });
50
+ try {
51
+ await index.load();
52
+ sIdx.succeed(colors.success('Index loaded.'));
53
+ }
54
+ catch (e) {
55
+ sIdx.fail(colors.warn('Could not load index (will attempt rebuild).'));
56
+ try {
57
+ await index.rebuildFromDisk();
58
+ await index.save();
59
+ }
60
+ catch {
61
+ // If even rebuild fails, keep going with empty list.
62
+ }
63
+ }
64
+ // Optional: enrich with backend published info (only if logged in)
65
+ if (canTryBackend()) {
66
+ const sNet = spinner('Fetching published snapshots ...');
67
+ try {
68
+ const published = await fetchPublishedSnapshots(repoName);
69
+ index.enrichFromBackend(published);
70
+ await index.save();
71
+ sNet.succeed(colors.success(`Loaded ${published.length} published snapshot${published.length === 1 ? '' : 's'}.`));
72
+ }
73
+ catch (e) {
74
+ sNet.fail(colors.warn('Could not load published snapshots (showing local/index only).'));
75
+ if (e instanceof ApiError) {
76
+ console.error(colors.dim(`Backend: ${e.message} (${e.status})`));
77
+ if (e.requestId)
78
+ console.error(colors.dim(`Request ID: ${e.requestId}`));
79
+ }
80
+ else {
81
+ console.error(colors.dim(String(e?.message || e)));
82
+ }
83
+ // continue with disk-only index
84
+ }
85
+ }
86
+ else {
87
+ // Not logged in: keep quiet but helpful (no auth prompts unless you want)
88
+ // console.error(colors.dim(`Not logged in. Showing local snapshots only. (${getConfigFilePath()})`));
89
+ }
90
+ const items = index.list(); // already sorted newest-first after load/save
91
+ // De-dupe rows (same snapshot appearing via local + published paths)
92
+ const keyOf = (r) => {
93
+ // Prefer snapshot_id if you have it in your row model
94
+ if (r.snapshot_id)
95
+ return `sid:${String(r.snapshot_id)}`;
96
+ // Else use merkle_root if available
97
+ if (r.merkle_root)
98
+ return `root:${String(r.merkle_root)}`;
99
+ // Fallback: id
100
+ return `id:${String(r.id)}`;
101
+ };
102
+ const score = (r) => {
103
+ // Prefer published rows, then prefer those with a timestamp
104
+ const kindScore = r.kind === 'published' ? 10 : 0;
105
+ const tsScore = typeof r.ts === 'number' ? r.ts : 0;
106
+ return kindScore * 1_000_000_000 + tsScore;
107
+ };
108
+ // De-dupe by merkle_root (one row per snapshot/root)
109
+ const dedup = new Map();
110
+ for (const it of items) {
111
+ const k = String(it.merkle_root ?? '').toLowerCase().trim();
112
+ if (!k)
113
+ continue;
114
+ const prev = dedup.get(k);
115
+ if (!prev) {
116
+ dedup.set(k, it);
117
+ continue;
118
+ }
119
+ // Prefer the one that has published meta (and/or file), else keep the newest by sort ts
120
+ const prevScore = (prev.published ? 1_000_000_000 : 0) +
121
+ (prev.file ? 100_000 : 0) +
122
+ logSortTs(prev);
123
+ const itScore = (it.published ? 1_000_000_000 : 0) +
124
+ (it.file ? 100_000 : 0) +
125
+ logSortTs(it);
126
+ if (itScore > prevScore)
127
+ dedup.set(k, it);
128
+ }
129
+ const limit = opts.limit && opts.limit > 0 ? opts.limit : undefined;
130
+ const rows = Array.from(dedup.values());
131
+ rows.sort((a, b) => logSortTs(b) - logSortTs(a));
132
+ const shown = limit ? rows.slice(0, limit) : rows;
133
+ const aheadCount = rows.filter((r) => r.kind === 'local').length;
134
+ console.log('');
135
+ console.log(colors.bold('πŸ“œ CodeQuill Snapshot Log'));
136
+ console.log(colors.dim('────────────────────────'));
137
+ if (shown.length === 0) {
138
+ console.log(colors.dim('No snapshots found.'));
139
+ console.log(colors.dim('Tip: run `codequill snapshot` to create one.'));
140
+ return;
141
+ }
142
+ // βœ” published | β†₯ local-only
143
+ for (const it of shown) {
144
+ const isPublished = !!it.published;
145
+ const isRemoteOnly = it.kind === 'remote' && !it.file;
146
+ const icon = isPublished ? colors.success('βœ”') : isRemoteOnly ? colors.info('☁') : colors.warn('β†₯');
147
+ const kindLabel = isPublished
148
+ ? colors.success(`published (${relativeTime(it.published?.published_at ?? 0)})`)
149
+ : isRemoteOnly
150
+ ? colors.info('remote')
151
+ : colors.warn('local only');
152
+ const ts = it.timestamp;
153
+ const when = ts ? colors.dim(relativeTime(ts)) : colors.dim('β€”');
154
+ const idLeft = colors.dim(shortHash(it.merkle_root, 10).padEnd(12));
155
+ const commit = it.commit ? colors.dim(shortCommit(it.commit).padEnd(14)) : colors.dim('β€”'.padEnd(14));
156
+ const snapId = colors.info(it.published?.snapshot_id ?? "");
157
+ console.log(`${icon} ${commit} ${when.padEnd(25)} ${kindLabel.padEnd(40)} ${snapId}`);
158
+ }
159
+ console.log(colors.dim('────────────────────────'));
160
+ // Summary
161
+ const latestLocal = index.latestLocalRoot();
162
+ const latestPub = index.latestPublishedRoot();
163
+ console.log(colors.dim(`Latest local: ${latestLocal ? shortHash(latestLocal, 16) : 'β€”'}`));
164
+ console.log(colors.dim(`Latest published: ${latestPub ? shortHash(latestPub, 16) : 'β€”'}`));
165
+ if (aheadCount > 0) {
166
+ console.log(colors.dim(`Status: ${aheadCount} snapshot${aheadCount === 1 ? '' : 's'} ahead of chain`));
167
+ }
168
+ else {
169
+ // Only say β€œup to date” if we actually have published metadata in index
170
+ const hasAnyPublished = items.some((x) => !!x.published);
171
+ if (hasAnyPublished)
172
+ console.log(colors.dim('Status: up to date with chain'));
173
+ else
174
+ console.log(colors.dim('Status: local snapshots only'));
175
+ }
176
+ }
177
+ export function registerLogCommand(program) {
178
+ program
179
+ .command('log')
180
+ .description('Show snapshot history for this repository (ordered by published time when available)')
181
+ .option('--limit <n>', 'Limit output rows', (v) => parseInt(v, 10))
182
+ .action(async (options) => {
183
+ await handleLog({
184
+ limit: options.limit,
185
+ });
186
+ });
187
+ }
188
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/commands/log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,147 @@
1
+ import { apiClient } from '../services/apiClient.js';
2
+ import { spinner, colors, tryOpenBrowser } from '../services/ui.js';
3
+ import { saveTokens } from '../services/authStore.js';
4
+ import { ApiError } from '../services/errors.js';
5
+ import { CLI_VERSION } from '../version.js';
6
+ import { getConfigFilePath } from '../services/config.js';
7
+ async function sleep(ms) {
8
+ return new Promise((res) => setTimeout(res, ms));
9
+ }
10
+ export async function handleLogin() {
11
+ // 1) Initialize CLI login (Stripe-style approval phrase)
12
+ const init = await apiClient.post('/v1/cli/auth/init', {
13
+ client_name: 'codequill-cli',
14
+ client_version: CLI_VERSION,
15
+ }, { auth: false });
16
+ const interval = Math.max(2, Math.min(30, init.interval ?? 5));
17
+ const deviceId = init.session_id ||
18
+ init.sessionId ||
19
+ init.device_code ||
20
+ init.deviceCode ||
21
+ init.code ||
22
+ init.id ||
23
+ init.session;
24
+ const urlRaw = init.login_url ||
25
+ init.authorization_url ||
26
+ init.authorize_url ||
27
+ init.verification_url ||
28
+ init.url ||
29
+ '';
30
+ const url = typeof urlRaw === 'string' ? urlRaw : String(urlRaw ?? '');
31
+ console.log(colors.bold('Opening browser for login…'));
32
+ if (typeof url === 'string' && url.length > 0) {
33
+ tryOpenBrowser(url);
34
+ console.log('If the browser does not open, visit this URL:', colors.info(url));
35
+ }
36
+ else {
37
+ console.log(colors.warn('Login URL not provided by server. Please open the CodeQuill app and approve the pending CLI session.'));
38
+ }
39
+ const phrase = init.phrase || init.approval_phrase || init.code_phrase || '';
40
+ if (phrase) {
41
+ console.log('On the authorization page, you should see this phrase:', colors.bold(`"${String(phrase)}"`));
42
+ }
43
+ // 2) Poll for approval/token
44
+ const s = spinner('Waiting for approval…');
45
+ const started = Date.now();
46
+ const timeoutMs = 3 * 60 * 1000; // 3 minutes default timeout
47
+ try {
48
+ const candidateKeys = ['session_id', 'sessionId', 'device_code', 'deviceCode', 'code', 'id', 'session'];
49
+ let workingKey = null;
50
+ while (true) {
51
+ if (Date.now() - started > timeoutMs) {
52
+ throw new ApiError('Login timed out. Please try again.', 408);
53
+ }
54
+ try {
55
+ let tokenRes = null;
56
+ if (workingKey) {
57
+ tokenRes = await apiClient.post('/v1/cli/auth/token', { [workingKey]: deviceId }, { auth: false });
58
+ }
59
+ else {
60
+ // try keys one by one until server accepts (non-400)
61
+ let lastErr = null;
62
+ for (const k of candidateKeys) {
63
+ try {
64
+ tokenRes = await apiClient.post('/v1/cli/auth/token', { [k]: deviceId }, { auth: false });
65
+ workingKey = k;
66
+ break;
67
+ }
68
+ catch (err) {
69
+ lastErr = err;
70
+ if (err instanceof ApiError && (err.status === 400 || err.status === 422)) {
71
+ // try next key
72
+ continue;
73
+ }
74
+ throw err; // other errors propagate
75
+ }
76
+ }
77
+ if (!workingKey && lastErr)
78
+ throw lastErr;
79
+ }
80
+ if (tokenRes.status === 'pending') {
81
+ s.text = 'Waiting for approval…';
82
+ await sleep(interval * 1000);
83
+ continue;
84
+ }
85
+ if (tokenRes.status === 'rejected') {
86
+ s.fail(colors.error('Login was rejected in the browser. No changes were made.'));
87
+ process.exitCode = 1;
88
+ return;
89
+ }
90
+ if (tokenRes.status === 'expired') {
91
+ s.fail(colors.warn("Your login session expired. Please run 'codequill login' again."));
92
+ process.exitCode = 1;
93
+ return;
94
+ }
95
+ // Some servers return tokens directly without a status field
96
+ const success = tokenRes;
97
+ if (!success || !success.access_token) {
98
+ throw new ApiError('Unexpected response from auth server', 500);
99
+ }
100
+ const margin = 30; // seconds safety margin
101
+ const nowSec = Math.floor(Date.now() / 1000);
102
+ const accessTtl = success.access_expires_in ?? success.expires_in ?? 0;
103
+ const refreshTtl = success.refresh_expires_in ?? (30 * 24 * 60 * 60); // default 30d if not provided
104
+ const access_expires_at = nowSec + Math.max(0, accessTtl - margin);
105
+ const refresh_expires_at = nowSec + Math.max(0, refreshTtl - margin);
106
+ saveTokens({
107
+ access_token: success.access_token,
108
+ refresh_token: success.refresh_token,
109
+ expires_at: access_expires_at,
110
+ access_expires_at,
111
+ refresh_expires_at,
112
+ });
113
+ s.succeed(colors.success('Login successful! Your CLI session is now active.'));
114
+ console.log(colors.dim(`Tokens saved to: ${getConfigFilePath()}`));
115
+ console.log(colors.dim("Tip: run `codequill whoami` to verify your session."));
116
+ return;
117
+ }
118
+ catch (e) {
119
+ if (e instanceof ApiError && e.status === 202) {
120
+ // Some backends may return 202 with a body. Wait and retry.
121
+ await sleep(interval * 1000);
122
+ continue;
123
+ }
124
+ throw e;
125
+ }
126
+ }
127
+ }
128
+ catch (e) {
129
+ s.fail(colors.error('Login failed.'));
130
+ if (e instanceof ApiError) {
131
+ console.error(colors.error(`${e.message} (${e.status})`));
132
+ }
133
+ else {
134
+ console.error(colors.error(String(e?.message || e)));
135
+ }
136
+ process.exitCode = 1;
137
+ }
138
+ }
139
+ export function registerLoginCommand(program) {
140
+ program
141
+ .command('login')
142
+ .description('Authenticate the CLI using approval phrase flow')
143
+ .action(async () => {
144
+ await handleLogin();
145
+ });
146
+ }
147
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,244 @@
1
+ import path from "node:path";
2
+ import fs from "node:fs/promises";
3
+ import { colors, shortHash, spinner, tryOpenBrowser } from "../services/ui.js";
4
+ import { resolvePath } from "../services/paths.js";
5
+ import { writeFileUtf8 } from "../services/fs.js";
6
+ import { keccakHex } from "../services/crypto.js";
7
+ import { normalizePath } from "../services/merkle.js";
8
+ import { ApiError } from "../services/errors.js";
9
+ import { assertAuthenticated, chainName } from "../services/utilities.js";
10
+ import { buildProofManifest } from "../services/manifests/proofManifest.js";
11
+ import { fetchSnapshotBundle } from "../services/api.js";
12
+ import { apiClient } from "../services/apiClient.js";
13
+ async function sleep(ms) {
14
+ return new Promise((res) => setTimeout(res, ms));
15
+ }
16
+ async function resolvePathHashWithDeviceFlow(args) {
17
+ if (!assertAuthenticated())
18
+ throw new ApiError("Not authenticated", 401);
19
+ const init = await apiClient.post("/v1/cli/decrypt/init", {
20
+ snapshot_id: args.snapshotId,
21
+ purpose: "prove",
22
+ path_norm: args.pathNorm,
23
+ });
24
+ const sessionId = init.session_id || init.sessionId || init.id;
25
+ if (!sessionId)
26
+ throw new ApiError("Decrypt init did not return session_id", 500);
27
+ const interval = Math.max(2, Math.min(30, Number(init.interval ?? 5)));
28
+ const url = String(init.approval_url ?? "");
29
+ const phrase = String(init.approval_phrase ?? "");
30
+ console.log(colors.bold("Approval required to decrypt path map (passkey)…"));
31
+ if (url) {
32
+ tryOpenBrowser(url);
33
+ console.log("If the browser does not open, visit:", colors.info(url));
34
+ }
35
+ else {
36
+ console.log(colors.warn("Approval URL not provided by server. Open the CodeQuill app and approve the pending request."));
37
+ }
38
+ if (phrase) {
39
+ console.log("On the approval page, you should see:", colors.bold(`"${phrase}"`));
40
+ }
41
+ const s = args.spinner ?? spinner("Waiting for approval…");
42
+ if (args.spinner) {
43
+ s.text = "Waiting for approval…";
44
+ }
45
+ const started = Date.now();
46
+ const timeoutMs = 3 * 60 * 1000;
47
+ try {
48
+ while (true) {
49
+ if (Date.now() - started > timeoutMs) {
50
+ s.fail(colors.error("Approval timed out. Please try again."));
51
+ throw new ApiError("Approval timed out. Please try again.", 408);
52
+ }
53
+ let poll;
54
+ try {
55
+ poll = await apiClient.post("/v1/cli/decrypt/result", { session_id: sessionId });
56
+ }
57
+ catch {
58
+ s.fail(colors.error("Approval polling failed."));
59
+ throw new ApiError("Approval polling failed.", 500);
60
+ }
61
+ if (poll.status === "pending") {
62
+ await sleep(interval * 1000);
63
+ continue;
64
+ }
65
+ if (poll.status === "rejected") {
66
+ s.fail(colors.error("Request rejected in the app. No proof was generated."));
67
+ throw new ApiError("Rejected", 403);
68
+ }
69
+ if (poll.status === "expired") {
70
+ s.fail(colors.warn("Request expired. Please run the command again."));
71
+ throw new ApiError("Expired", 410);
72
+ }
73
+ const ok = poll;
74
+ if (ok.status !== "approved" || !ok.path_hash) {
75
+ s.fail(colors.error("Unexpected decrypt result payload."));
76
+ throw new ApiError("Unexpected decrypt result payload", 500);
77
+ }
78
+ const ph = String(ok.path_hash).toLowerCase();
79
+ if (!/^[0-9a-f]{64}$/.test(ph)) {
80
+ s.fail(colors.error("Server returned invalid path_hash."));
81
+ throw new ApiError("Server returned invalid path_hash", 500);
82
+ }
83
+ s.succeed(colors.success("Approved. Path hash resolved."));
84
+ return ph;
85
+ }
86
+ }
87
+ catch (e) {
88
+ if (!args.spinner) {
89
+ try {
90
+ s.fail(colors.error("Approval flow aborted."));
91
+ }
92
+ catch { }
93
+ }
94
+ if (e instanceof ApiError)
95
+ throw e;
96
+ throw new ApiError(String(e?.message ?? e), 500);
97
+ }
98
+ }
99
+ export async function handleProve(opts) {
100
+ const targetFileAbs = resolvePath(opts.targetFile);
101
+ if (!opts.snapshotId || !String(opts.snapshotId).trim()) {
102
+ console.error(colors.error("Missing snapshot id."));
103
+ console.error(colors.dim("Usage: codequill prove <file> <snapshotId> [--disclose] [--out <file>]"));
104
+ process.exitCode = 1;
105
+ return;
106
+ }
107
+ // One spinner for the whole command (prevents β€œhanging spinner” artifacts)
108
+ const s = spinner(`Building proof for "${opts.targetFile}"…`);
109
+ try {
110
+ // 1) read target file + hash it
111
+ const bytes = await fs.readFile(targetFileAbs);
112
+ const currentHashNo0x = keccakHex(bytes);
113
+ // 2) fetch snapshot bundle
114
+ if (!assertAuthenticated())
115
+ return;
116
+ const sid = String(opts.snapshotId).trim();
117
+ const bundle = await fetchSnapshotBundle(sid);
118
+ const meta = bundle.meta ?? null;
119
+ const manifest = bundle.manifest;
120
+ if (!manifest || typeof manifest !== "object")
121
+ throw new Error("Invalid manifest JSON.");
122
+ if (!Array.isArray(manifest.files))
123
+ throw new Error("Invalid manifest: missing files[]");
124
+ if (!manifest.repo || !manifest.commit || !manifest.merkle_root) {
125
+ throw new Error("Invalid manifest: missing repo/commit/merkle_root.");
126
+ }
127
+ // 3) normalize path (must match snapshot normalization rules)
128
+ const targetPathNorm = normalizePath(opts.targetFile);
129
+ // 4) resolve salted path_hash via device flow
130
+ s.text = "Waiting for passkey approval…";
131
+ const targetPathHash = await resolvePathHashWithDeviceFlow({
132
+ snapshotId: sid,
133
+ pathNorm: targetPathNorm,
134
+ spinner: s,
135
+ });
136
+ // 5) ensure record exists in manifest by path_hash
137
+ s.start(`Building proof for "${opts.targetFile}"…`);
138
+ const rec = manifest.files.find((f) => String(f?.path_hash ?? "").toLowerCase() === targetPathHash);
139
+ if (!rec) {
140
+ throw new Error(`File not found in manifest (by path_hash).\n` +
141
+ `Path provided: ${targetPathNorm}\n` +
142
+ `Resolved path_hash: ${targetPathHash}\n`);
143
+ }
144
+ // 6) build proof manifest
145
+ const proof = buildProofManifest({
146
+ snapshotManifest: manifest,
147
+ targetPathNorm,
148
+ targetPathHash,
149
+ snapshotMeta: meta,
150
+ currentFileHash: currentHashNo0x,
151
+ disclosePathPlaintext: !!opts.disclose,
152
+ pathPlaintext: targetPathNorm,
153
+ });
154
+ // 8) write output
155
+ const defaultOut = path.join(".codequill", "proofs", `proof-${shortHash(proof.file.hash)}.json`);
156
+ const outPath = path.resolve(process.cwd(), opts.out ?? defaultOut);
157
+ await writeFileUtf8(outPath, JSON.stringify(proof, null, 2));
158
+ // 9) UX
159
+ s.succeed(colors.success("Proof built."));
160
+ console.log("");
161
+ console.log(colors.bold("πŸ“œ Proof of Inclusion"));
162
+ console.log(colors.dim("────────────────────────────────────────"));
163
+ console.log(proof.statement);
164
+ console.log(colors.dim("\nSnapshot"));
165
+ console.log(` Repository ${proof.repo}`);
166
+ console.log(` Commit ${proof.commit}`);
167
+ console.log(` Merkle Root ${proof.merkle_root}`);
168
+ if (proof.snapshot) {
169
+ console.log("");
170
+ console.log(colors.dim("On-chain"));
171
+ console.log(` Snapshot ID ${proof.snapshot.snapshot_id}`);
172
+ if (proof.snapshot.chain_id)
173
+ console.log(` Chain ${chainName(proof.snapshot.chain_id) ?? proof.snapshot.chain_id}`);
174
+ if (proof.snapshot.published_at)
175
+ console.log(` Published ${new Date(proof.snapshot.published_at * 1000).toUTCString()}`);
176
+ if (proof.snapshot.publisher_wallet)
177
+ console.log(` Authority ${proof.snapshot.publisher_wallet}`);
178
+ if (proof.snapshot.explorer_url)
179
+ console.log(` Tx ${proof.snapshot.explorer_url}`);
180
+ else if (proof.snapshot.tx_hash)
181
+ console.log(` Tx ${proof.snapshot.tx_hash}`);
182
+ if (proof.snapshot.manifest_cid)
183
+ console.log(` Manifest CID ${proof.snapshot.manifest_cid}`);
184
+ }
185
+ console.log("");
186
+ console.log(colors.dim("File (public-verifiable leaf inputs)"));
187
+ console.log(` File Hash ${proof.file.hash}`);
188
+ console.log(` Path Hash ${proof.file.path_hash}`);
189
+ console.log(` Verified βœ“ content matches snapshot record`);
190
+ const priv = proof.privacy;
191
+ if (priv) {
192
+ const disclosed = !!priv.disclosed_path;
193
+ const binding = priv.path_binding ?? "not_provided";
194
+ console.log("");
195
+ console.log(colors.dim("Privacy"));
196
+ console.log(` Disclosed path ${disclosed ? "yes" : "no"}`);
197
+ console.log(` Path binding ${binding}`);
198
+ if (disclosed) {
199
+ // Make the tradeoff explicit (since users will paste/share proofs)
200
+ console.log(colors.warn(" Warning plaintext path is included; share carefully"));
201
+ }
202
+ if (disclosed && typeof priv.path_plaintext === "string" && priv.path_plaintext.length) {
203
+ console.log(` Path (plaintext) ${priv.path_plaintext}`);
204
+ }
205
+ }
206
+ console.log("");
207
+ console.log(colors.dim("Proof"));
208
+ console.log(` Leaf ${proof.leaf}`);
209
+ console.log(` Steps ${proof.proof.length}`);
210
+ console.log(` Output ${outPath}`);
211
+ console.log(colors.dim("────────────────────────────────────────"));
212
+ }
213
+ catch (e) {
214
+ try {
215
+ s.fail(colors.error("Failed to build proof."));
216
+ }
217
+ catch { }
218
+ if (e instanceof ApiError) {
219
+ console.error(colors.error(`${e.message} (${e.status})`));
220
+ if (e.requestId)
221
+ console.error(colors.dim(`Request ID: ${e.requestId}`));
222
+ }
223
+ else {
224
+ console.error(colors.error(String(e?.message || e)));
225
+ }
226
+ process.exitCode = 1;
227
+ }
228
+ }
229
+ export function registerProveCommand(program) {
230
+ program
231
+ .command("prove <file> <snapshotId>")
232
+ .description("Generate a Merkle proof-of-inclusion for a file. Requires passkey approval to resolve private path hash.")
233
+ .option("--disclose", "Include plaintext path in the proof statement (privacy tradeoff).")
234
+ .option("--out <file>", "Write proof JSON to a specific file (overrides default)")
235
+ .action(async (file, snapshotId, options) => {
236
+ await handleProve({
237
+ targetFile: file,
238
+ snapshotId,
239
+ out: options.out,
240
+ disclose: !!options.disclose,
241
+ });
242
+ });
243
+ }
244
+ //# sourceMappingURL=prove.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prove.js","sourceRoot":"","sources":["../../src/commands/prove.ts"],"names":[],"mappings":"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"}