A history: true .zddc subtree (enabled by default on archive/<party>/working/)
routes markdown PUTs through WriteTextWithHistory: each save snapshots the
content into a hidden, immutable .history/<stem>/ store (content-addressed
blobs + an append-only log.jsonl carrying server-stamped {ts, email, sha,
prev}) before writing the live file. The live file at its natural path stays
the source of truth; no symlinks, no audit in the body/filename.
Reads: GET <file>?history=1 lists versions (newest-first, current flagged);
GET <file>?history=<sha> returns that version's bytes (hex-id guard against
traversal). Listings carry a per-file History flag so the browse client knows
where to offer the affordance.
History is subtree-inheriting and ignores inherit:false ACL fences (versioning
is a write behavior, not a permission), so fenced per-user homes under working/
are covered too. No-op saves dedup; pre-existing files lazy-seed their origin
version. Records (.yaml) keep their existing in-body-audit history path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
58 lines
1.5 KiB
Go
58 lines
1.5 KiB
Go
package zddc
|
|
|
|
import "testing"
|
|
|
|
func bptr(b bool) *bool { return &b }
|
|
|
|
func TestEffectiveHistory(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
chain PolicyChain
|
|
want bool
|
|
}{
|
|
{
|
|
name: "no levels, no embedded default",
|
|
chain: PolicyChain{},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "embedded default true, no explicit level",
|
|
chain: PolicyChain{Levels: []ZddcFile{{}, {}}, Embedded: ZddcFile{History: bptr(true)}},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "ancestor true inherits down to leaf (nil)",
|
|
chain: PolicyChain{Levels: []ZddcFile{{History: bptr(true)}, {}, {}}},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "leaf false overrides ancestor true",
|
|
chain: PolicyChain{Levels: []ZddcFile{{History: bptr(true)}, {History: bptr(false)}}},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "leaf true overrides embedded false",
|
|
chain: PolicyChain{Levels: []ZddcFile{{History: bptr(true)}}, Embedded: ZddcFile{History: bptr(false)}},
|
|
want: true,
|
|
},
|
|
{
|
|
// History must inherit THROUGH an inherit:false ACL fence —
|
|
// versioning is a write behavior, not a permission. The fenced
|
|
// middle level sets no History, so the ancestor's true wins.
|
|
name: "inherits through an inherit:false fence",
|
|
chain: PolicyChain{Levels: []ZddcFile{
|
|
{History: bptr(true)},
|
|
{ACL: ACLRules{Inherit: bptr(false)}},
|
|
{},
|
|
}},
|
|
want: true,
|
|
},
|
|
}
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
if got := tc.chain.EffectiveHistory(); got != tc.want {
|
|
t.Errorf("EffectiveHistory() = %v, want %v", got, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|