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,166 @@
|
|
|
1
|
+
import { loadTokens, isExpired, saveTokens, clearTokens } from './authStore.js';
|
|
2
|
+
import { ApiError } from './errors.js';
|
|
3
|
+
const DEFAULT_BASE_URL = 'https://api.codequill.xyz';
|
|
4
|
+
export class ApiClient {
|
|
5
|
+
baseUrl;
|
|
6
|
+
constructor(baseUrl) {
|
|
7
|
+
this.baseUrl = (baseUrl || process.env.CODEQUILL_API_BASE_URL || DEFAULT_BASE_URL).replace(/\/$/, '');
|
|
8
|
+
}
|
|
9
|
+
async ensureAuthHeader() {
|
|
10
|
+
const headers = {};
|
|
11
|
+
// 1) Explicit token override (CI / GHA)
|
|
12
|
+
const envToken = String(process.env.CODEQUILL_TOKEN || "").trim();
|
|
13
|
+
if (envToken) {
|
|
14
|
+
headers.Authorization = `Bearer ${envToken}`;
|
|
15
|
+
const githubId = String(process.env.CODEQUILL_GITHUB_ID || "").trim();
|
|
16
|
+
if (githubId) {
|
|
17
|
+
headers["X-GITHUB-ID"] = githubId;
|
|
18
|
+
}
|
|
19
|
+
return headers;
|
|
20
|
+
}
|
|
21
|
+
// 2) Normal interactive login tokens
|
|
22
|
+
const tokens = loadTokens();
|
|
23
|
+
if (!tokens)
|
|
24
|
+
return headers;
|
|
25
|
+
if (isExpired(tokens)) {
|
|
26
|
+
if (!tokens.refresh_token) {
|
|
27
|
+
throw new ApiError("Session expired. Please run `codequill login` again.", 401);
|
|
28
|
+
}
|
|
29
|
+
await this.refreshTokens(tokens.refresh_token);
|
|
30
|
+
const refreshed = loadTokens();
|
|
31
|
+
if (!refreshed) {
|
|
32
|
+
throw new ApiError("Session expired. Please run `codequill login` again.", 401);
|
|
33
|
+
}
|
|
34
|
+
headers.Authorization = `Bearer ${refreshed.access_token}`;
|
|
35
|
+
return headers;
|
|
36
|
+
}
|
|
37
|
+
headers.Authorization = `Bearer ${tokens.access_token}`;
|
|
38
|
+
return headers;
|
|
39
|
+
}
|
|
40
|
+
async refreshTokens(refreshToken) {
|
|
41
|
+
const url = `${this.baseUrl}/v1/cli/auth/refresh`;
|
|
42
|
+
const res = await fetch(url, {
|
|
43
|
+
method: 'POST',
|
|
44
|
+
headers: {
|
|
45
|
+
'Content-Type': 'application/json',
|
|
46
|
+
Accept: 'application/json',
|
|
47
|
+
'X-Nonce': this.makeNonce(),
|
|
48
|
+
},
|
|
49
|
+
body: JSON.stringify({ refresh_token: refreshToken }),
|
|
50
|
+
});
|
|
51
|
+
const text = await res.text();
|
|
52
|
+
let data = undefined;
|
|
53
|
+
try {
|
|
54
|
+
data = text ? JSON.parse(text) : undefined;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
data = text;
|
|
58
|
+
}
|
|
59
|
+
if (!res.ok) {
|
|
60
|
+
const reqId = res?.headers?.get?.('x-request-id')
|
|
61
|
+
|| res?.headers?.get?.('request-id')
|
|
62
|
+
|| res?.headers?.get?.('x-amzn-trace-id')
|
|
63
|
+
|| undefined;
|
|
64
|
+
if (res.status === 400 || res.status === 401 || res.status === 403) {
|
|
65
|
+
// Invalid/expired refresh token — clear local credentials
|
|
66
|
+
clearTokens();
|
|
67
|
+
const msg = 'Failed to refresh session (token expired or invalid). Please run `codequill login` again.';
|
|
68
|
+
throw new ApiError(msg, res.status, data, url, 'POST', reqId);
|
|
69
|
+
}
|
|
70
|
+
const msg = typeof data?.message === 'string' ? data.message : `Request failed with ${res.status}`;
|
|
71
|
+
throw new ApiError(msg, res.status, data, url, 'POST', reqId);
|
|
72
|
+
}
|
|
73
|
+
const success = data;
|
|
74
|
+
const margin = 30; // seconds safety margin
|
|
75
|
+
const nowSec = Math.floor(Date.now() / 1000);
|
|
76
|
+
const accessTtl = success.access_expires_in ?? success.expires_in ?? 0;
|
|
77
|
+
const refreshTtl = success.refresh_expires_in ?? 0;
|
|
78
|
+
const access_expires_at = nowSec + Math.max(0, accessTtl - margin);
|
|
79
|
+
const refresh_expires_at = refreshTtl ? nowSec + Math.max(0, refreshTtl - margin) : undefined;
|
|
80
|
+
saveTokens({
|
|
81
|
+
access_token: success.access_token,
|
|
82
|
+
refresh_token: success.refresh_token ?? refreshToken,
|
|
83
|
+
expires_at: access_expires_at,
|
|
84
|
+
access_expires_at,
|
|
85
|
+
refresh_expires_at,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
async get(path, opts) {
|
|
89
|
+
return this.request('GET', path, undefined, opts);
|
|
90
|
+
}
|
|
91
|
+
async post(path, body, opts) {
|
|
92
|
+
return this.request('POST', path, body, opts);
|
|
93
|
+
}
|
|
94
|
+
async postMultipart(path, form, opts) {
|
|
95
|
+
const url = `${this.baseUrl}${path.startsWith('/') ? '' : '/'}${path}`;
|
|
96
|
+
const headers = {
|
|
97
|
+
Accept: 'application/json',
|
|
98
|
+
'X-Nonce': this.makeNonce(),
|
|
99
|
+
};
|
|
100
|
+
if (opts?.auth !== false) {
|
|
101
|
+
Object.assign(headers, await this.ensureAuthHeader());
|
|
102
|
+
}
|
|
103
|
+
const res = await fetch(url, {
|
|
104
|
+
method: 'POST',
|
|
105
|
+
headers,
|
|
106
|
+
body: form,
|
|
107
|
+
});
|
|
108
|
+
const text = await res.text();
|
|
109
|
+
let data = undefined;
|
|
110
|
+
try {
|
|
111
|
+
data = text ? JSON.parse(text) : undefined;
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// keep raw text
|
|
115
|
+
data = text;
|
|
116
|
+
}
|
|
117
|
+
if (!res.ok) {
|
|
118
|
+
const msg = typeof data?.error === 'string' ? data.error : `Request failed with ${res.status}`;
|
|
119
|
+
const reqId = res?.headers?.get?.('x-request-id')
|
|
120
|
+
|| res?.headers?.get?.('request-id')
|
|
121
|
+
|| res?.headers?.get?.('x-amzn-trace-id')
|
|
122
|
+
|| undefined;
|
|
123
|
+
throw new ApiError(msg, res.status, data, url, 'POST', reqId);
|
|
124
|
+
}
|
|
125
|
+
return data;
|
|
126
|
+
}
|
|
127
|
+
async request(method, path, body, opts) {
|
|
128
|
+
const url = `${this.baseUrl}${path.startsWith('/') ? '' : '/'}${path}`;
|
|
129
|
+
const headers = {
|
|
130
|
+
'Content-Type': 'application/json',
|
|
131
|
+
'X-Nonce': this.makeNonce(),
|
|
132
|
+
Accept: 'application/json',
|
|
133
|
+
};
|
|
134
|
+
if (opts?.auth !== false) {
|
|
135
|
+
Object.assign(headers, await this.ensureAuthHeader());
|
|
136
|
+
}
|
|
137
|
+
const res = await fetch(url, {
|
|
138
|
+
method,
|
|
139
|
+
headers,
|
|
140
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
141
|
+
});
|
|
142
|
+
const text = await res.text();
|
|
143
|
+
let data = undefined;
|
|
144
|
+
try {
|
|
145
|
+
data = text ? JSON.parse(text) : undefined;
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
// keep raw text
|
|
149
|
+
data = text;
|
|
150
|
+
}
|
|
151
|
+
if (!res.ok) {
|
|
152
|
+
const msg = typeof data?.error === 'string' ? data.error : `Request failed with ${res.status}`;
|
|
153
|
+
const reqId = res?.headers?.get?.('x-request-id')
|
|
154
|
+
|| res?.headers?.get?.('request-id')
|
|
155
|
+
|| res?.headers?.get?.('x-amzn-trace-id')
|
|
156
|
+
|| undefined;
|
|
157
|
+
throw new ApiError(msg, res.status, data, url, method, reqId);
|
|
158
|
+
}
|
|
159
|
+
return data;
|
|
160
|
+
}
|
|
161
|
+
makeNonce() {
|
|
162
|
+
return crypto.randomUUID();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
export const apiClient = new ApiClient();
|
|
166
|
+
//# sourceMappingURL=apiClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiClient.js","sourceRoot":"","sources":["../../src/services/apiClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { ensureConfigDir, getConfigFilePath } from './config.js';
|
|
4
|
+
function readFileIfExists(file) {
|
|
5
|
+
try {
|
|
6
|
+
return fs.readFileSync(file, 'utf8');
|
|
7
|
+
}
|
|
8
|
+
catch (e) {
|
|
9
|
+
if (e && (e.code === 'ENOENT' || e.code === 'ENOTDIR'))
|
|
10
|
+
return null;
|
|
11
|
+
throw e;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function loadTokens() {
|
|
15
|
+
const file = getConfigFilePath();
|
|
16
|
+
const raw = readFileIfExists(file);
|
|
17
|
+
if (!raw)
|
|
18
|
+
return null;
|
|
19
|
+
try {
|
|
20
|
+
const parsed = JSON.parse(raw);
|
|
21
|
+
// Accept tokens if access_token + any access expiry are present
|
|
22
|
+
if (typeof parsed?.access_token === 'string') {
|
|
23
|
+
if (typeof parsed?.expires_at === 'number' || typeof parsed?.access_expires_at === 'number') {
|
|
24
|
+
return parsed;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function saveTokens(tokens) {
|
|
34
|
+
ensureConfigDir();
|
|
35
|
+
const file = getConfigFilePath();
|
|
36
|
+
const dir = path.dirname(file);
|
|
37
|
+
if (!fs.existsSync(dir)) {
|
|
38
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
39
|
+
}
|
|
40
|
+
// Ensure back-compat aliasing: mirror access_expires_at into expires_at if provided
|
|
41
|
+
const accessExp = typeof tokens.access_expires_at === 'number' ? tokens.access_expires_at : tokens.expires_at;
|
|
42
|
+
const toSave = { ...tokens, expires_at: accessExp };
|
|
43
|
+
const data = JSON.stringify(toSave, null, 2);
|
|
44
|
+
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
45
|
+
try {
|
|
46
|
+
fs.writeFileSync(tmp, data, { mode: 0o600 });
|
|
47
|
+
fs.renameSync(tmp, file); // atomic on POSIX
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
try {
|
|
51
|
+
if (fs.existsSync(tmp))
|
|
52
|
+
fs.rmSync(tmp, { force: true });
|
|
53
|
+
}
|
|
54
|
+
catch { /* ignore */ }
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
fs.chmodSync(file, 0o600);
|
|
58
|
+
}
|
|
59
|
+
catch { /* ignore */ }
|
|
60
|
+
}
|
|
61
|
+
export function isExpired(tokens) {
|
|
62
|
+
const now = Math.floor(Date.now() / 1000);
|
|
63
|
+
const accessExp = tokens.access_expires_at ?? tokens.expires_at;
|
|
64
|
+
return accessExp <= now;
|
|
65
|
+
}
|
|
66
|
+
export function isRefreshExpired(tokens) {
|
|
67
|
+
if (!tokens.refresh_token)
|
|
68
|
+
return true;
|
|
69
|
+
if (!tokens.refresh_expires_at)
|
|
70
|
+
return false; // unknown expiry; assume valid
|
|
71
|
+
const now = Math.floor(Date.now() / 1000);
|
|
72
|
+
return tokens.refresh_expires_at <= now;
|
|
73
|
+
}
|
|
74
|
+
export function clearTokens() {
|
|
75
|
+
const file = getConfigFilePath();
|
|
76
|
+
try {
|
|
77
|
+
if (fs.existsSync(file))
|
|
78
|
+
fs.rmSync(file, { force: true });
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// ignore
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=authStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authStore.js","sourceRoot":"","sources":["../../src/services/authStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
const DEFAULT_CONFIG_DIR = path.join(homedir(), '.config', 'codequill');
|
|
5
|
+
const CONFIG_DIR = process.env.CODEQUILL_CONFIG_DIR || DEFAULT_CONFIG_DIR;
|
|
6
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
7
|
+
const BASE_URL = (process.env.CODEQUILL_BASE_URL || "https://app.codequill.xyz").replace(/\/$/, '');
|
|
8
|
+
export function getBaseUrl() {
|
|
9
|
+
return BASE_URL;
|
|
10
|
+
}
|
|
11
|
+
export function getConfigFilePath() {
|
|
12
|
+
return CONFIG_FILE;
|
|
13
|
+
}
|
|
14
|
+
export function ensureConfigDir() {
|
|
15
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
16
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/services/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,kBAAkB,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;AACxE,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,kBAAkB,CAAC;AAC1E,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AACzD,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,2BAA2B,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAEpG,MAAM,UAAU,UAAU;IACtB,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC7B,OAAO,WAAW,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,eAAe;IAC3B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC7B,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/D,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { colors } from './ui.js';
|
|
2
|
+
export async function confirmDangerousAction(title, lines, subtitle, opts = {}) {
|
|
3
|
+
const prompt = opts.prompt ?? 'Proceed? (y/N): ';
|
|
4
|
+
const requireTty = opts.requireTty ?? true;
|
|
5
|
+
const defaultNo = opts.defaultNo ?? true;
|
|
6
|
+
// Guard: CI/non-interactive
|
|
7
|
+
if (requireTty && !process.stdin.isTTY) {
|
|
8
|
+
console.error(colors.error('Interactive confirmation requires a TTY.'));
|
|
9
|
+
console.error(colors.dim('Tip: pass --no-confirm to skip confirmation in CI.'));
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
// Pretty header
|
|
13
|
+
console.log('');
|
|
14
|
+
console.log(colors.bold(`⚠️ ${title}`));
|
|
15
|
+
console.log(colors.dim('────────────────────────────────────────'));
|
|
16
|
+
for (const l of lines)
|
|
17
|
+
console.log(l);
|
|
18
|
+
console.log(colors.dim('────────────────────────────────────────'));
|
|
19
|
+
if (subtitle) {
|
|
20
|
+
console.log(colors.dim(subtitle));
|
|
21
|
+
}
|
|
22
|
+
console.log('');
|
|
23
|
+
const stdin = process.stdin;
|
|
24
|
+
const stdout = process.stdout;
|
|
25
|
+
return new Promise((resolve) => {
|
|
26
|
+
const wasRaw = stdin.isRaw;
|
|
27
|
+
if (stdin.isTTY) {
|
|
28
|
+
stdin.setEncoding('utf8');
|
|
29
|
+
stdin.resume();
|
|
30
|
+
try {
|
|
31
|
+
stdin.setRawMode(false);
|
|
32
|
+
}
|
|
33
|
+
catch { }
|
|
34
|
+
}
|
|
35
|
+
stdout.write(prompt);
|
|
36
|
+
const onData = (data) => {
|
|
37
|
+
const input = String(data ?? '').trim();
|
|
38
|
+
cleanup();
|
|
39
|
+
if (!input)
|
|
40
|
+
return resolve(!defaultNo);
|
|
41
|
+
const v = input.toLowerCase();
|
|
42
|
+
resolve(v === 'y' || v === 'yes');
|
|
43
|
+
};
|
|
44
|
+
const cleanup = () => {
|
|
45
|
+
stdin.removeListener('data', onData);
|
|
46
|
+
if (stdin.isTTY && wasRaw) {
|
|
47
|
+
try {
|
|
48
|
+
stdin.setRawMode(true);
|
|
49
|
+
}
|
|
50
|
+
catch { }
|
|
51
|
+
}
|
|
52
|
+
stdin.pause();
|
|
53
|
+
stdout.write('\n');
|
|
54
|
+
};
|
|
55
|
+
stdin.on('data', onData);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=confirm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confirm.js","sourceRoot":"","sources":["../../src/services/confirm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { keccak256, toUtf8Bytes } from 'ethers';
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
// Returns 64-hex string (no 0x), lowercase
|
|
5
|
+
export function keccakHex(data) {
|
|
6
|
+
const h = keccak256(data); // ethers returns 0x-prefixed hex
|
|
7
|
+
return h.replace(/^0x/, '').toLowerCase();
|
|
8
|
+
}
|
|
9
|
+
// Returns 64-hex string (no 0x), lowercase
|
|
10
|
+
export function keccakUtf8(text) {
|
|
11
|
+
const bytes = toUtf8Bytes(text);
|
|
12
|
+
const h = keccak256(bytes);
|
|
13
|
+
return h.replace(/^0x/, '').toLowerCase();
|
|
14
|
+
}
|
|
15
|
+
export function hexToBytes(hexNo0x) {
|
|
16
|
+
const hex = hexNo0x.length % 2 === 1 ? `0${hexNo0x}` : hexNo0x;
|
|
17
|
+
const len = hex.length / 2;
|
|
18
|
+
const out = new Uint8Array(len);
|
|
19
|
+
for (let i = 0; i < len; i++) {
|
|
20
|
+
out[i] = parseInt(hex.substr(i * 2, 2), 16);
|
|
21
|
+
}
|
|
22
|
+
return out;
|
|
23
|
+
}
|
|
24
|
+
export function concatBytes(a, b) {
|
|
25
|
+
const out = new Uint8Array(a.length + b.length);
|
|
26
|
+
out.set(a, 0);
|
|
27
|
+
out.set(b, a.length);
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
export async function sha256File(filePathAbs) {
|
|
31
|
+
const buf = await fs.readFile(filePathAbs);
|
|
32
|
+
return createHash('sha256').update(buf).digest('hex');
|
|
33
|
+
}
|
|
34
|
+
export async function sha512File(filePathAbs) {
|
|
35
|
+
const buf = await fs.readFile(filePathAbs);
|
|
36
|
+
return createHash('sha512').update(buf).digest('hex');
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/services/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAC,UAAU,EAAC,MAAM,aAAa,CAAC;AAEvC,2CAA2C;AAC3C,MAAM,UAAU,SAAS,CAAC,IAAyB;IAC/C,MAAM,CAAC,GAAG,SAAS,CAAC,IAAW,CAAC,CAAC,CAAC,iCAAiC;IACnE,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;AAC9C,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,UAAU,CAAC,IAAY;IACnC,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAC3B,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAe;IACtC,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;IAC/D,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3B,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;IAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,GAAG,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,CAAa,EAAE,CAAa;IACpD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IAChD,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACd,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACrB,OAAO,GAAG,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,WAAmB;IAChD,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC3C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,WAAmB;IAChD,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC3C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export class ApiError extends Error {
|
|
2
|
+
status;
|
|
3
|
+
body;
|
|
4
|
+
url;
|
|
5
|
+
method;
|
|
6
|
+
requestId;
|
|
7
|
+
constructor(message, status, body, url, method, requestId) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = 'ApiError';
|
|
10
|
+
this.status = status;
|
|
11
|
+
this.body = body;
|
|
12
|
+
this.url = url;
|
|
13
|
+
this.method = method;
|
|
14
|
+
this.requestId = requestId;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/services/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,QAAS,SAAQ,KAAK;IACjC,MAAM,CAAS;IACf,IAAI,CAAW;IACf,GAAG,CAAU;IACb,MAAM,CAAU;IAChB,SAAS,CAAU;IACnB,YACE,OAAe,EACf,MAAc,EACd,IAAc,EACd,GAAY,EACZ,MAAe,EACf,SAAkB;QAElB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;CACF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export async function readFileUtf8(filePath) {
|
|
4
|
+
return await fs.readFile(filePath, 'utf8');
|
|
5
|
+
}
|
|
6
|
+
export async function writeFileUtf8(filePath, data) {
|
|
7
|
+
const dir = path.dirname(filePath);
|
|
8
|
+
// Ensure parent directory exists (mkdir -p)
|
|
9
|
+
await fs.mkdir(dir, { recursive: true });
|
|
10
|
+
// Write (creates file if missing, truncates if exists)
|
|
11
|
+
await fs.writeFile(filePath, data, 'utf8');
|
|
12
|
+
}
|
|
13
|
+
export async function ensureDir(p) {
|
|
14
|
+
await fs.mkdir(p, { recursive: true });
|
|
15
|
+
}
|
|
16
|
+
export async function fileExists(p) {
|
|
17
|
+
try {
|
|
18
|
+
await fs.stat(p);
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=fs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/services/fs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB;IAC/C,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB,EAAE,IAAY;IAC9D,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,4CAA4C;IAC5C,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,uDAAuD;IACvD,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,CAAS;IACrC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,CAAS;IACtC,IAAI,CAAC;QACD,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjB,OAAO,IAAI,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { execFile, execFileSync } from 'node:child_process';
|
|
4
|
+
import { normalizePath } from "./merkle.js";
|
|
5
|
+
export function runGit(args, opts) {
|
|
6
|
+
return new Promise((resolve) => {
|
|
7
|
+
const child = execFile('git', ['-C', opts.cwd, ...args], { encoding: 'buffer', windowsHide: true });
|
|
8
|
+
const chunksOut = [];
|
|
9
|
+
const chunksErr = [];
|
|
10
|
+
child.stdout?.on('data', (c) => chunksOut.push(c));
|
|
11
|
+
child.stderr?.on('data', (c) => chunksErr.push(c));
|
|
12
|
+
child.on('close', (code) => resolve({ stdout: Buffer.concat(chunksOut), stderr: Buffer.concat(chunksErr), code }));
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
function tryGit(args, opts) {
|
|
16
|
+
try {
|
|
17
|
+
const out = execFileSync('git', args, { cwd: opts.cwd, stdio: ['ignore', 'pipe', 'ignore'] });
|
|
18
|
+
return String(out).trim();
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function detectGitRepo(dir) {
|
|
25
|
+
// Quick check: look for .git or use git command
|
|
26
|
+
const gitDir = path.join(dir, '.git');
|
|
27
|
+
let isRepo = false;
|
|
28
|
+
if (fs.existsSync(gitDir)) {
|
|
29
|
+
isRepo = true;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
const inside = tryGit(['rev-parse', '--is-inside-work-tree'], { cwd: dir });
|
|
33
|
+
isRepo = inside === 'true';
|
|
34
|
+
}
|
|
35
|
+
if (!isRepo)
|
|
36
|
+
return { isRepo: false, remote: null };
|
|
37
|
+
const root = tryGit(['rev-parse', '--show-toplevel'], { cwd: dir }) || dir;
|
|
38
|
+
const head = tryGit(['rev-parse', 'HEAD'], { cwd: dir }) || undefined;
|
|
39
|
+
const branchRaw = tryGit(['rev-parse', '--abbrev-ref', 'HEAD'], { cwd: dir }) || null;
|
|
40
|
+
const branch = branchRaw && branchRaw !== 'HEAD' ? branchRaw : null; // null when detached
|
|
41
|
+
const remote = tryGit(['remote', 'get-url', 'origin'], { cwd: dir }) || null;
|
|
42
|
+
return { isRepo, root, head, branch, remote };
|
|
43
|
+
}
|
|
44
|
+
export function deriveRepoNameFromRemote(remote) {
|
|
45
|
+
if (!remote)
|
|
46
|
+
return null;
|
|
47
|
+
// Examples:
|
|
48
|
+
// git@github.com:user/name.git
|
|
49
|
+
// https://github.com/user/name.git
|
|
50
|
+
// https://github.com/user/name
|
|
51
|
+
let r = remote.trim();
|
|
52
|
+
r = r.replace(/\.git$/i, '');
|
|
53
|
+
const sshMatch = r.match(/^git@[^:]+:([^/]+)\/(.+)$/);
|
|
54
|
+
if (sshMatch) {
|
|
55
|
+
return `${sshMatch[1]}/${sshMatch[2]}`;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
const u = new URL(r);
|
|
59
|
+
if (u.hostname.toLowerCase().includes('github.com')) {
|
|
60
|
+
const parts = u.pathname.replace(/^\//, '').split('/');
|
|
61
|
+
if (parts.length >= 2 && parts[0] && parts[1]) {
|
|
62
|
+
return `${parts[0]}/${parts[1]}`;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// ignore
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
export function deriveRepoName(rootDir, remote) {
|
|
72
|
+
const fromRemote = deriveRepoNameFromRemote(remote);
|
|
73
|
+
if (fromRemote)
|
|
74
|
+
return fromRemote;
|
|
75
|
+
if (!rootDir)
|
|
76
|
+
return null;
|
|
77
|
+
return path.basename(rootDir) || null;
|
|
78
|
+
}
|
|
79
|
+
export async function listFilesAtCommit(repoRoot, commitHash) {
|
|
80
|
+
// Use -z to safely parse paths with spaces/newlines; keep mode to skip symlinks (120000)
|
|
81
|
+
const res = await runGit(['ls-tree', '-r', '-z', commitHash], { cwd: repoRoot, encoding: null });
|
|
82
|
+
if (res.code !== 0) {
|
|
83
|
+
const errTxt = res.stderr.toString('utf8').trim();
|
|
84
|
+
throw new Error(`Git error listing files for ${commitHash}: ${errTxt || 'unknown error'}`);
|
|
85
|
+
}
|
|
86
|
+
const entries = res.stdout.toString('utf8').split('\u0000').filter(Boolean);
|
|
87
|
+
const out = [];
|
|
88
|
+
for (const ent of entries) {
|
|
89
|
+
const tabIdx = ent.indexOf('\t');
|
|
90
|
+
if (tabIdx === -1)
|
|
91
|
+
continue;
|
|
92
|
+
const header = ent.slice(0, tabIdx);
|
|
93
|
+
const file = ent.slice(tabIdx + 1);
|
|
94
|
+
const parts = header.split(' ');
|
|
95
|
+
if (parts.length < 3)
|
|
96
|
+
continue;
|
|
97
|
+
const mode = parts[0];
|
|
98
|
+
if (mode.startsWith('120000'))
|
|
99
|
+
continue; // skip symlinks
|
|
100
|
+
out.push(normalizePath(file));
|
|
101
|
+
}
|
|
102
|
+
return out;
|
|
103
|
+
}
|
|
104
|
+
export async function listFilesForWorkingTree(repoRoot) {
|
|
105
|
+
// Tracked files in the working tree (respects gitignore for untracked by not including them)
|
|
106
|
+
const res = await runGit(['ls-files', '-z'], { cwd: repoRoot, encoding: null });
|
|
107
|
+
if (res.code !== 0) {
|
|
108
|
+
const errTxt = res.stderr.toString('utf8').trim();
|
|
109
|
+
throw new Error(`Git error listing files: ${errTxt || 'unknown error'}`);
|
|
110
|
+
}
|
|
111
|
+
return res.stdout.toString('utf8').split('\u0000').filter(Boolean).map(normalizePath);
|
|
112
|
+
}
|
|
113
|
+
export async function readFileAtCommit(repoRoot, commitHash, filePath) {
|
|
114
|
+
const res = await runGit(['show', `${commitHash}:${filePath}`], { cwd: repoRoot, encoding: null });
|
|
115
|
+
if (res.code !== 0) {
|
|
116
|
+
const errTxt = res.stderr.toString('utf8').trim();
|
|
117
|
+
throw new Error(`Git error reading ${filePath} at ${commitHash}: ${errTxt || 'unknown error'}`);
|
|
118
|
+
}
|
|
119
|
+
return res.stdout;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/services/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAC,QAAQ,EAAE,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAC,aAAa,EAAC,MAAM,aAAa,CAAC;AAU1C,MAAM,UAAU,MAAM,CAClB,IAAc,EACd,IAAuD;IAEvD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC3B,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;QACpG,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3D,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3D,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACvH,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,MAAM,CAAC,IAAc,EAAE,IAAqB;IACjD,IAAI,CAAC;QACD,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC9F,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAW;IACrC,gDAAgD;IAChD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACtC,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,MAAM,GAAG,IAAI,CAAC;IAClB,CAAC;SAAM,CAAC;QACJ,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,WAAW,EAAE,uBAAuB,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;QAC5E,MAAM,GAAG,MAAM,KAAK,MAAM,CAAC;IAC/B,CAAC;IAED,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAEpD,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC;IAC3E,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,SAAS,CAAC;IACtE,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,CAAC;IACtF,MAAM,MAAM,GAAG,SAAS,IAAI,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,qBAAqB;IAC1F,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,CAAC;IAC7E,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,MAAiC;IACtE,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,YAAY;IACZ,+BAA+B;IAC/B,mCAAmC;IACnC,+BAA+B;IAC/B,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAC7B,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IACtD,IAAI,QAAQ,EAAE,CAAC;QACX,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3C,CAAC;IACD,IAAI,CAAC;QACD,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;QACrB,IAAI,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YAClD,MAAM,KAAK,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACvD,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5C,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YACrC,CAAC;QACL,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACL,SAAS;IACb,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,MAAsB;IAClE,MAAM,UAAU,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACpD,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC;IAClC,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;AAC1C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,QAAgB,EAAE,UAAkB;IACxE,yFAAyF;IACzF,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACjG,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,+BAA+B,UAAU,KAAK,MAAM,IAAI,eAAe,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC5E,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,CAAC,CAAC;YAAE,SAAS;QAE5B,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAEnC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS;QAE/B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,SAAS,CAAC,gBAAgB;QAEzD,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,QAAgB;IAC1D,6FAA6F;IAC7F,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAChF,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,4BAA4B,MAAM,IAAI,eAAe,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,OAAO,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;AAC1F,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgB,EAAE,UAAkB,EAAE,QAAgB;IACzF,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,CAAC,MAAM,EAAE,GAAG,UAAU,IAAI,QAAQ,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACnG,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,OAAO,UAAU,KAAK,MAAM,IAAI,eAAe,EAAE,CAAC,CAAC;IACpG,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { getCliVersion } from "../utilities.js";
|
|
2
|
+
export function buildAttestationManifest(params) {
|
|
3
|
+
const timestamp = Math.floor(Date.now() / 1000);
|
|
4
|
+
const cliVersion = getCliVersion();
|
|
5
|
+
return {
|
|
6
|
+
version: 'codequill-attestation:v1',
|
|
7
|
+
ecosystem: params.ecosystem,
|
|
8
|
+
statement: buildAttestationStatement({
|
|
9
|
+
ecosystem: params.ecosystem,
|
|
10
|
+
subjectPurl: params.subject.purl,
|
|
11
|
+
snapshotId: params.snapshot.snapshot_id,
|
|
12
|
+
snapshotRepo: params.snapshot.repository_name,
|
|
13
|
+
snapshotCommit: params.snapshot.commit_hash,
|
|
14
|
+
snapshotRoot: params.snapshot.merkle_root,
|
|
15
|
+
artifactDigest: params.artifact.digest,
|
|
16
|
+
}),
|
|
17
|
+
snapshot: params.snapshot,
|
|
18
|
+
artifact: params.artifact,
|
|
19
|
+
subject: params.subject,
|
|
20
|
+
...(params.upstreams && params.upstreams.length ? { upstreams: params.upstreams } : {}),
|
|
21
|
+
timestamp,
|
|
22
|
+
generator: {
|
|
23
|
+
name: 'codequill-cli',
|
|
24
|
+
version: cliVersion,
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function buildAttestationStatement(args) {
|
|
29
|
+
return (`This document is a CodeQuill attestation manifest (v1). It asserts that the artifact ` +
|
|
30
|
+
`with sha256 digest ${args.artifactDigest} (subject: ${args.subjectPurl}) was built from ` +
|
|
31
|
+
`the published CodeQuill snapshot ${args.snapshotId} for repository "${args.snapshotRepo}" ` +
|
|
32
|
+
`at commit "${args.snapshotCommit}", anchored by Merkle root ${args.snapshotRoot}. ` +
|
|
33
|
+
`Upstream entries (if present) reference anchored CodeQuill attestations resolved by purl.`);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=attestationManifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attestationManifest.js","sourceRoot":"","sources":["../../../src/services/manifests/attestationManifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAmD9C,MAAM,UAAU,wBAAwB,CAAC,MAMxC;IACG,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,OAAO;QACH,OAAO,EAAE,0BAA0B;QACnC,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,SAAS,EAAE,yBAAyB,CAAC;YACjC,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,WAAW,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI;YAChC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,WAAW;YACvC,YAAY,EAAE,MAAM,CAAC,QAAQ,CAAC,eAAe;YAC7C,cAAc,EAAE,MAAM,CAAC,QAAQ,CAAC,WAAW;YAC3C,YAAY,EAAE,MAAM,CAAC,QAAQ,CAAC,WAAW;YACzC,cAAc,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM;SACzC,CAAC;QACF,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAC,SAAS,EAAE,MAAM,CAAC,SAAS,EAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACrF,SAAS;QACT,SAAS,EAAE;YACP,IAAI,EAAE,eAAe;YACrB,OAAO,EAAE,UAAU;SACtB;KACJ,CAAC;AACN,CAAC;AAED,SAAS,yBAAyB,CAAC,IAQlC;IACG,OAAO,CACH,uFAAuF;QACvF,sBAAsB,IAAI,CAAC,cAAc,cAAc,IAAI,CAAC,WAAW,mBAAmB;QAC1F,oCAAoC,IAAI,CAAC,UAAU,oBAAoB,IAAI,CAAC,YAAY,IAAI;QAC5F,cAAc,IAAI,CAAC,cAAc,8BAA8B,IAAI,CAAC,YAAY,IAAI;QACpF,2FAA2F,CAC9F,CAAC;AACN,CAAC"}
|