Public release release-01875e88a3e2
Source commit: 01875e88a3e25379c309489f9f057dd97c0d37de Public tree identity: sha256:8f37a1aa0cc8f408975daf9cabbe193f8f4c169c6d25e8795e67a3ed5083c76b
This commit is contained in:
commit
c1769967c1
210 changed files with 78680 additions and 0 deletions
230
scripts/resource-metering-contract-smoke.js
Normal file
230
scripts/resource-metering-contract-smoke.js
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
#!/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 wasmRuntime = read("crates/clusterflux-wasm-runtime/src/lib.rs");
|
||||
const wasmRuntimeTests = read("crates/clusterflux-wasm-runtime/src/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,/],
|
||||
[
|
||||
"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 [
|
||||
[
|
||||
"Wasm stores enforce a concrete memory limit",
|
||||
/StoreLimitsBuilder::new\(\)[\s\S]*memory_size\(runtime\.memory_bytes\)/,
|
||||
],
|
||||
[
|
||||
"Wasm compute uses a refillable fuel token bucket",
|
||||
/struct FuelTokenBucket[\s\S]*fractional_fuel_numerator[\s\S]*fn refill_after/,
|
||||
],
|
||||
["Wasmtime fuel consumption is enabled", /config\.consume_fuel\(true\)/],
|
||||
["Wasmtime epoch interruption is enabled", /config\.epoch_interruption\(true\)/],
|
||||
]) {
|
||||
expect(wasmRuntime, name, pattern);
|
||||
}
|
||||
|
||||
for (const [name, pattern] of [
|
||||
[
|
||||
"fuel refill preserves fractional credit",
|
||||
/frequent_refills_preserve_fractional_credit/,
|
||||
],
|
||||
[
|
||||
"linear memory growth is bounded per store",
|
||||
/wasm_linear_memory_growth_is_bounded_per_store/,
|
||||
],
|
||||
[
|
||||
"CPU-bound Wasm is interrupted without a host call",
|
||||
/epoch_interruption_aborts_cpu_bound_wasm_without_a_host_call/,
|
||||
],
|
||||
]) {
|
||||
expect(`${wasmRuntime}\n${wasmRuntimeTests}`, 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 control-plane limits and quota windows",
|
||||
/community_tier_resource_limits[\s\S]*LimitKind::ApiCall[\s\S]*LimitKind::ArtifactDownloadBytes[\s\S]*community_tier_quota_configuration[\s\S]*CoordinatorQuotaConfiguration::new/,
|
||||
],
|
||||
[
|
||||
"hosted zero-capability policy rejects native execution capabilities",
|
||||
/hosted_zero_capability_wasm_rejects_filesystem_and_command_capabilities[\s\S]*Capability::Command[\s\S]*Capability::Network[\s\S]*Capability::ArbitrarySyscalls/,
|
||||
],
|
||||
]) {
|
||||
expect(privateHostedLib, name, pattern);
|
||||
}
|
||||
assert.doesNotMatch(
|
||||
privateHostedLib,
|
||||
/HostedFuel|HostedMemoryBytes|HostedWallClockMs|HostedStateBytes/,
|
||||
"decorative hosted Wasm quota kinds must not return",
|
||||
);
|
||||
}
|
||||
|
||||
console.log("Resource metering contract smoke passed");
|
||||
Loading…
Add table
Add a link
Reference in a new issue