The PR #147 review forged origin: static as a JWT principal through three tools the first version never touched (brain_edit, brain_ingest_raw, ingest_raw + brain_promote), and through YAML spellings a key-name match missed (quoted, escaped, tagged, flow-mapped, merge keys, lone CR). - api.StampProvenance removes every spelling of origin/written_by from the frontmatter and appends the real values. A line is dropped if EITHER yaml.v3 (decoding quotes, escapes, tags, flow maps) or the brain's line-oriented readers would read it as provenance; complex keys, orphan values and merge keys are dropped outright. Lone CRs in frontmatter become LF. Principal values that are not bare words are quoted. - Applied as the last step of writeHallNote, UpdateNote, PromoteNote (re-attributed to the promoter), brain_edit (re-attributed to the editor) and both ingests (every page written or merged). REST /write and /promote carry no principal and stamp unknown. - Ingest: newlines in scalar fields fold to spaces; a page type must be a plain lower-case name (../raw wrote outside wiki/, pre-existing). - Audit: outcome is ok|error, never the error text, which echoed argument values. Tests: every escape from the review is a table case asserting the invariant on the file (parses as YAML, yaml.v3 and brain_get agree, exactly the stamped lines). Plus REST /write, REST capture AuthPath, body-line provenance in search, and quoted principals; two of the review's surviving flips now go red. Three tests renamed so names claim only what they assert. Refs #145 #144 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
52 lines
2.1 KiB
Go
52 lines
2.1 KiB
Go
package capturehttp_test
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/mathiasbq/hyperguild/ingestion/internal/audit"
|
|
"github.com/mathiasbq/hyperguild/ingestion/internal/brainstore"
|
|
"github.com/mathiasbq/hyperguild/ingestion/internal/capture"
|
|
"github.com/mathiasbq/hyperguild/ingestion/internal/capturehttp"
|
|
"github.com/mathiasbq/hyperguild/ingestion/internal/classification"
|
|
)
|
|
|
|
// The REST capture door derives AuthPath itself (hyperguild#145); a body
|
|
// field cannot set it, and static vs JWT are told apart.
|
|
func TestRESTCaptureStampsAuthPathFromAuthentication(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
name, authz, wantOrigin, wantBy string
|
|
v capturehttp.Validator
|
|
sovereign []string
|
|
}{
|
|
{"static", "Bearer " + staticTok, "origin: static\n", "written_by: local-cli\n", nil, nil},
|
|
{"jwt", "Bearer jwt", "origin: jwt\n", "written_by: koala-cli\n", fakeValidator{subject: "koala-cli"}, []string{"koala-cli"}},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
brainDir := t.TempDir()
|
|
cfg, err := classification.Load(t.TempDir())
|
|
require.NoError(t, err)
|
|
svc := capture.NewService(brainstore.New(brainDir), fakeTracker{}, cfg, audit.NewSlogSink(nil))
|
|
h := capturehttp.New(svc, tc.v, staticTok, "local-cli", capturehttp.NewOriginResolver(tc.sovereign))
|
|
rr := do(t, h, tc.authz, map[string]any{
|
|
"context": map[string]any{
|
|
"harness": "claude-code", "actor": "mathias", "classification": "internal",
|
|
"AuthPath": "static", "auth_path": "static", "principal": "local-cli",
|
|
},
|
|
"insights": []map[string]any{{"text": "rest provenance probe", "wing": "hyperguild", "hall": "facts"}},
|
|
})
|
|
require.Equal(t, 200, rr.Code, rr.Body.String())
|
|
matches, _ := filepath.Glob(filepath.Join(brainDir, "wiki/hyperguild/facts/*.md"))
|
|
require.Len(t, matches, 1)
|
|
b, err := os.ReadFile(matches[0])
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(b), tc.wantOrigin)
|
|
assert.Contains(t, string(b), tc.wantBy)
|
|
})
|
|
}
|
|
}
|