Collect sensitivity directly from document trees

This commit is contained in:
2026-10-09 03:39:12 +00:00
parent 528495c75a
commit ca1ba04676
3 changed files with 35 additions and 16 deletions

View File

@@ -245,7 +245,7 @@ Validate: `go test ./internal/engine -run 'Resolution|Metadata|Provenance|Histor
engine race tests, and the everyday check. Complexity is output-sensitive to engine race tests, and the everyday check. Complexity is output-sensitive to
affected events, not every delta times every field. affected events, not every delta times every field.
## Stage 9: Collect sensitivity directly from trees ## Stage 9: Collect sensitivity directly from trees — Complete
Roadmap candidate 5. Owner: engine `secret.go`. Keep fixed-point propagation Roadmap candidate 5. Owner: engine `secret.go`. Keep fixed-point propagation
unchanged until Stage 11 so collection is independently reviewable. unchanged until Stage 11 so collection is independently reviewable.

View File

@@ -9,17 +9,10 @@ type secretDependency struct {
func classifySecretPaths(schema *schemaDescriptor, predicate func(Path) bool, metadata Metadata, final *document.Node, applications []historyApplication, projections ...*document.Node) map[string]bool { func classifySecretPaths(schema *schemaDescriptor, predicate func(Path) bool, metadata Metadata, final *document.Node, applications []historyApplication, projections ...*document.Node) map[string]bool {
paths := make(map[string]Path) paths := make(map[string]Path)
finalPaths := make(map[string]*document.Node)
indexDocument(final, Path{}, finalPaths)
for pointer := range finalPaths {
addSecretPath(paths, pointer)
}
for _, application := range applications { for _, application := range applications {
applicationPaths := make(map[string]*document.Node) walkDocument(application.value, application.path, func(path Path, _ *document.Node) {
indexDocument(application.value, application.path, applicationPaths) addSecretPath(paths, path.String())
for pointer := range applicationPaths { })
addSecretPath(paths, pointer)
}
} }
var dependencies []secretDependency var dependencies []secretDependency
for pointer, history := range metadata.history { for pointer, history := range metadata.history {
@@ -65,16 +58,19 @@ func classifySecretPaths(schema *schemaDescriptor, predicate func(Path) bool, me
} }
secret := make(map[string]bool) secret := make(map[string]bool)
for _, tree := range append(projections, final) { classifyProjection := func(tree *document.Node) {
projected := make(map[string]*document.Node) walkDocument(tree, Path{}, func(path Path, node *document.Node) {
indexDocument(tree, Path{}, projected) pointer := path.String()
for pointer, node := range projected {
addSecretPath(paths, pointer) addSecretPath(paths, pointer)
if node.Sensitive { if node.Sensitive {
secret[pointer] = true secret[pointer] = true
} }
} })
} }
for _, tree := range projections {
classifyProjection(tree)
}
classifyProjection(final)
for pointer, path := range paths { for pointer, path := range paths {
if root, ok := schemaSecretRoot(schema, path); ok { if root, ok := schemaSecretRoot(schema, path); ok {
secret[root.String()] = true secret[root.String()] = true

View File

@@ -0,0 +1,23 @@
package engine
import "testing"
func TestSecretPredicateReceivesDetachedHistoricalPath(t *testing.T) {
path := Keys("records").Key("1")
metadata := Metadata{history: map[string][]Change{
path.String(): {{Path: path}},
}}
seen := false
classified := classifySecretPaths(nil, func(candidate Path) bool {
if candidate.String() != path.String() {
return false
}
seen = true
candidate.segments[0].key = "changed"
return true
}, metadata, nil, nil)
if !seen || !classified[path.String()] || classified["/changed/1"] {
t.Fatalf("classification after predicate mutation = %#v, predicate called: %v", classified, seen)
}
}