aeca52ea54
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
64 lines
2.7 KiB
Go
64 lines
2.7 KiB
Go
package store
|
|
|
|
import (
|
|
"os"
|
|
"regexp"
|
|
"testing"
|
|
)
|
|
|
|
// R-105 option A (`09` §3 decision 169): the two "slim DR record" fields are retired. Nothing writes
|
|
// `host_escrow.directive_json` any more (an escrow upload left a hand-made directive overwritten with `{}`), and
|
|
// nothing reads `hosts.dr_record_json` or the directive. The columns STAY (a column nobody reads is harmless,
|
|
// and dropping one is a schema change the hub's database backups would have to follow).
|
|
|
|
// COMPANION RED-PROOF (observed): on the pre-R-105 code SaveHostDRBundle overwrote the column — this failed with
|
|
// "the identity-blob save must leave directive_json alone; got {}". Restored.
|
|
func TestR105_IdentitySaveLeavesDirectiveColumnAlone(t *testing.T) {
|
|
st := newResetStore(t)
|
|
if err := st.UpsertHost(&Host{HostID: "h1", CustomerID: "c1", APIKey: "k"}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, _, err := st.SaveHostEscrow("h1", []byte("K"), "fp", "zero_knowledge", "2026-10-07T00:00:00Z", "sha"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := st.db.Exec(`UPDATE host_escrow SET directive_json = '{"hand":"made"}' WHERE host_id = 'h1'`); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := st.SaveHostDRBundle("h1", []byte("ID")); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var got string
|
|
if err := st.db.QueryRow(`SELECT directive_json FROM host_escrow WHERE host_id = 'h1'`).Scan(&got); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got != `{"hand":"made"}` {
|
|
t.Fatalf("the identity-blob save must leave directive_json alone; got %s", got)
|
|
}
|
|
b, err := st.GetHostDRBundle("h1")
|
|
if err != nil || b == nil || string(b.IdentityBlob) != "ID" || string(b.KEscrowBlob) != "K" {
|
|
t.Fatalf("the bundle must still carry both blobs; got %+v err=%v", b, err)
|
|
}
|
|
}
|
|
|
|
// No reader: outside the schema statements, the column names do not appear in the store's source, so a new reader
|
|
// cannot appear without this design being revisited.
|
|
// COMPANION RED-PROOF (observed): with `DRRecordJSON` still scanned this failed naming `dr_record_json` in the
|
|
// hosts select list. Restored.
|
|
func TestR105_RetiredColumnsHaveNoReader(t *testing.T) {
|
|
src, err := os.ReadFile("store.go")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
schema := regexp.MustCompile(`(?m)^\s*dr_record_json\s+TEXT NOT NULL DEFAULT '\{\}',$|ALTER TABLE host_escrow ADD COLUMN directive_json`)
|
|
rest := schema.ReplaceAllString(string(src), "")
|
|
for _, name := range []string{"dr_record_json", "directive_json", "DRRecordJSON", "DirectiveJSON"} {
|
|
if regexp.MustCompile(`\b` + name + `\b`).MatchString(stripComments(rest)) {
|
|
t.Errorf("%s is still read or written in store.go outside its schema statement", name)
|
|
}
|
|
}
|
|
}
|
|
|
|
func stripComments(s string) string {
|
|
return regexp.MustCompile(`(?m)//.*$`).ReplaceAllString(s, "")
|
|
}
|