feat(observability): log authenticated read routes

This commit is contained in:
Josh Creek
2026-09-01 16:14:20 +01:00
parent e62909d457
commit 5812386676
3 changed files with 73 additions and 3 deletions
+51
View File
@@ -961,6 +961,57 @@ func TestQueueRecoveryAPIIsAuthenticatedOwnerOnlyAndExpiresStaleTickets(t *testi
_ = response.Body.Close()
}
func TestReadOnlyAPIsEmitLifecycleEvents(t *testing.T) {
now := time.Unix(1000, 0).UTC()
sessions := domain.NewSessionStore()
session, token, err := sessions.Issue("player-a", time.Hour, now)
if err != nil {
t.Fatal(err)
}
queue := domain.NewQueue()
if _, err := queue.Create("player-a", "ticket-read-123456", "create-read-123456", domain.Candidate{PlayerID: "player-a", TicketID: "ticket-read-123456", Playlist: domain.Casual, EnqueuedAt: now}, now); err != nil {
t.Fatal(err)
}
proposal, err := domain.NewProposal("proposal-read-123456", domain.Casual, []string{"player-a", "player-b"}, now)
if err != nil {
t.Fatal(err)
}
events := make([]observability.Event, 0)
service := &Service{
Sessions: sessions, Queue: queue, Proposals: map[string]*domain.Proposal{proposal.ProposalID: &proposal},
RankedProfiles: map[string]domain.RankedProfile{"player-a": {Rating: domain.Rating{Value: 1500, RD: 100, Volatility: 0.06}}},
TierPolicy: domain.DefaultTierPolicy(), Now: func() time.Time { return now },
Assignment: func(_ context.Context, playerID, matchID string, _ time.Time) (AssignmentView, error) {
return AssignmentView{MatchID: matchID, PlayerID: playerID, ServerID: "server-read", Slot: 0, ProtocolVersion: 1, Transport: "enet", Endpoint: "127.0.0.1:30001", JoinAuthorisation: "join-token", ExpiresAt: now.Add(time.Minute)}, nil
},
Log: func(event observability.Event) { events = append(events, event) },
}
server := httptest.NewServer(service.Handler())
defer server.Close()
auth := "Bearer " + session.SessionID + ":" + token
for _, path := range []string{"/v1/queue/ticket-read-123456", "/v1/proposals/proposal-read-123456", "/v1/assignments/match-read-123456", "/api/v1/profile", "/v1/profile/ranked"} {
req, _ := http.NewRequest(http.MethodGet, server.URL+path, nil)
req.Header.Set("Authorization", auth)
response, requestErr := http.DefaultClient.Do(req)
if requestErr != nil {
t.Fatal(requestErr)
}
if response.StatusCode != http.StatusOK {
t.Fatalf("GET %s status = %d", path, response.StatusCode)
}
response.Body.Close()
}
seen := map[string]bool{}
for _, event := range events {
seen[event.Event] = true
}
for _, eventName := range []string{"queue_get", "proposal_get", "assignment_get", "profile_get", "ranked_profile_get"} {
if !seen[eventName] {
t.Fatalf("read event %q missing from %+v", eventName, events)
}
}
}
func TestAuthenticatedProposalAPIUsesRevisionAndIdempotencyPolicy(t *testing.T) {
now := time.Unix(1000, 0).UTC()
sessions := domain.NewSessionStore()