#!/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}`); } const coreLimits = read("crates/clusterflux-core/src/limits.rs"); // Phase 3 keeps the protocol dispatch in service.rs and the metered operation // implementations in focused service modules. Read the complete relevant // boundary so this contract follows the refactor instead of one mega-file. const coordinatorService = [ read("crates/clusterflux-coordinator/src/service.rs"), read("crates/clusterflux-coordinator/src/service/routing.rs"), read("crates/clusterflux-coordinator/src/service/processes.rs"), read("crates/clusterflux-coordinator/src/service/process_launch.rs"), read("crates/clusterflux-coordinator/src/service/artifacts.rs"), ].join("\n"); const coordinatorQuota = read("crates/clusterflux-coordinator/src/service/quota.rs"); const coordinatorLogs = read("crates/clusterflux-coordinator/src/service/logs.rs"); const coordinatorDebug = read("crates/clusterflux-coordinator/src/service/debug.rs"); const coordinatorTests = read("crates/clusterflux-coordinator/src/service/tests.rs"); const artifactDownloadSmoke = read("scripts/artifact-download-smoke.js"); const operatorPanelSmoke = read("scripts/operator-panel-smoke.js"); const quicSmoke = read("scripts/quic-smoke.js"); for (const [name, pattern] of [ ["API call limit kind", /\bApiCall,/], ["spawn limit kind", /\bSpawn,/], ["log bytes limit kind", /\bLogBytes,/], ["metadata bytes limit kind", /\bMetadataBytes,/], ["debug read bytes limit kind", /\bDebugReadBytes,/], ["UI event limit kind", /\bUiEvent,/], ["rendezvous attempt limit kind", /\bRendezvousAttempt,/], ["artifact download bytes limit kind", /\bArtifactDownloadBytes,/], ["hosted fuel limit kind", /\bHostedFuel,/], [ "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, amount\)\?/, ], ]) { expect(coreLimits, name, pattern); } for (const [name, pattern] of [ [ "rendezvous charges before transport planning", /handle_request_rendezvous[\s\S]*charge_rendezvous_attempt\([\s\S]*&scope\.tenant[\s\S]*&scope\.project[\s\S]*now_epoch_seconds[\s\S]*plan_authenticated_direct_bulk_transfer/, ], [ "artifact link creation preflights downloadable bytes before link creation", /handle_create_artifact_download_link[\s\S]*downloadable_size[\s\S]*can_charge_download\([\s\S]*&context\.tenant[\s\S]*&context\.project[\s\S]*downloadable_size[\s\S]*create_download_link/, ], [ "artifact delivery charges scoped bytes before advancing its offset", /handle_open_artifact_download_stream[\s\S]*stream_download_chunk\([\s\S]*charge_download\([\s\S]*&context\.tenant[\s\S]*&context\.project[\s\S]*streamed_bytes[\s\S]*delivered_offset = end/, ], ]) { expect(coordinatorService, name, pattern); } for (const [name, pattern] of [ [ "quota keys include tenant/project resource kind and window", /struct ProjectQuotaScope[\s\S]*tenant: TenantId[\s\S]*project: ProjectId[\s\S]*struct MeterKey[\s\S]*kind: LimitKind[\s\S]*window: u64/, ], [ "quota module discards expired windows for an accessed scope and kind", /fn meter_mut[\s\S]*self\.meters\.retain[\s\S]*existing\.scope != key\.scope[\s\S]*existing\.kind != kind[\s\S]*existing\.window == key\.window/, ], [ "quota module charges rendezvous attempts through the scoped window meter", /fn charge_rendezvous_attempt[\s\S]*self\.charge\([\s\S]*tenant[\s\S]*project[\s\S]*LimitKind::RendezvousAttempt/, ], [ "quota module charges authenticated API calls through the scoped window meter", /fn charge_api_call[\s\S]*self\.charge\(tenant, project, LimitKind::ApiCall, 1, now_epoch_seconds\)/, ], [ "quota module preflights and charges log bytes through the scoped window meter", /fn can_charge_log_bytes[\s\S]*LimitKind::LogBytes[\s\S]*fn charge_log_bytes[\s\S]*LimitKind::LogBytes/, ], [ "quota module preflights artifact download bytes through the scoped meter", /fn can_charge_download[\s\S]*self\.can_charge\([\s\S]*tenant[\s\S]*project[\s\S]*LimitKind::ArtifactDownloadBytes/, ], [ "quota status reports current scoped window usage", /fn project_status[\s\S]*for kind in LimitKind::ALL[\s\S]*self\.used\(tenant, project, kind, now_epoch_seconds\)/, ], ]) { expect(coordinatorQuota, name, pattern); } for (const [source, name, pattern] of [ [ coordinatorService, "authenticated API calls are charged after session authorization and before dispatch", /authenticate_cli_session[\s\S]*authorize_authenticated_user_operation[\s\S]*charge_api_call[\s\S]*match request/, ], [ coordinatorLogs, "signed node log ingestion preflights and charges bytes before accepting the report", /handle_report_task_log[\s\S]*authorize_node_for_process_or_termination[\s\S]*can_charge_log_bytes[\s\S]*charge_log_bytes[\s\S]*TaskLogRecorded/, ], [ coordinatorDebug, "debug reads charge the scoped debug-read budget before audit state is recorded", /record_debug_audit_event[\s\S]*charge_debug_read[\s\S]*DebugAuditEvent/, ], [ coordinatorTests, "tests prove API-call and log-byte quota enforcement and project isolation", /authenticated_api_calls_are_metered_per_tenant_and_project_before_dispatch[\s\S]*project-a[\s\S]*project-b[\s\S]*signed_node_log_ingestion_checks_scoped_quota_before_accepting_bytes[\s\S]*LogBytes/, ], ]) { expect(source, name, pattern); } for (const [name, source, patterns] of [ [ "rendezvous smoke", quicSmoke, [/charged_rendezvous_attempts, 1/, /coordinator bulk relay is disabled/], ], [ "artifact download smoke", artifactDownloadSmoke, [ /downloaded\.response\.charged_download_bytes,[\s\S]*packageEvent\.artifact_size_bytes/, /retaining_node_reverse_stream/, /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); } } const privateHostedLibSource = maybeRead(["private", "hosted-policy", "src", "lib.rs"]); const privateHostedTests = maybeRead(["private", "hosted-policy", "src", "tests.rs"]); const privateHostedLib = privateHostedLibSource ? [privateHostedLibSource, privateHostedTests].filter(Boolean).join("\n") : null; if (privateHostedLib) { for (const [name, pattern] of [ [ "private hosted configuration owns exact limits and quota windows", /community_tier_resource_limits[\s\S]*LimitKind::ApiCall[\s\S]*LimitKind::HostedFuel[\s\S]*community_tier_quota_configuration[\s\S]*CoordinatorQuotaConfiguration::new/, ], [ "hosted zero-capability Wasm budget preflight is atomic across every resource kind", /preflight_zero_capability_hosted_wasm\([\s\S]*let mut trial_meter = 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]*\*meter = trial_meter/, ], [ "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/, ], [ "hosted tests prove tenant/project quota isolation", /hosted_resource_usage_is_isolated_by_tenant_and_project\([\s\S]*project-a[\s\S]*project-b[\s\S]*HostedFuel/, ], ]) { expect(privateHostedLib, name, pattern); } } console.log("Resource metering contract smoke passed");