Repository navigation
test(scale): qualify Fly.io filesystem admission before SCALE26 #882
Description
Problem
Fly.io is operationally simpler than GCP for the final #745 certification, but its attached Volume is a mount beneath the Machine root filesystem. GraphForge currently rejects durable absolute paths that cross a volume boundary with GF_UNSUPPORTED_FILESYSTEM / ancestor_cross_volume. Fly also caps a Volume at 500 GB, while the existing cloud workflow incorrectly admits only filesystems with at least 1 TiB capacity.
Provisioning an oversized Machine or running S24/S25 before proving exact-path durability would waste money and could tempt an unsafe admission bypass. The 128 GiB milestone figure is a hard certification ceiling, not a required Machine size: GraphForge persistent scale is designed to remain disk-bound through streamed and sharded phases.
Objective
Add one disposable, script-driven Fly qualification path that uses the exact certification path shape, emits only sanitized typed evidence, and proves or disqualifies Fly before any ladder or SCALE26 run.
Requirements
- Use the authenticated local
flyctl; do not require a cloud project, VPC, service account, or persistent infrastructure stack. - Create a temporary app, one small qualification Volume, one Machine, and one immutable OCI image; expose no public service.
- Pin region and resolved image digest in evidence.
- Configure restart disabled, autostop disabled, and automatic Machine destruction. Default the qualification to a small Machine; do not encode 128 GiB as a requirement.
- Record phase-level peak RSS so the later ladder can verify memory remains bounded and plateaus as scale rises. Continued material RSS growth with edge count is an architectural failure signal, not justification for a larger Machine.
- Mount the Fly Volume as the process working/temp root and run a real public-facade durable create/publish/reopen/portable-round-trip smoke through the exact absolute path shape used by test(scale): certify the S26 billion-edge round trip on OVHC-AGENCY #745.
- Emit an allowlisted sanitized JSON result with typed success or first failure; exclude graph/package content, secrets, credentials, resource IDs, and absolute host paths.
- Always destroy the Machine, Volume, app, and temporary credential/config state.
- Do not weaken filesystem admission or treat a relative path/chroot workaround as proof.
Acceptance Criteria
- Controller has a read-only/dry-run mode and refuses mutable image tags, missing region, non-empty resource names, or an unclean exact-SHA source tree.
- Machine config proves no services/ports,
restart.policy=no,auto_destroy=true, fixed region, explicit CPU/RAM, and one mounted Volume. - Smoke evidence reports observed Linux/filesystem/capacity and typed GraphForge admission outcome without sensitive paths.
- A Fly
ancestor_cross_volume, device-identity, unsupported-filesystem, or insufficient-memory result blocks S24/S25/SCALE26 and disqualifies Fly on the current tree. - Teardown is idempotent and verified by empty app/Machine/Volume lookups.
- Tests cover configuration, evidence sanitization, failure classification, no-full-run gating, and teardown planning.
BDD Completion Scenarios
Scenario: Fly is rejected safely
Given the exact certification path is rooted on an attached Fly Volume
When GraphForge rejects its mount ancestry
Then sanitized evidence records the typed admission failure
And no ladder or SCALE26 command runs.
Scenario: Qualification remains disposable
Given any controller success, failure, timeout, or interruption
When cleanup executes
Then the exact temporary Machine, Volume, and app are removed
And no public service or persistent secret remains.
Non-goals
Changing filesystem admission, running S24/S25, running SCALE26, selecting the final SCALE26 Machine size, accepting a 500-GB capacity projection, or closing #745.
Related Issues
- Parent and close gate: test(scale): certify the S26 billion-edge round trip on OVHC-AGENCY #745
- Milestone tracker: epic(scale): close billion-edge scale and hardened interchange #735
Activity