docs: publish Preview 19 dogfood evidence
Export the reviewed allowlisted snapshot from private source commit 05928cebd01b586cf9e9d4b8c8537a7605a6068c. This records the exact candidate, bounded capacity result, stateful migration scratch requirement, authenticated batch identity proof, and immediate live acceptance evidence. AI-Assisted: OpenAI Codex Signed-off-by: Cole Speelman <crspeelman@gmail.com>
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
package agentclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gamertan.com/observatory/internal/httpserver"
|
||||
"gamertan.com/observatory/internal/identity"
|
||||
"gamertan.com/observatory/internal/model"
|
||||
"gamertan.com/observatory/internal/nativeprotocol"
|
||||
"gamertan.com/observatory/internal/query"
|
||||
"gamertan.com/observatory/internal/storage"
|
||||
)
|
||||
|
||||
type transportFunc func(*http.Request) (*http.Response, error)
|
||||
|
||||
func (f transportFunc) RoundTrip(request *http.Request) (*http.Response, error) { return f(request) }
|
||||
|
||||
func TestSendRequiresMatchingAcknowledgementAndDoesNotRedirect(t *testing.T) {
|
||||
credential := "obs1.source." + strings.Repeat("a", 64)
|
||||
var authorization, path string
|
||||
client, err := New("https://observatory.example", credential, transportFunc(func(request *http.Request) (*http.Response, error) {
|
||||
authorization = request.Header.Get("Authorization")
|
||||
path = request.URL.Path
|
||||
body, readErr := io.ReadAll(request.Body)
|
||||
if readErr != nil {
|
||||
t.Fatal(readErr)
|
||||
}
|
||||
digest := sha256.Sum256(body)
|
||||
if request.Header.Get(nativeprotocol.WireDigestHeader) != hex.EncodeToString(digest[:]) || request.Header.Get(nativeprotocol.StreamHeader) != "access" || request.Header.Get(nativeprotocol.SequenceHeader) != "1" {
|
||||
t.Fatalf("missing framed batch metadata: %v", request.Header)
|
||||
}
|
||||
response := fmt.Sprintf(`{"source_id":"source","stream_id":"access","sequence":1,"digest":"%s","batch_digest":"%s","duplicate":false}`, strings.Repeat("a", 64), hex.EncodeToString(digest[:]))
|
||||
return &http.Response{StatusCode: http.StatusAccepted, Header: make(http.Header), Body: io.NopCloser(strings.NewReader(response))}, nil
|
||||
}))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
batch := model.Batch{Version: 1, SourceID: "source", StreamID: "access", Sequence: 1, ObservedAt: now, Signal: model.SignalLogs, Records: []model.Observation{{Timestamp: now, Name: "request"}}}
|
||||
if _, err := client.Send(context.Background(), batch); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if authorization != "Bearer "+credential || path != "/api/v2/ingest/native" {
|
||||
t.Fatalf("authorization=%q path=%q", authorization, path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendAcceptsRealServerBatchDigestRatherThanPrivateSegmentDigest(t *testing.T) {
|
||||
root := filepath.Join(t.TempDir(), "data")
|
||||
if err := os.Mkdir(root, 0o700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
store, err := storage.Open(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer store.Close()
|
||||
identities, err := identity.Open(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer identities.Close()
|
||||
token, err := store.CreateSource(context.Background(), "source", model.Scope{OrganizationID: "organization", ProjectID: "project", EnvironmentID: "production", ServiceID: "service"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
server, err := httpserver.New(store, identities, httpserver.Options{
|
||||
PublicOrigin: "https://observatory.example", MaxBodyBytes: 1 << 20, MaxQueryRows: 100,
|
||||
QueryBudget: query.Budget{MaxDuration: time.Second, MaxRows: 100, MaxScannedBytes: 1 << 20, MaxMemoryBytes: 1 << 20}, SessionLifetime: time.Hour,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
client, err := New("https://observatory.example", token, transportFunc(func(request *http.Request) (*http.Response, error) {
|
||||
request.RemoteAddr = "127.0.0.1:40000"
|
||||
response := httptest.NewRecorder()
|
||||
server.Handler().ServeHTTP(response, request)
|
||||
return response.Result(), nil
|
||||
}))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
batch := model.Batch{Version: 1, SourceID: "source", StreamID: "access", Sequence: 1, ObservedAt: now, Signal: model.SignalLogs, Records: []model.Observation{{Timestamp: now, Name: "request"}}}
|
||||
ack, err := client.Send(context.Background(), batch)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expected, err := batch.Digest()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if ack.BatchDigest != expected || ack.Digest == ack.BatchDigest {
|
||||
t.Fatalf("ack=%+v expected batch digest=%s", ack, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendRejectsMismatchedAcknowledgementWithoutEchoingBody(t *testing.T) {
|
||||
credential := "obs1.source." + strings.Repeat("a", 64)
|
||||
client, err := New("https://observatory.example", credential, transportFunc(func(*http.Request) (*http.Response, error) {
|
||||
return &http.Response{StatusCode: http.StatusAccepted, Header: make(http.Header), Body: io.NopCloser(strings.NewReader(`{"source_id":"source","stream_id":"access","sequence":1,"digest":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","batch_digest":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"}`))}, nil
|
||||
}))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
batch := model.Batch{Version: 1, SourceID: "source", StreamID: "access", Sequence: 1, ObservedAt: now, Signal: model.SignalLogs, Records: []model.Observation{{Timestamp: now, Name: "request", Body: "do-not-echo"}}}
|
||||
_, err = client.Send(context.Background(), batch)
|
||||
if err == nil || strings.Contains(err.Error(), "do-not-echo") {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendAlertTransitionUsesExactEndpointAndRejectsMismatchedAcknowledgement(t *testing.T) {
|
||||
credential := "obs1.source." + strings.Repeat("a", 64)
|
||||
now := time.Date(2026, 8, 18, 23, 50, 0, 0, time.UTC)
|
||||
transition := model.AlertTransition{Version: model.AlertTransitionVersion, RuleID: "rule-a", RuleRevision: 2, AgentEpoch: strings.Repeat("b", 32), Sequence: 3, StreamID: "requests", BatchSequence: 8, SegmentDigest: strings.Repeat("c", 64), WindowStart: now.Add(-time.Minute), WindowEnd: now, State: "matched", ObservedAt: now}
|
||||
digest, err := transition.Digest()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var path, authorization string
|
||||
client, err := New("https://observatory.example", credential, transportFunc(func(request *http.Request) (*http.Response, error) {
|
||||
path = request.URL.Path
|
||||
authorization = request.Header.Get("Authorization")
|
||||
body, readErr := io.ReadAll(request.Body)
|
||||
if readErr != nil || !strings.Contains(string(body), `"segment_digest":"`+transition.SegmentDigest+`"`) {
|
||||
t.Fatalf("body=%q err=%v", string(body), readErr)
|
||||
}
|
||||
response := fmt.Sprintf(`{"source_id":"source","rule_id":"rule-a","rule_revision":2,"agent_epoch":"%s","sequence":3,"digest":"%s","duplicate":false}`, transition.AgentEpoch, digest)
|
||||
return &http.Response{StatusCode: http.StatusAccepted, Header: make(http.Header), Body: io.NopCloser(strings.NewReader(response))}, nil
|
||||
}))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ack, err := client.SendAlertTransition(context.Background(), transition)
|
||||
if err != nil || ack.Digest != digest || path != "/api/v1/agent/alert-transition" || authorization != "Bearer "+credential {
|
||||
t.Fatalf("ack=%+v path=%q authorization=%q err=%v", ack, path, authorization, err)
|
||||
}
|
||||
|
||||
mismatch, err := New("https://observatory.example", credential, transportFunc(func(*http.Request) (*http.Response, error) {
|
||||
return &http.Response{StatusCode: http.StatusAccepted, Header: make(http.Header), Body: io.NopCloser(strings.NewReader(fmt.Sprintf(`{"source_id":"source","rule_id":"rule-a","rule_revision":2,"agent_epoch":"%s","sequence":4,"digest":"%s","duplicate":false}`, transition.AgentEpoch, digest)))}, nil
|
||||
}))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err = mismatch.SendAlertTransition(context.Background(), transition); err == nil || !strings.Contains(err.Error(), "does not match") {
|
||||
t.Fatalf("mismatch err=%v", err)
|
||||
}
|
||||
wrongSource, err := New("https://observatory.example", credential, transportFunc(func(*http.Request) (*http.Response, error) {
|
||||
return &http.Response{StatusCode: http.StatusAccepted, Header: make(http.Header), Body: io.NopCloser(strings.NewReader(fmt.Sprintf(`{"source_id":"other","rule_id":"rule-a","rule_revision":2,"agent_epoch":"%s","sequence":3,"digest":"%s","duplicate":false}`, transition.AgentEpoch, digest)))}, nil
|
||||
}))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err = wrongSource.SendAlertTransition(context.Background(), transition); err == nil || !strings.Contains(err.Error(), "does not match") {
|
||||
t.Fatalf("wrong source err=%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnrollAndRevokeUseExactHTTPSEndpoints(t *testing.T) {
|
||||
enrollment := "obse1." + strings.Repeat("e", 64)
|
||||
credential := "obs1.source." + strings.Repeat("a", 64)
|
||||
var methods []string
|
||||
transport := transportFunc(func(request *http.Request) (*http.Response, error) {
|
||||
methods = append(methods, request.Method+" "+request.URL.Path)
|
||||
switch request.URL.Path {
|
||||
case "/api/v1/agent/enroll":
|
||||
if request.Header.Get("Authorization") != "Bearer "+enrollment {
|
||||
t.Fatal("enrollment authorization missing")
|
||||
}
|
||||
return &http.Response{StatusCode: http.StatusCreated, Header: make(http.Header), Body: io.NopCloser(strings.NewReader(`{"source_id":"source","credential":"` + credential + `"}`))}, nil
|
||||
case "/api/v1/agent/source":
|
||||
if request.Header.Get("Authorization") != "Bearer "+credential {
|
||||
t.Fatal("source authorization missing")
|
||||
}
|
||||
return &http.Response{StatusCode: http.StatusNoContent, Header: make(http.Header), Body: http.NoBody}, nil
|
||||
default:
|
||||
t.Fatalf("unexpected endpoint %s", request.URL.Path)
|
||||
return nil, nil
|
||||
}
|
||||
})
|
||||
result, err := Enroll(context.Background(), "https://observatory.example", enrollment, transport)
|
||||
if err != nil || result.SourceID != "source" || result.Credential != credential {
|
||||
t.Fatalf("result=%+v err=%v", result, err)
|
||||
}
|
||||
if err = RevokeSource(context.Background(), "https://observatory.example", credential, transport); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(methods) != 2 || methods[0] != "POST /api/v1/agent/enroll" || methods[1] != "DELETE /api/v1/agent/source" {
|
||||
t.Fatalf("methods=%v", methods)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user