run402 4.17.0 → 4.17.2
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/fixtures/buzz-v0.5.2-cli-capabilities.json +93 -0
- package/fixtures/run402-buzz-doctor-v1-contract.json +140 -0
- package/lib/buzz-doctor-contract.mjs +1 -1
- package/lib/buzz-doctor-contract.test.mjs +8 -1
- package/lib/buzz-doctor.mjs +41 -10
- package/lib/buzz-doctor.test.mjs +40 -0
- package/package.json +3 -1
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixture_version": 1,
|
|
3
|
+
"fixture_id": "buzz-cli-v0.5.2-capabilities",
|
|
4
|
+
"purpose": "released_buzz_cli_capability_first_compatibility",
|
|
5
|
+
"buzz_release": {
|
|
6
|
+
"version": "0.5.2",
|
|
7
|
+
"release_tag": "v0.5.2",
|
|
8
|
+
"release_tag_commit": "3e48f1b2365d326ee1c9582448d86a99b44ecd5d",
|
|
9
|
+
"run402_change_required": false
|
|
10
|
+
},
|
|
11
|
+
"help_probes": [
|
|
12
|
+
{
|
|
13
|
+
"argv": ["buzz", "--help"],
|
|
14
|
+
"exit_code": 0,
|
|
15
|
+
"stdout_contains": [
|
|
16
|
+
"Buzz CLI — interact with a Buzz relay",
|
|
17
|
+
"users",
|
|
18
|
+
"social",
|
|
19
|
+
"Errors are JSON on stderr"
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"argv": ["buzz", "users", "get", "--help"],
|
|
24
|
+
"exit_code": 0,
|
|
25
|
+
"stdout_contains": [
|
|
26
|
+
"Usage: buzz users get",
|
|
27
|
+
"--pubkey",
|
|
28
|
+
"Omit for your own profile"
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"argv": ["buzz", "social", "publish", "--help"],
|
|
33
|
+
"exit_code": 0,
|
|
34
|
+
"stdout_contains": [
|
|
35
|
+
"Usage: buzz social publish",
|
|
36
|
+
"--content"
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"argv": ["buzz", "social", "event", "--help"],
|
|
41
|
+
"exit_code": 0,
|
|
42
|
+
"stdout_contains": [
|
|
43
|
+
"Usage: buzz social event",
|
|
44
|
+
"--event"
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"version_probe": {
|
|
49
|
+
"argv": ["buzz", "--version"],
|
|
50
|
+
"supported": false,
|
|
51
|
+
"exit_code": 1,
|
|
52
|
+
"stderr_json": {
|
|
53
|
+
"error": "user_error",
|
|
54
|
+
"retryable": false
|
|
55
|
+
},
|
|
56
|
+
"message_contains": "unexpected argument '--version'"
|
|
57
|
+
},
|
|
58
|
+
"json_contract": {
|
|
59
|
+
"default_output_format": "json",
|
|
60
|
+
"users_get_success_stdout": {
|
|
61
|
+
"type": "array",
|
|
62
|
+
"empty_array_means": "public_self_profile_unverified",
|
|
63
|
+
"profile_pubkey_field": "pubkey"
|
|
64
|
+
},
|
|
65
|
+
"social_event_success_stdout": {
|
|
66
|
+
"type": "array",
|
|
67
|
+
"event_pubkey_field": "pubkey"
|
|
68
|
+
},
|
|
69
|
+
"error_stderr": {
|
|
70
|
+
"type": "object",
|
|
71
|
+
"required_fields": ["error", "message", "retryable"],
|
|
72
|
+
"stdout_is_empty": true
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"managed_sidecar": {
|
|
76
|
+
"distribution": "bundled_with_buzz_desktop",
|
|
77
|
+
"session_discovery": "managed_agent_path",
|
|
78
|
+
"public_package_manager_install": false,
|
|
79
|
+
"repair_surface": "buzz_settings",
|
|
80
|
+
"repair_destination": "Buzz Desktop > Settings > Updates",
|
|
81
|
+
"repair_instruction": "Open Buzz Desktop > Settings > Updates, install the available Buzz update or reinstall Buzz Desktop if no update is offered, then restart this agent and rerun setup."
|
|
82
|
+
},
|
|
83
|
+
"public_self_observation": {
|
|
84
|
+
"argv": ["buzz", "users", "get"],
|
|
85
|
+
"requires_private_key_value_inspection": false,
|
|
86
|
+
"empty_or_malformed_result": "BUZZ_AGENT_TARGET_UNVERIFIED"
|
|
87
|
+
},
|
|
88
|
+
"write_surface_policy": {
|
|
89
|
+
"capability_probes_use_help_only": true,
|
|
90
|
+
"publish_is_never_invoked_by_doctor": true,
|
|
91
|
+
"event_read_requires_explicit_event_id_and_is_not_used_for_self_discovery": true
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"contract_id": "run402.buzz-doctor.v1",
|
|
4
|
+
"mode": "buzz",
|
|
5
|
+
"canonical_invocation": [
|
|
6
|
+
"run402",
|
|
7
|
+
"--wallet",
|
|
8
|
+
"<profile>",
|
|
9
|
+
"doctor",
|
|
10
|
+
"--buzz",
|
|
11
|
+
"--buzz-agent",
|
|
12
|
+
"<npub-or-hex>"
|
|
13
|
+
],
|
|
14
|
+
"flags": {
|
|
15
|
+
"mode": "--buzz",
|
|
16
|
+
"agent": "--buzz-agent",
|
|
17
|
+
"profile": "--wallet"
|
|
18
|
+
},
|
|
19
|
+
"check_order": [
|
|
20
|
+
"session_shell",
|
|
21
|
+
"node_runtime",
|
|
22
|
+
"run402_cli",
|
|
23
|
+
"buzz_cli",
|
|
24
|
+
"buzz_agent_target",
|
|
25
|
+
"run402_api",
|
|
26
|
+
"run402_console",
|
|
27
|
+
"buzz_relay",
|
|
28
|
+
"wallet_profile"
|
|
29
|
+
],
|
|
30
|
+
"statuses": [
|
|
31
|
+
"ok",
|
|
32
|
+
"warning",
|
|
33
|
+
"blocked"
|
|
34
|
+
],
|
|
35
|
+
"codes_by_check": {
|
|
36
|
+
"session_shell": [
|
|
37
|
+
"BUZZ_PREFLIGHT_SHELL_UNAVAILABLE"
|
|
38
|
+
],
|
|
39
|
+
"node_runtime": [
|
|
40
|
+
"BUZZ_PREFLIGHT_NODE_UNAVAILABLE",
|
|
41
|
+
"BUZZ_PREFLIGHT_NODE_INCOMPATIBLE"
|
|
42
|
+
],
|
|
43
|
+
"run402_cli": [
|
|
44
|
+
"BUZZ_PREFLIGHT_RUN402_UNAVAILABLE",
|
|
45
|
+
"BUZZ_PREFLIGHT_RUN402_INCOMPATIBLE",
|
|
46
|
+
"BUZZ_PREFLIGHT_RUN402_UPDATE_AVAILABLE"
|
|
47
|
+
],
|
|
48
|
+
"buzz_cli": [
|
|
49
|
+
"BUZZ_PREFLIGHT_BUZZ_CLI_UNAVAILABLE",
|
|
50
|
+
"BUZZ_PREFLIGHT_BUZZ_CLI_INCOMPATIBLE"
|
|
51
|
+
],
|
|
52
|
+
"buzz_agent_target": [
|
|
53
|
+
"BUZZ_AGENT_TARGET_REQUIRED",
|
|
54
|
+
"BUZZ_AGENT_TARGET_UNVERIFIED",
|
|
55
|
+
"BUZZ_AGENT_TARGET_MISMATCH"
|
|
56
|
+
],
|
|
57
|
+
"run402_api": [
|
|
58
|
+
"BUZZ_PREFLIGHT_API_UNREACHABLE"
|
|
59
|
+
],
|
|
60
|
+
"run402_console": [
|
|
61
|
+
"BUZZ_PREFLIGHT_CONSOLE_UNREACHABLE"
|
|
62
|
+
],
|
|
63
|
+
"buzz_relay": [
|
|
64
|
+
"BUZZ_PREFLIGHT_RELAY_UNSAFE",
|
|
65
|
+
"BUZZ_PREFLIGHT_RELAY_UNREACHABLE"
|
|
66
|
+
],
|
|
67
|
+
"wallet_profile": [
|
|
68
|
+
"BUZZ_PREFLIGHT_WALLET_PROFILE_REQUIRED",
|
|
69
|
+
"BUZZ_PREFLIGHT_WALLET_PROFILE_NOT_FOUND",
|
|
70
|
+
"BUZZ_PREFLIGHT_WALLET_PROFILE_MISMATCH"
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
"next_action": {
|
|
74
|
+
"required_fields": [
|
|
75
|
+
"type",
|
|
76
|
+
"surface",
|
|
77
|
+
"command",
|
|
78
|
+
"why",
|
|
79
|
+
"safe_to_auto_execute",
|
|
80
|
+
"requires_approval",
|
|
81
|
+
"destructive",
|
|
82
|
+
"idempotent",
|
|
83
|
+
"spend_impact"
|
|
84
|
+
],
|
|
85
|
+
"surfaces": [
|
|
86
|
+
"shell",
|
|
87
|
+
"buzz_chat",
|
|
88
|
+
"buzz_settings"
|
|
89
|
+
],
|
|
90
|
+
"shell_required_fields": [
|
|
91
|
+
"argv"
|
|
92
|
+
],
|
|
93
|
+
"non_shell_forbidden_fields": [
|
|
94
|
+
"argv",
|
|
95
|
+
"cwd"
|
|
96
|
+
],
|
|
97
|
+
"cardinality_per_actionable_check": 1
|
|
98
|
+
},
|
|
99
|
+
"exit_behavior": {
|
|
100
|
+
"passed_or_warning_only": 0,
|
|
101
|
+
"completed_with_blocked_checks": 1,
|
|
102
|
+
"usage_error": 1,
|
|
103
|
+
"completed_report_stream": "stdout",
|
|
104
|
+
"usage_error_stream": "stderr"
|
|
105
|
+
},
|
|
106
|
+
"freshness": {
|
|
107
|
+
"max_age_seconds": 60,
|
|
108
|
+
"binding_fields": [
|
|
109
|
+
"contract_id",
|
|
110
|
+
"expected_subject_hex",
|
|
111
|
+
"wallet_profile",
|
|
112
|
+
"node_executable",
|
|
113
|
+
"run402_executable",
|
|
114
|
+
"relay_origin"
|
|
115
|
+
]
|
|
116
|
+
},
|
|
117
|
+
"setup_rejection_codes": [
|
|
118
|
+
"BUZZ_PREFLIGHT_REPORT_INVALID",
|
|
119
|
+
"BUZZ_PREFLIGHT_REPORT_STALE",
|
|
120
|
+
"BUZZ_PREFLIGHT_REPORT_MISMATCH"
|
|
121
|
+
],
|
|
122
|
+
"zero_mutation": {
|
|
123
|
+
"mutation_state": "not_started",
|
|
124
|
+
"forbidden": [
|
|
125
|
+
"buzz_event_publish",
|
|
126
|
+
"buzz_arbitrary_sign",
|
|
127
|
+
"run402_profile_create_or_select",
|
|
128
|
+
"run402_wallet_create",
|
|
129
|
+
"run402_identity_link_mutation",
|
|
130
|
+
"run402_faucet",
|
|
131
|
+
"run402_tier_mutation",
|
|
132
|
+
"run402_project_mutation",
|
|
133
|
+
"run402_deploy"
|
|
134
|
+
],
|
|
135
|
+
"allowed_lossy_local_writes": [
|
|
136
|
+
"cli_update_cache",
|
|
137
|
+
"redacted_diagnostic_queue"
|
|
138
|
+
]
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
|
|
3
|
-
const CONTRACT_URL = new URL("
|
|
3
|
+
const CONTRACT_URL = new URL("../fixtures/run402-buzz-doctor-v1-contract.json", import.meta.url);
|
|
4
4
|
|
|
5
5
|
export const BUZZ_DOCTOR_CONTRACT = deepFreeze(JSON.parse(readFileSync(CONTRACT_URL, "utf8")));
|
|
6
6
|
export const BUZZ_DOCTOR_CONTRACT_ID = BUZZ_DOCTOR_CONTRACT.contract_id;
|
|
@@ -9,7 +9,9 @@ import {
|
|
|
9
9
|
validateBuzzDoctorReport,
|
|
10
10
|
} from "./buzz-doctor-contract.mjs";
|
|
11
11
|
|
|
12
|
-
const FIXTURE = JSON.parse(readFileSync(new URL("
|
|
12
|
+
const FIXTURE = JSON.parse(readFileSync(new URL("../fixtures/buzz-v0.5.2-cli-capabilities.json", import.meta.url), "utf8"));
|
|
13
|
+
const RELEASED_FIXTURE = JSON.parse(readFileSync(new URL("../../buzz/fixtures/buzz-v0.5.2-cli-capabilities.json", import.meta.url), "utf8"));
|
|
14
|
+
const RELEASED_CONTRACT = JSON.parse(readFileSync(new URL("../../buzz/fixtures/run402-buzz-doctor-v1-contract.json", import.meta.url), "utf8"));
|
|
13
15
|
|
|
14
16
|
function shellAction() {
|
|
15
17
|
return {
|
|
@@ -47,6 +49,11 @@ function passingReport(now) {
|
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
describe("Buzz doctor v1 frozen contract", () => {
|
|
52
|
+
it("packages byte-semantic copies of the released Buzz fixture and frozen doctor contract", () => {
|
|
53
|
+
assert.deepEqual(FIXTURE, RELEASED_FIXTURE);
|
|
54
|
+
assert.deepEqual(BUZZ_DOCTOR_CONTRACT, RELEASED_CONTRACT);
|
|
55
|
+
});
|
|
56
|
+
|
|
50
57
|
it("freezes the ordered checks, flags, statuses, exit streams, freshness binding, and zero-mutation verdict", () => {
|
|
51
58
|
assert.equal(BUZZ_DOCTOR_CONTRACT_ID, "run402.buzz-doctor.v1");
|
|
52
59
|
assert.deepEqual(BUZZ_DOCTOR_CHECK_ORDER, [
|
package/lib/buzz-doctor.mjs
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from "./buzz-doctor-contract.mjs";
|
|
16
16
|
|
|
17
17
|
const BUZZ_CAPABILITIES = JSON.parse(readFileSync(
|
|
18
|
-
new URL("
|
|
18
|
+
new URL("../fixtures/buzz-v0.5.2-cli-capabilities.json", import.meta.url),
|
|
19
19
|
"utf8",
|
|
20
20
|
));
|
|
21
21
|
|
|
@@ -42,7 +42,10 @@ export const BUZZ_DOCTOR_REPAIR_MATRIX = Object.freeze({
|
|
|
42
42
|
BUZZ_PREFLIGHT_API_UNREACHABLE: { type: "restore_run402_api_access", surface: "buzz_settings" },
|
|
43
43
|
BUZZ_PREFLIGHT_CONSOLE_UNREACHABLE: { type: "restore_run402_console_access", surface: "buzz_settings" },
|
|
44
44
|
BUZZ_PREFLIGHT_RELAY_UNSAFE: { type: "repair_buzz_relay_url", surface: "buzz_settings" },
|
|
45
|
-
BUZZ_PREFLIGHT_RELAY_UNREACHABLE: {
|
|
45
|
+
BUZZ_PREFLIGHT_RELAY_UNREACHABLE: {
|
|
46
|
+
type: ["repair_buzz_relay_tls", "repair_buzz_relay_dns", "repair_buzz_relay_service", "restore_buzz_relay_access"],
|
|
47
|
+
surface: "buzz_settings",
|
|
48
|
+
},
|
|
46
49
|
BUZZ_PREFLIGHT_WALLET_PROFILE_REQUIRED: { type: "rerun_buzz_setup_with_explicit_identity", surface: "buzz_chat" },
|
|
47
50
|
BUZZ_PREFLIGHT_WALLET_PROFILE_NOT_FOUND: { type: "create_buzz_wallet_profile", surface: "shell" },
|
|
48
51
|
BUZZ_PREFLIGHT_WALLET_PROFILE_MISMATCH: { type: "rerun_buzz_doctor", surface: "shell" },
|
|
@@ -343,9 +346,11 @@ async function checkBuzzRelay({ relay, lookup, pinnedRelayRead }) {
|
|
|
343
346
|
failure: error.message,
|
|
344
347
|
});
|
|
345
348
|
}
|
|
346
|
-
|
|
349
|
+
const failure = safeFailure(error);
|
|
350
|
+
return warning("buzz_relay", "BUZZ_PREFLIGHT_RELAY_UNREACHABLE", "The configured Buzz relay is safe to probe but unavailable; founder-agent setup may continue without community installation or enrollment.", relayAvailabilityRepair(relay.origin, failure), {
|
|
347
351
|
origin: relay.origin,
|
|
348
|
-
failure
|
|
352
|
+
failure,
|
|
353
|
+
community_operations: "unavailable",
|
|
349
354
|
});
|
|
350
355
|
}
|
|
351
356
|
}
|
|
@@ -686,12 +691,36 @@ function relayUnsafeRepair() {
|
|
|
686
691
|
});
|
|
687
692
|
}
|
|
688
693
|
|
|
689
|
-
function
|
|
694
|
+
function relayAvailabilityRepair(origin, failure) {
|
|
695
|
+
if (failure === "tls_handshake_failed") {
|
|
696
|
+
return nonShellAction({
|
|
697
|
+
type: "repair_buzz_relay_tls",
|
|
698
|
+
surface: "buzz_settings",
|
|
699
|
+
command: `Ask the Buzz community operator to provision a valid TLS certificate and public hostname route for ${origin}; after the endpoint completes verified TLS, restart this agent and rerun Run402 setup.`,
|
|
700
|
+
why: "Reconnect cannot repair a relay hostname whose public TLS handshake fails; community installation and enrollment stay unavailable until the endpoint is fixed.",
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
if (failure === "dns") {
|
|
704
|
+
return nonShellAction({
|
|
705
|
+
type: "repair_buzz_relay_dns",
|
|
706
|
+
surface: "buzz_settings",
|
|
707
|
+
command: `Ask the Buzz community operator to publish working public DNS for ${origin}; after the hostname resolves publicly, restart this agent and rerun Run402 setup.`,
|
|
708
|
+
why: "Community installation and enrollment require a publicly resolvable relay, while founder-agent setup remains independent.",
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
if (failure.startsWith("http_") || failure === "nip11_invalid" || failure === "redirect_rejected" || failure === "response_too_large") {
|
|
712
|
+
return nonShellAction({
|
|
713
|
+
type: "repair_buzz_relay_service",
|
|
714
|
+
surface: "buzz_settings",
|
|
715
|
+
command: `Ask the Buzz community operator to restore the public NIP-11 endpoint at ${origin}; after it returns a bounded non-redirecting JSON response, restart this agent and rerun Run402 setup.`,
|
|
716
|
+
why: "Community installation and enrollment require the relay's public NIP-11 service, while founder-agent setup remains independent.",
|
|
717
|
+
});
|
|
718
|
+
}
|
|
690
719
|
return nonShellAction({
|
|
691
720
|
type: "restore_buzz_relay_access",
|
|
692
721
|
surface: "buzz_settings",
|
|
693
|
-
command: `
|
|
694
|
-
why: "
|
|
722
|
+
command: `Ask the Buzz community operator to restore public relay access at ${origin}; after the endpoint is reachable, restart this agent and rerun Run402 setup.`,
|
|
723
|
+
why: "Community installation and enrollment require a live public relay, while founder-agent setup remains independent.",
|
|
695
724
|
});
|
|
696
725
|
}
|
|
697
726
|
|
|
@@ -777,11 +806,13 @@ function safeOrigin(value) {
|
|
|
777
806
|
|
|
778
807
|
function safeFailure(error) {
|
|
779
808
|
if (error?.name === "AbortError") return "timeout";
|
|
780
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
781
|
-
if (/certificate|tls|ssl/i.test(message)) return "
|
|
782
|
-
if (/dns|getaddrinfo|enotfound/i.test(message)) return "dns";
|
|
809
|
+
const message = error instanceof Error ? `${error.message} ${error.code ?? ""} ${error.cause?.message ?? ""} ${error.cause?.code ?? ""}` : String(error);
|
|
810
|
+
if (/certificate|tls|ssl|eproto|secure tls connection|handshake/i.test(message)) return "tls_handshake_failed";
|
|
811
|
+
if (/dns|dns_empty|getaddrinfo|enotfound|eai_again/i.test(message)) return "dns";
|
|
783
812
|
if (/timeout|timed out|abort/i.test(message)) return "timeout";
|
|
784
813
|
if (/redirect/i.test(message)) return "redirect_rejected";
|
|
814
|
+
if (/response_too_large/i.test(message)) return "response_too_large";
|
|
815
|
+
if (/nip11_invalid/i.test(message)) return "nip11_invalid";
|
|
785
816
|
if (/http_\d+/.test(message)) return message.match(/http_\d+/)[0];
|
|
786
817
|
return "network";
|
|
787
818
|
}
|
package/lib/buzz-doctor.test.mjs
CHANGED
|
@@ -194,6 +194,46 @@ describe("Buzz doctor bounded zero-mutation runner", () => {
|
|
|
194
194
|
assert.equal(report.ok, true);
|
|
195
195
|
});
|
|
196
196
|
|
|
197
|
+
it("keeps founder setup usable when a public relay hostname fails TLS and returns an operator repair", async () => {
|
|
198
|
+
const tlsError = Object.assign(new Error("write EPROTO ssl3 alert handshake failure"), { code: "EPROTO" });
|
|
199
|
+
const dependencies = healthyDependencies({
|
|
200
|
+
env: {
|
|
201
|
+
...healthyDependencies().env,
|
|
202
|
+
BUZZ_RELAY_URL: "wss://kychee.com.communities.buzz.xyz",
|
|
203
|
+
},
|
|
204
|
+
pinnedRelayRead: async () => { throw tlsError; },
|
|
205
|
+
});
|
|
206
|
+
const report = await buildBuzzDoctorReport(dependencies);
|
|
207
|
+
const relay = report.checks.find((check) => check.name === "buzz_relay");
|
|
208
|
+
assert.equal(report.ok, true);
|
|
209
|
+
assert.equal(relay.status, "warning");
|
|
210
|
+
assert.equal(relay.code, "BUZZ_PREFLIGHT_RELAY_UNREACHABLE");
|
|
211
|
+
assert.equal(relay.value.failure, "tls_handshake_failed");
|
|
212
|
+
assert.equal(relay.value.community_operations, "unavailable");
|
|
213
|
+
assert.equal(relay.next_actions[0].type, "repair_buzz_relay_tls");
|
|
214
|
+
assert.match(relay.next_actions[0].command, /kychee\.com\.communities\.buzz\.xyz/);
|
|
215
|
+
assert.doesNotMatch(relay.next_actions[0].command, /reconnect/i);
|
|
216
|
+
assert.equal(relay.next_actions[0].surface, "buzz_settings");
|
|
217
|
+
assert.equal("argv" in relay.next_actions[0], false);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it("continues to block an unsafe relay destination before making the pinned read", async () => {
|
|
221
|
+
let reads = 0;
|
|
222
|
+
const dependencies = healthyDependencies({
|
|
223
|
+
lookup: async () => [
|
|
224
|
+
{ address: "93.184.216.34", family: 4 },
|
|
225
|
+
{ address: "127.0.0.1", family: 4 },
|
|
226
|
+
],
|
|
227
|
+
pinnedRelayRead: async () => { reads += 1; return { ok: true }; },
|
|
228
|
+
});
|
|
229
|
+
const report = await buildBuzzDoctorReport(dependencies);
|
|
230
|
+
const relay = report.checks.find((check) => check.name === "buzz_relay");
|
|
231
|
+
assert.equal(report.ok, false);
|
|
232
|
+
assert.equal(relay.status, "blocked");
|
|
233
|
+
assert.equal(relay.code, "BUZZ_PREFLIGHT_RELAY_UNSAFE");
|
|
234
|
+
assert.equal(reads, 0);
|
|
235
|
+
});
|
|
236
|
+
|
|
197
237
|
it("rejects private, loopback, link-local, mapped, and documentation addresses", () => {
|
|
198
238
|
for (const address of ["127.0.0.1", "10.0.0.1", "169.254.169.254", "192.0.2.1", "::1", "fc00::1", "fe80::1", "::ffff:127.0.0.1", "2001:db8::1"]) {
|
|
199
239
|
assert.equal(isPublicAddress(address), false, address);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "run402",
|
|
3
|
-
"version": "4.17.
|
|
3
|
+
"version": "4.17.2",
|
|
4
4
|
"description": "CLI for Run402 — provision Postgres databases, deploy static sites, generate images, and manage wallets via x402 and MPP micropayments.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"files": [
|
|
16
16
|
"cli.mjs",
|
|
17
17
|
"lib/",
|
|
18
|
+
"fixtures/",
|
|
18
19
|
"core-dist/",
|
|
19
20
|
"sdk/"
|
|
20
21
|
],
|
|
@@ -26,6 +27,7 @@
|
|
|
26
27
|
"@x402/evm": "^2.19.0",
|
|
27
28
|
"@x402/extensions": "^2.19.0",
|
|
28
29
|
"@x402/fetch": "^2.19.0",
|
|
30
|
+
"ipaddr.js": "1.9.1",
|
|
29
31
|
"json-canonicalize": "2.0.0",
|
|
30
32
|
"mppx": "^0.4.7",
|
|
31
33
|
"tsx": "^4.21.0",
|