// Package claim_test covers the claim-property envelope (brain#21). package claim_test import ( "testing" "github.com/mathiasbq/hyperguild/ingestion/internal/claim" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestValidateEnvelope(t *testing.T) { tests := []struct { name string fm map[string]string wantErr string }{ { name: "absent is fine — the fields are opt-in on new writes", fm: map[string]string{"wing": "homelab", "hall": "facts"}, }, { name: "complete envelope with provenance", fm: map[string]string{ "half_life": "durable", "applies": "universal", "claim_provenance": "asserted", }, }, { name: "inferred provenance is equally valid — it just must be stated", fm: map[string]string{ "half_life": "volatile", "applies": "local", "claim_provenance": "inferred", }, }, { // A value nobody can act on is worse than no value: a lint // silently skips it, so the note looks classified and isn't. name: "unknown half_life value", fm: map[string]string{"half_life": "forever", "claim_provenance": "asserted"}, wantErr: `half_life: "forever" is not one of volatile, seasonal, durable`, }, { name: "unknown applies value", fm: map[string]string{"applies": "galaxy", "claim_provenance": "asserted"}, wantErr: `applies: "galaxy" is not one of local, homelab, universal`, }, { // brain#21: a value a model inferred must never be // indistinguishable from one Mathias asserted. Writing the field // without saying who set it is exactly that laundering. name: "envelope field without provenance", fm: map[string]string{"half_life": "durable"}, wantErr: "claim_provenance is required when half_life or applies is set", }, { name: "applies without provenance", fm: map[string]string{"applies": "homelab"}, wantErr: "claim_provenance is required when half_life or applies is set", }, { name: "unknown provenance value", fm: map[string]string{"half_life": "durable", "claim_provenance": "probably"}, wantErr: `claim_provenance: "probably" is not one of asserted, inferred`, }, { // Provenance alone says who set fields that aren't there. name: "provenance without any envelope field", fm: map[string]string{"claim_provenance": "asserted"}, wantErr: "claim_provenance is set but neither half_life nor applies is", }, { // The glossary wing has used scope: homelab-core since #5. The // envelope deliberately does NOT claim that key (brain#21). name: "glossary scope is untouched", fm: map[string]string{"scope": "homelab-core", "term": "koala"}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := claim.ValidateEnvelope(tt.fm) if tt.wantErr == "" { assert.NoError(t, err) return } require.Error(t, err) assert.Contains(t, err.Error(), tt.wantErr) }) } }