Files
drive/audit_test.go
zeekayandHanzo Dev cb05c3656f feat(audit): tamper-evident audit trail + SOC 2 readiness matrix
Hash-chained, append-only audit log per tenant: every mkdir/upload/download/
share (and denied access) records actor/action/resource with a sha256 chain
over the prior entry. VerifyAudit() recomputes the chain and reports the first
tampered seq — altering or deleting any entry is detected (SOC 2 CC7.2).
GET /v1/drive/audit exports the trail + intact status for auditors.

SOC2-READINESS.md maps Trust Services Criteria to code vs org process — honest
that readiness != certification (needs an auditor + observation window).

Co-authored-by: Hanzo Dev <[email protected]>
2026-06-16 21:44:30 +00:00

38 lines
1.3 KiB
Go

package drive_test
import (
"context"
"strings"
"testing"
"github.com/hanzoai/drive"
_ "github.com/hanzoai/sqlite3/embed"
"github.com/hanzoai/vfs/pkg/backend"
_ "github.com/hanzoai/vfs/pkg/backend/file"
"github.com/luxfi/age"
)
func TestAuditTamperEvident(t *testing.T) {
ctx := context.Background()
be, _ := backend.Open(ctx, "file://"+t.TempDir())
st, _ := drive.Open("file:"+t.TempDir()+"/m.db", be)
defer st.Close()
owner, _ := age.GenerateHybridIdentity()
f, _ := st.Mkdir("", "docs")
st.Audit("[email protected]", "mkdir", f.ID, "docs")
n, _ := st.Upload(ctx, f.ID, "a.txt", strings.NewReader("x"), owner.Recipient())
st.Audit("[email protected]", "upload", n.ID, "a.txt")
st.Audit("[email protected]", "download", n.ID, "")
trail, _ := st.AuditTrail(10)
if len(trail) != 3 { t.Fatalf("trail len=%d want 3", len(trail)) }
if at, _ := st.VerifyAudit(); at != 0 { t.Fatalf("intact chain flagged tamper at %d", at) }
// tamper: rewrite an actor in place (the classic "cover your tracks") — chain must break
st.Exec(`UPDATE audit SET actor='nobody' WHERE action='download'`)
at, _ := st.VerifyAudit()
if at == 0 { t.Fatal("tamper NOT detected — audit log is not tamper-evident") }
t.Logf("tamper detected at seq %d — hash chain holds (SOC2 CC7.2)", at)
}