#!/usr/bin/env node const assert = require("assert"); const fs = require("fs"); const path = require("path"); const repo = path.resolve(__dirname, ".."); function read(relativePath) { return fs.readFileSync(path.join(repo, relativePath), "utf8"); } function maybeRead(segments) { const fullPath = path.join(repo, ...segments); if (!fs.existsSync(fullPath)) return null; return fs.readFileSync(fullPath, "utf8"); } function expect(source, name, pattern) { assert.match(source, pattern, `missing resource metering evidence: ${name}`); } function expectGate(script, gateName) { assert( script.includes("node scripts/resource-metering-contract-smoke.js"), `${gateName} must run resource-metering-contract-smoke.js` ); } const coreLimits = read("crates/disasmer-core/src/limits.rs"); const coordinatorService = read("crates/disasmer-coordinator/src/service.rs"); const artifactDownloadSmoke = read("scripts/artifact-download-smoke.js"); const operatorPanelSmoke = read("scripts/operator-panel-smoke.js"); const quicSmoke = read("scripts/quic-smoke.js"); const publicAcceptance = read("scripts/acceptance-public.sh"); const publicSplit = read("scripts/verify-public-split.sh"); const privateAcceptance = read("scripts/acceptance-private.sh"); for (const [name, pattern] of [ ["API call limit kind", /LimitKind::ApiCall/], ["spawn limit kind", /LimitKind::Spawn/], ["log bytes limit kind", /LimitKind::LogBytes/], ["metadata bytes limit kind", /LimitKind::MetadataBytes/], ["debug read bytes limit kind", /LimitKind::DebugReadBytes/], ["UI event limit kind", /LimitKind::UiEvent/], ["rendezvous attempt limit kind", /LimitKind::RendezvousAttempt/], ["artifact download bytes limit kind", /LimitKind::ArtifactDownloadBytes/], ["hosted fuel limit kind", /LimitKind::HostedFuel/], [ "preflight can check without consuming", /pub fn can_charge\([\s\S]*used\.saturating_add\(amount\) > limit/, ], [ "charge goes through preflight", /pub fn charge\([\s\S]*self\.can_charge\(limits, kind\.clone\(\), amount\)\?/, ], ]) { expect(coreLimits, name, pattern); } for (const [name, pattern] of [ [ "rendezvous charges before transport planning", /CoordinatorRequest::RequestRendezvous[\s\S]*rendezvous_meter\.charge\([\s\S]*LimitKind::RendezvousAttempt[\s\S]*plan_authenticated_direct_bulk_transfer/, ], [ "artifact link creation preflights downloadable bytes before link creation", /CoordinatorRequest::CreateArtifactDownloadLink[\s\S]*downloadable_size[\s\S]*download_meter\.can_charge\([\s\S]*LimitKind::ArtifactDownloadBytes[\s\S]*create_download_link/, ], [ "artifact stream opening and chunks charge download bytes", /CoordinatorRequest::OpenArtifactDownloadStream[\s\S]*open_download_stream\([\s\S]*&mut self\.download_meter[\s\S]*stream_download_chunk\([\s\S]*charged_download_bytes/, ], ]) { expect(coordinatorService, name, pattern); } for (const [name, source, patterns] of [ [ "rendezvous smoke", quicSmoke, [/charged_rendezvous_attempts, 1/, /coordinator bulk relay is disabled/], ], [ "artifact download smoke", artifactDownloadSmoke, [ /charged_download_bytes, 16/, /revoked/, ], ], [ "operator panel smoke", operatorPanelSmoke, [ /type: "submit_panel_event"/, /max_events: 1/, /used_events, 1/, /rate limit/i, /max_download_bytes: 1/, /exceeds download limit/, ], ], ]) { for (const pattern of patterns) { expect(source, name, pattern); } } expectGate(publicAcceptance, "public acceptance"); expectGate(publicSplit, "public split acceptance"); expectGate(privateAcceptance, "private acceptance"); const privateHostedLib = maybeRead(["private", "hosted-policy", "src", "lib.rs"]); const privateHostedSmoke = maybeRead([ "private", "hosted-policy", "scripts", "hosted-community-smoke.js", ]); if (privateHostedLib && privateHostedSmoke) { for (const [name, pattern] of [ [ "hosted API authorization meters API calls before policy decisions", /fn authorize\([\s\S]*LimitKind::ApiCall[\s\S]*policy\.decide/, ], [ "hosted spawn preflights before process start", /pub fn start_user_node_process\([\s\S]*LimitKind::Spawn[\s\S]*let active = self\.coordinator\.start_process/, ], [ "hosted zero-capability Wasm preflights through trial meter", /preflight_zero_capability_hosted_wasm\([\s\S]*let mut trial_meter = self\.meter\.clone\(\)[\s\S]*LimitKind::HostedFuel[\s\S]*LimitKind::HostedMemoryBytes[\s\S]*LimitKind::HostedWallClockMs[\s\S]*LimitKind::HostedStateBytes[\s\S]*LimitKind::LogBytes[\s\S]*LimitKind::MetadataBytes[\s\S]*LimitKind::UiEvent[\s\S]*LimitKind::ApiCall[\s\S]*self\.meter = trial_meter/, ], [ "hosted log recording preflights log bytes before storing logs", /record_user_node_task_completion\([\s\S]*LimitKind::LogBytes[\s\S]*self\.logs\.push/, ], [ "hosted debug reads preflight before inspection is created", /debug_process\([\s\S]*LimitKind::DebugReadBytes[\s\S]*DebugEpoch::pause/, ], [ "hosted tests cover each zero-capability Wasm budget", /hosted_zero_capability_wasm_preflight_rejects_each_budget_over_limit\([\s\S]*LimitKind::HostedFuel[\s\S]*LimitKind::LogBytes[\s\S]*LimitKind::MetadataBytes[\s\S]*LimitKind::UiEvent[\s\S]*LimitKind::ApiCall/, ], ]) { expect(privateHostedLib, name, pattern); } for (const [name, pattern] of [ ["running service denies hosted native compute", /hosted_native_command_preflight/], ["running service rejects non-zero hosted capabilities", /required_capabilities: \["Network"\]/], ["running service rejects hosted fuel overage", /resource limit exceeded.*HostedFuel/i], ["running service rejects spawn quota before retry succeeds", /quotaExhausted[\s\S]*resource limit exceeded.*Spawn/i], ["spawn quota survives fresh client retry", /quotaRetryFromFreshClient[\s\S]*resource limit exceeded.*Spawn/i], ["spawn quota survives node reconnect", /quotaAfterNodeReconnect[\s\S]*resource limit exceeded.*Spawn/i], ["running service rejects over-limit logs", /resource limit exceeded.*LogBytes/i], ["running service exposes scoped debug inspection", /type: "debug_process"[\s\S]*debug_inspection/], ]) { expect(privateHostedSmoke, name, pattern); } } console.log("Resource metering contract smoke passed");