p2.6: partition dcache by caller class; pin restricted workspace

Digest, chunk-embed, and question-embed keys include fleet|restricted so
a fleet caller cannot observe a restricted cache hit. Digest.Run takes
the class from permit_restricted.

A permit_restricted caller whose keys.toml workspace is not
guardian-star is refused at Search (no Honcho request) and flagged at
serve start and keys reload.

docs: P3 restricted callers search like the fleet; cache/logs isolate.
This commit is contained in:
2026-09-23 11:51:39 -07:00
parent 7be4ed1d43
commit 3687636ed7
12 changed files with 202 additions and 67 deletions
+32 -6
View File
@@ -12,8 +12,8 @@ func TestHitMissAndNormalise(t *testing.T) {
t.Fatal(err)
}
defer d.Close()
k1 := DigestKey("abc", "What Share?", "m", PromptVersion)
k2 := DigestKey("abc", "what share?", "m", PromptVersion)
k1 := DigestKey("abc", "What Share?", "m", PromptVersion, ClassFleet)
k2 := DigestKey("abc", "what share?", "m", PromptVersion, ClassFleet)
if k1 != k2 {
t.Fatal("normalise")
}
@@ -25,15 +25,41 @@ func TestHitMissAndNormalise(t *testing.T) {
if !ok || h.Text != "forty two" {
t.Fatalf("%v %v", ok, h)
}
k3 := DigestKey("abd", "what share?", "m", PromptVersion)
k3 := DigestKey("abd", "what share?", "m", PromptVersion, ClassFleet)
if _, ok := d.GetDigest(k3); ok {
t.Fatal("changed content must miss")
}
}
func TestCallerClassPartitions(t *testing.T) {
d, err := Open(filepath.Join(t.TempDir(), "c.db"), 1<<20, nil)
if err != nil {
t.Fatal(err)
}
defer d.Close()
fleet := DigestKey("h", "q", "m", PromptVersion, ClassFleet)
restr := DigestKey("h", "q", "m", PromptVersion, ClassRestricted)
if fleet == restr {
t.Fatal("classes must not share a key")
}
d.PutDigest(restr, "secret", 1)
if _, ok := d.GetDigest(fleet); ok {
t.Fatal("fleet must not hit restricted digest")
}
if h, ok := d.GetDigest(restr); !ok || h.Text != "secret" {
t.Fatalf("restricted hit %v %+v", ok, h)
}
if EmbedKey("h", 0, "e", ClassFleet) == EmbedKey("h", 0, "e", ClassRestricted) {
t.Fatal("embed class")
}
if QuestionEmbedKey("q", "e", ClassFleet) == QuestionEmbedKey("q", "e", ClassRestricted) {
t.Fatal("question embed class")
}
}
func TestPromptVersionInvalidates(t *testing.T) {
k1 := DigestKey("h", "q", "m", "1")
k2 := DigestKey("h", "q", "m", "2")
k1 := DigestKey("h", "q", "m", "1", ClassFleet)
k2 := DigestKey("h", "q", "m", "2", ClassFleet)
if k1 == k2 {
t.Fatal("version")
}
@@ -59,7 +85,7 @@ func TestEvictUnderCap(t *testing.T) {
}
defer d.Close()
for i := 0; i < 20; i++ {
d.PutDigest(DigestKey("h", string(rune('a'+i)), "m", "1"), "xxxxxxxxxxxxxxxxxxxx", 1)
d.PutDigest(DigestKey("h", string(rune('a'+i)), "m", "1", ClassFleet), "xxxxxxxxxxxxxxxxxxxx", 1)
}
if d.Size() > 400 {
t.Fatalf("size %d", d.Size())