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.
- package/LICENSE +21 -0
- package/README.md +121 -0
- package/dist/commands/attest.js +442 -0
- package/dist/commands/attest.js.map +1 -0
- package/dist/commands/backup.js +370 -0
- package/dist/commands/backup.js.map +1 -0
- package/dist/commands/claim.js +104 -0
- package/dist/commands/claim.js.map +1 -0
- package/dist/commands/log.js +188 -0
- package/dist/commands/log.js.map +1 -0
- package/dist/commands/login.js +147 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/prove.js +244 -0
- package/dist/commands/prove.js.map +1 -0
- package/dist/commands/publish.js +243 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/pull.js +174 -0
- package/dist/commands/pull.js.map +1 -0
- package/dist/commands/quota.js +94 -0
- package/dist/commands/quota.js.map +1 -0
- package/dist/commands/revoke.js +97 -0
- package/dist/commands/revoke.js.map +1 -0
- package/dist/commands/snapshot.js +128 -0
- package/dist/commands/snapshot.js.map +1 -0
- package/dist/commands/status.js +234 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/verifyAttestation.js +212 -0
- package/dist/commands/verifyAttestation.js.map +1 -0
- package/dist/commands/verifyProof.js +145 -0
- package/dist/commands/verifyProof.js.map +1 -0
- package/dist/commands/wait.js +36 -0
- package/dist/commands/wait.js.map +1 -0
- package/dist/commands/who.js +55 -0
- package/dist/commands/who.js.map +1 -0
- package/dist/commands/why.js +412 -0
- package/dist/commands/why.js.map +1 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -0
- package/dist/launcher.js +69 -0
- package/dist/launcher.js.map +1 -0
- package/dist/services/api.js +51 -0
- package/dist/services/api.js.map +1 -0
- package/dist/services/apiClient.js +166 -0
- package/dist/services/apiClient.js.map +1 -0
- package/dist/services/authStore.js +84 -0
- package/dist/services/authStore.js.map +1 -0
- package/dist/services/config.js +19 -0
- package/dist/services/config.js.map +1 -0
- package/dist/services/confirm.js +58 -0
- package/dist/services/confirm.js.map +1 -0
- package/dist/services/crypto.js +38 -0
- package/dist/services/crypto.js.map +1 -0
- package/dist/services/errors.js +17 -0
- package/dist/services/errors.js.map +1 -0
- package/dist/services/fs.js +25 -0
- package/dist/services/fs.js.map +1 -0
- package/dist/services/git.js +121 -0
- package/dist/services/git.js.map +1 -0
- package/dist/services/manifests/attestationManifest.js +35 -0
- package/dist/services/manifests/attestationManifest.js.map +1 -0
- package/dist/services/manifests/proofManifest.js +151 -0
- package/dist/services/manifests/proofManifest.js.map +1 -0
- package/dist/services/manifests/snapshotManifest.js +214 -0
- package/dist/services/manifests/snapshotManifest.js.map +1 -0
- package/dist/services/merkle.js +92 -0
- package/dist/services/merkle.js.map +1 -0
- package/dist/services/paths.js +16 -0
- package/dist/services/paths.js.map +1 -0
- package/dist/services/snapshotIndex.js +401 -0
- package/dist/services/snapshotIndex.js.map +1 -0
- package/dist/services/txWaiter.js +84 -0
- package/dist/services/txWaiter.js.map +1 -0
- package/dist/services/ui.js +98 -0
- package/dist/services/ui.js.map +1 -0
- package/dist/services/utilities.js +45 -0
- package/dist/services/utilities.js.map +1 -0
- package/dist/services/zip.js +24 -0
- package/dist/services/zip.js.map +1 -0
- package/dist/types/api.js +2 -0
- package/dist/types/api.js.map +1 -0
- package/dist/version.js +7 -0
- package/dist/version.js.map +1 -0
- 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":"AACA,OAAO,EAAC,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAC,MAAM,mBAAmB,CAAC;AACxF,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAC,aAAa,EAAsD,MAAM,8BAA8B,CAAC;AAmBhH,SAAS,SAAS,CAAC,EAAqB;IACpC,OAAO,CAAC,OAAO,EAAE,CAAC,SAAS,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAClG,CAAC;AAED,SAAS,aAAa;IAClB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,IAAI,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa;QAAE,OAAO,KAAK,CAAC;IAC7D,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,uBAAuB,CAAC,QAAgB;IACnD,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,CAA6B,+BAA+B,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC3H,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;IAChE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACpB,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,YAAY,EAAE,CAAC,CAAC,YAAY;QAC5B,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,YAAY,EAAE,CAAC,CAAC,YAAY;QAC5B,cAAc,EAAE,CAAC,CAAC,cAAc;KACnC,CAAC,CAAC,CAAC;AACR,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAgB;IAC5C,mCAAmC;IACnC,MAAM,GAAG,GAAG,aAAa,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACzC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,iEAAiE,CAAC,CAAC,CAAC;QAC/F,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACX,CAAC;IAED,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC,CAAC;QAC9E,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,qEAAqE,CAAC,CAAC,CAAC;QACjG,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACX,CAAC;IAED,kEAAkE;IAClE,MAAM,IAAI,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,IAAI,aAAa,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAElE,IAAI,CAAC;QACD,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC;IAClD,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QACd,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC,CAAC;QACvE,IAAI,CAAC;YACD,MAAM,KAAK,CAAC,eAAe,EAAE,CAAC;YAC9B,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACL,qDAAqD;QACzD,CAAC;IACL,CAAC;IAED,mEAAmE;IACnE,IAAI,aAAa,EAAE,EAAE,CAAC;QAClB,MAAM,IAAI,GAAG,OAAO,CAAC,kCAAkC,CAAC,CAAC;QACzD,IAAI,CAAC;YACD,MAAM,SAAS,GAAG,MAAM,uBAAuB,CAAC,QAAQ,CAAC,CAAC;YAC1D,KAAK,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;YACnC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,SAAS,CAAC,MAAM,sBAAsB,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QACvH,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC,CAAC;YACzF,IAAI,CAAC,YAAY,QAAQ,EAAE,CAAC;gBACxB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBACjE,IAAI,CAAC,CAAC,SAAS;oBAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;YAC7E,CAAC;iBAAM,CAAC;gBACJ,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACvD,CAAC;YACD,gCAAgC;QACpC,CAAC;IACL,CAAC;SAAM,CAAC;QACJ,0EAA0E;QAC1E,sGAAsG;IAC1G,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,8CAA8C;IAE1E,qEAAqE;IACrE,MAAM,KAAK,GAAG,CAAC,CAAM,EAAE,EAAE;QACrB,sDAAsD;QACtD,IAAI,CAAC,CAAC,WAAW;YAAE,OAAO,OAAO,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC;QACzD,oCAAoC;QACpC,IAAI,CAAC,CAAC,WAAW;YAAE,OAAO,QAAQ,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC;QAC1D,eAAe;QACf,OAAO,MAAM,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAChC,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,CAAC,CAAM,EAAE,EAAE;QACrB,4DAA4D;QAC5D,MAAM,SAAS,GAAG,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACpD,OAAO,SAAS,GAAG,aAAa,GAAG,OAAO,CAAC;IAC/C,CAAC,CAAC;IAEF,qDAAqD;IACrD,MAAM,KAAK,GAAG,IAAI,GAAG,EAA6B,CAAC;IAEnD,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;QACrB,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;QAC5D,IAAI,CAAC,CAAC;YAAE,SAAS;QAEjB,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,CAAC,IAAI,EAAE,CAAC;YACR,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACjB,SAAS;QACb,CAAC;QAED,wFAAwF;QACxF,MAAM,SAAS,GACX,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;YACpC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;YACzB,SAAS,CAAC,IAAI,CAAC,CAAC;QAEpB,MAAM,OAAO,GACT,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;YAClC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;YACvB,SAAS,CAAC,EAAE,CAAC,CAAC;QAElB,IAAI,OAAO,GAAG,SAAS;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACpE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACxC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAEjD,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAClD,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,MAAM,CAAC;IAEjE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC,CAAC;IAEpD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC,CAAC;QACxE,OAAO;IACX,CAAC;IAED,6BAA6B;IAC7B,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;QACrB,MAAM,WAAW,GAAG,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC;QACnC,MAAM,YAAY,GAAG,EAAE,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;QAEtD,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEpG,MAAM,SAAS,GAAG,WAAW;YACzB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,cAAc,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC;YAChF,CAAC,CAAC,YAAY;gBACV,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;gBACvB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAEpC,MAAM,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC;QACxB,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEjE,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QACpE,MAAM,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QACtG,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,WAAW,IAAI,EAAE,CAAC,CAAA;QAC3D,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC;IAC1F,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC,CAAC;IAEpD,UAAU;IACV,MAAM,WAAW,GAAG,KAAK,CAAC,eAAe,EAAE,CAAC;IAC5C,MAAM,SAAS,GAAG,KAAK,CAAC,mBAAmB,EAAE,CAAC;IAE9C,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,qBAAqB,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAC/F,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,qBAAqB,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAE3F,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,UAAU,YAAY,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC;IAC3G,CAAC;SAAM,CAAC;QACJ,wEAAwE;QACxE,MAAM,eAAe,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACzD,IAAI,eAAe;YAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC,CAAC;;YACzE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC,CAAC;IACjE,CAAC;AACL,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAgB;IAC/C,OAAO;SACF,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,sFAAsF,CAAC;SACnG,MAAM,CAAC,aAAa,EAAE,mBAAmB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;SAClE,MAAM,CAAC,KAAK,EAAE,OAAY,EAAE,EAAE;QAC3B,MAAM,SAAS,CAAC;YACZ,KAAK,EAAE,OAAO,CAAC,KAAK;SACvB,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -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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"}
|