Security hardening and release readiness

ober

7937f014e29bbc4aa3bbd16917b38721ba4d939f

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..f4242bb
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,75 @@
+name: CI
+
+on:
+  push:
+    branches: [main, master]
+  pull_request:
+  workflow_dispatch:
+
+permissions:
+  contents: read
+
+env:
+  JERBOA_VERSION: v0.2.3
+  JERBUILD: ${{ github.workspace }}/.jerboa/bin/jerbuild
+  JERBOA_AWS_REPO: https://git.sr.ht/~lisp/jerboa-aws
+  JERBOA_PROTON_BRIDGE_REPO: https://git.sr.ht/~lisp/jerboa-proton-bridge
+  JERBOA_YUBIKEY_REPO: https://git.sr.ht/~lisp/jerboa-yubikey
+  JERBOA_PGP_REPO: https://git.sr.ht/~lisp/jerboa-pgp
+  JERBOA_CRYPTO_REPO: https://git.sr.ht/~lisp/jerboa-crypto
+  JERBOA_FUSE_REPO: https://git.sr.ht/~lisp/jerboa-fuse
+  JERBOA_MAIL_REPO: https://git.sr.ht/~lisp/jerboa-mail
+  JERBOA_HTTPS_REPO: https://git.sr.ht/~lisp/jerboa-https
+  JERBOA_SSL_REPO: https://git.sr.ht/~lisp/jerboa-ssl
+  JERBOA_AWS_DIR: ${{ github.workspace }}/.deps/jerboa-aws
+  JERBOA_PROTON_BRIDGE_DIR: ${{ github.workspace }}/.deps/jerboa-proton-bridge
+  JERBOA_YUBIKEY_DIR: ${{ github.workspace }}/.deps/jerboa-yubikey
+  JERBOA_PGP_DIR: ${{ github.workspace }}/.deps/jerboa-pgp
+  JERBOA_CRYPTO_DIR: ${{ github.workspace }}/.deps/jerboa-crypto
+  JERBOA_FUSE_DIR: ${{ github.workspace }}/.deps/jerboa-fuse
+  JERBOA_MAIL_DIR: ${{ github.workspace }}/.deps/jerboa-mail
+  JERBOA_HTTPS_DIR: ${{ github.workspace }}/.deps/jerboa-https
+  JERBOA_SSL_DIR: ${{ github.workspace }}/.deps/jerboa-ssl
+
+jobs:
+  build-test-audit:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: Install system tools
+        run: |
+          set -eu
+          sudo apt-get update
+          sudo apt-get install -y --no-install-recommends build-essential git curl ca-certificates libssl-dev pkg-config
+          command -v cargo
+          cargo --version
+
+      - name: Install Jerboa toolchain
+        run: sh support/ensure-jerboa.sh "$JERBOA_VERSION" .jerboa/bin
+
+      - name: Fetch dependencies
+        run: |
+          set -eu
+          mkdir -p .deps
+          git clone --depth 1 "$JERBOA_AWS_REPO" "$JERBOA_AWS_DIR"
+          git clone --depth 1 "$JERBOA_PROTON_BRIDGE_REPO" "$JERBOA_PROTON_BRIDGE_DIR"
+          git clone --depth 1 "$JERBOA_YUBIKEY_REPO" "$JERBOA_YUBIKEY_DIR"
+          git clone --depth 1 "$JERBOA_PGP_REPO" "$JERBOA_PGP_DIR"
+          git clone --depth 1 "$JERBOA_CRYPTO_REPO" "$JERBOA_CRYPTO_DIR"
+          git clone --depth 1 "$JERBOA_FUSE_REPO" "$JERBOA_FUSE_DIR"
+          git clone --depth 1 "$JERBOA_MAIL_REPO" "$JERBOA_MAIL_DIR"
+          git clone --depth 1 "$JERBOA_HTTPS_REPO" "$JERBOA_HTTPS_DIR"
+          git clone --depth 1 "$JERBOA_SSL_REPO" "$JERBOA_SSL_DIR"
+
+      - name: Test
+        run: make test
+
+      - name: CLI doctor smoke
+        run: make run ARGS='doctor'
+
+      - name: Install cargo-audit
+        run: cargo install cargo-audit --locked
+
+      - name: Release evidence
+        run: make release-evidence
diff --git a/.github/workflows/security-baseline.yml b/.github/workflows/security-baseline.yml
new file mode 100644
index 0000000..28a713e
--- /dev/null
+++ b/.github/workflows/security-baseline.yml
@@ -0,0 +1,35 @@
+name: Security Baseline
+
+on:
+  push:
+    branches: [main, master]
+  pull_request:
+  workflow_dispatch:
+
+permissions:
+  contents: read
+
+jobs:
+  baseline:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: Required release files
+        run: |
+          set -eu
+          test -f LICENSE
+          test -f SECURITY.md
+          test -f .gitignore
+          find . -maxdepth 1 -iname "README*" -type f | grep -q .
+
+      - name: High-confidence secret scan
+        run: |
+          set -eu
+          pattern="(BEGIN (RSA|OPENSSH|EC|DSA|PRIVATE) KEY|ghp_[A-Za-z0-9_]{20,}|github_pat_[A-Za-z0-9_]{20,}|sk-(ant-api03|proj|svcacct)-[A-Za-z0-9_-]{30,}|AKIA[0-9A-Z]{16})"
+          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
diff --git a/.gitignore b/.gitignore
index d6f198f..e53a6b9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,10 @@
 *.so
 *.dylib
 *.o
+.deps/
+.jerboa/*
+!.jerboa/
+!.jerboa/security.json
 cache/
 tmp/
 mount/
diff --git a/.jerboa/security.json b/.jerboa/security.json
new file mode 100644
index 0000000..c492ce4
--- /dev/null
+++ b/.jerboa/security.json
@@ -0,0 +1,48 @@
+{
+  "version": 1,
+  "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"],
+    "tests": ["test/**", "tests/**", "**/*-test.ss", "fixtures/**"],
+    "generated": ["build/**", "dist/**", "target/**", "*.so", "*.dylib", "*.wpo", "*-main.c"],
+    "vendor": ["vendor/**", "third_party/**"],
+    "docs": ["README.md", "docs/**", "*.md"]
+  },
+  "policy": {
+    "failOn": ["critical", "high"],
+    "imports": { "directChezscheme": "allow-in-ffi-boundaries" },
+    "ffi": { "allowed": true, "requireDynamicWindCleanup": true },
+    "process": { "shellInterpolation": "deny" },
+    "network": { "requireTimeouts": true, "rawRemoteOutputEvidence": "deny" },
+    "eval": { "stringEval": "deny", "bareRead": "deny", "allowReadEval": false },
+    "crypto": { "forbidSecretLogging": true, "requireRustSecCleanBackends": true },
+    "credentials": {
+      "plaintextCache": "deny",
+      "rawCredentialEvidence": "deny",
+      "vaultPasswordStorage": "deny"
+    },
+    "storage": {
+      "remotePlaintextFilenames": "deny",
+      "remotePlaintextBodies": "deny",
+      "fuseMountEvidence": "target-required"
+    },
+    "targetEvidence": {
+      "storageProof": "fail-closed",
+      "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",
+        "target_platform_smoke_status=target-evidence-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"
+      ]
+    }
+  },
+  "suppressions": []
+}
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/Makefile b/Makefile
index 4f58562..a27980b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,23 +1,54 @@
-JERBOA_HOME ?= $(realpath $(CURDIR)/../jerboa)
-SCHEME      ?= $(JERBOA_HOME)/.chez/bin/scheme
-JERBOA_PROTON_BRIDGE_DIR ?= $(realpath $(CURDIR)/../jerboa-proton-bridge)
-JERBOA_HTTPS_DIR ?= $(realpath $(CURDIR)/../jerboa-https)
-JERBOA_SSL_DIR ?= $(realpath $(CURDIR)/../jerboa-ssl)
-JERBOA_YUBIKEY_DIR ?= $(realpath $(CURDIR)/../jerboa-yubikey)
-JERBOA_PGP_DIR ?= $(realpath $(CURDIR)/../jerboa-pgp)
-JERBOA_CRYPTO_DIR ?= $(realpath $(CURDIR)/../jerboa-crypto)
-JERBOA_FUSE_DIR ?= $(realpath $(CURDIR)/../jerboa-fuse)
-JERBOA_MAIL_DIR ?= $(realpath $(CURDIR)/../jerboa-mail)
-JERBOA_AWS_DIR ?= $(realpath $(CURDIR)/../jerboa-aws)
-LIBDIRS := $(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:$(JERBOA_HOME)/lib
-XC_LIBDIRS := $(LIBDIRS):$(JERBOA_HOME)/.chez-cross-ta6le/lib:$(JERBOA_HOME)/.chez-cross-tarm64le/lib:$(JERBOA_HOME)/.chez-cross-ta6fb/lib
-JERBOA_NATIVE_DIR ?= $(JERBOA_HOME)/jerboa-native-rs/target/release
-RUN_ENV := JERBOA_HOME=$(JERBOA_HOME) \
+JERBOA_VERSION ?= v0.2.3
+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)
+JERBOA_HOME ?= $(JH)
+
+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 = $(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
+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
+RUN_ENV := JERBOA_HOME=$(JH) \
 	JERBOA_SSL_LIB=$(JERBOA_SSL_DIR) \
 	JERBOA_CRYPTO_LIB=$(JERBOA_CRYPTO_DIR) \
-	DYLD_LIBRARY_PATH=$(JERBOA_NATIVE_DIR):$(JERBOA_CRYPTO_DIR):$(JERBOA_FUSE_DIR):$(JERBOA_PROTON_BRIDGE_DIR)/proton-bridge-native/target/release:$${DYLD_LIBRARY_PATH:-} \
+	JERBOA_FUSE_LIB=$(JERBOA_FUSE_DIR) \
+	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):$(JERBOA_PROTON_BRIDGE_DIR)/proton-bridge-native/target/release:$${LD_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
@@ -28,8 +59,11 @@ BUNDLE_OUTPUT ?= dist/jerboa-drive-$(HOST_OS)-$(HOST_ARCH)
 INSTALL_PREFIX ?= $(HOME)/.local
 INSTALL_BINDIR ?= $(INSTALL_PREFIX)/bin
 INSTALL_OPTDIR ?= $(INSTALL_PREFIX)/opt/jerboa-drive
+DIST_DIR ?= $(CURDIR)/dist
+RELEASE_EVIDENCE_DIR ?= $(DIST_DIR)/release-evidence
+TARGET_EVIDENCE_DIR ?= $(DIST_DIR)/target-evidence
 
-.PHONY: help run test integration s3-integration doctor binary bundle install linux linux-amd64 linux-arm64 freebsd freebsd-amd64 clean
+.PHONY: help ensure-jerboa-tools ensure-deps deps run test integration s3-integration doctor 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
 .DEFAULT_GOAL := help
 
 help:
@@ -39,6 +73,8 @@ help:
 	@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 clean                 Remove generated local artifacts"
@@ -53,8 +89,7 @@ help:
 	@echo "  make freebsd-amd64         Cross-build ./protonstorage-freebsd-amd64"
 	@echo ""
 	@echo "Environment:"
-	@echo "  JERBOA_HOME = $(JERBOA_HOME)"
-	@echo "  SCHEME      = $(SCHEME)"
+	@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)"
@@ -67,29 +102,154 @@ help:
 	@echo "  JERBOA_NATIVE_DIR = $(JERBOA_NATIVE_DIR)"
 	@echo "  INSTALL_PREFIX = $(INSTALL_PREFIX)"
 
-run:
+ensure-jerboa-tools:
+	@if "$(JERBUILD)" --jerboa-home >/dev/null 2>&1; then \
+	  echo "=== Using Jerboa toolchain: $(JERBUILD) ==="; \
+	elif [ -x "$(JERBOA_TOOL_DIR)/jerbuild" ] && "$(JERBOA_TOOL_DIR)/jerbuild" --jerboa-home >/dev/null 2>&1; then \
+	  echo "=== Using downloaded Jerboa toolchain: $(JERBOA_TOOL_DIR) ==="; \
+	elif command -v jerbuild >/dev/null 2>&1 && jerbuild --jerboa-home >/dev/null 2>&1; then \
+	  echo "=== Using Jerboa toolchain from PATH: $$(command -v jerbuild) ==="; \
+	else \
+	  echo "=== Fetching Jerboa $(JERBOA_VERSION) release tools into $(JERBOA_TOOL_DIR) ==="; \
+	  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; \
+	  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: ensure-jerboa-tools ensure-deps
+	@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
+
+run: deps
 	$(RUN_ENV) \
-		$(SCHEME) -q --libdirs $(LIBDIRS) --script main.ss -- $(ARGS)
+		"$(JERBUILD)" exec --libdirs "$(LIBDIRS)" main.ss -- $(ARGS)
 
 doctor:
 	$(MAKE) run ARGS='doctor'
 
-test:
+test: deps
 	$(RUN_ENV) \
-		$(SCHEME) -q --libdirs $(LIBDIRS) --script test/test-all.ss
+		"$(JERBUILD)" exec --libdirs "$(LIBDIRS)" test/test-all.ss
 
-integration:
+integration: deps
 	$(RUN_ENV) \
-		$(SCHEME) -q --libdirs $(LIBDIRS) --script test/integration-drive.ss
+		"$(JERBUILD)" exec --libdirs "$(LIBDIRS)" test/integration-drive.ss
 
-s3-integration:
+s3-integration: deps
 	$(RUN_ENV) \
-		$(SCHEME) -q --libdirs $(LIBDIRS) --script test/integration-s3.ss
+		"$(JERBUILD)" exec --libdirs "$(LIBDIRS)" test/integration-s3.ss
 
-binary:
-	$(RUN_ENV) BINARY_LIBDIRS='$(LIBDIRS)' \
-	JERBOA_CHEZ_PREFIX=$(JERBOA_HOME)/.chez \
-		bash $(JERBOA_HOME)/support/build-binary.sh support/binary-entry.ss $(BINARY_OUTPUT)
+binary: deps
+	$(RUN_ENV) "$(JERBUILD)" binary --libdirs "$(LIBDIRS)" support/binary-entry.ss $(BINARY_OUTPUT)
+
+binary-doctor-smoke: binary
+	$(RUN_ENV) ./$(BINARY_OUTPUT) doctor
+
+audit: deps
+	$(MAKE) -C "$(JERBOA_PROTON_BRIDGE_DIR)" JERBUILD="$(JERBUILD)" audit
+
+verify: security test doctor audit
+
+security:
+	@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})"; \
+	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; \
+	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#*:}; \
+	  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 \
+	      $(MAKE) -C "$$dir" JERBUILD="$(JERBUILD)" release-evidence || status=1; \
+	  else \
+	    echo "$$label release-evidence target missing"; \
+	    status=1; \
+	  fi; \
+	done; \
+	exit "$$status"
+
+sbom: deps
+	@REPO_ROOT="$(CURDIR)" \
+	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_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
+	@REPO_ROOT="$(CURDIR)" \
+	DIST_DIR="$(DIST_DIR)" \
+	JERBUILD="$(JERBUILD)" \
+	MAKE="$(MAKE)" \
+	BINARY_OUTPUT="$(BINARY_OUTPUT)" \
+	sh scripts/reproducibility-report.sh
+
+target-evidence:
+	@REPO_ROOT="$(CURDIR)" \
+	DIST_DIR="$(DIST_DIR)" \
+	TARGET_EVIDENCE_DIR="$(TARGET_EVIDENCE_DIR)" \
+	sh scripts/target-evidence.sh
+
+release-evidence:
+	@REPO_ROOT="$(CURDIR)" \
+	DIST_DIR="$(DIST_DIR)" \
+	RELEASE_EVIDENCE_DIR="$(RELEASE_EVIDENCE_DIR)" \
+	TARGET_EVIDENCE_DIR="$(TARGET_EVIDENCE_DIR)" \
+	JERBUILD="$(JERBUILD)" \
+	sh scripts/release-evidence.sh
 
 bundle: binary
 	JERBOA_PROTON_BRIDGE_DIR="$(JERBOA_PROTON_BRIDGE_DIR)" \
diff --git a/README.md b/README.md
index bbe7a16..14d912a 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,8 @@ backend is S3-compatible storage with client-side encryption.
 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.
+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:
 
@@ -105,11 +106,10 @@ Current runtime code is Scheme/Jerboa only:
 - [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, raw content-session-key and
-  block decrypt calls, content-key signature verification, and encrypted-block
-  SHA-256 verification, plus OpenPGP node-key generation, signed link-name
-  encryption, node-passphrase encrypt/sign helpers, content-key packet
-  generation, and content block encryption.
+  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.
@@ -122,7 +122,8 @@ Current runtime code is Scheme/Jerboa only:
 - [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.
+  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
@@ -309,6 +310,7 @@ make integration
 make s3-integration
 make doctor
 make bundle
+make release-evidence
 ```
 
 `make integration` skips unless `PROTONDRIVE_INTEGRATION=1` is set. When
@@ -329,6 +331,12 @@ provider multipart upload.
 `dist/protonstorage-<os>-<arch>.tar.gz` with the binary, native Jerboa
 libraries, and a wrapper that sets the runtime library search path.
 
+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.
+
 ## Remaining Work
 
 - Prove the encrypted S3 live integration against each target provider.
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..afab891
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,38 @@
+# 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.
+
+Repository-specific credential, local state, FUSE, native-code, and release
+gate details 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.
+
+## Supported Status
+
+No public production-support commitment exists yet. Security-sensitive releases must be cut from a clean checkout after:
+
+- `git status --short` shows only intentional release changes.
+- A secret scan is clean for the working tree, and history has been reviewed or intentionally reset before first public release.
+- The documented build and test commands pass.
+- `make run ARGS='doctor'` passes.
+- Dependency and native-code audits are clean, or accepted risks are documented.
+- `make release-evidence` writes current test, audit, dependency, SBOM, and
+  reproducibility evidence.
+- Target Drive/S3/FUSE release proof must be marker-validated. Raw Proton or
+  S3 account output, tokens, credentials, vault passwords, PIV PINs, plaintext
+  file bodies, and plaintext remote object manifests must not be preserved in
+  evidence.
+- Any FFI, filesystem, network, shell, or credential-handling behavior is documented.
+
+## Security Expectations
+
+- Do not commit secrets, private keys, tokens, production `.env` files, operational hostnames, customer/user data, or private infrastructure details.
+- Do not implement cryptography directly. Use audited libraries or delegated components.
+- Prefer Rust for byte-level parsing, FFI boundaries, crypto-adjacent integration, and sandbox setup.
+- Prefer Jerboa for policy, orchestration, configuration, routing, tests, and high-level behavior.
+- Document file I/O, shell execution, network access, FFI ownership/lifetime rules, and credential storage before publication.
+- Daemons and hostile-input parsers require threat models, fuzz harnesses, regression corpora, resource limits, sandboxing documentation, and review before public production use.
+
+## Reporting
+
+Before public release, report issues privately to the repository owner. After public release, replace this section with a dedicated advisory contact, supported versions, and disclosure window.
diff --git a/bin/protonstorage b/bin/protonstorage
index d9445d0..4274bb6 100755
--- a/bin/protonstorage
+++ b/bin/protonstorage
@@ -2,8 +2,22 @@
 set -euo pipefail
 
 DIR="$(cd "$(dirname "$0")/.." && pwd)"
-JERBOA_HOME="${JERBOA_HOME:-"$DIR/../jerboa"}"
-SCHEME="${SCHEME:-"$JERBOA_HOME/.chez/bin/scheme"}"
+if [ -z "${JERBUILD:-}" ]; then
+  if [ -x "$DIR/.jerboa/bin/jerbuild" ]; then
+    JERBUILD="$DIR/.jerboa/bin/jerbuild"
+  elif [ -x "$DIR/../jerboa/dist/jerbuild" ]; then
+    JERBUILD="$DIR/../jerboa/dist/jerbuild"
+  elif [ -x "$DIR/../jerboa/jerbuild" ]; then
+    JERBUILD="$DIR/../jerboa/jerbuild"
+  else
+    JERBUILD="$(command -v jerbuild || true)"
+  fi
+fi
+if [ -z "$JERBUILD" ] || [ ! -x "$JERBUILD" ]; then
+  echo "ERROR: jerbuild not found; set JERBUILD=/path/to/jerbuild or run make deps" >&2
+  exit 1
+fi
+JERBOA_HOME="${JERBOA_HOME:-"$("$JERBUILD" --jerboa-home)"}"
 JERBOA_PROTON_BRIDGE_DIR="${JERBOA_PROTON_BRIDGE_DIR:-"$DIR/../jerboa-proton-bridge"}"
 JERBOA_YUBIKEY_DIR="${JERBOA_YUBIKEY_DIR:-"$DIR/../jerboa-yubikey"}"
 JERBOA_PGP_DIR="${JERBOA_PGP_DIR:-"$DIR/../jerboa-pgp"}"
@@ -18,11 +32,12 @@ JERBOA_NATIVE_DIR="${JERBOA_NATIVE_DIR:-"$JERBOA_HOME/jerboa-native-rs/target/re
 export JERBOA_HOME
 export JERBOA_SSL_LIB="$JERBOA_SSL_DIR"
 export JERBOA_CRYPTO_LIB="$JERBOA_CRYPTO_DIR"
+export JERBOA_FUSE_LIB="$JERBOA_FUSE_DIR"
 PROTON_BRIDGE_NATIVE_DIR="$JERBOA_PROTON_BRIDGE_DIR/proton-bridge-native/target/release"
 export DYLD_LIBRARY_PATH="$JERBOA_NATIVE_DIR:$JERBOA_CRYPTO_DIR:$JERBOA_FUSE_DIR:$PROTON_BRIDGE_NATIVE_DIR:${DYLD_LIBRARY_PATH:-}"
 export DYLD_FALLBACK_LIBRARY_PATH="$JERBOA_NATIVE_DIR:${DYLD_FALLBACK_LIBRARY_PATH:-}"
 export LD_LIBRARY_PATH="$JERBOA_NATIVE_DIR:$JERBOA_CRYPTO_DIR:$JERBOA_FUSE_DIR:$PROTON_BRIDGE_NATIVE_DIR:${LD_LIBRARY_PATH:-}"
 
-exec "$SCHEME" -q \
+exec "$JERBUILD" exec \
   --libdirs "$DIR:$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:$JERBOA_HOME/lib" \
-  --script "$DIR/main.ss" -- "$@"
+  "$DIR/main.ss" -- "$@"
diff --git a/docs/dependency-provenance.md b/docs/dependency-provenance.md
new file mode 100644
index 0000000..d52dbba
--- /dev/null
+++ b/docs/dependency-provenance.md
@@ -0,0 +1,28 @@
+# Dependency Provenance
+
+`jerboa-drive` is a credentialed storage client. Production evidence must cover
+the local source tree and the sibling Jerboa libraries it delegates to:
+
+- `jerboa-proton-bridge` for Proton SRP/FIDO2/OpenPGP/Drive crypto helper
+  symbols. Its strict build keeps SRP/OpenPGP/Drive crypto disabled until
+  RustSec-clean backends exist.
+- `jerboa-yubikey` for hardware-backed unlock/auth flows.
+- `jerboa-aws` for S3-compatible storage requests.
+- `jerboa-pgp`, `jerboa-crypto`, `jerboa-fuse`, `jerboa-mail`,
+  `jerboa-https`, and `jerboa-ssl` for crypto, filesystem, mail/HTTP, and TLS
+  support.
+
+`make dependency-evidence` runs sibling `release-evidence` targets when they
+exist and fails closed when any required sibling gate fails or is missing.
+Sibling evidence discovery parses Makefile target definitions instead of using
+dry-run make recipes, so stale copied evidence is not accepted when a sibling
+target is missing.
+Current known blockers are live Proton/S3/FUSE integration evidence and
+external credential/storage/FFI review. Sibling release evidence is expected
+for `jerboa-proton-bridge`, `jerboa-aws`, `jerboa-pgp`, `jerboa-crypto`,
+`jerboa-fuse`, `jerboa-mail`, `jerboa-https`, `jerboa-ssl`, and
+`jerboa-yubikey`.
+
+No public production release should enable Proton SRP/OpenPGP/Drive crypto
+until those backends are RustSec-clean or explicitly accepted with owner, date,
+scope, and mitigation.
diff --git a/docs/release-evidence.md b/docs/release-evidence.md
new file mode 100644
index 0000000..5c1a014
--- /dev/null
+++ b/docs/release-evidence.md
@@ -0,0 +1,84 @@
+# Release Evidence
+
+Drive release evidence is written under `dist/release-evidence/`:
+
+```sh
+make release-evidence
+```
+
+The gate records:
+
+- high-confidence tracked-file secret scan output,
+- local smoke test output,
+- `doctor` output through both `jerbuild exec` and the standalone binary,
+- delegated Proton Bridge native dependency audit output,
+- sibling dependency release-evidence output,
+- target Drive/S3/FUSE proof status,
+- SBOM/source/dependency hashes, and
+- post-warm two-build binary reproducibility output.
+
+The target is allowed to fail after writing evidence. A failed target means the
+repo is not production-releasable yet, but the evidence directory should explain
+which gate blocked publication.
+
+Current expected blockers are live Proton/S3/FUSE integration evidence and
+external credential/storage/FFI review. The former Proton Bridge and PGP
+RustSec blockers were removed from the production dependency graph by disabling
+strict-audit-blocked SRP/OpenPGP/Drive crypto paths. Release evidence should
+record those paths as fail-closed until RustSec-clean backends exist.
+
+## Reproducibility
+
+`make reproducibility-report` performs an unmeasured warmup build and a
+stabilization build before comparing two measured standalone binaries. The
+release gate requires the measured binary SHA-256 values and source manifest to
+match.
+
+The report also records generated compiler scratch input hashes from the fixed
+`JERBUILD_BINARY_OBJ_DIR`. Some bundled std `.so`/`.wpo` scratch files can drift
+while the final executable remains byte-identical, so
+`generated_input_status` is diagnostic and is recorded with
+`generated_input_policy=diagnostic-scratch-not-release-gate`.
+
+## Target Storage Proof
+
+`make target-evidence` always writes `dist/target-evidence/status.txt`.
+Without a proof file, local evidence records target-only gates as
+`blocked-not-run` and `target_storage_proof_status=not-run`.
+
+Release hosts may attach reviewed proof with:
+
+```sh
+JDRIVE_TARGET_STORAGE_PROOF_FILE=/path/to/proof.txt make target-evidence
+```
+
+Production/release review can require that proof:
+
+```sh
+JDRIVE_REQUIRE_TARGET_STORAGE_PROOF=1 \
+JDRIVE_TARGET_STORAGE_PROOF_FILE=/path/to/proof.txt \
+make release-evidence
+```
+
+The proof file must contain these exact marker lines and must not contain raw
+Proton/S3 account output, tokens, credentials, vault passwords, PIV PINs,
+plaintext file bodies, plaintext remote manifests, or plaintext object keys
+derived from local filenames:
+
+```text
+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
+target_platform_smoke_status=target-evidence-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
+```
+
+Missing, empty, or marker-incomplete proof files fail closed as
+`status=blocked-target-proof`. Accepted proof files are copied to
+`dist/target-evidence/target-storage-proof.txt` and hashed.
diff --git a/docs/security-model.md b/docs/security-model.md
new file mode 100644
index 0000000..8b0d516
--- /dev/null
+++ b/docs/security-model.md
@@ -0,0 +1,86 @@
+# jerboa-drive Security Model
+
+`jerboa-drive` is a Jerboa-native encrypted storage client with two security
+surfaces:
+
+- Proton Drive access through Proton API sessions, SRP/FIDO2 auth, OpenPGP key
+  material, and optional FUSE mounts. In the strict build, SRP/OpenPGP/Drive
+  crypto paths delegated to Proton Bridge are disabled until RustSec-clean
+  backends exist.
+- S3-compatible storage with local drive-key wrapping and remote encrypted
+  manifests/objects.
+
+## Trust Boundaries
+
+- Proton credentials, refresh tokens, key pass material, S3 drive keys, vault
+  passwords, and YubiKey PIV PINs are secrets.
+- `~/.jproton` and `~/.jdrive` are local state roots. They may contain
+  encrypted credential vaults, encrypted S3 drive-key vaults, daemon marker
+  files, cache directories, and staging directories.
+- Remote S3 object keys are opaque implementation details. Plaintext paths and
+  file contents must not be stored in S3 object keys or unencrypted object
+  bodies.
+- FUSE exposes decrypted filenames and file contents to local processes with
+  access to the mountpoint. Use OS permissions, mountpoint ownership, and an
+  encrypted local disk for multi-user or stolen-device threat models.
+
+## Credential Storage
+
+The Proton credential vault stores the Proton username/password and, after a
+successful login, reusable session material. The S3 profile vault stores a
+random drive key. Both vault formats use `scrypt` key derivation and
+`chacha20-poly1305` authenticated encryption.
+
+The vault password is not stored. Noninteractive use should pass vault
+passwords through an environment variable selected with `--vault-password-env`.
+Do not commit shell profiles, CI variables, logs, or command transcripts that
+contain vault passwords, Proton tokens, AWS credentials, or PIV PINs.
+
+## File System Safety
+
+Profile names are restricted to letters, digits, `.`, `-`, and `_`. Profile
+marker and vault writers only write known profile-owned files. S3 sync and cp
+refuse local symlinks to avoid following attacker-controlled paths during tree
+uploads.
+
+Current daemon state is foreground-supervised. `drive daemon stop` clears local
+marker files; unmounting a live FUSE mount is still delegated to the platform
+unmount command.
+
+## Native Code And FFI
+
+Drive content decrypt/encrypt helpers are delegated to the
+`jerboa-proton-bridge` Rust native library. The Scheme module loads native
+symbols lazily, so library import remains safe in verifier and documentation
+contexts. Current strict builds report SRP/OpenPGP/Drive crypto helpers as
+disabled and assert fail-closed behavior before live Proton credentials or
+plaintext payloads are processed.
+
+Release builds must audit the Proton bridge Rust dependency graph with
+`cargo-audit`, run the Jerboa scanner over changed Scheme/Rust code, and record
+dependency provenance for the sibling Jerboa libraries listed in
+[`dependency-provenance.md`](dependency-provenance.md).
+
+## Network And Remote State
+
+Network access is explicit through Proton Drive API calls and S3-compatible
+requests. API responses are treated as untrusted JSON and are validated before
+key fields are used. S3 manifest updates use conditional writes against the
+manifest ETag to avoid silent concurrent-writer overwrites.
+
+## Release Gates
+
+Before production release:
+
+- `make test` must pass from a clean checkout.
+- `make run ARGS='doctor'` must pass.
+- `make release-evidence` must write test, audit, dependency, SBOM, and
+  reproducibility evidence.
+- The high-confidence secret scan and Jerboa security scanner must be clean, or
+  accepted exceptions must be documented with owner/date/rationale.
+- `cargo-audit` must pass for the Proton bridge native dependency.
+- Target Drive/S3/FUSE proof must be marker-complete and must not preserve raw
+  Proton/S3 output, credentials, tokens, vault passwords, PIV PINs, plaintext
+  files, or plaintext remote state.
+- Live Proton and S3 integration tests should be run with disposable accounts
+  or buckets before publishing release artifacts.
diff --git a/main.ss b/main.ss
index 490e6fb..9480fc2 100644
--- a/main.ss
+++ b/main.ss
@@ -1,34 +1,6 @@
 #!chezscheme
 ;;; Script entry point for jerboa-protonstorage.