@c4roa0/agentpay-user 0.0.0-stage → 0.3.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/AGENTS.md +137 -0
- package/CONTRIBUTING.md +16 -0
- package/LICENSE +373 -0
- package/NOTICE.md +20 -0
- package/README.md +84 -2
- package/SECURITY.md +16 -0
- package/doc/README.md +52 -0
- package/doc/TODO.md +97 -0
- package/doc/architecture.md +96 -0
- package/doc/design.md +60 -0
- package/doc/develope.md +68 -0
- package/doc/plans/user-wallet-distribution.md +91 -0
- package/doc/reference/harness-skill-runtime.md +120 -0
- package/doc/reference/local-cache-foundation.md +176 -0
- package/doc/reference/local-safe-owner-ui.md +25 -0
- package/doc/reference/local-update.md +18 -0
- package/doc/reference/multi-service-runtime.md +119 -0
- package/doc/reference/npm-integration-verification.md +67 -0
- package/doc/reference/onboarding-writing.md +48 -0
- package/doc/reference/original-order-recovery.md +97 -0
- package/doc/reference/private-anvil-onboarding-config.example.json +18 -0
- package/doc/reference/public-deployment-settings.md +56 -0
- package/doc/reference/random-skill-contract.md +18 -0
- package/doc/reference/result-file-cache.md +166 -0
- package/doc/reference/runtime-address-recovery.md +42 -0
- package/doc/reference/runtime-result-cache.md +157 -0
- package/doc/reference/runtime-startup-recovery.md +141 -0
- package/doc/reference/skill-input-output-cache.md +93 -0
- package/doc/reference/wallet-identity-policy-history.md +23 -0
- package/doc/runbooks/commands.md +89 -0
- package/doc/runbooks/deployment-authorization-update.md +42 -0
- package/doc/runbooks/emergency-payment-stop.md +80 -0
- package/doc/runbooks/local-autostart.md +212 -0
- package/doc/runbooks/local-cache.md +115 -0
- package/doc/runbooks/local-update.md +84 -0
- package/doc/runbooks/market-connection.md +73 -0
- package/doc/runbooks/npm-publication.md +56 -0
- package/doc/runbooks/official-test-package.md +62 -0
- package/doc/runbooks/order-cancellation.md +56 -0
- package/doc/runbooks/order-support.md +41 -0
- package/doc/runbooks/policy-renewal.md +80 -0
- package/doc/runbooks/private-anvil-terminal-setup.md +58 -0
- package/doc/runbooks/runtime-skill-client.md +155 -0
- package/doc/runbooks/safe-owner-web.md +104 -0
- package/doc/runbooks/safe-policy-migration.md +36 -0
- package/doc/runbooks/safe-policy-setup.md +52 -0
- package/doc/runbooks/terminal-authorization-preview.md +38 -0
- package/doc/runbooks/unlock-wallet.md +68 -0
- package/doc/runbooks/user-onboarding.md +87 -0
- package/doc/runbooks/wallet-identity.md +59 -0
- package/doc/security/public-source-review-2026-11-06.md +71 -0
- package/doc/usage.md +54 -0
- package/package.json +49 -4
- package/progress.md +178 -0
- package/run +29 -0
- package/scripts/agentpay-cli.mjs +11 -0
- package/scripts/authorize-existing-safe.mjs +211 -0
- package/scripts/autostart.mjs +186 -0
- package/scripts/cancel-order.mjs +76 -0
- package/scripts/check-installation.mjs +26 -0
- package/scripts/check-official-test-package.mjs +35 -0
- package/scripts/check-purchase-readiness.mjs +275 -0
- package/scripts/configure-runtime-client.mjs +16 -0
- package/scripts/guide-policy.mjs +64 -0
- package/scripts/initialize-caller-credential.mjs +11 -0
- package/scripts/install-skill-bundle.mjs +176 -0
- package/scripts/install-user.mjs +24 -0
- package/scripts/local-service.mjs +60 -0
- package/scripts/lock.mjs +11 -0
- package/scripts/login-notify.mjs +39 -0
- package/scripts/migrate-safe-policy.mjs +165 -0
- package/scripts/official-paid-test.mjs +9 -0
- package/scripts/poll-unconfirmed-notice.mjs +75 -0
- package/scripts/prepare-onboarding.mjs +33 -0
- package/scripts/preview-policy.mjs +65 -0
- package/scripts/random-model-ack-smoke.mjs +235 -0
- package/scripts/random-reject-smoke.mjs +147 -0
- package/scripts/renew.mjs +9 -0
- package/scripts/repair.mjs +10 -0
- package/scripts/revoke.mjs +9 -0
- package/scripts/select-skill-bundle.mjs +39 -0
- package/scripts/setup-local.mjs +199 -0
- package/scripts/status.mjs +13 -0
- package/scripts/test-package.mjs +35 -0
- package/scripts/unlock.mjs +13 -0
- package/scripts/update.mjs +7 -0
- package/scripts/user-setup.mjs +219 -0
- package/scripts/verify-npm-release.mjs +32 -0
- package/src/active-skill.mjs +160 -0
- package/src/anvil-onboarding-state.mjs +96 -0
- package/src/anvil-onboarding.mjs +1036 -0
- package/src/authorization-question-checkpoint.mjs +114 -0
- package/src/autostart-files.mjs +50 -0
- package/src/cache-management-cli.mjs +302 -0
- package/src/cache-management.mjs +47 -0
- package/src/caller-auth.mjs +58 -0
- package/src/client-request-lock.mjs +44 -0
- package/src/connect-market.mjs +408 -0
- package/src/demo-unlock-secret.mjs +64 -0
- package/src/deployment-status.mjs +198 -0
- package/src/file-cache-cli.mjs +83 -0
- package/src/file-cache-owner.mjs +74 -0
- package/src/file-cache-settings.mjs +50 -0
- package/src/file-cache.mjs +790 -0
- package/src/file-download.mjs +281 -0
- package/src/finalization-disclosure.mjs +16 -0
- package/src/guided-setup.mjs +194 -0
- package/src/index.mjs +1231 -0
- package/src/install-and-setup.mjs +38 -0
- package/src/install-preflight.mjs +201 -0
- package/src/install-user.mjs +279 -0
- package/src/installation-paths.mjs +31 -0
- package/src/invocation-result.mjs +148 -0
- package/src/invocation-store.mjs +385 -0
- package/src/local-data-directory.mjs +117 -0
- package/src/local-info.mjs +181 -0
- package/src/local-services.mjs +156 -0
- package/src/local-time.mjs +36 -0
- package/src/local-update.mjs +306 -0
- package/src/local-wallet-ipc.mjs +93 -0
- package/src/login-reminder.mjs +28 -0
- package/src/market-download-url.mjs +21 -0
- package/src/node-version.mjs +12 -0
- package/src/npm-update.mjs +126 -0
- package/src/official-paid-test.mjs +407 -0
- package/src/official-test-package.mjs +41 -0
- package/src/official-test-update.mjs +162 -0
- package/src/order-cancellation.mjs +241 -0
- package/src/order-closure.mjs +42 -0
- package/src/order-list-panel.mjs +110 -0
- package/src/order-review.mjs +424 -0
- package/src/order-status-panel.mjs +65 -0
- package/src/order-support.mjs +365 -0
- package/src/owner-approval-server.mjs +332 -0
- package/src/owner-signer.mjs +67 -0
- package/src/policy-info.mjs +38 -0
- package/src/policy-migration.mjs +84 -0
- package/src/policy-operations.mjs +67 -0
- package/src/policy-preview-server.mjs +236 -0
- package/src/policy-terminal-guide.mjs +377 -0
- package/src/prepare-local-services.mjs +143 -0
- package/src/prepare-onboarding.mjs +210 -0
- package/src/private-journal-files.mjs +29 -0
- package/src/readiness-profile.mjs +30 -0
- package/src/renew-policy.mjs +605 -0
- package/src/repair-market-wallet.mjs +137 -0
- package/src/restore-wallet.mjs +255 -0
- package/src/result-cache-view.mjs +276 -0
- package/src/runtime-client.mjs +1145 -0
- package/src/runtime-connection-settings.mjs +101 -0
- package/src/runtime-recovery.mjs +667 -0
- package/src/runtime-status.mjs +32 -0
- package/src/safe-owner-anvil.mjs +115 -0
- package/src/safe-policy-plan.mjs +195 -0
- package/src/service-reference.mjs +233 -0
- package/src/service-url.mjs +52 -0
- package/src/settlement-response.mjs +69 -0
- package/src/setup-autostart.mjs +197 -0
- package/src/setup-demo.mjs +152 -0
- package/src/skill-bundle.mjs +142 -0
- package/src/skill-client.mjs +198 -0
- package/src/skill-install-prompt.mjs +31 -0
- package/src/skill-package.mjs +50 -0
- package/src/skill-zip.mjs +220 -0
- package/src/status-panel.mjs +589 -0
- package/src/transport.mjs +48 -0
- package/src/uninstall-local.mjs +299 -0
- package/src/user-cli.mjs +354 -0
- package/src/user-setup-guide.mjs +193 -0
- package/src/wallet-control.mjs +182 -0
- package/src/wallet-ipc-error.mjs +16 -0
- package/src/wallet-package.mjs +22 -0
- package/update-pair.json +6 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
3
|
+
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
4
|
+
// If a copy was not distributed with this file, see https://mozilla.org/MPL/2.0/.
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { resolveUserDataDir } from "../src/local-data-directory.mjs";
|
|
7
|
+
import { installAndSetup } from "../src/install-and-setup.mjs";
|
|
8
|
+
try {
|
|
9
|
+
const args = process.argv.slice(2);
|
|
10
|
+
if (args.length !== 2 || args[0] !== "--market")
|
|
11
|
+
throw Error("Usage: agentpay install --market MARKET_URL");
|
|
12
|
+
if (!process.stdin.isTTY)
|
|
13
|
+
throw Error(
|
|
14
|
+
"Run Install in an interactive terminal so setup can continue.",
|
|
15
|
+
);
|
|
16
|
+
process.exitCode = await installAndSetup({
|
|
17
|
+
userDir: fileURLToPath(new URL("..", import.meta.url)),
|
|
18
|
+
market: args[1],
|
|
19
|
+
dataDir: await resolveUserDataDir(),
|
|
20
|
+
});
|
|
21
|
+
} catch (error) {
|
|
22
|
+
if (!error.messageDisplayed) console.error(error.message);
|
|
23
|
+
process.exitCode = 1;
|
|
24
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { walletCliPath } from "../src/wallet-package.mjs";
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
5
|
+
// If a copy was not distributed with this file, see https://mozilla.org/MPL/2.0/.
|
|
6
|
+
import { spawn } from "node:child_process";
|
|
7
|
+
import { join, resolve } from "node:path";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
import {
|
|
10
|
+
readServiceSettings,
|
|
11
|
+
runtimeEnvironment,
|
|
12
|
+
listenerPresent,
|
|
13
|
+
} from "../src/local-services.mjs";
|
|
14
|
+
const [role, directory, ...extra] = process.argv.slice(2);
|
|
15
|
+
try {
|
|
16
|
+
if (!["wallet", "runtime"].includes(role) || !directory || extra.length)
|
|
17
|
+
throw Error("Invalid service arguments.");
|
|
18
|
+
const dataDir = resolve(directory),
|
|
19
|
+
settings = await readServiceSettings(dataDir);
|
|
20
|
+
const address =
|
|
21
|
+
role === "wallet"
|
|
22
|
+
? join(dataDir, "wallet", "wallet.sock")
|
|
23
|
+
: { host: "127.0.0.1", port: Number(new URL(settings.runtimeUrl).port) };
|
|
24
|
+
if (await listenerPresent(address))
|
|
25
|
+
throw Error(
|
|
26
|
+
"A process already uses this Wallet socket or Runtime port. Stop it explicitly before starting managed services.",
|
|
27
|
+
);
|
|
28
|
+
const userDir = fileURLToPath(new URL("..", import.meta.url));
|
|
29
|
+
const entry =
|
|
30
|
+
role === "wallet"
|
|
31
|
+
? walletCliPath()
|
|
32
|
+
: join(userDir, "src/index.mjs");
|
|
33
|
+
const env = Object.fromEntries(
|
|
34
|
+
["HOME", "PATH", "LANG", "LC_ALL", "TZ", "TMPDIR"]
|
|
35
|
+
.filter((k) => process.env[k])
|
|
36
|
+
.map((k) => [k, process.env[k]]),
|
|
37
|
+
);
|
|
38
|
+
if (role === "runtime")
|
|
39
|
+
Object.assign(env, runtimeEnvironment(dataDir, settings));
|
|
40
|
+
const child = spawn(
|
|
41
|
+
process.execPath,
|
|
42
|
+
[entry, ...(role === "wallet" ? ["serve", join(dataDir, "wallet")] : [])],
|
|
43
|
+
{ env, stdio: "inherit", shell: false },
|
|
44
|
+
);
|
|
45
|
+
const stop = () => child.kill("SIGTERM");
|
|
46
|
+
process.on("SIGTERM", stop);
|
|
47
|
+
process.on("SIGINT", stop);
|
|
48
|
+
child.once("error", () => {
|
|
49
|
+
console.error("Local service could not start.");
|
|
50
|
+
process.exitCode = 1;
|
|
51
|
+
});
|
|
52
|
+
child.once("exit", (code) => {
|
|
53
|
+
process.off("SIGTERM", stop);
|
|
54
|
+
process.off("SIGINT", stop);
|
|
55
|
+
process.exitCode = code ?? 1;
|
|
56
|
+
});
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error(error.message);
|
|
59
|
+
process.exitCode = 1;
|
|
60
|
+
}
|
package/scripts/lock.mjs
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
3
|
+
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
4
|
+
// If a copy was not distributed with this file, see https://mozilla.org/MPL/2.0/.
|
|
5
|
+
import { controlWallet } from "../src/wallet-control.mjs";
|
|
6
|
+
try {
|
|
7
|
+
process.exitCode = await controlWallet("lock");
|
|
8
|
+
} catch {
|
|
9
|
+
console.error("Could not start Wallet lock. Check your local installation.");
|
|
10
|
+
process.exitCode = 1;
|
|
11
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { walletCliPath } from "../src/wallet-package.mjs";
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
5
|
+
// If a copy was not distributed with this file, see https://mozilla.org/MPL/2.0/.
|
|
6
|
+
import { execFile } from "node:child_process";
|
|
7
|
+
import { promisify } from "node:util";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
import { resolveUserDataDir } from "../src/local-data-directory.mjs";
|
|
11
|
+
import { remindLockedWallet } from "../src/login-reminder.mjs";
|
|
12
|
+
const execute = promisify(execFile);
|
|
13
|
+
try {
|
|
14
|
+
if (process.argv.length > 3) throw Error();
|
|
15
|
+
const dataDir = await resolveUserDataDir({ argument: process.argv[2] });
|
|
16
|
+
const cli = walletCliPath();
|
|
17
|
+
await remindLockedWallet({
|
|
18
|
+
status: async () => {
|
|
19
|
+
const { stdout } = await execute(
|
|
20
|
+
process.execPath,
|
|
21
|
+
[cli, "status", join(dataDir, "wallet")],
|
|
22
|
+
{ timeout: 3000, maxBuffer: 16384 },
|
|
23
|
+
);
|
|
24
|
+
return JSON.parse(stdout);
|
|
25
|
+
},
|
|
26
|
+
notify: () =>
|
|
27
|
+
execute(
|
|
28
|
+
"notify-send",
|
|
29
|
+
[
|
|
30
|
+
"--app-name=AgentPay",
|
|
31
|
+
"AgentPay Wallet is locked",
|
|
32
|
+
"To resume payments, open the User folder in a terminal and run: agentpay wallet unlock",
|
|
33
|
+
],
|
|
34
|
+
{ timeout: 5000, maxBuffer: 4096 },
|
|
35
|
+
),
|
|
36
|
+
});
|
|
37
|
+
} catch {
|
|
38
|
+
/* Notifications are best effort; no secret, prompt or background unlock. */
|
|
39
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
3
|
+
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
4
|
+
// If a copy was not distributed with this file, see https://mozilla.org/MPL/2.0/.
|
|
5
|
+
import { readFile } from "node:fs/promises";
|
|
6
|
+
import { join, resolve } from "node:path";
|
|
7
|
+
import { createInterface } from "node:readline/promises";
|
|
8
|
+
import { callWallet, readCapability } from "@c4roa0/agentpay-wallet";
|
|
9
|
+
import {
|
|
10
|
+
migrationSummary,
|
|
11
|
+
migratedPublicPolicy,
|
|
12
|
+
syncMigratedPublicPolicy,
|
|
13
|
+
} from "../src/policy-migration.mjs";
|
|
14
|
+
import { executeAnvilOwnerCall } from "../src/safe-owner-anvil.mjs";
|
|
15
|
+
|
|
16
|
+
const [command, directory, argument, ...extra] = process.argv.slice(2);
|
|
17
|
+
const withArgument = [
|
|
18
|
+
"preview",
|
|
19
|
+
"prepare",
|
|
20
|
+
"complete",
|
|
21
|
+
"cancel",
|
|
22
|
+
"authorize-test",
|
|
23
|
+
];
|
|
24
|
+
if (
|
|
25
|
+
!directory ||
|
|
26
|
+
extra.length ||
|
|
27
|
+
![...withArgument, "status", "export", "refresh"].includes(command) ||
|
|
28
|
+
(withArgument.includes(command) ? !argument : argument !== undefined)
|
|
29
|
+
) {
|
|
30
|
+
throw new Error(
|
|
31
|
+
"usage: migrate-safe-policy.mjs <preview|prepare|status|export|authorize-test|complete|cancel|refresh> <private-user-data-dir> [target.json|migration-id|test-owner-address]",
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
const walletDir = join(resolve(directory), "wallet");
|
|
35
|
+
const capability = await readCapability(walletDir, "admin");
|
|
36
|
+
const call = (method, params = {}) =>
|
|
37
|
+
callWallet(join(walletDir, "wallet.sock"), capability, method, params);
|
|
38
|
+
const print = (value) =>
|
|
39
|
+
process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
|
|
40
|
+
if (["preview", "prepare"].includes(command)) {
|
|
41
|
+
const target = JSON.parse(await readFile(resolve(argument), "utf8"));
|
|
42
|
+
const status = await call("policyMigrationStatus");
|
|
43
|
+
if (status.state === "pending") {
|
|
44
|
+
if (
|
|
45
|
+
target.expectedPolicyId !== status.plan.source.policyId ||
|
|
46
|
+
target.policyId.toLowerCase() !== status.plan.destination.policyId ||
|
|
47
|
+
target.factory.toLowerCase() !==
|
|
48
|
+
status.plan.destination.factory.toLowerCase() ||
|
|
49
|
+
target.module.toLowerCase() !==
|
|
50
|
+
status.plan.destination.module.toLowerCase()
|
|
51
|
+
)
|
|
52
|
+
throw new Error("MIGRATION_CONFLICT");
|
|
53
|
+
print({ ...status, summary: migrationSummary(status.plan), resumed: true });
|
|
54
|
+
} else {
|
|
55
|
+
const plan = await call("previewPolicyMigration", { target });
|
|
56
|
+
print({ summary: migrationSummary(plan) });
|
|
57
|
+
if (command === "prepare") {
|
|
58
|
+
await confirm(
|
|
59
|
+
`MIGRATE ${plan.migrationId}`,
|
|
60
|
+
"Pause Wallet signing and save this migration",
|
|
61
|
+
);
|
|
62
|
+
print(
|
|
63
|
+
await call("preparePolicyMigration", {
|
|
64
|
+
target,
|
|
65
|
+
migrationId: plan.migrationId,
|
|
66
|
+
}),
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
} else if (command === "refresh") {
|
|
71
|
+
const preview = await call("previewPolicyMigrationRefresh");
|
|
72
|
+
print({
|
|
73
|
+
previousMigrationId: preview.previousMigrationId,
|
|
74
|
+
summary: migrationSummary(preview.plan),
|
|
75
|
+
});
|
|
76
|
+
await confirm(
|
|
77
|
+
`MIGRATE ${preview.plan.migrationId}`,
|
|
78
|
+
"Save the recalculated remaining budget for the same destination",
|
|
79
|
+
);
|
|
80
|
+
print(
|
|
81
|
+
await call("refreshPolicyMigration", {
|
|
82
|
+
previousMigrationId: preview.previousMigrationId,
|
|
83
|
+
migrationId: preview.plan.migrationId,
|
|
84
|
+
}),
|
|
85
|
+
);
|
|
86
|
+
} else if (command === "authorize-test") {
|
|
87
|
+
let status = await call("policyMigrationStatus");
|
|
88
|
+
if (status.state !== "pending") throw new Error("MIGRATION_NOT_PENDING");
|
|
89
|
+
print({ summary: migrationSummary(status.plan), chain: status.chain });
|
|
90
|
+
if (status.chain.expired) throw new Error("MIGRATION_POLICY_EXPIRED");
|
|
91
|
+
const migrationId = status.plan.migrationId;
|
|
92
|
+
await confirm(
|
|
93
|
+
`AUTHORIZE ${migrationId}`,
|
|
94
|
+
"Submit the displayed Safe owner transactions on private Anvil",
|
|
95
|
+
);
|
|
96
|
+
while (status.chain.calls.length) {
|
|
97
|
+
print(
|
|
98
|
+
await executeAnvilOwnerCall(status.plan, argument, status.chain.calls[0]),
|
|
99
|
+
);
|
|
100
|
+
// Never submit the next call until independent Wallet chain inspection succeeds.
|
|
101
|
+
status = await call("policyMigrationStatus");
|
|
102
|
+
if (
|
|
103
|
+
status.state !== "pending" ||
|
|
104
|
+
status.plan.migrationId !== migrationId ||
|
|
105
|
+
status.chain.expired
|
|
106
|
+
)
|
|
107
|
+
throw new Error("MIGRATION_CHANGED");
|
|
108
|
+
}
|
|
109
|
+
print({ ownerTransactionsVerified: true, migrationId, next: "complete" });
|
|
110
|
+
} else if (command === "complete") {
|
|
111
|
+
const status = await call("completePolicyMigration", {
|
|
112
|
+
migrationId: argument,
|
|
113
|
+
});
|
|
114
|
+
const publicPolicyPath = await syncMigratedPublicPolicy(
|
|
115
|
+
resolve(directory),
|
|
116
|
+
status.plan,
|
|
117
|
+
);
|
|
118
|
+
print({
|
|
119
|
+
...status,
|
|
120
|
+
publicPolicyConfig: migratedPublicPolicy(status.plan),
|
|
121
|
+
publicPolicyPath,
|
|
122
|
+
next: "Synchronize runtime deployment metadata, restart callers, check readiness, then unlock Wallet. Admission remains an operator decision.",
|
|
123
|
+
});
|
|
124
|
+
} else if (command === "cancel") {
|
|
125
|
+
await confirm(
|
|
126
|
+
`CANCEL ${argument}`,
|
|
127
|
+
"Cancel only if the old Policy is still active and the replacement does not exist",
|
|
128
|
+
);
|
|
129
|
+
print(await call("cancelPolicyMigration", { migrationId: argument }));
|
|
130
|
+
} else {
|
|
131
|
+
const status = await call("policyMigrationStatus");
|
|
132
|
+
if (command === "export") {
|
|
133
|
+
if (status.state !== "pending" || status.chain.expired)
|
|
134
|
+
throw new Error("MIGRATION_NOT_PENDING_OR_EXPIRED");
|
|
135
|
+
// Export only the next call: confirm it on chain and export again. This prevents
|
|
136
|
+
// an owner UI from treating creation-before-revocation as a supported ordering.
|
|
137
|
+
const { calls, ...chain } = status.chain;
|
|
138
|
+
print({
|
|
139
|
+
summary: migrationSummary(status.plan),
|
|
140
|
+
chain,
|
|
141
|
+
safe: status.plan.source.safe,
|
|
142
|
+
chainId: status.plan.source.chainId,
|
|
143
|
+
nextSafeCall: calls[0] ?? null,
|
|
144
|
+
});
|
|
145
|
+
} else print(status);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async function confirm(expected, action) {
|
|
149
|
+
// Public confirmation prompts may be captured by run_debug's tee; input must
|
|
150
|
+
// still come from the interactive terminal, never a pipe/environment variable.
|
|
151
|
+
if (!process.stdin.isTTY) throw new Error("OWNER_AUTHORIZATION_TTY_REQUIRED");
|
|
152
|
+
const prompt = createInterface({
|
|
153
|
+
input: process.stdin,
|
|
154
|
+
output: process.stderr,
|
|
155
|
+
});
|
|
156
|
+
try {
|
|
157
|
+
if (
|
|
158
|
+
(await prompt.question(`${action}. Type '${expected}': `)).trim() !==
|
|
159
|
+
expected
|
|
160
|
+
)
|
|
161
|
+
throw new Error("OWNER_AUTHORIZATION_NOT_CONFIRMED");
|
|
162
|
+
} finally {
|
|
163
|
+
prompt.close();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
3
|
+
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
4
|
+
// If a copy was not distributed with this file, see https://mozilla.org/MPL/2.0/.
|
|
5
|
+
import { runOfficialPaidTest } from "../src/official-paid-test.mjs";
|
|
6
|
+
if (process.argv.length !== 2) {
|
|
7
|
+
console.error("Use agentpay payment test.");
|
|
8
|
+
process.exitCode = 2;
|
|
9
|
+
} else process.exitCode = await runOfficialPaidTest();
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
3
|
+
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
4
|
+
// If a copy was not distributed with this file, see https://mozilla.org/MPL/2.0/.
|
|
5
|
+
// Poll only through the authenticated, bounded Wallet IPC notice operation.
|
|
6
|
+
import { lstat, readFile } from "node:fs/promises";
|
|
7
|
+
import { join, resolve } from "node:path";
|
|
8
|
+
import { assertUnixMilliseconds } from "@c4roa0/agentpay-protocol";
|
|
9
|
+
import { callWallet } from "@c4roa0/agentpay-wallet";
|
|
10
|
+
|
|
11
|
+
const [dataArg, settlementArg] = process.argv.slice(2);
|
|
12
|
+
if (!dataArg || !settlementArg || process.argv.length !== 4)
|
|
13
|
+
throw new Error(
|
|
14
|
+
"usage: poll-unconfirmed-notice.mjs <user-dir> <settlement-url>",
|
|
15
|
+
);
|
|
16
|
+
const url = new URL(settlementArg);
|
|
17
|
+
if (
|
|
18
|
+
url.protocol !== "http:" ||
|
|
19
|
+
!["127.0.0.1", "localhost", "[::1]"].includes(url.hostname)
|
|
20
|
+
)
|
|
21
|
+
throw new Error("loopback required");
|
|
22
|
+
const dataDir = resolve(dataArg);
|
|
23
|
+
const checkpoint = JSON.parse(
|
|
24
|
+
await readFile(join(dataDir, "runtime/unconfirmed-smoke.json"), "utf8"),
|
|
25
|
+
);
|
|
26
|
+
if (!/^0x[0-9a-f]{64}$/.test(checkpoint.orderId || ""))
|
|
27
|
+
throw new Error("Order checkpoint missing");
|
|
28
|
+
const tokenPath = join(dataDir, "wallet/agent.token");
|
|
29
|
+
const info = await lstat(tokenPath);
|
|
30
|
+
if (
|
|
31
|
+
!info.isFile() ||
|
|
32
|
+
info.isSymbolicLink() ||
|
|
33
|
+
info.uid !== process.getuid() ||
|
|
34
|
+
info.mode & 0o077
|
|
35
|
+
)
|
|
36
|
+
throw new Error("unsafe Wallet capability");
|
|
37
|
+
const token = (await readFile(tokenPath, "utf8")).trim();
|
|
38
|
+
if (!/^[0-9a-f]{64}$/.test(token)) throw new Error("invalid Wallet capability");
|
|
39
|
+
const answer = await callWallet(
|
|
40
|
+
join(dataDir, "wallet/wallet.sock"),
|
|
41
|
+
token,
|
|
42
|
+
"pollSettlementNotices",
|
|
43
|
+
{ settlementUrl: url.toString(), limit: 50 },
|
|
44
|
+
);
|
|
45
|
+
const notices = answer?.notices || [];
|
|
46
|
+
const matches = notices.filter(
|
|
47
|
+
(notice) =>
|
|
48
|
+
notice.orderId === checkpoint.orderId &&
|
|
49
|
+
notice.type === "delivery_confirmation_required",
|
|
50
|
+
);
|
|
51
|
+
if (
|
|
52
|
+
matches.length !== 1 ||
|
|
53
|
+
matches[0].state !== "delivered" ||
|
|
54
|
+
matches[0].payload?.orderId !== checkpoint.orderId ||
|
|
55
|
+
!Number.isSafeInteger(matches[0].payload?.releaseScheduledAtMs)
|
|
56
|
+
) {
|
|
57
|
+
throw new Error("one bound Wallet reminder was not returned");
|
|
58
|
+
}
|
|
59
|
+
process.stdout.write(
|
|
60
|
+
`${JSON.stringify(
|
|
61
|
+
{
|
|
62
|
+
ok: true,
|
|
63
|
+
orderId: checkpoint.orderId,
|
|
64
|
+
walletAuthenticated: true,
|
|
65
|
+
uniqueOrderNotice: true,
|
|
66
|
+
noticeState: matches[0].state,
|
|
67
|
+
availableActions: matches[0].payload.actions,
|
|
68
|
+
releaseScheduledAtMs: assertUnixMilliseconds(
|
|
69
|
+
matches[0].payload.releaseScheduledAtMs,
|
|
70
|
+
),
|
|
71
|
+
},
|
|
72
|
+
null,
|
|
73
|
+
2,
|
|
74
|
+
)}\n`,
|
|
75
|
+
);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
3
|
+
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
4
|
+
// If a copy was not distributed with this file, see https://mozilla.org/MPL/2.0/.
|
|
5
|
+
import { createInterface } from "node:readline/promises";
|
|
6
|
+
import { isAbsolute } from "node:path";
|
|
7
|
+
import { prepareOnboarding } from "../src/prepare-onboarding.mjs";
|
|
8
|
+
let terminal;
|
|
9
|
+
try {
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
if (args.length !== 2 || !args.every(isAbsolute))
|
|
12
|
+
throw Error(
|
|
13
|
+
"Usage: node scripts/prepare-onboarding.mjs ABSOLUTE_PUBLIC_DEPLOYMENT_JSON ABSOLUTE_LOCAL_CONFIG_JSON",
|
|
14
|
+
);
|
|
15
|
+
if (!process.stdin.isTTY)
|
|
16
|
+
throw Error("Run this command in an interactive terminal.");
|
|
17
|
+
terminal = createInterface({ input: process.stdin, output: process.stdout });
|
|
18
|
+
await prepareOnboarding({
|
|
19
|
+
inputPath: args[0],
|
|
20
|
+
outputPath: args[1],
|
|
21
|
+
ask: (prompt) => terminal.question(`${prompt}\n> `),
|
|
22
|
+
write: (line) => console.log(line),
|
|
23
|
+
});
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.error(
|
|
26
|
+
error.code === "EEXIST"
|
|
27
|
+
? "The local configuration already exists. Reuse it with user-setup.mjs; use a different filename for a deliberate new configuration."
|
|
28
|
+
: error.message,
|
|
29
|
+
);
|
|
30
|
+
process.exitCode = 1;
|
|
31
|
+
} finally {
|
|
32
|
+
terminal?.close();
|
|
33
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
3
|
+
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
4
|
+
// If a copy was not distributed with this file, see https://mozilla.org/MPL/2.0/.
|
|
5
|
+
import { readFile } from "node:fs/promises";
|
|
6
|
+
import { createPolicyPreviewServer } from "../src/policy-preview-server.mjs";
|
|
7
|
+
try {
|
|
8
|
+
const demo = process.argv[2] === "--demo";
|
|
9
|
+
const [path, delegateArg, portArg = "6580"] = process.argv.slice(2);
|
|
10
|
+
const delegate = demo ? `0x${"5".repeat(40)}` : delegateArg;
|
|
11
|
+
const host = demo ? process.argv[4] || "127.0.0.1" : "127.0.0.1";
|
|
12
|
+
if (!["127.0.0.1", "0.0.0.0"].includes(host))
|
|
13
|
+
throw new Error("Preview host must be 127.0.0.1 or 0.0.0.0");
|
|
14
|
+
const port = Number(demo ? process.argv[3] || "6580" : portArg);
|
|
15
|
+
if (
|
|
16
|
+
(demo
|
|
17
|
+
? process.argv.length > 5
|
|
18
|
+
: !path || !delegate || process.argv.length > 5) ||
|
|
19
|
+
!Number.isInteger(port) ||
|
|
20
|
+
port < 1024 ||
|
|
21
|
+
port > 65535
|
|
22
|
+
)
|
|
23
|
+
throw new Error(
|
|
24
|
+
"Usage: preview-policy.mjs PUBLIC_DEPLOYMENT_JSON WALLET_DELEGATE [PORT] | --demo [PORT] [HOST]",
|
|
25
|
+
);
|
|
26
|
+
const deployment = demo
|
|
27
|
+
? {
|
|
28
|
+
chainId: 31337,
|
|
29
|
+
rpcUrl: "http://127.0.0.1:8545",
|
|
30
|
+
module: `0x${"1".repeat(40)}`,
|
|
31
|
+
token: `0x${"2".repeat(40)}`,
|
|
32
|
+
factory: `0x${"3".repeat(40)}`,
|
|
33
|
+
registry: `0x${"4".repeat(40)}`,
|
|
34
|
+
tokenDecimals: 6,
|
|
35
|
+
source: "界面演示:全部地址是虚构示例,不读取真实 Wallet 或链",
|
|
36
|
+
}
|
|
37
|
+
: JSON.parse(await readFile(path, "utf8"));
|
|
38
|
+
const server = createPolicyPreviewServer({
|
|
39
|
+
deployment,
|
|
40
|
+
delegate,
|
|
41
|
+
demoNetworkPreview: demo && host === "0.0.0.0",
|
|
42
|
+
...(demo
|
|
43
|
+
? {
|
|
44
|
+
inspect: async () => ({
|
|
45
|
+
demo: true,
|
|
46
|
+
message: "仅展示页面流程;未执行链上核对,不可签名",
|
|
47
|
+
}),
|
|
48
|
+
}
|
|
49
|
+
: {}),
|
|
50
|
+
});
|
|
51
|
+
server.on("error", () => {
|
|
52
|
+
console.error("本地预览无法启动,请检查端口和配置。");
|
|
53
|
+
process.exitCode = 1;
|
|
54
|
+
});
|
|
55
|
+
server.listen(port, host, () =>
|
|
56
|
+
console.log(
|
|
57
|
+
`授权预览:http://${host === "0.0.0.0" ? "服务器IP" : host}:${port}/ (监听 ${host},仅预览,不签名、不写链)`,
|
|
58
|
+
),
|
|
59
|
+
);
|
|
60
|
+
process.on("SIGINT", () => server.close());
|
|
61
|
+
process.on("SIGTERM", () => server.close());
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error(error.message);
|
|
64
|
+
process.exitCode = 1;
|
|
65
|
+
}
|