docs(samba): CHANGELOG v0.144.0 + REPORT + CONTEXT + README §16 + REUSE
Records the R-7 slice 1 ship, the four red-proof outcomes, live-validation evidence, the two bugs live validation caught, and the Part-4 Step-1 enumeration finding + the reported design fork (share data classified but not yet in a live backup run — needs a Viktor ruling, suggested R-7b).
This commit is contained in:
@@ -1,5 +1,66 @@
|
||||
## Changelog
|
||||
|
||||
### v0.144.0 — „Megosztás": LAN SMB file sharing (R-7 slice 1) (2026-07-18)
|
||||
|
||||
The customer turns on network sharing, sets ONE household SMB password, and exports folders. The box
|
||||
appears in Windows Explorer's Network view as `\\FELHOM`; opening a share and writing to it works, and
|
||||
every SMB write lands as uid:gid 1000 so apps and both backup tiers see consistent ownership. SMB is
|
||||
an **embedded controller feature**, not a catalog app — it needs host networking (the R-6 spike
|
||||
verdict), its config is a generated share list, and its roots ride the backup classification.
|
||||
|
||||
- **New infra image `felhom-samba:1.0.0`** (`controller/infra-images/samba/`, built by
|
||||
`controller/scripts/build-samba-image.sh`): pinned alpine 3.21 (`sha256:48b0309c…`) + smbd + **nmbd**
|
||||
+ wsdd + tini. Dumb by design — `smb.conf` is bind-mounted READ-ONLY, nothing is templated inside,
|
||||
no name/password is baked, passdb lives on a named volume. nmbd is REQUIRED alongside wsdd: the R-6
|
||||
spike proved wsdd-only leaves the box *visible* but the Explorer double-click fails `0x80070035`
|
||||
(no flat-name resolution). Anonymous pull verified from the guest.
|
||||
- **Settings (`internal/settings/smb.go`, new):** `SMBSettings{Enabled, ServerName, UserSet}` +
|
||||
`SMBShare{Name, Path, ReadOnly, Offsite, CreatedAt}` registry with NetBIOS-safe validation
|
||||
(≤15 chars, no slash/dot) and case-insensitive name-collision refusal. **The household SMB password
|
||||
is NEVER persisted** — only the `UserSet` boolean.
|
||||
- **Renderers (`internal/infra/samba.go`, new):** pure `RenderSambaConfig` (hardened global block:
|
||||
`server min protocol = SMB2`, `bind interfaces only = yes`, `interfaces = lo eth0`,
|
||||
`disable netbios = no`, `map to guest = never`, per-share force-user block) and
|
||||
`RenderSambaCompose` (`network_mode: host`, pinned image, config `:ro`, passdb volume, one bind per
|
||||
share — `:ro` for read-only shares as defence in depth beside smb.conf). Exact smb.conf golden test.
|
||||
- **Lifecycle (`internal/stacks/samba.go`, new):** `ensureSamba` joins `EnsureBaseStack` after
|
||||
filebrowser, gated on `SMB.Enabled` (the cloudflared conditional-deploy precedent); `ReconcileSamba`
|
||||
runs after every mutation. Idempotent — unchanged config + running container performs **zero**
|
||||
compose calls. Config writes are atomic (tmp+fsync+rename). The password is applied via
|
||||
`smbpasswd` on **STDIN** (never argv, never logged). Disable = `compose down`; the passdb volume and
|
||||
every shared folder are KEPT. A share on a disconnected/decommissioned drive is rendered ABSENT from
|
||||
smb.conf (never export a dead mountpoint) while its config is retained.
|
||||
- **Protection:** `samba` is protected in CODE (`config.alwaysProtectedStacks`) because
|
||||
`cfg.Stacks.Protected` comes from the golden-generated controller.yaml and predates it. This also
|
||||
makes the app-backup loops correctly skip it (it is infrastructure, not a customer app).
|
||||
- **UI (`internal/web/sharing_handlers.go` + `templates/sharing.html`, new):** a new top-nav category
|
||||
**„Megosztás"** → **„Hálózati megosztás"**. Enable/server-name card, household password, shares table
|
||||
(Név · Mappa · Írásvédett · Felhőmentés · Törlés — "a mappa és a fájlok megmaradnak"), and a create
|
||||
flow (new folder under `<storage>/shares/` or an existing folder via the browse modal).
|
||||
- **Picker security:** every customer-supplied path goes through `sharingResolvePath` — absolute →
|
||||
`EvalSymlinks` → containment in a registered LIVE storage root → deny-listed system subtree →
|
||||
is-a-directory. Refusals are **uniform** so the picker can never act as a filesystem oracle. The
|
||||
deny-list is DERIVED from `stacks.ProtectedHDDPaths` (provably a subset, so it can only shrink,
|
||||
never drift); the drive root is an exact-match denial so user-data folders under it stay shareable.
|
||||
`sharingResolveStorageRoot` is a separate, strictly tighter check for the new-folder parent.
|
||||
- **Backup classification [R4] (`internal/stacks/samba_classify.go`, new):** `ClassifiedBinds("samba")`
|
||||
resolves from the shares registry instead of catalog metadata. Felhőmentés ON → `mandatory`
|
||||
(offsite + tier-2); OFF → `optional` (tier-2 only); smb.conf/passdb never classified. Verified
|
||||
through the real `ComputeCaptureSet` tier filter including the negative. **Zero backup-engine edits.**
|
||||
- **KNOWN GAP (reported design fork, not improvised):** making that seam correct does NOT by itself put
|
||||
share data into a live tier-2/offsite RUN. `backup.RunTier2` short-circuits on `os.Stat(unitDir)`
|
||||
before it ever calls `GetStackClassifiedBinds`, and the offsite runner enumerates
|
||||
`settings.GetOffboxApps()` — both are recovery-unit shaped, which a share-only infra stack has not.
|
||||
Teaching them about one is more than an enumeration tweak, so per the task's STOP clause it is
|
||||
reported rather than improvised. See `REPORT.md`.
|
||||
- Live-validated end-to-end on demo guest 9201 through the REAL endpoints (curl against the exact
|
||||
routes the UI posts to; the UI is password-gated so no browser leg): enable → password → create both
|
||||
share kinds → guard refusals (appdata/backups//etc/drive-root all uniform 400) → smb.conf + container
|
||||
+ `:ro` bind verified on the box → Windows 11 workstation: `Test-NetConnection 445` True, nbtstat
|
||||
`FELHOM <00>/<03>/<20> Registered`, `ping FELHOM` resolves, SMB write/read byte-compare PASS, and a
|
||||
**write to the read-only share refused with no effect**. SMB-written files land as `1000:1000`.
|
||||
Explorer render is Viktor's remaining human leg.
|
||||
|
||||
### Build infra — build root relocated (2026-07-18)
|
||||
|
||||
- `controller/build.sh`: `REPO_DIR` + `WEBSITE_ASSETS_DIR` repointed `/home/kisfenyo/…` →
|
||||
|
||||
Reference in New Issue
Block a user