@chest-gate/cli 0.1.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/app.d.ts.map +1 -1
- package/dist/commands/app.js +179 -1
- package/dist/commands/app.js.map +1 -1
- package/dist/commands/login.d.ts +3 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +228 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +3 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +49 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/whoami.d.ts +3 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +57 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/credentials.d.ts +24 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +61 -0
- package/dist/credentials.js.map +1 -0
- package/dist/dashboard-sig.d.ts +25 -0
- package/dist/dashboard-sig.d.ts.map +1 -0
- package/dist/dashboard-sig.js +26 -0
- package/dist/dashboard-sig.js.map +1 -0
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/commands/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/commands/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,eAAO,MAAM,UAAU,SAEtB,CAAC"}
|
package/dist/commands/app.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
|
+
import { readFile } from "node:fs/promises";
|
|
5
|
+
import { Keypair } from "@solana/web3.js";
|
|
6
|
+
import { hashManifest, signAppMessage, } from "@chest-gate/proxy";
|
|
4
7
|
import { loadManifest } from "../manifest.js";
|
|
5
|
-
|
|
8
|
+
import { ensureKeypair } from "../keypair.js";
|
|
9
|
+
export const appCommand = new Command("app").description("Manage Chest Gate App manifests and publish them to the chest.sh registry");
|
|
6
10
|
appCommand
|
|
7
11
|
.command("validate")
|
|
8
12
|
.description("Validate an app.md manifest against the schema")
|
|
@@ -39,4 +43,178 @@ appCommand
|
|
|
39
43
|
console.log(chalk.gray("Note: ") +
|
|
40
44
|
chalk.gray("payout wallet is resolved from the on-chain author record at publish time, not declared in app.md."));
|
|
41
45
|
});
|
|
46
|
+
const KINDS = ["skill", "plugin", "mcp"];
|
|
47
|
+
/** Match server-side canonicalization: lowercase, trim, dedupe, no whitespace. */
|
|
48
|
+
function canonicalizeEndpointsCsv(input) {
|
|
49
|
+
return Array.from(new Set(input
|
|
50
|
+
.split(",")
|
|
51
|
+
.map((s) => s.trim().toLowerCase())
|
|
52
|
+
.filter(Boolean))).join(",");
|
|
53
|
+
}
|
|
54
|
+
const DEFAULT_SERVER = process.env.CHEST_SERVER || "https://gate.chest.sh";
|
|
55
|
+
const DASHBOARD_BASE = process.env.CHEST_DASHBOARD || "https://chest.sh";
|
|
56
|
+
appCommand
|
|
57
|
+
.command("publish")
|
|
58
|
+
.description("Publish an app to the chest.sh registry (signed with ~/.chest/wallet.json)")
|
|
59
|
+
.requiredOption("-m, --manifest <path>", "Path to a JSON manifest with the app fields (see below)")
|
|
60
|
+
.option("--server <url>", "chest.sh API origin", DEFAULT_SERVER)
|
|
61
|
+
.option("--wallet-key <path>", "Path to Solana keypair JSON for the author wallet (signs the publish). " +
|
|
62
|
+
"Fallback: CHEST_WALLET_KEY_PATH env, CHEST_WALLET_KEY inline JSON, " +
|
|
63
|
+
"or ~/.chest/wallet.json (same wallet `chest-gate keypair` writes).")
|
|
64
|
+
.option("--dry-run", "Print the canonical manifest hash + signature without POSTing")
|
|
65
|
+
.addHelpText("after", `
|
|
66
|
+
Manifest JSON shape (file passed via --manifest):
|
|
67
|
+
|
|
68
|
+
{
|
|
69
|
+
"slug": "my-skill", // ^[a-z0-9][a-z0-9-]{1,63}$
|
|
70
|
+
"name": "My Skill",
|
|
71
|
+
"kind": "skill", // "skill" | "plugin" | "mcp"
|
|
72
|
+
"tagline": "One-line summary",
|
|
73
|
+
"description": null, // long form, optional
|
|
74
|
+
"readme": "# My Skill\\n...", // markdown, optional
|
|
75
|
+
"endpointsCsv": "smoke-1234,gate-foo", // comma-separated GATE slugs
|
|
76
|
+
"version": "0.1.0",
|
|
77
|
+
"sourceUrl": "https://github.com/me/my-skill",
|
|
78
|
+
"homepageUrl": null,
|
|
79
|
+
"installJson": { ... } // any JSON, optional
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
The author wallet (~/.chest/wallet.json by default) signs the canonical
|
|
83
|
+
message "chest-app/v4:{author}:{slug}:{manifestHash}:{version}:{windowTs}"
|
|
84
|
+
and the server binds the slug to that pubkey on first publish.
|
|
85
|
+
`)
|
|
86
|
+
.action(async (opts) => {
|
|
87
|
+
console.log(chalk.bold("\n ⚡ Chest App Publish\n"));
|
|
88
|
+
const manifestPath = resolve(process.cwd(), opts.manifest);
|
|
89
|
+
let raw;
|
|
90
|
+
try {
|
|
91
|
+
raw = await readFile(manifestPath, "utf-8");
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
console.error(chalk.red(` Error: cannot read ${opts.manifest}: ${err.message}`));
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
let parsed;
|
|
98
|
+
try {
|
|
99
|
+
parsed = JSON.parse(raw);
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
console.error(chalk.red(` Error: ${opts.manifest} is not valid JSON: ${err.message}`));
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
const errs = [];
|
|
106
|
+
if (typeof parsed.slug !== "string" || !/^[a-z0-9][a-z0-9-]{1,63}$/.test(parsed.slug)) {
|
|
107
|
+
errs.push("slug must match ^[a-z0-9][a-z0-9-]{1,63}$");
|
|
108
|
+
}
|
|
109
|
+
if (typeof parsed.name !== "string" || !parsed.name.trim())
|
|
110
|
+
errs.push("name is required");
|
|
111
|
+
if (!KINDS.includes(parsed.kind)) {
|
|
112
|
+
errs.push(`kind must be one of: ${KINDS.join(", ")}`);
|
|
113
|
+
}
|
|
114
|
+
if (typeof parsed.tagline !== "string" || !parsed.tagline.trim())
|
|
115
|
+
errs.push("tagline is required");
|
|
116
|
+
if (typeof parsed.endpointsCsv !== "string" || !parsed.endpointsCsv.trim()) {
|
|
117
|
+
errs.push("endpointsCsv is required (comma-separated gate slugs)");
|
|
118
|
+
}
|
|
119
|
+
if (typeof parsed.version !== "string" || !parsed.version.trim())
|
|
120
|
+
errs.push("version is required");
|
|
121
|
+
if (errs.length > 0) {
|
|
122
|
+
console.error(chalk.red(" Manifest failed validation:"));
|
|
123
|
+
for (const e of errs)
|
|
124
|
+
console.error(chalk.gray(" · ") + e);
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
let secretKey;
|
|
128
|
+
if (process.env.CHEST_WALLET_KEY) {
|
|
129
|
+
try {
|
|
130
|
+
secretKey = new Uint8Array(JSON.parse(process.env.CHEST_WALLET_KEY));
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
console.error(chalk.red(" Error: CHEST_WALLET_KEY must be a JSON array of 64 bytes"));
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else if (opts.walletKey || process.env.CHEST_WALLET_KEY_PATH) {
|
|
138
|
+
const path = (opts.walletKey || process.env.CHEST_WALLET_KEY_PATH).replace(/^~/, process.env.HOME || "");
|
|
139
|
+
const raw = await readFile(path, "utf-8");
|
|
140
|
+
secretKey = new Uint8Array(JSON.parse(raw));
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
const local = await ensureKeypair();
|
|
144
|
+
secretKey = local.keypair;
|
|
145
|
+
}
|
|
146
|
+
const authorWallet = Keypair.fromSecretKey(secretKey).publicKey.toBase58();
|
|
147
|
+
const slugClean = parsed.slug.toLowerCase();
|
|
148
|
+
const versionClean = parsed.version.trim();
|
|
149
|
+
const endpointsCanonical = canonicalizeEndpointsCsv(parsed.endpointsCsv);
|
|
150
|
+
if (!endpointsCanonical) {
|
|
151
|
+
console.error(chalk.red(" Error: endpointsCsv must contain at least one non-empty slug"));
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
154
|
+
if (endpointsCanonical !== parsed.endpointsCsv) {
|
|
155
|
+
console.log(chalk.gray(" endpointsCsv canonicalized: ") +
|
|
156
|
+
chalk.gray(parsed.endpointsCsv) +
|
|
157
|
+
chalk.gray(" → ") +
|
|
158
|
+
chalk.white(endpointsCanonical));
|
|
159
|
+
}
|
|
160
|
+
const manifestFields = {
|
|
161
|
+
name: parsed.name.trim(),
|
|
162
|
+
kind: parsed.kind,
|
|
163
|
+
tagline: parsed.tagline.trim(),
|
|
164
|
+
description: parsed.description ?? null,
|
|
165
|
+
readme: parsed.readme ?? null,
|
|
166
|
+
endpointsCsv: endpointsCanonical,
|
|
167
|
+
sourceUrl: parsed.sourceUrl ?? null,
|
|
168
|
+
homepageUrl: parsed.homepageUrl ?? null,
|
|
169
|
+
installJson: parsed.installJson ?? null,
|
|
170
|
+
};
|
|
171
|
+
const manifestHashHex = hashManifest(manifestFields);
|
|
172
|
+
const sigBase64 = signAppMessage({ author: authorWallet, slug: slugClean, manifestHash: manifestHashHex, version: versionClean }, secretKey);
|
|
173
|
+
console.log(chalk.gray(" Slug: ") + chalk.white(slugClean));
|
|
174
|
+
console.log(chalk.gray(" Version: ") + chalk.white(versionClean));
|
|
175
|
+
console.log(chalk.gray(" Author wallet: ") + chalk.cyan(authorWallet));
|
|
176
|
+
console.log(chalk.gray(" Manifest hash: ") + chalk.gray(manifestHashHex));
|
|
177
|
+
console.log(chalk.gray(" Server: ") + chalk.gray(opts.server));
|
|
178
|
+
console.log();
|
|
179
|
+
if (opts.dryRun) {
|
|
180
|
+
console.log(chalk.yellow(" --dry-run set, skipping POST."));
|
|
181
|
+
console.log(chalk.gray(" X-App-Sig: ") + chalk.gray(sigBase64));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
try {
|
|
185
|
+
const res = await fetch(`${opts.server}/api/apps`, {
|
|
186
|
+
method: "POST",
|
|
187
|
+
headers: { "Content-Type": "application/json", "X-App-Sig": sigBase64 },
|
|
188
|
+
body: JSON.stringify({
|
|
189
|
+
slug: slugClean,
|
|
190
|
+
name: manifestFields.name,
|
|
191
|
+
kind: manifestFields.kind,
|
|
192
|
+
tagline: manifestFields.tagline,
|
|
193
|
+
description: manifestFields.description,
|
|
194
|
+
readme: manifestFields.readme,
|
|
195
|
+
authorWallet,
|
|
196
|
+
endpointsCsv: manifestFields.endpointsCsv,
|
|
197
|
+
version: versionClean,
|
|
198
|
+
sourceUrl: manifestFields.sourceUrl,
|
|
199
|
+
homepageUrl: manifestFields.homepageUrl,
|
|
200
|
+
installJson: manifestFields.installJson,
|
|
201
|
+
}),
|
|
202
|
+
});
|
|
203
|
+
const body = (await res.json().catch(() => ({})));
|
|
204
|
+
if (!res.ok) {
|
|
205
|
+
console.error(chalk.red(` Error ${res.status}: ${body.error ?? res.statusText}`));
|
|
206
|
+
if (res.status === 403 && typeof body.error === "string" && body.error.includes("different wallet")) {
|
|
207
|
+
console.error(chalk.gray(` Slug "${slugClean}" is already published by another wallet. Pick a new slug.`));
|
|
208
|
+
}
|
|
209
|
+
process.exit(1);
|
|
210
|
+
}
|
|
211
|
+
const created = body.created;
|
|
212
|
+
console.log(chalk.green(created ? " ✓ Published" : " ✓ Updated"));
|
|
213
|
+
console.log(chalk.gray(" Listing: ") + chalk.cyan(`${DASHBOARD_BASE}/apps/${slugClean}`));
|
|
214
|
+
}
|
|
215
|
+
catch (err) {
|
|
216
|
+
console.error(chalk.red(` Error: could not reach ${opts.server}: ${err.message}`));
|
|
217
|
+
process.exit(1);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
42
220
|
//# sourceMappingURL=app.js.map
|
package/dist/commands/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/commands/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,WAAW,CACtD,
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/commands/app.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2BpC,eAAO,MAAM,YAAY,SAwGrB,CAAC"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { createServer } from "node:http";
|
|
4
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
5
|
+
import { hostname } from "node:os";
|
|
6
|
+
import { createInterface } from "node:readline/promises";
|
|
7
|
+
import { stdin, stdout } from "node:process";
|
|
8
|
+
import open from "open";
|
|
9
|
+
import { loadCredentials, saveCredentials, getDefaultGateUrl, getDefaultWebUrl, } from "../credentials.js";
|
|
10
|
+
const LOGIN_TIMEOUT_MS = 5 * 60 * 1000;
|
|
11
|
+
export const loginCommand = new Command("login")
|
|
12
|
+
.description("Sign in to Chest. Opens a browser, returns a CLI token to this device.")
|
|
13
|
+
.option("--web-url <url>", "Override chest.sh URL", getDefaultWebUrl())
|
|
14
|
+
.option("--gate-url <url>", "Override gate.chest.sh URL", getDefaultGateUrl())
|
|
15
|
+
.option("--port <port>", "Loopback port (default: random)")
|
|
16
|
+
.option("-f, --force", "Skip the 'already logged in' prompt")
|
|
17
|
+
.option("--no-browser", "Print the URL instead of opening a browser")
|
|
18
|
+
.action(async (opts) => {
|
|
19
|
+
console.log(chalk.bold("\n ⚡ Chest Login\n"));
|
|
20
|
+
const existing = await loadCredentials();
|
|
21
|
+
if (existing && existing.source === "file" && !opts.force) {
|
|
22
|
+
if (!stdin.isTTY) {
|
|
23
|
+
console.error(chalk.red(" Already logged in. Pass --force to mint a new token, or set CHEST_TOKEN env var.\n"));
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
console.log(chalk.gray(` Already logged in as `) +
|
|
27
|
+
chalk.cyan(existing.ownerWallet || existing.label) +
|
|
28
|
+
chalk.gray(`.`));
|
|
29
|
+
console.log(chalk.gray(" Re-running mints a new token; the old one stays valid until revoked."));
|
|
30
|
+
const rl = createInterface({ input: stdin, output: stdout });
|
|
31
|
+
const answer = await rl.question(chalk.gray(" Continue? (y/N) "));
|
|
32
|
+
rl.close();
|
|
33
|
+
if (answer.trim().toLowerCase() !== "y") {
|
|
34
|
+
console.log(chalk.gray("\n Cancelled.\n"));
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
console.log();
|
|
38
|
+
}
|
|
39
|
+
if (!stdin.isTTY && !process.env.CI_ALLOW_NON_TTY_LOGIN) {
|
|
40
|
+
console.error(chalk.red(" Non-interactive shell detected. Set CHEST_TOKEN instead of running `login`.\n"));
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
const webUrl = (opts.webUrl || getDefaultWebUrl()).replace(/\/$/, "");
|
|
44
|
+
const gateUrl = (opts.gateUrl || getDefaultGateUrl()).replace(/\/$/, "");
|
|
45
|
+
const verifier = base64url(randomBytes(32));
|
|
46
|
+
const challenge = base64url(createHash("sha256").update(verifier).digest());
|
|
47
|
+
const state = base64url(randomBytes(24));
|
|
48
|
+
const host = hostname() || "unknown";
|
|
49
|
+
const portArg = opts.port ? parseInt(opts.port, 10) : 0;
|
|
50
|
+
if (opts.port && (!Number.isFinite(portArg) || portArg < 0 || portArg > 65535)) {
|
|
51
|
+
console.error(chalk.red(` Invalid --port: ${opts.port}`));
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
const result = await runLoopbackFlow({
|
|
55
|
+
webUrl,
|
|
56
|
+
state,
|
|
57
|
+
challenge,
|
|
58
|
+
hostname: host,
|
|
59
|
+
desiredPort: portArg,
|
|
60
|
+
openBrowser: opts.noBrowser !== true,
|
|
61
|
+
});
|
|
62
|
+
if (result.kind === "error") {
|
|
63
|
+
console.error(chalk.red(` ✗ ${result.message}\n`));
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
process.stdout.write(chalk.gray(" Exchanging code… "));
|
|
67
|
+
const exchanged = await exchangeCode({
|
|
68
|
+
gateUrl,
|
|
69
|
+
code: result.code,
|
|
70
|
+
verifier,
|
|
71
|
+
});
|
|
72
|
+
if (!exchanged.ok) {
|
|
73
|
+
console.log(chalk.red("failed"));
|
|
74
|
+
console.error(chalk.red(`\n ✗ ${exchanged.error}\n`));
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
console.log(chalk.green("done"));
|
|
78
|
+
const creds = {
|
|
79
|
+
version: 1,
|
|
80
|
+
token: exchanged.token,
|
|
81
|
+
ownerWallet: exchanged.ownerWallet,
|
|
82
|
+
tokenId: exchanged.tokenId,
|
|
83
|
+
label: exchanged.label,
|
|
84
|
+
gateUrl,
|
|
85
|
+
createdAt: new Date().toISOString(),
|
|
86
|
+
};
|
|
87
|
+
const path = await saveCredentials(creds);
|
|
88
|
+
console.log();
|
|
89
|
+
console.log(chalk.green(" ✓ Logged in as ") + chalk.cyan(exchanged.ownerWallet));
|
|
90
|
+
console.log(chalk.gray(` Token label: `) + chalk.white(exchanged.label));
|
|
91
|
+
console.log(chalk.gray(` Saved to: `) + chalk.white(path));
|
|
92
|
+
console.log();
|
|
93
|
+
console.log(chalk.gray(" Manage tokens at ") + chalk.cyan(`${webUrl}/dashboard/agent-wallet`));
|
|
94
|
+
console.log();
|
|
95
|
+
});
|
|
96
|
+
function runLoopbackFlow(args) {
|
|
97
|
+
return new Promise((resolve) => {
|
|
98
|
+
let settled = false;
|
|
99
|
+
const finish = (r) => {
|
|
100
|
+
if (settled)
|
|
101
|
+
return;
|
|
102
|
+
settled = true;
|
|
103
|
+
try {
|
|
104
|
+
server.close();
|
|
105
|
+
}
|
|
106
|
+
catch { }
|
|
107
|
+
clearTimeout(timer);
|
|
108
|
+
resolve(r);
|
|
109
|
+
};
|
|
110
|
+
const server = createServer((req, res) => {
|
|
111
|
+
const url = new URL(req.url || "/", `http://127.0.0.1`);
|
|
112
|
+
if (url.pathname !== "/callback") {
|
|
113
|
+
res.writeHead(404, { "content-type": "text/plain" });
|
|
114
|
+
res.end("not found");
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const recvState = url.searchParams.get("state");
|
|
118
|
+
const code = url.searchParams.get("code");
|
|
119
|
+
const error = url.searchParams.get("error");
|
|
120
|
+
if (error) {
|
|
121
|
+
res.writeHead(400, { "content-type": "text/html; charset=utf-8" });
|
|
122
|
+
res.end(htmlPage("Login failed", error, false));
|
|
123
|
+
finish({ kind: "error", message: `Browser returned error: ${error}` });
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (!recvState || recvState !== args.state) {
|
|
127
|
+
res.writeHead(400, { "content-type": "text/html; charset=utf-8" });
|
|
128
|
+
res.end(htmlPage("Invalid state", "State mismatch. Try again.", false));
|
|
129
|
+
finish({ kind: "error", message: "State mismatch on callback (possible CSRF)." });
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (!code) {
|
|
133
|
+
res.writeHead(400, { "content-type": "text/html; charset=utf-8" });
|
|
134
|
+
res.end(htmlPage("Missing code", "No authorization code on the callback.", false));
|
|
135
|
+
finish({ kind: "error", message: "Callback missing code parameter." });
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
|
|
139
|
+
res.end(htmlPage("You're signed in", "You can close this tab and return to the terminal.", true));
|
|
140
|
+
finish({ kind: "ok", code });
|
|
141
|
+
});
|
|
142
|
+
server.on("error", (err) => {
|
|
143
|
+
finish({ kind: "error", message: `Loopback server failed: ${err.message}` });
|
|
144
|
+
});
|
|
145
|
+
server.listen(args.desiredPort, "127.0.0.1", () => {
|
|
146
|
+
const addr = server.address();
|
|
147
|
+
if (!addr || typeof addr === "string") {
|
|
148
|
+
finish({ kind: "error", message: "Could not bind loopback server." });
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const port = addr.port;
|
|
152
|
+
const params = new URLSearchParams({
|
|
153
|
+
state: args.state,
|
|
154
|
+
challenge: args.challenge,
|
|
155
|
+
port: String(port),
|
|
156
|
+
hostname: args.hostname,
|
|
157
|
+
});
|
|
158
|
+
const loginUrl = `${args.webUrl}/cli/login?${params.toString()}`;
|
|
159
|
+
console.log(chalk.gray(" Opening browser to authorize this device…"));
|
|
160
|
+
console.log(chalk.gray(" If it doesn't open, visit:"));
|
|
161
|
+
console.log(chalk.cyan(` ${loginUrl}`));
|
|
162
|
+
console.log();
|
|
163
|
+
console.log(chalk.gray(` Listening on http://127.0.0.1:${port}/callback`));
|
|
164
|
+
console.log();
|
|
165
|
+
if (args.openBrowser) {
|
|
166
|
+
open(loginUrl).catch(() => {
|
|
167
|
+
// Non-fatal; the user can still copy the URL.
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
const timer = setTimeout(() => {
|
|
172
|
+
finish({ kind: "error", message: "Timed out waiting for browser sign-in (5 min)." });
|
|
173
|
+
}, LOGIN_TIMEOUT_MS);
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
async function exchangeCode(args) {
|
|
177
|
+
let res;
|
|
178
|
+
try {
|
|
179
|
+
res = await fetch(`${args.gateUrl}/v1/cli/exchange`, {
|
|
180
|
+
method: "POST",
|
|
181
|
+
headers: { "content-type": "application/json" },
|
|
182
|
+
body: JSON.stringify({ code: args.code, verifier: args.verifier }),
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
return { ok: false, error: `Network error: ${err.message}` };
|
|
187
|
+
}
|
|
188
|
+
if (!res.ok) {
|
|
189
|
+
let msg = `${res.status} ${res.statusText}`;
|
|
190
|
+
try {
|
|
191
|
+
const body = (await res.json());
|
|
192
|
+
msg = body.error || body.message || msg;
|
|
193
|
+
}
|
|
194
|
+
catch { }
|
|
195
|
+
return { ok: false, error: msg };
|
|
196
|
+
}
|
|
197
|
+
const body = (await res.json());
|
|
198
|
+
if (!body.token || !body.ownerWallet || !body.tokenId) {
|
|
199
|
+
return { ok: false, error: "Malformed response from gate." };
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
ok: true,
|
|
203
|
+
token: body.token,
|
|
204
|
+
ownerWallet: body.ownerWallet,
|
|
205
|
+
tokenId: body.tokenId,
|
|
206
|
+
label: body.label || "CLI",
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function base64url(buf) {
|
|
210
|
+
return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
211
|
+
}
|
|
212
|
+
function htmlPage(title, body, ok) {
|
|
213
|
+
const accent = ok ? "#10b981" : "#ef4444";
|
|
214
|
+
return `<!doctype html>
|
|
215
|
+
<html><head><meta charset="utf-8"><title>${title}</title>
|
|
216
|
+
<style>
|
|
217
|
+
body { margin:0; min-height:100vh; display:grid; place-items:center;
|
|
218
|
+
font:15px/1.5 -apple-system,BlinkMacSystemFont,sans-serif; background:#0b0b0d; color:#e5e5e5; }
|
|
219
|
+
.card { background:#141418; border:1px solid #26262c; border-radius:12px;
|
|
220
|
+
padding:32px 36px; max-width:420px; }
|
|
221
|
+
.dot { display:inline-block; width:10px; height:10px; border-radius:50%;
|
|
222
|
+
background:${accent}; margin-right:10px; vertical-align:middle; }
|
|
223
|
+
h1 { margin:0 0 8px; font-size:18px; font-weight:600; }
|
|
224
|
+
p { margin:0; color:#a3a3aa; }
|
|
225
|
+
</style></head>
|
|
226
|
+
<body><div class="card"><h1><span class="dot"></span>${title}</h1><p>${body}</p></div></body></html>`;
|
|
227
|
+
}
|
|
228
|
+
//# 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 @@
|
|
|
1
|
+
{"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,aAAa,SA+CtB,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { loadCredentials, deleteCredentials, getCredentialsPath } from "../credentials.js";
|
|
4
|
+
export const logoutCommand = new Command("logout")
|
|
5
|
+
.description("Sign out: revoke the CLI token and remove local credentials.")
|
|
6
|
+
.option("--keep-remote", "Delete local credentials but don't revoke the token on the server")
|
|
7
|
+
.action(async (opts) => {
|
|
8
|
+
console.log(chalk.bold("\n ⚡ Chest Logout\n"));
|
|
9
|
+
const creds = await loadCredentials();
|
|
10
|
+
if (!creds) {
|
|
11
|
+
console.log(chalk.gray(" Not logged in.\n"));
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (creds.source === "env") {
|
|
15
|
+
console.log(chalk.yellow(" CHEST_TOKEN env var is set; logout doesn't unset env vars.\n"));
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (!opts.keepRemote && creds.tokenId && creds.gateUrl) {
|
|
19
|
+
process.stdout.write(chalk.gray(" Revoking token on server… "));
|
|
20
|
+
try {
|
|
21
|
+
const res = await fetch(`${creds.gateUrl}/v1/cli/revoke`, {
|
|
22
|
+
method: "POST",
|
|
23
|
+
headers: {
|
|
24
|
+
"content-type": "application/json",
|
|
25
|
+
authorization: `Bearer ${creds.token}`,
|
|
26
|
+
},
|
|
27
|
+
body: JSON.stringify({ tokenId: creds.tokenId }),
|
|
28
|
+
});
|
|
29
|
+
if (res.ok) {
|
|
30
|
+
console.log(chalk.green("done"));
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
console.log(chalk.yellow(`skipped (${res.status})`));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
console.log(chalk.yellow(`skipped (${err.message})`));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const removed = await deleteCredentials();
|
|
41
|
+
if (removed) {
|
|
42
|
+
console.log(chalk.green(` ✓ Removed ${getCredentialsPath()}`));
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
console.log(chalk.gray(` No credentials file at ${getCredentialsPath()}`));
|
|
46
|
+
}
|
|
47
|
+
console.log();
|
|
48
|
+
});
|
|
49
|
+
//# sourceMappingURL=logout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE3F,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,8DAA8D,CAAC;KAC3E,MAAM,CAAC,eAAe,EAAE,mEAAmE,CAAC;KAC5F,MAAM,CAAC,KAAK,EAAE,IAA8B,EAAE,EAAE;IAC/C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC;IAEhD,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAC;IACtC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC;QAC9C,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CAAC,gEAAgE,CAAC,CAC/E,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QACvD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC,CAAC;QACjE,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,KAAK,CAAC,OAAO,gBAAgB,EAAE;gBACxD,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,aAAa,EAAE,UAAU,KAAK,CAAC,KAAK,EAAE;iBACvC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;aACjD,CAAC,CAAC;YACH,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;gBACX,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;YACnC,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,YAAa,GAAa,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,iBAAiB,EAAE,CAAC;IAC1C,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,eAAe,kBAAkB,EAAE,EAAE,CAAC,CAAC,CAAC;IAClE,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,4BAA4B,kBAAkB,EAAE,EAAE,CAAC,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,CAAC,GAAG,EAAE,CAAC;AAChB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,aAAa,SAyCtB,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { loadCredentials } from "../credentials.js";
|
|
4
|
+
export const whoamiCommand = new Command("whoami")
|
|
5
|
+
.description("Show the wallet and CLI token currently signed in on this device.")
|
|
6
|
+
.action(async () => {
|
|
7
|
+
const creds = await loadCredentials();
|
|
8
|
+
if (!creds) {
|
|
9
|
+
console.log(chalk.gray("\n Not logged in. Run ") + chalk.white("chest-gate login") + chalk.gray(".\n"));
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
if (creds.source === "env") {
|
|
13
|
+
console.log();
|
|
14
|
+
console.log(chalk.gray(" Source: ") + chalk.white("CHEST_TOKEN env var"));
|
|
15
|
+
console.log(chalk.gray(" Gate: ") + chalk.white(creds.gateUrl));
|
|
16
|
+
console.log();
|
|
17
|
+
// Best-effort resolve via /v1/cli/session.
|
|
18
|
+
const session = await fetchSession(creds.gateUrl, creds.token);
|
|
19
|
+
if (session) {
|
|
20
|
+
console.log(chalk.green(" ✓ ") + chalk.cyan(session.ownerWallet));
|
|
21
|
+
console.log(chalk.gray(" Token label: ") + chalk.white(session.label));
|
|
22
|
+
if (session.lastUsedAt) {
|
|
23
|
+
console.log(chalk.gray(" Last used: ") + chalk.white(session.lastUsedAt));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
console.log(chalk.yellow(" Could not verify token with the gate."));
|
|
28
|
+
}
|
|
29
|
+
console.log();
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
console.log();
|
|
33
|
+
console.log(chalk.green(" ✓ ") + chalk.cyan(creds.ownerWallet));
|
|
34
|
+
console.log(chalk.gray(" Token label: ") + chalk.white(creds.label));
|
|
35
|
+
console.log(chalk.gray(" Token id: ") + chalk.white(creds.tokenId));
|
|
36
|
+
console.log(chalk.gray(" Gate: ") + chalk.white(creds.gateUrl));
|
|
37
|
+
console.log(chalk.gray(" Logged in: ") + chalk.white(creds.createdAt));
|
|
38
|
+
const session = await fetchSession(creds.gateUrl, creds.token);
|
|
39
|
+
if (session?.lastUsedAt) {
|
|
40
|
+
console.log(chalk.gray(" Last used: ") + chalk.white(session.lastUsedAt));
|
|
41
|
+
}
|
|
42
|
+
console.log();
|
|
43
|
+
});
|
|
44
|
+
async function fetchSession(gateUrl, token) {
|
|
45
|
+
try {
|
|
46
|
+
const res = await fetch(`${gateUrl}/v1/cli/session`, {
|
|
47
|
+
headers: { authorization: `Bearer ${token}` },
|
|
48
|
+
});
|
|
49
|
+
if (!res.ok)
|
|
50
|
+
return null;
|
|
51
|
+
return (await res.json());
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=whoami.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface Credentials {
|
|
2
|
+
version: 1;
|
|
3
|
+
token: string;
|
|
4
|
+
ownerWallet: string;
|
|
5
|
+
tokenId: string;
|
|
6
|
+
label: string;
|
|
7
|
+
gateUrl: string;
|
|
8
|
+
createdAt: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ResolvedCredentials extends Credentials {
|
|
11
|
+
source: "env" | "file";
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Load credentials, preferring CHEST_TOKEN env over the on-disk file.
|
|
15
|
+
* Returns null if neither is present.
|
|
16
|
+
*/
|
|
17
|
+
export declare function loadCredentials(): Promise<ResolvedCredentials | null>;
|
|
18
|
+
export declare function requireCredentials(): Promise<ResolvedCredentials>;
|
|
19
|
+
export declare function saveCredentials(creds: Credentials): Promise<string>;
|
|
20
|
+
export declare function deleteCredentials(): Promise<boolean>;
|
|
21
|
+
export declare function getCredentialsPath(): string;
|
|
22
|
+
export declare function getDefaultGateUrl(): string;
|
|
23
|
+
export declare function getDefaultWebUrl(): string;
|
|
24
|
+
//# sourceMappingURL=credentials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,CAAC,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAoB,SAAQ,WAAW;IACtD,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAoB3E;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAMvE;AAED,wBAAsB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAMzE;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAI1D;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir, chmod, unlink } from "node:fs/promises";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
const CHEST_DIR = join(homedir(), ".chest");
|
|
6
|
+
const CREDENTIALS_PATH = join(CHEST_DIR, "credentials.json");
|
|
7
|
+
const DEFAULT_GATE_URL = "https://gate.chest.sh";
|
|
8
|
+
/**
|
|
9
|
+
* Load credentials, preferring CHEST_TOKEN env over the on-disk file.
|
|
10
|
+
* Returns null if neither is present.
|
|
11
|
+
*/
|
|
12
|
+
export async function loadCredentials() {
|
|
13
|
+
const envToken = process.env.CHEST_TOKEN?.trim();
|
|
14
|
+
if (envToken) {
|
|
15
|
+
return {
|
|
16
|
+
version: 1,
|
|
17
|
+
token: envToken,
|
|
18
|
+
ownerWallet: "",
|
|
19
|
+
tokenId: "",
|
|
20
|
+
label: "CHEST_TOKEN env",
|
|
21
|
+
gateUrl: process.env.CHEST_GATE_URL?.trim() || DEFAULT_GATE_URL,
|
|
22
|
+
createdAt: "",
|
|
23
|
+
source: "env",
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
if (!existsSync(CREDENTIALS_PATH))
|
|
27
|
+
return null;
|
|
28
|
+
const raw = await readFile(CREDENTIALS_PATH, "utf-8");
|
|
29
|
+
const parsed = JSON.parse(raw);
|
|
30
|
+
return { ...parsed, source: "file" };
|
|
31
|
+
}
|
|
32
|
+
export async function requireCredentials() {
|
|
33
|
+
const creds = await loadCredentials();
|
|
34
|
+
if (!creds) {
|
|
35
|
+
throw new Error("Not logged in. Run `chest-gate login` first.");
|
|
36
|
+
}
|
|
37
|
+
return creds;
|
|
38
|
+
}
|
|
39
|
+
export async function saveCredentials(creds) {
|
|
40
|
+
await mkdir(CHEST_DIR, { recursive: true, mode: 0o700 });
|
|
41
|
+
await chmod(CHEST_DIR, 0o700).catch(() => { });
|
|
42
|
+
await writeFile(CREDENTIALS_PATH, JSON.stringify(creds, null, 2), { mode: 0o600 });
|
|
43
|
+
await chmod(CREDENTIALS_PATH, 0o600).catch(() => { });
|
|
44
|
+
return CREDENTIALS_PATH;
|
|
45
|
+
}
|
|
46
|
+
export async function deleteCredentials() {
|
|
47
|
+
if (!existsSync(CREDENTIALS_PATH))
|
|
48
|
+
return false;
|
|
49
|
+
await unlink(CREDENTIALS_PATH);
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
export function getCredentialsPath() {
|
|
53
|
+
return CREDENTIALS_PATH;
|
|
54
|
+
}
|
|
55
|
+
export function getDefaultGateUrl() {
|
|
56
|
+
return process.env.CHEST_GATE_URL?.trim() || DEFAULT_GATE_URL;
|
|
57
|
+
}
|
|
58
|
+
export function getDefaultWebUrl() {
|
|
59
|
+
return process.env.CHEST_WEB_URL?.trim() || "https://chest.sh";
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sign dashboard-bound API actions (archive, unlist, etc.) with the local
|
|
3
|
+
* deployer / author keypair. Mirrors `signDashboardMessage` in
|
|
4
|
+
* server-auth/dashboard-auth.ts byte-for-byte so the server's
|
|
5
|
+
* `verifyDashboardSignature` accepts the result.
|
|
6
|
+
*
|
|
7
|
+
* Canonical message (utf-8):
|
|
8
|
+
* "chest-dashboard:{wallet}:{action}:{resourceId}:{windowTs}"
|
|
9
|
+
*
|
|
10
|
+
* wallet = base58 Solana pubkey of the signer
|
|
11
|
+
* action = e.g. "deployment:archive", "app:unlist"
|
|
12
|
+
* resourceId = the slug (or "-" when unused)
|
|
13
|
+
* windowTs = Math.floor(Date.now() / 300_000), 5-minute window
|
|
14
|
+
*
|
|
15
|
+
* Output: ed25519 signature, base64-encoded, sent in the X-Dashboard-Sig
|
|
16
|
+
* header.
|
|
17
|
+
*/
|
|
18
|
+
export type DashboardAction = "deployment:archive" | "deployment:unlist" | "app:archive" | "app:unlist";
|
|
19
|
+
export interface DashboardSignatureInput {
|
|
20
|
+
wallet: string;
|
|
21
|
+
action: DashboardAction;
|
|
22
|
+
resourceId: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function signDashboardMessage(input: DashboardSignatureInput, secretKey: Uint8Array): string;
|
|
25
|
+
//# sourceMappingURL=dashboard-sig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-sig.d.ts","sourceRoot":"","sources":["../src/dashboard-sig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,MAAM,MAAM,eAAe,GACvB,oBAAoB,GACpB,mBAAmB,GACnB,aAAa,GACb,YAAY,CAAC;AAEjB,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,eAAe,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAID,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,uBAAuB,EAC9B,SAAS,EAAE,UAAU,GACpB,MAAM,CAOR"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sign dashboard-bound API actions (archive, unlist, etc.) with the local
|
|
3
|
+
* deployer / author keypair. Mirrors `signDashboardMessage` in
|
|
4
|
+
* server-auth/dashboard-auth.ts byte-for-byte so the server's
|
|
5
|
+
* `verifyDashboardSignature` accepts the result.
|
|
6
|
+
*
|
|
7
|
+
* Canonical message (utf-8):
|
|
8
|
+
* "chest-dashboard:{wallet}:{action}:{resourceId}:{windowTs}"
|
|
9
|
+
*
|
|
10
|
+
* wallet = base58 Solana pubkey of the signer
|
|
11
|
+
* action = e.g. "deployment:archive", "app:unlist"
|
|
12
|
+
* resourceId = the slug (or "-" when unused)
|
|
13
|
+
* windowTs = Math.floor(Date.now() / 300_000), 5-minute window
|
|
14
|
+
*
|
|
15
|
+
* Output: ed25519 signature, base64-encoded, sent in the X-Dashboard-Sig
|
|
16
|
+
* header.
|
|
17
|
+
*/
|
|
18
|
+
import { ed25519 } from "@noble/curves/ed25519";
|
|
19
|
+
const WINDOW_MS = 300_000;
|
|
20
|
+
export function signDashboardMessage(input, secretKey) {
|
|
21
|
+
const seed = secretKey.length === 64 ? secretKey.slice(0, 32) : secretKey;
|
|
22
|
+
const windowTs = Math.floor(Date.now() / WINDOW_MS);
|
|
23
|
+
const msg = new TextEncoder().encode(`chest-dashboard:${input.wallet}:${input.action}:${input.resourceId}:${windowTs}`);
|
|
24
|
+
return Buffer.from(ed25519.sign(msg, seed)).toString("base64");
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=dashboard-sig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-sig.js","sourceRoot":"","sources":["../src/dashboard-sig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAchD,MAAM,SAAS,GAAG,OAAO,CAAC;AAE1B,MAAM,UAAU,oBAAoB,CAClC,KAA8B,EAC9B,SAAqB;IAErB,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;IACpD,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAClC,mBAAmB,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,UAAU,IAAI,QAAQ,EAAE,CAClF,CAAC;IACF,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACjE,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -7,11 +7,14 @@ import { statusCommand } from "./commands/status.js";
|
|
|
7
7
|
import { keypairCommand } from "./commands/keypair.js";
|
|
8
8
|
import { splitCommand } from "./commands/split.js";
|
|
9
9
|
import { appCommand } from "./commands/app.js";
|
|
10
|
+
import { loginCommand } from "./commands/login.js";
|
|
11
|
+
import { logoutCommand } from "./commands/logout.js";
|
|
12
|
+
import { whoamiCommand } from "./commands/whoami.js";
|
|
10
13
|
const program = new Command();
|
|
11
14
|
program
|
|
12
15
|
.name("chest-gate")
|
|
13
16
|
.description("One command to monetise any API with x402 on Solana")
|
|
14
|
-
.version("0.
|
|
17
|
+
.version("0.2.0");
|
|
15
18
|
program.addCommand(gateCommand);
|
|
16
19
|
program.addCommand(deployCommand);
|
|
17
20
|
program.addCommand(initCommand);
|
|
@@ -19,5 +22,8 @@ program.addCommand(statusCommand);
|
|
|
19
22
|
program.addCommand(keypairCommand);
|
|
20
23
|
program.addCommand(splitCommand);
|
|
21
24
|
program.addCommand(appCommand);
|
|
25
|
+
program.addCommand(loginCommand);
|
|
26
|
+
program.addCommand(logoutCommand);
|
|
27
|
+
program.addCommand(whoamiCommand);
|
|
22
28
|
program.parse();
|
|
23
29
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,qDAAqD,CAAC;KAClE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAElC,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chest-gate/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Chest Gate CLI. One command to monetise any API with x402 on Solana.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"x402",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@chest-gate/proxy": "^0.1.0",
|
|
39
39
|
"@coral-xyz/anchor": "^0.32.1",
|
|
40
|
+
"@noble/curves": "^1.0.0",
|
|
40
41
|
"@solana/kit": "^5.5.0",
|
|
41
42
|
"@solana/spl-token": "^0.4.14",
|
|
42
43
|
"@solana/web3.js": "^1.98.4",
|
|
@@ -46,6 +47,7 @@
|
|
|
46
47
|
"ed25519-hd-key": "^1.3.0",
|
|
47
48
|
"gray-matter": "^4.0.3",
|
|
48
49
|
"inquirer": "^12.0.0",
|
|
50
|
+
"open": "^11.0.0",
|
|
49
51
|
"yaml": "^2.7.0"
|
|
50
52
|
},
|
|
51
53
|
"devDependencies": {
|