chore!: make jdrive S3-only

ober

82aa4cc2b7d498ca3d8fc7bff04b061f7631e2eb

diff --git a/.gitignore b/.gitignore
index e53a6b9..fc6cebe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,8 +9,6 @@ cache/
 tmp/
 mount/
 dist/
+build/
 *-main.c
-protonstorage-bin
-protonstorage-linux-amd64
-protonstorage-linux-arm64
-protonstorage-freebsd-amd64
+jdrive-bin
diff --git a/.jerboa/security.json b/.jerboa/security.json
index b995b4c..689350a 100644
--- a/.jerboa/security.json
+++ b/.jerboa/security.json
@@ -3,10 +3,10 @@
   "repo": "jerboa-drive",
   "extends": ["jerboa:cli", "jerboa:crypto", "jerboa:ffi", "jerboa:network", "jerboa:credentialed-client", "jerboa:storage"],
   "paths": {
-    "production": ["*.ss", "*.sls", "lib/**/*.ss", "lib/**/*.sls", "protonstorage/**/*.ss", "support/**/*.ss", "Makefile"],
+    "production": ["*.ss", "*.sls", "lib/**/*.ss", "lib/**/*.sls", "jdrive/**/*.ss", "support/**/*.ss", "Makefile"],
     "tests": ["test/**", "tests/**", "**/*-test.ss", "fixtures/**"],
     "generated": ["build/**", "dist/**", "target/**", "*.so", "*.dylib", "*.wpo", "*-main.c"],
-    "vendor": ["vendor/**", "third_party/**"],
+    "vendor": ["vendor/**", "third_party/**", ".deps/**"],
     "docs": ["README.md", "docs/**", "*.md"]
   },
   "policy": {
@@ -16,7 +16,7 @@
     "process": { "shellInterpolation": "deny" },
     "network": { "requireTimeouts": true, "rawRemoteOutputEvidence": "deny" },
     "eval": { "stringEval": "deny", "bareRead": "deny", "allowReadEval": false },
-    "crypto": { "forbidSecretLogging": true, "requireRustSecCleanBackends": true },
+    "crypto": { "forbidSecretLogging": true, "requireReviewedNativeBackends": true },
     "credentials": {
       "plaintextCache": "deny",
       "rawCredentialEvidence": "deny",
@@ -25,23 +25,22 @@
     "storage": {
       "remotePlaintextFilenames": "deny",
       "remotePlaintextBodies": "deny",
-      "fuseMountEvidence": "target-required"
+      "rollbackDetection": "required"
     },
     "targetEvidence": {
       "storageProof": "fail-closed",
       "forbidPrivateProofMaterial": true,
       "requiredMarkers": [
-        "proton_live_drive_status=target-evidence-recorded",
         "s3_encrypted_roundtrip_status=target-evidence-recorded",
-        "fuse_mount_smoke_status=target-evidence-recorded",
         "credential_redaction_status=target-evidence-recorded",
         "no_plaintext_remote_state_status=target-evidence-recorded",
         "vault_permissions_status=target-evidence-recorded",
-        "proton_crypto_disabled_status=confirmed",
+        "manifest_rollback_status=target-evidence-recorded",
         "target_platform_smoke_status=target-evidence-recorded",
+        "crypto_ffi_review_status=current-run-recorded",
         "production_storage_review_status=current-run-recorded",
         "raw_remote_output_status=not-preserved",
-        "sensitive_artifact_policy=no-proton-passwords-tokens-s3-keys-vault-passwords-piv-pins-plaintext-files-or-raw-account-output-preserved"
+        "sensitive_artifact_policy=no-aws-keys-vault-passwords-piv-pins-plaintext-files-or-raw-account-output-preserved"
       ]
     }
   },
diff --git a/.jerbuild.release-darwin b/.jerbuild.release-darwin
index a2d0439..0ef088b 100644
--- a/.jerbuild.release-darwin
+++ b/.jerbuild.release-darwin
@@ -1,25 +1,15 @@
 (entry "support/binary-entry.ss")
-(output "protonstorage-bin")
+(output "jdrive-bin")
 (libdirs
   "support/vendor-overrides"
   "."
   "build/release-inputs/jerboa-aws/lib"
-  "build/release-inputs/jerboa-proton-bridge"
   "build/release-inputs/jerboa-yubikey"
   "build/release-inputs/jerboa-yubikey/lib"
-  "build/release-inputs/jerboa-pgp"
-  "build/release-inputs/jerboa-crypto/lib"
-  "build/release-inputs/jerboa-fuse/lib"
-  "build/release-inputs/jerboa-mail"
-  "build/release-inputs/jerboa-https/lib"
-  "build/release-inputs/jerboa-ssl/lib")
+  "build/release-inputs/jerboa-crypto/lib")
 (extra-sources "support/bundle-system-symbols.c")
 (extra-ldflags
-  "build/release-inputs/jerboa-ssl/jerboa_ssl_shim.dylib"
-  "build/release-inputs/jerboa-fuse/libjerboa_fuse_mount.so"
-  "build/release-inputs/jerboa-proton-bridge/proton-bridge-native/target/release/libproton_bridge_native.dylib"
-  "build/release-inputs/jerboa-yubikey/yubikey-native/target/release/libyubikey_native.dylib"
-  "build/release-inputs/jerboa-pgp/pgp-native/target/release/libjpgp_native.dylib")
-(main-c "support/bundle-main.c")
+  "build/release-inputs/jerboa-crypto/jerboa_crypto_shim.so"
+  "build/release-inputs/jerboa-yubikey/yubikey-native/target/release/libyubikey_native.dylib")
 (ffi-symbols "support/bundle-ffi-symbols.list")
 (static-native #t)
diff --git a/.jerbuild.release-elf b/.jerbuild.release-elf
index 4dc4741..84e4855 100644
--- a/.jerbuild.release-elf
+++ b/.jerbuild.release-elf
@@ -1,25 +1,15 @@
 (entry "support/binary-entry.ss")
-(output "protonstorage-bin")
+(output "jdrive-bin")
 (libdirs
   "support/vendor-overrides"
   "."
   "build/release-inputs/jerboa-aws/lib"
-  "build/release-inputs/jerboa-proton-bridge"
   "build/release-inputs/jerboa-yubikey"
   "build/release-inputs/jerboa-yubikey/lib"
-  "build/release-inputs/jerboa-pgp"
-  "build/release-inputs/jerboa-crypto/lib"
-  "build/release-inputs/jerboa-fuse/lib"
-  "build/release-inputs/jerboa-mail"
-  "build/release-inputs/jerboa-https/lib"
-  "build/release-inputs/jerboa-ssl/lib")
+  "build/release-inputs/jerboa-crypto/lib")
 (extra-sources "support/bundle-system-symbols.c")
 (extra-ldflags
-  "build/release-inputs/jerboa-ssl/jerboa_ssl_shim.so"
-  "build/release-inputs/jerboa-fuse/libjerboa_fuse_mount.so"
-  "build/release-inputs/jerboa-proton-bridge/proton-bridge-native/target/release/libproton_bridge_native.so"
-  "build/release-inputs/jerboa-yubikey/yubikey-native/target/release/libyubikey_native.so"
-  "build/release-inputs/jerboa-pgp/pgp-native/target/release/libjpgp_native.so")
-(main-c "support/bundle-main.c")
+  "build/release-inputs/jerboa-crypto/jerboa_crypto_shim.so"
+  "build/release-inputs/jerboa-yubikey/yubikey-native/target/release/libyubikey_native.so")
 (ffi-symbols "support/bundle-ffi-symbols.list")
 (static-native #t)
diff --git a/Makefile b/Makefile
index 9119c6c..4643911 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,7 @@
-JERBOA_VERSION ?= v0.2.3
+JERBOA_VERSION ?= v0.2.8
 JERBOA_TOOL_DIR ?= $(CURDIR)/.jerboa/bin
 JERBUILD ?= $(shell if [ -x "$(CURDIR)/jerbuild" ]; then echo "$(CURDIR)/jerbuild"; \
 	elif [ -x "$(JERBOA_TOOL_DIR)/jerbuild" ]; then echo "$(JERBOA_TOOL_DIR)/jerbuild"; \
-	elif [ -x "$(CURDIR)/../jerboa/dist/jerbuild" ]; then echo "$(CURDIR)/../jerboa/dist/jerbuild"; \
-	elif [ -x "$(CURDIR)/../jerboa/jerbuild" ]; then echo "$(CURDIR)/../jerboa/jerbuild"; \
 	elif command -v jerbuild >/dev/null 2>&1; then command -v jerbuild; \
 	else echo "$(JERBOA_TOOL_DIR)/jerbuild"; fi)
 JH = $(shell "$(JERBUILD)" --jerboa-home 2>/dev/null)
@@ -11,63 +9,28 @@ JERBOA_HOME ?= $(JH)
 NATIVE_LOADER_OVERRIDE_DIR := $(CURDIR)/support/vendor-overrides
 
 DEPS_DIR ?= $(CURDIR)/.deps
-LOCAL_PROTON_BRIDGE_DIR := $(CURDIR)/../jerboa-proton-bridge
-LOCAL_HTTPS_DIR := $(CURDIR)/../jerboa-https
-LOCAL_SSL_DIR := $(CURDIR)/../jerboa-ssl
-LOCAL_YUBIKEY_DIR := $(CURDIR)/../jerboa-yubikey
-LOCAL_PGP_DIR := $(CURDIR)/../jerboa-pgp
-LOCAL_CRYPTO_DIR := $(CURDIR)/../jerboa-crypto
-LOCAL_FUSE_DIR := $(CURDIR)/../jerboa-fuse
-LOCAL_MAIL_DIR := $(CURDIR)/../jerboa-mail
-LOCAL_AWS_DIR := $(CURDIR)/../jerboa-aws
-JERBOA_PROTON_BRIDGE_DIR ?= $(if $(wildcard $(LOCAL_PROTON_BRIDGE_DIR)/.),$(realpath $(LOCAL_PROTON_BRIDGE_DIR)),$(DEPS_DIR)/jerboa-proton-bridge)
-JERBOA_HTTPS_DIR ?= $(if $(wildcard $(LOCAL_HTTPS_DIR)/.),$(realpath $(LOCAL_HTTPS_DIR)),$(DEPS_DIR)/jerboa-https)
-JERBOA_SSL_DIR ?= $(if $(wildcard $(LOCAL_SSL_DIR)/.),$(realpath $(LOCAL_SSL_DIR)),$(DEPS_DIR)/jerboa-ssl)
-JERBOA_YUBIKEY_DIR ?= $(if $(wildcard $(LOCAL_YUBIKEY_DIR)/.),$(realpath $(LOCAL_YUBIKEY_DIR)),$(DEPS_DIR)/jerboa-yubikey)
-JERBOA_PGP_DIR ?= $(if $(wildcard $(LOCAL_PGP_DIR)/.),$(realpath $(LOCAL_PGP_DIR)),$(DEPS_DIR)/jerboa-pgp)
-JERBOA_CRYPTO_DIR ?= $(if $(wildcard $(LOCAL_CRYPTO_DIR)/.),$(realpath $(LOCAL_CRYPTO_DIR)),$(DEPS_DIR)/jerboa-crypto)
-JERBOA_FUSE_DIR ?= $(if $(wildcard $(LOCAL_FUSE_DIR)/.),$(realpath $(LOCAL_FUSE_DIR)),$(DEPS_DIR)/jerboa-fuse)
-JERBOA_MAIL_DIR ?= $(if $(wildcard $(LOCAL_MAIL_DIR)/.),$(realpath $(LOCAL_MAIL_DIR)),$(DEPS_DIR)/jerboa-mail)
-JERBOA_AWS_DIR ?= $(if $(wildcard $(LOCAL_AWS_DIR)/.),$(realpath $(LOCAL_AWS_DIR)),$(DEPS_DIR)/jerboa-aws)
-LIBDIRS = $(NATIVE_LOADER_OVERRIDE_DIR):$(CURDIR):$(JERBOA_AWS_DIR)/lib:$(JERBOA_PROTON_BRIDGE_DIR):$(JERBOA_YUBIKEY_DIR):$(JERBOA_YUBIKEY_DIR)/lib:$(JERBOA_PGP_DIR):$(JERBOA_CRYPTO_DIR)/lib:$(JERBOA_FUSE_DIR)/lib:$(JERBOA_MAIL_DIR):$(JERBOA_HTTPS_DIR)/lib:$(JERBOA_SSL_DIR)/lib:$(JH)/lib
-XC_LIBDIRS = $(LIBDIRS):$(JH)/.chez-cross-ta6le/lib:$(JH)/.chez-cross-tarm64le/lib:$(JH)/.chez-cross-ta6fb/lib
+DEPS_STAMP := $(DEPS_DIR)/.locked
+JERBOA_AWS_DIR ?= $(DEPS_DIR)/jerboa-aws
+JERBOA_YUBIKEY_DIR ?= $(DEPS_DIR)/jerboa-yubikey
+JERBOA_CRYPTO_DIR ?= $(DEPS_DIR)/jerboa-crypto
+LIBDIRS = $(NATIVE_LOADER_OVERRIDE_DIR):$(CURDIR):$(JERBOA_AWS_DIR)/lib:$(JERBOA_YUBIKEY_DIR):$(JERBOA_YUBIKEY_DIR)/lib:$(JERBOA_CRYPTO_DIR)/lib:$(JH)/lib
 JERBOA_NATIVE_DIR ?= $(JH)/jerboa-native-rs/target/release
-PROTON_BRIDGE_NATIVE_DIR := $(JERBOA_PROTON_BRIDGE_DIR)/proton-bridge-native/target/release
 UNAME_S := $(shell uname -s)
 ifeq ($(UNAME_S),Darwin)
-  LD_VAR = DYLD_LIBRARY_PATH
   SO_EXT = .dylib
-  FUSE_SO_EXT = .so
 else
-  LD_VAR = LD_LIBRARY_PATH
   SO_EXT = .so
-  FUSE_SO_EXT = .so
 endif
-YUBIKEY_NATIVE_LIB := $(JERBOA_YUBIKEY_DIR)/yubikey-native/target/release/libyubikey_native$(SO_EXT)
-PGP_NATIVE_LIB := $(JERBOA_PGP_DIR)/pgp-native/target/release/libjpgp_native$(SO_EXT)
-PROTON_BRIDGE_NATIVE_LIB := $(PROTON_BRIDGE_NATIVE_DIR)/libproton_bridge_native$(SO_EXT)
-SSL_NATIVE_LIB := $(JERBOA_SSL_DIR)/jerboa_ssl_shim$(SO_EXT)
-FUSE_NATIVE_LIB := $(JERBOA_FUSE_DIR)/libjerboa_fuse_mount$(FUSE_SO_EXT)
+YUBIKEY_NATIVE_DIR := $(JERBOA_YUBIKEY_DIR)/yubikey-native/target/release
+YUBIKEY_NATIVE_LIB := $(YUBIKEY_NATIVE_DIR)/libyubikey_native$(SO_EXT)
 BINARY_NATIVE_INPUT_DIR := $(CURDIR)/build/release-inputs
 BINARY_RELEASE_CONFIG := $(if $(filter Darwin,$(UNAME_S)),.jerbuild.release-darwin,.jerbuild.release-elf)
 RUN_ENV := JERBOA_HOME=$(JH) \
-	JERBOA_SSL_LIB=$(JERBOA_SSL_DIR) \
-	JERBOA_SSL_ALLOW_DYNAMIC_NATIVE=1 \
 	JERBOA_CRYPTO_LIB=$(JERBOA_CRYPTO_DIR) \
 	JERBOA_CRYPTO_ALLOW_DYNAMIC_NATIVE=1 \
-	JERBOA_FUSE_LIB=$(JERBOA_FUSE_DIR) \
-	JPGP_ALLOW_DYNAMIC_NATIVE=1 \
-	JPGP_NATIVE_LIB=$(PGP_NATIVE_LIB) \
 	JYUBIKEY_DEV_NATIVE=1 \
-	JYUBIKEY_NATIVE_LIB=$(YUBIKEY_NATIVE_LIB) \
-	PROTON_BRIDGE_NATIVE_LIB=$(PROTON_BRIDGE_NATIVE_LIB) \
-	DYLD_LIBRARY_PATH=$(JERBOA_NATIVE_DIR):$(JERBOA_CRYPTO_DIR):$(JERBOA_FUSE_DIR):$(PROTON_BRIDGE_NATIVE_DIR):$${DYLD_LIBRARY_PATH:-} \
-	DYLD_FALLBACK_LIBRARY_PATH=$(JERBOA_NATIVE_DIR):$${DYLD_FALLBACK_LIBRARY_PATH:-} \
-	LD_LIBRARY_PATH=$(JERBOA_NATIVE_DIR):$(JERBOA_CRYPTO_DIR):$(JERBOA_FUSE_DIR):$(PROTON_BRIDGE_NATIVE_DIR):$${LD_LIBRARY_PATH:-}
-BINARY_OUTPUT ?= protonstorage-bin
-LINUX_AMD64_CC ?= x86_64-linux-musl-gcc
-LINUX_ARM64_CC ?= aarch64-linux-musl-gcc
-FREEBSD_AMD64_CC ?= $(JERBOA_HOME)/support/cross-cc-freebsd-amd64
+	JYUBIKEY_NATIVE_LIB=$(YUBIKEY_NATIVE_LIB)
+BINARY_OUTPUT ?= jdrive-bin
 HOST_OS := $(shell uname -s | tr '[:upper:]' '[:lower:]')
 HOST_ARCH := $(shell uname -m)
 BUNDLE_OUTPUT ?= dist/jerboa-drive-$(HOST_OS)-$(HOST_ARCH)
@@ -78,57 +41,25 @@ DIST_DIR ?= $(CURDIR)/dist
 RELEASE_EVIDENCE_DIR ?= $(DIST_DIR)/release-evidence
 TARGET_EVIDENCE_DIR ?= $(DIST_DIR)/target-evidence
 
-.PHONY: help ensure-jerboa-tools ensure-deps native-runtime deps run test integration s3-integration doctor binary-release-inputs binary binary-doctor-smoke audit verify security dependency-evidence sbom reproducibility-report target-evidence release-evidence bundle install linux linux-amd64 linux-arm64 freebsd freebsd-amd64 clean lint
+.PHONY: help ensure-jerboa-tools ensure-deps native-runtime deps run test s3-integration doctor binary-release-inputs binary binary-doctor-smoke audit verify security dependency-evidence sbom reproducibility-report target-evidence release-evidence bundle install clean lint
 .DEFAULT_GOAL := help
 
-lib/libjerboa_native$(SO_EXT): ensure-jerboa-tools
-	@mkdir -p lib
-	@src="$(JERBOA_NATIVE_DIR)/libjerboa_native$(SO_EXT)"; \
-	 sibling="$(CURDIR)/../jerboa/lib/libjerboa_native$(SO_EXT)"; \
-	 if [ -f "$$src" ]; then \
-	   ln -sf "$$src" "$@"; \
-	 elif [ -f "$$sibling" ]; then \
-	   ln -sf "$$sibling" "$@"; \
-	 else \
-	   echo "ERROR: libjerboa_native$(SO_EXT) not found in $(JERBOA_NATIVE_DIR) or sibling jerboa/lib; run make -C ../jerboa native" >&2; \
-	   exit 1; \
-	 fi
-
 help:
 	@echo "jerboa-drive"
 	@echo ""
 	@echo "Development:"
-	@echo "  make run ARGS='help'       Run the CLI"
-	@echo "  make doctor                Check native Jerboa implementation status"
-	@echo "  make test                  Run smoke tests"
-	@echo "  make target-evidence       Write target Drive/S3/FUSE proof status"
-	@echo "  make release-evidence      Write test/audit/SBOM/reproducibility evidence"
-	@echo "  make integration           Run opt-in live Drive test when enabled"
-	@echo "  make s3-integration        Run opt-in live encrypted S3 test when enabled"
+	@echo "  make run ARGS='help'       Run the S3 CLI"
+	@echo "  make doctor                Show S3 implementation status"
+	@echo "  make test                  Run local S3 tests"
+	@echo "  make s3-integration        Run opt-in live encrypted S3 test"
 	@echo "  make clean                 Remove generated local artifacts"
 	@echo ""
 	@echo "Build:"
-	@echo "  make                       Show this help"
-	@echo "  make binary                Build ./$(BINARY_OUTPUT) for this host"
+	@echo "  make binary                Build ./$(BINARY_OUTPUT)"
 	@echo "  make bundle                Package ./$(BUNDLE_OUTPUT).tar.gz"
 	@echo "  make install               Install jdrive to $(INSTALL_BINDIR)"
-	@echo "  make linux-amd64           Cross-build ./protonstorage-linux-amd64"
-	@echo "  make linux-arm64           Cross-build ./protonstorage-linux-arm64"
-	@echo "  make freebsd-amd64         Cross-build ./protonstorage-freebsd-amd64"
 	@echo ""
-	@echo "Environment:"
-	@echo "  JERBUILD = $(JERBUILD)"
-	@echo "  JERBOA_PROTON_BRIDGE_DIR = $(JERBOA_PROTON_BRIDGE_DIR)"
-	@echo "  JERBOA_YUBIKEY_DIR = $(JERBOA_YUBIKEY_DIR)"
-	@echo "  JERBOA_PGP_DIR = $(JERBOA_PGP_DIR)"
-	@echo "  JERBOA_CRYPTO_DIR = $(JERBOA_CRYPTO_DIR)"
-	@echo "  JERBOA_FUSE_DIR = $(JERBOA_FUSE_DIR)"
-	@echo "  JERBOA_MAIL_DIR = $(JERBOA_MAIL_DIR)"
-	@echo "  JERBOA_AWS_DIR = $(JERBOA_AWS_DIR)"
-	@echo "  JERBOA_HTTPS_DIR = $(JERBOA_HTTPS_DIR)"
-	@echo "  JERBOA_SSL_DIR = $(JERBOA_SSL_DIR)"
-	@echo "  JERBOA_NATIVE_DIR = $(JERBOA_NATIVE_DIR)"
-	@echo "  INSTALL_PREFIX = $(INSTALL_PREFIX)"
+	@echo "Dependencies are fetched at locked commits into $(DEPS_DIR)."
 
 ensure-jerboa-tools:
 	@if "$(JERBUILD)" --jerboa-home >/dev/null 2>&1; then \
@@ -142,47 +73,24 @@ ensure-jerboa-tools:
 	  sh support/ensure-jerboa.sh "$(JERBOA_VERSION)" "$(JERBOA_TOOL_DIR)"; \
 	fi
 	@"$(JERBUILD)" --jerboa-home >/dev/null || { \
-	  echo "ERROR: Jerboa toolchain is unavailable; set JERBUILD=/path/to/jerbuild or JERBOA_VERSION=<tag>" >&2; \
+	  echo "ERROR: Jerboa toolchain is unavailable; set JERBUILD=/path/to/jerbuild" >&2; \
 	  exit 1; \
 	}
 
-ensure-deps:
-	@test -d "$(JERBOA_PROTON_BRIDGE_DIR)" || { echo "ERROR: JERBOA_PROTON_BRIDGE_DIR missing: $(JERBOA_PROTON_BRIDGE_DIR)" >&2; exit 1; }
-	@test -d "$(JERBOA_AWS_DIR)" || { echo "ERROR: JERBOA_AWS_DIR missing: $(JERBOA_AWS_DIR)" >&2; exit 1; }
-	@test -d "$(JERBOA_YUBIKEY_DIR)" || { echo "ERROR: JERBOA_YUBIKEY_DIR missing: $(JERBOA_YUBIKEY_DIR)" >&2; exit 1; }
-	@test -d "$(JERBOA_PGP_DIR)" || { echo "ERROR: JERBOA_PGP_DIR missing: $(JERBOA_PGP_DIR)" >&2; exit 1; }
-	@test -d "$(JERBOA_CRYPTO_DIR)" || { echo "ERROR: JERBOA_CRYPTO_DIR missing: $(JERBOA_CRYPTO_DIR)" >&2; exit 1; }
-	@test -d "$(JERBOA_FUSE_DIR)" || { echo "ERROR: JERBOA_FUSE_DIR missing: $(JERBOA_FUSE_DIR)" >&2; exit 1; }
-	@test -d "$(JERBOA_MAIL_DIR)" || { echo "ERROR: JERBOA_MAIL_DIR missing: $(JERBOA_MAIL_DIR)" >&2; exit 1; }
-	@test -d "$(JERBOA_HTTPS_DIR)" || { echo "ERROR: JERBOA_HTTPS_DIR missing: $(JERBOA_HTTPS_DIR)" >&2; exit 1; }
-	@test -d "$(JERBOA_SSL_DIR)" || { echo "ERROR: JERBOA_SSL_DIR missing: $(JERBOA_SSL_DIR)" >&2; exit 1; }
+$(DEPS_STAMP): dependency-lock.tsv support/fetch-locked-deps.sh
+	@sh support/fetch-locked-deps.sh dependency-lock.tsv .deps
+	@touch "$@"
+
+ensure-deps: $(DEPS_STAMP)
 
 native-runtime: ensure-jerboa-tools
 	@command -v cargo >/dev/null 2>&1 || { echo "ERROR: cargo not found on PATH." >&2; exit 1; }
 	cargo build --release --manifest-path "$(JH)/jerboa-native-rs/Cargo.toml" --no-default-features --features tls,crypto
 
-deps: ensure-jerboa-tools ensure-deps native-runtime lib/libjerboa_native$(SO_EXT)
-	@if [ ! -f "$(JERBOA_SSL_DIR)/lib/jerboa-ssl.sls" ] || [ ! -f "$(JERBOA_SSL_DIR)/jerboa_ssl_shim$(SO_EXT)" ]; then \
-	  $(MAKE) -C "$(JERBOA_SSL_DIR)" JERBUILD="$(JERBUILD)" build; \
-	fi
-	@if [ ! -f "$(JERBOA_HTTPS_DIR)/lib/jerboa-https.sls" ]; then \
-	  $(MAKE) -C "$(JERBOA_HTTPS_DIR)" JERBUILD="$(JERBUILD)" SSL_DIR="$(JERBOA_SSL_DIR)" build; \
-	fi
-	@if [ ! -f "$(JERBOA_CRYPTO_DIR)/lib/jerboa-crypto.sls" ] || [ ! -f "$(JERBOA_CRYPTO_DIR)/jerboa_crypto_shim.so" ]; then \
-	  $(MAKE) -C "$(JERBOA_CRYPTO_DIR)" JERBUILD="$(JERBUILD)" build; \
-	fi
-	@if [ ! -f "$(JERBOA_FUSE_DIR)/lib/jerboa-fuse.sls" ] || [ ! -f "$(JERBOA_FUSE_DIR)/libjerboa_fuse_mount$(FUSE_SO_EXT)" ]; then \
-	  $(MAKE) -C "$(JERBOA_FUSE_DIR)" JERBUILD="$(JERBUILD)" build; \
-	fi
-	@if [ ! -f "$(PROTON_BRIDGE_NATIVE_DIR)/libproton_bridge_native$(SO_EXT)" ]; then \
-	  $(MAKE) -C "$(JERBOA_PROTON_BRIDGE_DIR)" JERBUILD="$(JERBUILD)" native; \
-	fi
-	@if [ ! -f "$(YUBIKEY_NATIVE_LIB)" ]; then \
-	  $(MAKE) -C "$(JERBOA_YUBIKEY_DIR)" JERBUILD="$(JERBUILD)" native; \
-	fi
-	@if [ ! -f "$(PGP_NATIVE_LIB)" ]; then \
-	  $(MAKE) -C "$(JERBOA_PGP_DIR)" JERBUILD="$(JERBUILD)" build-native; \
-	fi
+deps: ensure-jerboa-tools ensure-deps native-runtime
+	@$(MAKE) -C "$(JERBOA_AWS_DIR)" JERBUILD="$(JERBUILD)" transpile
+	@$(MAKE) -C "$(JERBOA_CRYPTO_DIR)" JERBUILD="$(JERBUILD)" build
+	@$(MAKE) -C "$(JERBOA_YUBIKEY_DIR)" JERBUILD="$(JERBUILD)" native
 
 run: deps
 	$(RUN_ENV) \
@@ -195,10 +103,6 @@ test: deps
 	$(RUN_ENV) \
 		"$(JERBUILD)" exec --libdirs "$(LIBDIRS)" test/test-all.ss
 
-integration: deps
-	$(RUN_ENV) \
-		"$(JERBUILD)" exec --libdirs "$(LIBDIRS)" test/integration-drive.ss
-
 s3-integration: deps
 	$(RUN_ENV) \
 		"$(JERBUILD)" exec --libdirs "$(LIBDIRS)" test/integration-s3.ss
@@ -207,27 +111,20 @@ binary-release-inputs: deps
 	rm -rf "$(BINARY_NATIVE_INPUT_DIR)"
 	mkdir -p "$(BINARY_NATIVE_INPUT_DIR)"
 	ln -s "$(JERBOA_AWS_DIR)" "$(BINARY_NATIVE_INPUT_DIR)/jerboa-aws"
-	ln -s "$(JERBOA_PROTON_BRIDGE_DIR)" "$(BINARY_NATIVE_INPUT_DIR)/jerboa-proton-bridge"
 	ln -s "$(JERBOA_YUBIKEY_DIR)" "$(BINARY_NATIVE_INPUT_DIR)/jerboa-yubikey"
-	ln -s "$(JERBOA_PGP_DIR)" "$(BINARY_NATIVE_INPUT_DIR)/jerboa-pgp"
 	ln -s "$(JERBOA_CRYPTO_DIR)" "$(BINARY_NATIVE_INPUT_DIR)/jerboa-crypto"
-	ln -s "$(JERBOA_FUSE_DIR)" "$(BINARY_NATIVE_INPUT_DIR)/jerboa-fuse"
-	ln -s "$(JERBOA_MAIL_DIR)" "$(BINARY_NATIVE_INPUT_DIR)/jerboa-mail"
-	ln -s "$(JERBOA_HTTPS_DIR)" "$(BINARY_NATIVE_INPUT_DIR)/jerboa-https"
-	ln -s "$(JERBOA_SSL_DIR)" "$(BINARY_NATIVE_INPUT_DIR)/jerboa-ssl"
 
 binary: binary-release-inputs
 	JERBOA_NATIVE_A="$(JERBOA_NATIVE_DIR)/libjerboa_native.a" \
 		"$(JERBUILD)" build --config "$(BINARY_RELEASE_CONFIG)"
-	@if [ "$(BINARY_OUTPUT)" != protonstorage-bin ]; then \
-	  cp protonstorage-bin "$(BINARY_OUTPUT)"; \
-	fi
 
-binary-doctor-smoke: binary
-	$(RUN_ENV) ./$(BINARY_OUTPUT) doctor
+binary-doctor-smoke: bundle
+	"$(BUNDLE_OUTPUT)/jdrive" doctor
 
 audit: deps
-	$(MAKE) -C "$(JERBOA_PROTON_BRIDGE_DIR)" JERBUILD="$(JERBUILD)" audit
+	@$(MAKE) -C "$(JERBOA_AWS_DIR)" JERBUILD="$(JERBUILD)" security
+	@$(MAKE) -C "$(JERBOA_CRYPTO_DIR)" JERBUILD="$(JERBUILD)" audit
+	@$(MAKE) -C "$(JERBOA_YUBIKEY_DIR)" JERBUILD="$(JERBUILD)" audit
 
 verify: security test doctor audit reproducibility-report sbom target-evidence
 
@@ -236,46 +133,29 @@ lint: security
 security:
 	@test -f scripts/sanitize-evidence.sh || { echo "missing scripts/sanitize-evidence.sh" >&2; exit 1; }
 	@bash scripts/package-security-test.sh
-	@test -f dependency-lock.tsv || { echo "missing dependency-lock.tsv" >&2; exit 1; }
+	@test -f dependency-lock.tsv || { echo "missing dependency lock" >&2; exit 1; }
 	@test -f support/fetch-locked-deps.sh || { echo "missing locked dependency fetcher" >&2; exit 1; }
 	@! grep -R -E 'uses:[[:space:]]*[^[:space:]]+@(v[0-9]+|main|master|stable)([[:space:]]|$$)' .forgejo/workflows
-	@! grep -R -F 'git clone --depth 1' .github support scripts
-	@awk -F '\t' 'NF != 4 || $$1 !~ /^[a-z0-9-]+$$/ || $$3 !~ /^[0-9a-f]{40}$$/ || $$4 !~ /^[0-9a-f]{40}$$/ { exit 1 } END { if (NR != 9) exit 1 }' dependency-lock.tsv
+	@! grep -R -F 'git clone --depth 1' .forgejo support scripts
+	@awk -F '\t' 'NF != 4 || $$1 !~ /^[a-z0-9-]+$$/ || $$3 !~ /^[0-9a-f]{40}$$/ || $$4 !~ /^[0-9a-f]{40}$$/ { exit 1 } END { if (NR != 3) exit 1 }' dependency-lock.tsv
 	@grep -q 'sanitize-evidence' docs/release-evidence.md || { echo "missing release evidence sanitizer docs" >&2; exit 1; }
 	@grep -q 'host-private' docs/release-evidence.md || { echo "missing host-private proof docs" >&2; exit 1; }
 	@set -eu; \
-	pattern="(BEGIN (RSA|OPENSSH|EC|DSA|PRIVATE) KEY|ghp_[A-Za-z0-9_]{20,}|github_pat_[A-Za-z0-9_]{20,}|glpat-[A-Za-z0-9_-]{20,}|gldt-[A-Za-z0-9_-]{20,}|glrt-[A-Za-z0-9_-]{20,}|Authorization['\\\"]?[[:space:]]*[:=][[:space:]]*['\\\"]?Bearer[[:space:]]+[A-Za-z0-9_-]{20,}\\.[A-Za-z0-9_-]{20,}\\.[A-Za-z0-9_-]{20,}|PROTONDRIVE_(USERNAME|PASSWORD|VAULT_PASSWORD|ACCESS_TOKEN|REFRESH_TOKEN)=['\\\"]?[A-Za-z0-9_./+=:-]{24,}|JDRIVE_(S3_TEST_SECRET|S3_TEST_ACCESS|VAULT_PASSWORD)=['\\\"]?[A-Za-z0-9_./+=:-]{24,}|AKIA[0-9A-Z]{16}|ASIA[0-9A-Z]{16})"; \
+	pattern="(BEGIN (RSA|OPENSSH|EC|DSA|PRIVATE) KEY|ghp_[A-Za-z0-9_]{20,}|github_pat_[A-Za-z0-9_]{20,}|glpat-[A-Za-z0-9_-]{20,}|gldt-[A-Za-z0-9_-]{20,}|glrt-[A-Za-z0-9_-]{20,}|Authorization['\"]?[[:space:]]*[:=][[:space:]]*['\"]?Bearer[[:space:]]+[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}|AKIA[0-9A-Z]{16}|ASIA[0-9A-Z]{16}|JDRIVE_(S3_TEST_SECRET|S3_TEST_ACCESS|VAULT_PASSWORD)=['\"]?[A-Za-z0-9_./+=:-]{24,})"; \
 	matches="$$(git grep -n -I -E "$$pattern" -- . ":!*.png" ":!*.jpg" ":!*.jpeg" ":!*.gif" ":!*.so" ":!*.dylib" ":!*.o" ":!*.a" ":!*.boot" ":!*.tar.gz" || true)"; \
-	if [ -n "$$matches" ]; then \
-	  echo "$$matches"; \
-	  echo "High-confidence secret pattern found."; \
-	  exit 1; \
-	fi; \
+	if [ -n "$$matches" ]; then echo "$$matches"; exit 1; fi; \
 	echo "secret_scan_status=pass"
 
 dependency-evidence: deps
 	@set -eu; \
 	status=0; \
 	for item in \
-	  "jerboa-proton-bridge:$(JERBOA_PROTON_BRIDGE_DIR)" \
-	  "jerboa-yubikey:$(JERBOA_YUBIKEY_DIR)" \
 	  "jerboa-aws:$(JERBOA_AWS_DIR)" \
-	  "jerboa-pgp:$(JERBOA_PGP_DIR)" \
-	  "jerboa-crypto:$(JERBOA_CRYPTO_DIR)" \
-	  "jerboa-fuse:$(JERBOA_FUSE_DIR)" \
-	  "jerboa-mail:$(JERBOA_MAIL_DIR)" \
-	  "jerboa-https:$(JERBOA_HTTPS_DIR)" \
-	  "jerboa-ssl:$(JERBOA_SSL_DIR)"; do \
-	  label=$${item%%:*}; \
-	  dir=$${item#*:}; \
+	  "jerboa-yubikey:$(JERBOA_YUBIKEY_DIR)" \
+	  "jerboa-crypto:$(JERBOA_CRYPTO_DIR)"; do \
+	  label=$${item%%:*}; dir=$${item#*:}; \
 	  echo "==> $$label dependency evidence"; \
-	  if awk 'BEGIN { found=0 } /^[^#[:space:]][^:]*:/ { split($$0, a, ":"); n=split(a[1], t, /[[:space:]]+/); for (i=1; i<=n; i++) if (t[i] == "release-evidence") found=1 } END { exit(found ? 0 : 1) }' "$$dir/Makefile"; then \
-	    env -u DIST_DIR -u RELEASE_EVIDENCE_DIR -u SBOM_DIR -u REPRO_DIR -u TARGET_EVIDENCE_DIR \
-	      $(MAKE) -C "$$dir" JERBUILD="$(JERBUILD)" release-evidence || status=1; \
-	  else \
-	    echo "$$label release-evidence target missing"; \
-	    status=1; \
-	  fi; \
+	  $(MAKE) -C "$$dir" JERBUILD="$(JERBUILD)" release-evidence || status=1; \
 	done; \
 	exit "$$status"
 
@@ -284,15 +164,9 @@ sbom: deps
 	DIST_DIR="$(DIST_DIR)" \
 	JERBUILD="$(JERBUILD)" \
 	BINARY_OUTPUT="$(BINARY_OUTPUT)" \
-	JERBOA_PROTON_BRIDGE_DIR="$(JERBOA_PROTON_BRIDGE_DIR)" \
-	JERBOA_YUBIKEY_DIR="$(JERBOA_YUBIKEY_DIR)" \
 	JERBOA_AWS_DIR="$(JERBOA_AWS_DIR)" \
-	JERBOA_PGP_DIR="$(JERBOA_PGP_DIR)" \
+	JERBOA_YUBIKEY_DIR="$(JERBOA_YUBIKEY_DIR)" \
 	JERBOA_CRYPTO_DIR="$(JERBOA_CRYPTO_DIR)" \
-	JERBOA_FUSE_DIR="$(JERBOA_FUSE_DIR)" \
-	JERBOA_MAIL_DIR="$(JERBOA_MAIL_DIR)" \
-	JERBOA_HTTPS_DIR="$(JERBOA_HTTPS_DIR)" \
-	JERBOA_SSL_DIR="$(JERBOA_SSL_DIR)" \
 	sh scripts/sbom.sh
 
 reproducibility-report: deps
@@ -318,11 +192,8 @@ release-evidence:
 	sh scripts/release-evidence.sh
 
 bundle: binary
-	JERBOA_PROTON_BRIDGE_DIR="$(JERBOA_PROTON_BRIDGE_DIR)" \
 	JERBOA_YUBIKEY_DIR="$(JERBOA_YUBIKEY_DIR)" \
-	JERBOA_PGP_DIR="$(JERBOA_PGP_DIR)" \
-	JERBOA_FUSE_DIR="$(JERBOA_FUSE_DIR)" \
-	JERBOA_SSL_DIR="$(JERBOA_SSL_DIR)" \
+	JERBOA_CRYPTO_DIR="$(JERBOA_CRYPTO_DIR)" \
 		bash support/package-bundle.sh "$(BINARY_OUTPUT)" "$(BUNDLE_OUTPUT)"
 
 install: bundle
@@ -331,48 +202,7 @@ install: bundle
 	ln -sfn "$(INSTALL_OPTDIR)/jdrive" "$(INSTALL_BINDIR)/jdrive"
 	@echo "Installed jdrive -> $(INSTALL_BINDIR)/jdrive"
 
-linux: linux-amd64
-
-linux-amd64:
-	@command -v $(LINUX_AMD64_CC) >/dev/null 2>&1 || { echo "ERROR: $(LINUX_AMD64_CC) not found on PATH."; exit 1; }
-	@test -d "$(JERBOA_HOME)/.chez-cross-ta6le" || { echo "ERROR: cross Chez prefix missing: $(JERBOA_HOME)/.chez-cross-ta6le"; exit 1; }
-	@test -f "$(JERBOA_HOME)/build/chez/xc-ta6le/s/xpatch" || { echo "ERROR: xpatch missing: $(JERBOA_HOME)/build/chez/xc-ta6le/s/xpatch"; exit 1; }
-	$(RUN_ENV) BINARY_LIBDIRS='$(XC_LIBDIRS)' \
-	JERBOA_CHEZ_PREFIX=$(JERBOA_HOME)/.chez \
-	JERBOA_CROSS_PREFIX=$(JERBOA_HOME)/.chez-cross-ta6le \
-	JERBOA_XPATCH=$(JERBOA_HOME)/build/chez/xc-ta6le/s/xpatch \
-	TARGET_MACHINE=ta6le CC=$(LINUX_AMD64_CC) \
-		bash $(JERBOA_HOME)/support/build-binary.sh support/binary-entry.ss protonstorage-linux-amd64
-
-linux-arm64:
-	@command -v $(LINUX_ARM64_CC) >/dev/null 2>&1 || { echo "ERROR: $(LINUX_ARM64_CC) not found on PATH."; exit 1; }
-	@test -d "$(JERBOA_HOME)/.chez-cross-tarm64le" || { echo "ERROR: cross Chez prefix missing: $(JERBOA_HOME)/.chez-cross-tarm64le"; exit 1; }
-	@test -f "$(JERBOA_HOME)/build/chez/xc-tarm64le/s/xpatch" || { echo "ERROR: xpatch missing: $(JERBOA_HOME)/build/chez/xc-tarm64le/s/xpatch"; exit 1; }
-	$(RUN_ENV) BINARY_LIBDIRS='$(XC_LIBDIRS)' \
-	JERBOA_CHEZ_PREFIX=$(JERBOA_HOME)/.chez \
-	JERBOA_CROSS_PREFIX=$(JERBOA_HOME)/.chez-cross-tarm64le \
-	JERBOA_XPATCH=$(JERBOA_HOME)/build/chez/xc-tarm64le/s/xpatch \
-	TARGET_MACHINE=tarm64le CC=$(LINUX_ARM64_CC) \
-		bash $(JERBOA_HOME)/support/build-binary.sh support/binary-entry.ss protonstorage-linux-arm64
-
-freebsd: freebsd-amd64
-
-freebsd-amd64:
-	@command -v $(firstword $(FREEBSD_AMD64_CC)) >/dev/null 2>&1 || { echo "ERROR: $(FREEBSD_AMD64_CC) not found or not executable."; exit 1; }
-	@test -d "$(JERBOA_HOME)/.chez-cross-ta6fb" || { echo "ERROR: cross Chez prefix missing: $(JERBOA_HOME)/.chez-cross-ta6fb"; exit 1; }
-	@test -f "$(JERBOA_HOME)/build/chez/xc-ta6fb/s/xpatch" || { echo "ERROR: xpatch missing: $(JERBOA_HOME)/build/chez/xc-ta6fb/s/xpatch"; exit 1; }
-	$(RUN_ENV) BINARY_LIBDIRS='$(XC_LIBDIRS)' \
-	JERBOA_CHEZ_PREFIX=$(JERBOA_HOME)/.chez \
-	JERBOA_CROSS_PREFIX=$(JERBOA_HOME)/.chez-cross-ta6fb \
-	JERBOA_XPATCH=$(JERBOA_HOME)/build/chez/xc-ta6fb/s/xpatch \
-	TARGET_MACHINE=ta6fb CC='$(FREEBSD_AMD64_CC)' \
-		bash $(JERBOA_HOME)/support/build-binary.sh support/binary-entry.ss protonstorage-freebsd-amd64
-
 clean:
-	rm -rf cache tmp mount dist build/release-inputs protonstorage-bin protonstorage-linux-amd64 protonstorage-linux-arm64 protonstorage-freebsd-amd64
-	rm -f lib/libjerboa_native$(SO_EXT)
-	rm -f protonstorage-bin-main.c protonstorage-bin.wp.so
-	rm -f protonstorage-linux-amd64-main.c protonstorage-linux-amd64.wp.so
-	rm -f protonstorage-linux-arm64-main.c protonstorage-linux-arm64.wp.so
-	rm -f protonstorage-freebsd-amd64-main.c protonstorage-freebsd-amd64.wp.so
+	rm -rf cache tmp mount dist build/release-inputs jdrive-bin
+	rm -f jdrive-bin-main.c jdrive-bin.wp.so
 	rm -f petite_boot.h scheme_boot.h program_boot.h
diff --git a/README.md b/README.md
index acd131c..a499a61 100644
--- a/README.md
+++ b/README.md
@@ -1,377 +1,114 @@
 # jerboa-drive
 
-Jerboa-native encrypted remote drive and storage access.
+`jdrive` is a Jerboa-native, client-side encrypted drive backed by an
+S3-compatible object store. The remote service sees opaque encrypted objects;
+profile configuration and wrapped key material stay under `~/.jdrive` by
+default.
 
-This project is intended to become a single deployable Jerboa application for
-remote storage, with YubiKey-gated access and no rclone or Go helper in the
-runtime path. The Proton Drive backend is currently experimental; the primary
-backend is S3-compatible storage with client-side encryption.
+The project currently supports one storage backend: S3.
 
-## User Documentation
+## Quick start
 
-Start with [docs/user-guide.md](docs/user-guide.md) for installation, local
-state layout, authentication, encrypted credential vault setup, listing remote
-files, reading and writing Drive content, FUSE mounts, configuration variables,
-and troubleshooting. See [docs/security-model.md](docs/security-model.md) for
-credential, local state, FUSE, native-code, and release-gate expectations.
-
-Short installed-binary form:
-
-```sh
-jdrive login --username you@example.com
-jdrive ls --username you@example.com
-jdrive creds store --profile default --username you@example.com
-jdrive tree --profile default --max-depth 3
-```
-
-The `protonstorage` command and historical `drive ...` prefix still work, but
-neither is required. If Proton requires TOTP and you did not pass
-`--totp-code`, `jdrive` prompts for the current code.
-
-After `jdrive creds store`, commands such as `jdrive ls`, `jdrive volumes`, and
-`jdrive mount` use the selected profile's encrypted credentials automatically
-when you do not pass `--username` or token options.
-
-## Encrypted S3 Backend
-
-The S3 backend stores local profile state under `~/.jdrive`, not XDG. It uses
-AWS-compatible credentials from the normal AWS environment/profile files, wraps
-a random drive key in a local `scrypt` + `chacha20-poly1305` vault, encrypts
-the remote manifest, and stores file contents under opaque S3 object keys.
-
-Bootstrap a profile:
-
-```sh
-jdrive s3 init --bucket BUCKET --prefix jdrive --region us-east-1
-jdrive s3 profile-status
-jdrive s3 unlock-test
-```
-
-For S3-compatible providers, add an HTTPS `--endpoint URL --path-style` when
-needed. Plaintext S3 endpoints are rejected.
-Use `--aws-profile NAME` to select an AWS profile.
-
-Add optional built-in YubiKey PIV unlock material:
-
-```sh
-jdrive s3 init --bucket BUCKET --yubikey-mode piv
-```
-
-Daily operations:
-
-```sh
-jdrive s3 mkdir /backups
-jdrive s3 cp ./notes.txt /backups/notes.txt
-jdrive s3 cp -r ./backup-dir /backups
-jdrive s3 cp /backups/notes.txt ./notes-restored.txt
-jdrive s3 cp -r /backups ./restored-backups
-jdrive s3 cp -r /backups /archive
-jdrive s3 mv /archive/backups/notes.txt /archive/notes.txt
-jdrive s3 sync ./backup-dir /backups --delete
-jdrive s3 check ./backup-dir /backups
-jdrive s3 ls /backups
-jdrive s3 cat /backups/notes.txt
-jdrive s3 cat /backups/notes.txt --offset 0 --size 4096
-jdrive s3 get /backups/notes.txt ./notes-restored.txt
-jdrive s3 rm -r /backups/backup-dir
-```
-
-Set `JDRIVE_VAULT_PASSWORD` or pass `--vault-password-env ENV_NAME` for
-automation. Set `JDRIVE_PIV_PIN` or pass `--piv-pin-env ENV_NAME` when the
-profile was initialized with `--yubikey-mode piv`.
-
-Files are stored as independently encrypted chunks by default. Override the
-64 MiB default with `--chunk-size N` for testing or provider tuning. Encrypted
-chunk objects larger than 16 MiB use S3 multipart upload internally, so the
-bucket provider still only sees encrypted object parts. Manifest commits use
-S3 conditional writes against the manifest ETag; concurrent writers fail with a
-retryable conflict instead of silently overwriting each other.
-
-`sync` and `cp` treat paths beginning with `/` as encrypted remote paths unless
-the source is an existing local absolute path. That supports local-to-remote,
-remote-to-local, and remote-to-remote encrypted copies. `check` and `sync`
-support simple `*` wildcards through repeated `--include PATTERN` and
-`--exclude PATTERN`.
-
-Decrypted remote names are validated again when a manifest is loaded. File
-output — single-file `get` and recursive downloads alike — uses a retained
-destination-directory descriptor, no-follow component walks, and atomic file
-publication, so traversal components and concurrent symlink replacement cannot
-redirect output outside the selected local root.
-
-## Runtime Status
-
-Current runtime code is Scheme/Jerboa only:
-
-- [main.ss](main.ss) - script entry point.
-- [protonstorage/cli.ss](protonstorage/cli.ss) - command dispatch.
-- [protonstorage/drive/api.ss](protonstorage/drive/api.ss) - direct Proton
-  Drive HTTPS API calls through Jerboa HTTPS/JSON, including block upload
-  reservation and multipart encrypted-block upload.
-- [protonstorage/drive/auth.ss](protonstorage/drive/auth.ss) - native SRP,
-  FIDO2/YubiKey, and TOTP auth flow.
-- [protonstorage/drive/discovery.ss](protonstorage/drive/discovery.ss) -
-  active volume/share/root resolution.
-- [protonstorage/drive/crypto.ss](protonstorage/drive/crypto.ss) - Drive
-  name hashing, key/passphrase decrypt wrappers, disabled raw
-  content-session-key and block decrypt calls, disabled OpenPGP write helpers,
-  and encrypted-block SHA-256 verification. The disabled OpenPGP/Drive crypto
-  paths fail closed until the Proton backend is RustSec-clean.
-- [protonstorage/drive/client.ss](protonstorage/drive/client.ss) - end-to-end
-  root unlock, decrypted traversal, file read pipeline, folder-path resolution,
-  folder creation, file upload, and revision replacement.
-- [protonstorage/drive/fs.ss](protonstorage/drive/fs.ss) - recursive FUSE
-  metadata mapping with reader, mkdir, buffered create/write, unlink/rmdir,
-  and rename/move callbacks through `jerboa-fuse`.
-- [protonstorage/drive/local.ss](protonstorage/drive/local.ss) - local
-  CLI/FUSE profile paths, cache/staging directory setup, and foreground daemon
-  marker status.
-- [protonstorage/drive/write.ss](protonstorage/drive/write.ss) - create-folder
-  and create-file request payload assembly from unlocked keys and generated
-  Drive crypto, encrypted block upload plans, encrypted xattrs, manifest
-  signatures, and revision commit payloads. The live crypto assembly paths
-  currently fail closed while Proton OpenPGP/Drive crypto is disabled.
-- [protonstorage/s3/config.ss](protonstorage/s3/config.ss) - S3-compatible
-  endpoint, credential, region, path-style, and object-key helpers.
-- [protonstorage/s3/drive.ss](protonstorage/s3/drive.ss) - encrypted S3 drive
-  profile/vault, encrypted manifest, encrypted object upload/download/list,
-  chunked encrypted storage, ranged reads, sync/check helpers, checksum
-  verification, retry wrappers, and optional YubiKey PIV unlock material
-  through `jerboa-yubikey`.
-
-The cloned Go/rclone/Proton client projects under `~/mine` are references only.
-They are used to map endpoint shapes and crypto behavior while porting.
-
-## Implemented API Surface
-
-The Jerboa module `(protonstorage drive api)` currently covers:
-
-- `/core/v4/users`
-- `/core/v4/keys/salts`
-- `/core/v4/addresses`
-- `/core/v4/addresses/{addressID}`
-- `/drive/volumes`
-- `/drive/shares`
-- `/drive/shares/{shareID}`
-- `/drive/shares/{shareID}/links/{linkID}`
-- `/drive/shares/{shareID}/folders/{linkID}/children`
-- `/drive/shares/{shareID}/links/{linkID}/checkAvailableHashes`
-- `/drive/shares/{shareID}/links/{linkID}/move`
-- `/drive/shares/{shareID}/folders`
-- `/drive/shares/{shareID}/files`
-- `/drive/shares/{shareID}/files/{linkID}/revisions`
-- `/drive/shares/{shareID}/files/{linkID}/revisions/{revisionID}`
-- `/drive/shares/{shareID}/folders/{linkID}/trash_multiple`
-- `/drive/shares/{shareID}/folders/{linkID}/delete_multiple`
-- `/drive/shares/{shareID}/trash`
-- `/drive/blocks`
-
-Inspect the native surface:
+Build the dependencies pinned in `dependency-lock.tsv`, then inspect the CLI:
 
 ```sh
-make run ARGS='drive status'
+make deps
+make run ARGS='help'
 ```
 
-Authenticated calls use Proton session material from the environment:
+Create a profile using the normal AWS credential chain:
 
 ```sh
-export PROTONDRIVE_UID='...'
-export PROTONDRIVE_ACCESS_TOKEN='...'
-```
-
-Examples:
+export AWS_PROFILE=personal
+export AWS_REGION=us-east-1
 
-```sh
-make run ARGS='drive user'
-make run ARGS='drive volumes'
-make run ARGS='drive shares'
-make run ARGS='drive link --share SHARE_ID --link LINK_ID'
-make run ARGS='drive children --share SHARE_ID --link LINK_ID'
+make run ARGS='s3 init --profile default --bucket my-private-bucket'
+make run ARGS='s3 profile-status --profile default'
 ```
 
-Fresh native login uses SRP and FIDO2/YubiKey when Proton requests it:
-
-```sh
-export PROTONDRIVE_PASSWORD='...'
-make run ARGS='drive login --username you@example.com'
-make run ARGS='drive root-children-decrypted --username you@example.com'
-make run ARGS='drive tree-decrypted --username you@example.com --max-depth 3'
-```
+The initializer prompts for a vault password unless
+`--vault-password-env NAME` names an environment variable containing it. Use a
+unique, high-entropy password and do not store it in the repository.
 
-For local CLI use, Proton login credentials can be stored in the selected
-profile as an encrypted vault protected by a separate vault password. The vault
-uses `scrypt` and `chacha20-poly1305`; the vault password is still required to
-unlock stored credentials. After the first successful full login, the encrypted
-vault also stores Proton's reusable session tokens and key pass so later
-commands can refresh the session without TOTP. Profiles live under
-`~/.jproton/profiles/<profile>/` by default.
+Upload, inspect, and restore data:
 
 ```sh
-make run ARGS='drive credentials store --profile default'
-make run ARGS='drive credentials status --profile default'
-make run ARGS='drive credentials unlock-test --profile default'
-make run ARGS='drive root-children-decrypted --profile default'
+make run ARGS='s3 cp notes.txt jdrive:/notes.txt'
+make run ARGS='s3 ls jdrive:/'
+make run ARGS='s3 cat jdrive:/notes.txt'
+make run ARGS='s3 get jdrive:/notes.txt restored-notes.txt'
+make run ARGS='s3 sync ./photos jdrive:/photos --delete'
 ```
 
-For automation, set `PROTONSTORAGE_VAULT_PASSWORD` or pass
-`--vault-password-env ENV_NAME` instead of typing the vault password.
+Run `jdrive help` for all commands and options. See
+[the user guide](docs/user-guide.md) for profile, sync, range-read, YubiKey,
+and packaging details.
 
-The default FUSE command mounts a decrypted, read-only Drive tree:
+## Configuration
 
-```sh
-mkdir -p /tmp/proton-root
-make run ARGS='drive mount-root --username you@example.com --mountpoint /tmp/proton-root'
-```
+The main environment variables are:
 
-The writable mount buffers created file data in memory and commits it through
-the native encrypted upload/revision pipeline when the file handle is flushed or
-released. It also supports folder creation, unlink/rmdir through Proton trash,
-and rename/move through the Proton move endpoint:
+- `AWS_PROFILE`, `AWS_REGION`, `AWS_DEFAULT_REGION`, and the standard AWS
+  credential variables used by `jerboa-aws`.
+- `JDRIVE_S3_BUCKET`, `JDRIVE_S3_PREFIX`, `JDRIVE_S3_ENDPOINT`, and
+  `JDRIVE_S3_PATH_STYLE` for the object-store target.
+- `JDRIVE_PROFILE` and `JDRIVE_STATE_DIR` for local profile selection.
 
-```sh
-mkdir -p /tmp/proton-rw
-make run ARGS='drive mount-root-write --username you@example.com --mountpoint /tmp/proton-rw'
-```
+Endpoint overrides make MinIO and other S3-compatible services usable. Path
+style can be enabled with `--path-style` or `JDRIVE_S3_PATH_STYLE=1`.
 
-The product-level FUSE CLI surface also has a profile-aware mount command and
-local state inspection commands. `drive daemon start` currently runs the same
-FUSE daemon in the foreground so it can be supervised by a service manager; a
-background control socket is not implemented yet (see
-[Planned / Not Yet Implemented](#planned--not-yet-implemented)).
+## Storage and encryption
 
-```sh
-make run ARGS='drive cache init --profile default'
-make run ARGS='drive cache status --profile default'
-make run ARGS='drive daemon status --profile default'
-make run ARGS='drive mount --username you@example.com --mountpoint /tmp/proton-root'
-make run ARGS='drive mount --username you@example.com --mountpoint /tmp/proton-rw --writable'
-make run ARGS='drive daemon start --username you@example.com --mountpoint /tmp/proton-rw --writable --foreground'
-```
+Each profile has a local configuration document and encrypted key vault. Drive
+manifests, file records, and chunk records are authenticated and encrypted
+before upload. Large files use independently authenticated chunks, enabling
+bounded-memory transfer and range reads. Manifest generations are recorded
+locally so rollback or tampering is rejected.
 
-File reads use the same recursive pipeline and write plaintext bytes to stdout:
+The implementation uses `jerboa-crypto` for OpenSSL-backed primitives,
+`jerboa-aws` for SigV4/S3 requests, and `jerboa-yubikey` for optional PIV-backed
+unlock material. The detailed trust boundaries are in
+[the security model](docs/security-model.md).
 
-```sh
-make run ARGS='drive read-file --username you@example.com --link FILE_LINK_ID --offset 0 --size 4096'
-```
-
-The current read path resolves the root, unlocks the file node key, decrypts
-and verifies Proton Drive `ContentKeyPacket` values, selects the active
-revision, downloads storage blocks, verifies each encrypted block hash, and
-decrypts block packets with the content session key.
-
-The write-side surface can now generate locked Drive node keys, encrypt signed
-link names, encrypt/sign node passphrases, reserve upload blocks, and submit
-encrypted block payloads using Proton's `Block` multipart field. It can also
-generate `ContentKeyPacket` values and encrypt content blocks with the generated
-session key, assemble create-folder/create-file payloads, build encrypted block
-metadata with encrypted detached signatures, encrypt revision xattrs, sign
-revision manifests, upload blocks, and commit file revisions under decrypted
-folder paths.
-
-Write commands require a fresh native login because Drive key unlock needs
-mailbox key material:
+## Development
 
 ```sh
-make run ARGS='drive create-folder --username you@example.com --parent-path / --name docs'
-make run ARGS='drive upload-file --username you@example.com --parent-path /docs --path ./notes.txt --mime-type text/plain'
-make run ARGS='drive rename-child --username you@example.com --parent-path /docs --name notes.txt --new-name notes-renamed.txt'
-make run ARGS='drive move-child --username you@example.com --parent-path /docs --name notes-renamed.txt --new-parent-path /archive'
-make run ARGS='drive trash-child --username you@example.com --parent-path /archive --name notes-renamed.txt'
+make test
+make security
+make binary
+make bundle
 ```
 
-`drive create-root-folder` and `drive upload-root-file` remain as root-folder
-aliases. If a file already has an unfinished draft revision, uploads stop by
-default. Pass `--replace-existing-draft` to delete that draft revision and
-create a new one for an active file. Cross-folder move and FUSE rename
-re-encrypt the moved node passphrase for the destination parent key.
-
-## Reference Clones
-
-Relevant reference projects cloned under `~/mine`:
+On macOS and other non-Linux platforms, `make binary` is the canonical
+pre-commit build. Linux release CI uses the repository's static pipeline.
+`make bundle` produces `dist/jerboa-drive-<os>-<arch>.tar.gz`; run the packaged
+`jdrive` launcher rather than the internal binary directly.
 
-- `/Users/user/mine/rclone`
-- `/Users/user/mine/Proton-API-Bridge`
-- `/Users/user/mine/rclone-go-proton-api`
-- `/Users/user/mine/go-proton-api`
-- `/Users/user/mine/gopenpgp`
-- `/Users/user/mine/go-crypto`
-- `/Users/user/mine/go-srp`
-- `/Users/user/mine/proton-drive-upstream`
-- `/Users/user/mine/proton-ios-drive`
-- `/Users/user/mine/proton-android-drive`
-- `/Users/user/mine/proton-webclients`
-- `/Users/user/mine/jerboa-proton-bridge`
-- `/Users/user/mine/jerboa-yubikey`
-- `/Users/user/mine/jerboa-crypto`
-- `/Users/user/mine/jerboa-fuse`
-
-## Build and Test
+The local integration test is opt-in because it creates and removes objects in
+a real bucket:
 
 ```sh
-make
-make binary
-make linux-amd64
-make linux-arm64
-make freebsd-amd64
-make test
-make integration
 make s3-integration
-make doctor
-make bundle
-make release-evidence
 ```
 
-`make integration` skips unless `PROTONDRIVE_INTEGRATION=1` is set. When
-enabled, it uses `PROTONDRIVE_USERNAME` and `PROTONDRIVE_PASSWORD`, creates a
-disposable folder under `PROTONDRIVE_TEST_PARENT_PATH` or `/`, uploads one small
-file, moves it between two disposable folders, and trashes the disposable root
-during cleanup.
-
-`make s3-integration` skips unless `JDRIVE_S3_INTEGRATION=1` is set. When
-enabled, it requires `JDRIVE_S3_TEST_BUCKET`, uses standard AWS credentials or
-`JDRIVE_S3_TEST_AWS_PROFILE`, writes under `JDRIVE_S3_TEST_PREFIX` or a
-disposable prefix, syncs two encrypted chunked files, checks them, reads a
-range, restores a file, and removes remote test entries. Set
-`JDRIVE_S3_TEST_MULTIPART=1` to also upload a large encrypted object through
-provider multipart upload.
-
-`make bundle` builds the host binary and writes
-`dist/protonstorage-<os>-<arch>.tar.gz` with the binary, native Jerboa
-libraries, and a native launcher. The release binary records only
-bundle-relative native-library paths. The launcher validates the bundle's
-ownership and modes and removes inherited loader and development-native
-selectors before starting it; development `make run` keeps its explicit local
-library workflow.
-
-Release dependency and provenance evidence is documented in
-[`docs/dependency-provenance.md`](docs/dependency-provenance.md) and
-[`docs/release-evidence.md`](docs/release-evidence.md). `make release-evidence`
-writes the local evidence bundle under `dist/release-evidence/` and fails
-closed while upstream dependency gates remain blocked.
+Use only a disposable test prefix and review the test's required environment
+before enabling it.
 
-## Planned / Not Yet Implemented
+## Repository layout
 
-The following are **not** implemented yet. They are listed here so the README
-does not overstate current capability:
+- `jdrive/cli.ss` — command parsing and dispatch.
+- `jdrive/s3/config.ss` — S3 target configuration.
+- `jdrive/s3/drive.ss` — profile vault, encrypted manifests, transfers, sync,
+  and object operations.
+- `test/test-all.ss` — local crypto, manifest, path, and vault tests.
+- `support/` — reproducible build, native bundle, and launcher hardening.
+- `scripts/` — security and release-evidence checks.
 
-- **Daemon control socket / background lifecycle.** `drive daemon start` runs
-  the FUSE daemon in the foreground only, so it can be supervised by a service
-  manager. There is no background daemon and no control socket.
-- **Durable operation queue.** Create/upload/rename/move/trash operations are
-  not journaled; there is no persistent queue that survives a crash or restart.
-- **Multi-writer merge.** Concurrent writers are handled fail-fast: manifest
-  commits use S3 conditional writes against the manifest ETag, so a conflicting
-  writer fails with a retryable error instead of being merged. There is no
-  merge/conflict-resolution policy beyond that.
-- **Indexed cache states.** On-demand cache-state tracking (online-only,
-  available, pinned, dirty, uploading) is not implemented. `drive cache init`
-  and `drive cache status` only create and report local cache/staging paths;
-  `metadata.db` and indexed cache state are planned persistence layers.
+Dependencies are fetched at locked commits into the ignored `.deps/`
+directory. Build files never depend on adjacent source checkouts.
 
-Other remaining work:
+## Release policy
 
-- Prove the encrypted S3 live integration against each target provider.
-- Add richer metadata update operations beyond size-changing writes and
-  rename/move.
-- Collapse the native dynamic library bundle further when Jerboa supports a
-  fully static bridge path.
+`VERSION` is authoritative. Every pull request must advance it and keep package
+metadata and user-visible output synchronized. Changes are merged only through
+a reviewed Forgejo pull request.
diff --git a/SECURITY.md b/SECURITY.md
index 7e5c800..7c5c47e 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -1,40 +1,27 @@
-# Security Policy
+# Security policy
 
-This repository is part of the Jerboa ecosystem. Treat it as experimental unless the README and release notes explicitly state a stronger support level.
+Please report vulnerabilities privately to the repository maintainers on
+`git.jerboa.sh`. Do not open a public issue containing credentials, exploit
+details, plaintext customer data, or bucket identifiers.
 
-Repository-specific credential, local state, FUSE, native-code, and release
-gate details are documented in [docs/security-model.md](docs/security-model.md).
+Repository-specific credential, local-state, native-code, object-storage, and
+release expectations are documented in
+[docs/security-model.md](docs/security-model.md).
 
-Production claims require the release gates tracked in `~/Release-plan.md` and `~/mine/jerboa-production-readiness.md` to be complete for this repository.
+Before submitting a security-sensitive change:
 
-## Supported Status
+```sh
+make security
+make test
+make binary
+make bundle
+```
 
-No public production-support commitment exists yet. Security-sensitive releases must be cut from a clean checkout after:
+Do not commit AWS credentials, vault passwords, PIV PINs, profile vaults,
+plaintext fixtures derived from real data, authorization headers, or raw
+account output. Release and target evidence must be processed by
+`scripts/sanitize-evidence.sh` before it is shared.
 
-- `git status --short` shows only intentional release changes.