R-126: refuse a .fab export without a password to a network drive (09 decision 128)

An export to a registered network drive (Kind=network) with no bundle
password now answers 400 with a household sentence (hu+en); with a
password it runs; a local drive is unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-05 21:25:42 +02:00
parent 034a2b7363
commit 33c397380e
5 changed files with 120 additions and 0 deletions
+12
View File
@@ -204,6 +204,18 @@ func (s *Server) apiExportStart(w http.ResponseWriter, r *http.Request) {
return
}
// R-126 (operator ruling 2026-10-05, 09 §3 decision 128): a `.fab` carries the app's secrets in
// plaintext unless a bundle password is set, and a network drive is reachable by every device on
// the household's LAN. So an export WITHOUT a password to any network drive is refused; with a
// password it proceeds. The destination is already known to be registered (isValidDrivePath), so
// IsNetworkStoragePath classifies it by its Kind — the only discriminator (see RefuseAsAppNamespace).
// Pinned by TestExportStart_NetworkDriveNeedsPassword.
if req.Password == "" && s.settings.IsNetworkStoragePath(req.DestDrive) {
s.logger.Printf("[INFO] [web] apiExportStart: refused — no password for network drive %q (stack=%s)", req.DestDrive, req.StackName)
jsonError(w, s.msg(r, "app_export.network_drive_needs_password"), http.StatusBadRequest)
return
}
err := s.appExporter.StartExport(appexport.ExportRequest{
StackName: req.StackName,
DestDrive: req.DestDrive,