package ai import ( "context" "encoding/json" "errors" "strings" "testing" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgconn" "github.com/missionworkforce/missionmatch/internal/platform/scrub" ) // TestAllowExternalRefusesForbiddenPayload proves the external lane will not carry a payload that still // holds a private data marker, so a misclassified candidate fact is caught before it leaves the machine. func TestAllowExternalRefusesForbiddenPayload(t *testing.T) { if _, err := AllowExternal("openai", []scrub.Provenance{scrub.ProvenancePublicCache}, scrub.ClassRequirementNormalize, []byte("normalize scope for candidate 11111111-1111-1111-1111-111111111111")); err == nil { t.Fatal("a payload with a private data marker must be refused before it can leave for an external backend") } } // TestAllowExternalRefusesUnknownClass proves the external lane fails closed on any class outside the // four public classes, for example an attempt to route slate contents. func TestAllowExternalRefusesUnknownClass(t *testing.T) { if _, err := AllowExternal("openai", []scrub.Provenance{scrub.ProvenancePublicCache}, scrub.EgressClass("SLATE_CONTENTS"), []byte("clean public text")); err == nil { t.Fatal("a class outside the public allow list must be refused") } } // TestAllowExternalReturnsAuditMetadataNeverContent proves a permitted call yields the audit metadata the // orchestrator records: backend, payload class, byte count, and content hash, and never the content. func TestAllowExternalReturnsAuditMetadataNeverContent(t *testing.T) { payload := []byte("Public solicitation notice, analyst support services, clearance intelligence indicated.") meta, err := AllowExternal("openai", []scrub.Provenance{scrub.ProvenancePublicCache}, scrub.ClassRequirementNormalize, payload) if err != nil { t.Fatalf("clean public text under a permitted class must be allowed: %v", err) } if meta["backend"] != "openai" { t.Errorf("expected backend openai, got %v", meta["backend"]) } if meta["payload_class"] != string(scrub.ClassRequirementNormalize) { t.Errorf("expected the payload class recorded, got %v", meta["payload_class"]) } if meta["byte_count"] != len(payload) { t.Errorf("expected byte_count %d, got %v", len(payload), meta["byte_count"]) } if meta["content_sha256"] != scrub.ContentHash(payload) { t.Errorf("expected the content hash recorded, got %v", meta["content_sha256"]) } blob, _ := json.Marshal(meta) if strings.Contains(string(blob), "solicitation") || strings.Contains(string(blob), "analyst") { t.Fatal("audit metadata must record backend, class, bytes, and hash, never the content itself") } } // Gate 2: the audit metadata must record the PROVENANCE alongside the class, because the provenance is now // the primary control and an audit that omits it cannot answer the question an assessor will actually ask, // which is where the data that left came from. func TestExternalAuditRecordsProvenance(t *testing.T) { meta, err := AllowExternal("openai", []scrub.Provenance{scrub.ProvenancePublicCache}, scrub.ClassRequirementNormalize, []byte("public notice text")) if err != nil { t.Fatalf("a public payload was refused: %v", err) } if len(meta["provenance"].([]string)) != 1 || meta["provenance"].([]string)[0] != string(scrub.ProvenancePublicCache) { t.Fatalf("the audit metadata does not record the provenance: %v", meta) } if _, ok := meta["content_sha256"]; !ok { t.Fatal("the audit metadata lost its content hash") } if _, ok := meta["content"]; ok { t.Fatal("the audit metadata carries CONTENT, which it must never do") } } // A tenant sourced payload is refused before any audit metadata is produced, so a caller cannot record a // call it was not permitted to make. func TestTenantProvenanceIsRefusedAtTheWrapper(t *testing.T) { for _, p := range []scrub.Provenance{scrub.ProvenanceTenantUpload, scrub.ProvenanceTenantRecord} { meta, err := AllowExternal("openai", []scrub.Provenance{p}, scrub.ClassRequirementNormalize, []byte("harmless looking text")) if err == nil { t.Fatalf("provenance %s was allowed to egress", p) } if meta != nil { t.Fatalf("audit metadata was produced for a refused call: %v", meta) } } } // ============================================================================ // THE PERSISTED AUDIT ROW. Added 29 July 2026 closing finding three. // ============================================================================ // // The tests above assert the SHAPE OF A MAP. They passed for two days while no row was ever written, // because the only caller logged the map and persisted nothing. A test that proves metadata is produced is // not a test that proves it is recorded, and the difference is the whole finding. // auditDB is a DBTX whose one insert either succeeds or fails, so the fail closed path is proven rather // than argued. It also CAPTURES the arguments, which is how the never content promise is checked. type auditDB struct { fail bool rows int captured []any } func (d *auditDB) Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error) { return pgconn.CommandTag{}, nil } func (d *auditDB) Query(context.Context, string, ...interface{}) (pgx.Rows, error) { return nil, errors.New("audit tests never Query") } func (d *auditDB) QueryRow(_ context.Context, _ string, args ...interface{}) pgx.Row { d.rows++ d.captured = args return auditRow{fail: d.fail} } type auditRow struct{ fail bool } func (r auditRow) Scan(...any) error { if r.fail { return errors.New("audit_logs is unavailable") } return nil } func publicProvs() []scrub.Provenance { return []scrub.Provenance{scrub.ProvenancePublicCache} } const noticePayload = "Elevator maintenance services. Department: VA. NAICS: 238290." // AN EXTERNAL CALL THAT CANNOT BE AUDITED MUST NOT HAPPEN. This is the fail closed assertion, and it is the // reason the gate and the row are one function: a caller that got metadata back and sent anyway would be // making an unrecorded egress, which is worse than a refused one because a refusal is visible. func TestExternalEgressIsRefusedWhenItsAuditRowCannotBeWritten(t *testing.T) { db := &auditDB{fail: true} meta, err := AllowExternalAudited(context.Background(), db, nil, "megamind-gateway", publicProvs(), scrub.ClassRequirementNormalize, []byte(noticePayload)) if err == nil { t.Fatal("egress was PERMITTED while its audit row could not be written, so an unrecorded external call is possible") } if meta != nil { t.Error("metadata was returned alongside the refusal, which invites a caller to send anyway") } if db.rows != 1 { t.Errorf("the insert was attempted %d times, want 1: this test would pass while measuring nothing if the audit write were never reached", db.rows) } if !strings.Contains(err.Error(), "audit") { t.Errorf("the refusal does not say the audit was the cause: %v", err) } } // THE ROW IS WRITTEN, IT CARRIES THE FOUR REQUIRED FIELDS, AND IT CARRIES NO CONTENT. func TestExternalEgressWritesOneAuditRowCarryingMetadataAndNeverContent(t *testing.T) { db := &auditDB{} meta, err := AllowExternalAudited(context.Background(), db, nil, "megamind-gateway", publicProvs(), scrub.ClassRequirementNormalize, []byte(noticePayload)) if err != nil { t.Fatalf("a permitted payload with a writable audit was refused: %v", err) } if db.rows != 1 { t.Fatalf("wrote %d audit rows, want exactly 1", db.rows) } // The action and the entity must be findable, because an audit row nobody can query is a row nobody reads. var sawAction, sawHash bool for _, a := range db.captured { s := argString(a) if s == ActionExternalInference { sawAction = true } if s == meta["content_sha256"] { sawHash = true } // THE NEVER CONTENT PROMISE. No argument may carry the payload text. if strings.Contains(s, "Elevator maintenance") || strings.Contains(s, "238290") { t.Error("an audit argument carries the payload CONTENT, which the boundary promises it never does") } } if !sawAction { t.Errorf("no argument held the action %q", ActionExternalInference) } if !sawHash { t.Error("no argument held the content hash, so the row cannot be tied to the payload it authorised") } // The four fields the recorded owner decision requires, by name. blob := findJSON(db.captured) if blob == nil { t.Fatal("no JSON payload was passed to the insert, so the metadata was not recorded at all") } var got map[string]any if err := json.Unmarshal(blob, &got); err != nil { t.Fatalf("the recorded metadata is not valid JSON: %v", err) } for _, field := range []string{"backend", "payload_class", "byte_count", "content_sha256"} { if _, ok := got[field]; !ok { t.Errorf("the audit row does not record %q", field) } } if got["payload_class"] != string(scrub.ClassRequirementNormalize) { t.Errorf("payload_class recorded as %v, want %s", got["payload_class"], scrub.ClassRequirementNormalize) } } // A REFUSED PAYLOAD WRITES NOTHING. The gate runs first, so a forbidden payload never reaches the audit // table. Without this, a refusal would still leave a row implying an external call was authorised. func TestARefusedPayloadWritesNoAuditRow(t *testing.T) { db := &auditDB{} if _, err := AllowExternalAudited(context.Background(), db, nil, "megamind-gateway", []scrub.Provenance{scrub.ProvenanceTenantUpload}, scrub.ClassRequirementNormalize, []byte(noticePayload)); err == nil { t.Fatal("a tenant upload was permitted to the external lane") } if db.rows != 0 { t.Errorf("a refused payload wrote %d audit rows, want 0", db.rows) } } // WHICH BACKEND ACTUALLY SERVED IT. The gateway falls back to the local runtime on failure, so the served // model is the only thing that distinguishes a real external call from a failure that became a local one. func TestOutcomeRowRecordsTheModelThatActuallyServed(t *testing.T) { db := &auditDB{} if err := RecordExternalOutcome(context.Background(), db, nil, "abc123", "openai:gpt-4o-mini", 412); err != nil { t.Fatalf("recording the outcome failed: %v", err) } if db.rows != 1 { t.Fatalf("wrote %d rows, want 1", db.rows) } blob := findJSON(db.captured) if blob == nil { t.Fatal("no JSON payload recorded") } var got map[string]any if err := json.Unmarshal(blob, &got); err != nil { t.Fatalf("not valid JSON: %v", err) } if got["served_model"] != "openai:gpt-4o-mini" { t.Errorf("served_model recorded as %v, want openai:gpt-4o-mini", got["served_model"]) } if got["content_sha256"] != "abc123" { t.Errorf("the outcome row is not tied to the egress row by content hash, got %v", got["content_sha256"]) } } // argString renders an insert argument for inspection, following the pointer that sqlc uses for a nullable // column. A nil pointer must not be dereferenced, and a non string argument is simply not a string. func argString(a any) string { switch v := a.(type) { case string: return v case *string: if v == nil { return "" } return *v } return "" } func findJSON(args []any) []byte { for _, a := range args { if b, ok := a.([]byte); ok && len(b) > 0 && b[0] == '{' { return b } } return nil }