# Storage certification ## Why a certification is per-volume Atomic rename, same-file-store guarantees, and symlink refusal are properties of a specific filesystem behind a specific mount — not of "Kubernetes" or "a PVC". Change the CSI driver, the StorageClass, the access mode, the backend, or the mount options and any of them can differ. A certification that does not name all five is not transferable. ## What is certified | Property | Why it matters | |---|---| | Same file store for staging and content | A rename across stores is a copy, so publication stops being atomic. | | Atomic rename | The publish path's default strategy. | | Atomic create (`O_EXCL`) | Makes a publish create-only rather than a silent overwrite. | | Symlink refusal | Stops a replaced parent from redirecting a write outside the root. | | Ranged read | The download contract depends on it. | ## Running the certification ```bash kubectl apply -f infra/fileserver/kubernetes/pvc-certification-job.yaml kubectl logs job/fileserver-pvc-certification ``` The job writes a machine-readable result to the claim itself, carrying the full tuple: ```json { "kubernetesVersion": "...", "csiDriver": "...", "storageClass": "...", "accessMode": "ReadWriteOnce", "backend": "ext2/ext3", "mountOptions": "rw,relatime", "atomicMove": true, "sameFileStore": true, "atomicCreate": true } ``` The job fails closed: a volume whose staging and content areas are on different stores is not certified, because its publish would silently degrade to a copy. ## Network filesystems ```bash docker compose -f infra/fileserver/nfs/compose.yml up -d FILESERVER_NFS_TESTS=true ./gradlew :adapter:outbound:fileserver:test ``` The mount is `hard`, deliberately. A `soft` mount converts a slow server into a short write, which is exactly the corruption this design refuses to accept. ## Startup enforcement `FileserverStartupValidator` re-runs the probe at boot and refuses to accept traffic when a required capability is missing — `ATOMIC_MOVE_REQUIRED` on a filesystem that cannot prove an atomic move fails closed rather than degrading silently. ## Adding a new store Extend `ContentStoreContract` and pass it. A prose claim of compatibility is not accepted; the contract is executable precisely so a future object-storage adapter has to demonstrate the same offset, digest, and create-only behaviour the local store does.