fix(server): carry history through the paths-tree merge

mergeOverlay (used to thread embedded defaults' paths: tree into chain
levels) didn't copy the new History *bool, so EffectiveHistory never saw
history: true on archive/<party>/working/ — the feature would have silently
never triggered. Add the field to the overlay and a HistoryAt defaults test
that exercises the real cascade (working/ + fenced homes true; sibling slots
false).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZDDC 2026-05-28 12:48:49 -05:00
parent 6efe71e573
commit d00afa1ddc
2 changed files with 31 additions and 0 deletions

View file

@ -48,6 +48,34 @@ func TestDefaultToolAt_FromEmbeddedConvention(t *testing.T) {
}
}
// TestHistoryAt_Defaults — the embedded convention enables edit-history
// versioning on archive/<party>/working/ and (because history is
// subtree-inheriting and ignores the auto_own_fenced homes' inherit:false)
// on the per-user homes and any depth beneath them. Sibling slots do not
// get history.
func TestHistoryAt_Defaults(t *testing.T) {
resetCache()
root := t.TempDir()
cases := []struct {
path string
want bool
}{
{filepath.Join(root, "Project-X", "archive", "Acme", "working"), true},
{filepath.Join(root, "Project-X", "archive", "Acme", "working", "alice@example.com"), true},
{filepath.Join(root, "Project-X", "archive", "Acme", "working", "alice@example.com", "notes"), true},
{filepath.Join(root, "Project-X", "archive", "Acme", "mdl"), false},
{filepath.Join(root, "Project-X", "archive", "Acme", "incoming"), false},
{filepath.Join(root, "Project-X", "archive", "Acme", "staging"), false},
{filepath.Join(root, "Project-X", "archive", "Acme", "received"), false},
{filepath.Join(root, "Project-X", "archive"), false},
}
for _, tc := range cases {
if got := HistoryAt(root, tc.path); got != tc.want {
t.Errorf("HistoryAt(%q) = %v, want %v", tc.path[len(root):], got, tc.want)
}
}
}
// TestDirToolAt — the trailing-slash form floors at "browse" for
// every path (the embedded convention sets dir_tool nowhere), and an
// on-disk .zddc can override it for a subtree.

View file

@ -88,6 +88,9 @@ func mergeOverlay(base, top ZddcFile) ZddcFile {
if top.DropTarget != nil {
out.DropTarget = top.DropTarget
}
if top.History != nil {
out.History = top.History
}
// Worm: presence (non-nil, even empty) marks the WORM zone.
// Concat-dedupe across levels (a deeper .zddc adds controllers);
// preserve a non-nil empty slice so `worm: []` survives the