package credentialops

import (
	"bytes"
	"context"
	"crypto/sha256"
	"database/sql"
	"encoding/base64"
	"encoding/hex"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"reflect"
	"strings"
	"sync"
	"testing"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"go.uber.org/zap/zaptest"

	"iop/apps/control-plane/internal/credentialseal"
	"iop/apps/control-plane/internal/credentialstore"
)

// fakeSealer is a deterministic test sealer that produces a fixed envelope
// from any input. It records each Seal call for assertion.
type fakeSealer struct {
	mu       sync.Mutex
	calls    []sealCall
	envelope credentialstore.SecretEnvelope
	err      error
}

type sealCall struct {
	plaintext []byte
	ctx_      credentialseal.Context
}

func newFakeSealer(t *testing.T) *fakeSealer {
	t.Helper()
	return &fakeSealer{
		envelope: credentialstore.SecretEnvelope{
			Algorithm:  "AES-256-GCM",
			KeyID:      "fake-key",
			KeyVersion: 1,
			Nonce:      []byte("fake-nonce-01234"),
			Ciphertext: []byte("fake-ciphertext-val"),
			AAD:        []byte("fake-aad-val"),
		},
	}
}

func (f *fakeSealer) Seal(_ context.Context, plaintext []byte, ctx_ credentialseal.Context) (credentialstore.SecretEnvelope, error) {
	f.mu.Lock()
	defer f.mu.Unlock()
	if f.err != nil {
		return credentialstore.SecretEnvelope{}, f.err
	}
	f.calls = append(f.calls, sealCall{plaintext: append([]byte(nil), plaintext...), ctx_: ctx_})
	return f.envelope, nil
}

func (f *fakeSealer) callCount() int {
	f.mu.Lock()
	defer f.mu.Unlock()
	return len(f.calls)
}

type logCapture struct {
	mu  sync.Mutex
	buf bytes.Buffer
}

func (lc *logCapture) Write(p []byte) (n int, err error) {
	lc.mu.Lock()
	defer lc.mu.Unlock()
	return lc.buf.Write(p)
}

func (lc *logCapture) String() string {
	lc.mu.Lock()
	defer lc.mu.Unlock()
	return lc.buf.String()
}

func newTestServiceWithLogs(t *testing.T, sealer SecretSealer) (*Service, *credentialstore.Store, *credentialstore.IssuedPrincipal, *logCapture) {
	t.Helper()
	ctx := context.Background()

	reg := credentialstore.EnvelopeKeyRegistry(newFakeKeyRegistryForService())
	dbPath := "file:iop_credentialops_test_" + strings.ReplaceAll(t.Name(), "/", "_") + ".db?mode=memory&cache=shared"
	store, err := credentialstore.Open(ctx, dbPath, credentialstore.WithEnvelopeKeyRegistry(reg))
	if err != nil {
		t.Fatalf("open store: %v", err)
	}
	t.Cleanup(func() { _ = store.Close() })

	issued, err := store.CreatePrincipalWithToken(ctx, credentialstore.CreatePrincipalInput{Alias: "test-principal"})
	if err != nil {
		t.Fatalf("create principal: %v", err)
	}

	capture := &logCapture{}
	core := zapcore.NewCore(zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig()), zapcore.AddSync(capture), zapcore.DebugLevel)
	logger := zap.New(core)

	svc := NewService(store, logger, sealer, nil)
	return svc, store, issued, capture
}

func newTestService(t *testing.T, sealer SecretSealer) (*Service, *credentialstore.Store, *credentialstore.IssuedPrincipal) {
	t.Helper()
	svc, store, issued, _ := newTestServiceWithLogs(t, sealer)
	return svc, store, issued
}

type fakeKeyRegistryForService struct {
	keys map[string]map[uint64]bool
}

func newFakeKeyRegistryForService() *fakeKeyRegistryForService {
	f := &fakeKeyRegistryForService{keys: make(map[string]map[uint64]bool)}
	f.RegisterKey("fake-key", 1)
	return f
}

func (f *fakeKeyRegistryForService) RegisterKey(keyID string, version uint64) {
	if f.keys[keyID] == nil {
		f.keys[keyID] = make(map[uint64]bool)
	}
	f.keys[keyID][version] = true
}

func (f *fakeKeyRegistryForService) HasEnvelopeKey(_ context.Context, keyID string, keyVersion uint64) (bool, error) {
	if versions, ok := f.keys[keyID]; ok {
		return versions[keyVersion], nil
	}
	return false, nil
}

var _ credentialstore.EnvelopeKeyRegistry = (*fakeKeyRegistryForService)(nil)

func digestOf(raw []byte) string {
	sum := sha256.Sum256(raw)
	return hex.EncodeToString(sum[:])
}

// ---------------------------------------------------------------------------
// API-1: Own-principal lifecycle & Create/Rotate Secret Handoff
// ---------------------------------------------------------------------------

func TestServiceCreateAndRotatePassSuppliedSecretOnlyToSealer(t *testing.T) {
	fake := newFakeSealer(t)
	svc, store, issued := newTestService(t, fake)
	ctx := context.Background()

	secret1 := []byte("provider-secret-payload-alpha")
	created, err := svc.CreateSlot(ctx, []byte(issued.RawToken), CreateSlotInput{
		Vendor:         "openai",
		CredentialKind: credentialstore.CredentialKindBearer,
		Alias:          "create-slot-1",
		ProviderSecret: secret1,
	})
	if err != nil {
		t.Fatalf("CreateSlot: %v", err)
	}
	if created.Alias != "create-slot-1" {
		t.Fatalf("CreateSlot alias mismatch: got %q want create-slot-1", created.Alias)
	}
	if created.Status != credentialstore.StatusDraft {
		t.Fatalf("CreateSlot initial status: got %q want draft", created.Status)
	}

	if fake.callCount() != 1 {
		t.Fatalf("sealer call count after create: got %d want 1", fake.callCount())
	}
	if string(fake.calls[0].plaintext) != "provider-secret-payload-alpha" {
		t.Fatalf("sealer received plaintext mismatch: got %q", string(fake.calls[0].plaintext))
	}
	if fake.calls[0].ctx_.PrincipalID != issued.Principal.ID {
		t.Fatalf("sealer ctx PrincipalID mismatch: got %q want %q", fake.calls[0].ctx_.PrincipalID, issued.Principal.ID)
	}

	storedSlot, err := store.GetSlot(ctx, issued.Principal.ID, created.ID)
	if err != nil {
		t.Fatalf("GetSlot from store: %v", err)
	}
	if string(storedSlot.Envelope.Ciphertext) != "fake-ciphertext-val" {
		t.Fatalf("stored envelope ciphertext mismatch: got %q", string(storedSlot.Envelope.Ciphertext))
	}

	_, err = svc.CreateRoute(ctx, []byte(issued.RawToken), CreateRouteInput{
		SlotID:        created.ID,
		Alias:         "route-1",
		ProfileID:     "openai",
		UpstreamModel: "gpt-4o",
	})
	if err != nil {
		t.Fatalf("CreateRoute: %v", err)
	}
	activeSlot, err := svc.GetSlot(ctx, []byte(issued.RawToken), created.ID)
	if err != nil {
		t.Fatalf("GetSlot: %v", err)
	}

	secret2 := []byte("provider-secret-payload-beta")
	rotated, err := svc.RotateSlot(ctx, []byte(issued.RawToken), RotateSlotInput{
		SlotID:         created.ID,
		Revision:       activeSlot.Revision,
		ProviderSecret: secret2,
	})
	if err != nil {
		t.Fatalf("RotateSlot: %v", err)
	}
	if rotated.Revision != activeSlot.Revision+1 {
		t.Fatalf("RotateSlot revision: got %d want %d", rotated.Revision, activeSlot.Revision+1)
	}

	if fake.callCount() != 2 {
		t.Fatalf("sealer call count after rotate: got %d want 2", fake.callCount())
	}
	if string(fake.calls[1].plaintext) != "provider-secret-payload-beta" {
		t.Fatalf("sealer received plaintext mismatch on rotate: got %q", string(fake.calls[1].plaintext))
	}
	if fake.calls[1].ctx_.SlotID != created.ID {
		t.Fatalf("sealer ctx SlotID mismatch: got %q want %q", fake.calls[1].ctx_.SlotID, created.ID)
	}
}

func TestServiceScopesOperationsToAuthenticatedPrincipal(t *testing.T) {
	svc, _, issued := newTestService(t, newFakeSealer(t))
	ctx := context.Background()

	slot, err := svc.CreateSlot(ctx, []byte(issued.RawToken), CreateSlotInput{
		Vendor:         "openai",
		CredentialKind: credentialstore.CredentialKindBearer,
		Alias:          "lifecycle-slot",
		ProviderSecret: []byte("secret-data"),
	})
	if err != nil {
		t.Fatalf("CreateSlot: %v", err)
	}

	route, err := svc.CreateRoute(ctx, []byte(issued.RawToken), CreateRouteInput{
		SlotID:        slot.ID,
		Alias:         "lifecycle-route",
		ProfileID:     "openai",
		UpstreamModel: "gpt-4o",
	})
	if err != nil {
		t.Fatalf("CreateRoute: %v", err)
	}
	_ = route

	activeSlot, err := svc.GetSlot(ctx, []byte(issued.RawToken), slot.ID)
	if err != nil {
		t.Fatalf("GetSlot: %v", err)
	}
	if activeSlot.Status != credentialstore.StatusActive {
		t.Fatalf("GetSlot status: got %q want active", activeSlot.Status)
	}

	disabled, err := svc.DisableSlot(ctx, []byte(issued.RawToken), slot.ID, activeSlot.Revision)
	if err != nil {
		t.Fatalf("DisableSlot: %v", err)
	}
	if disabled.Status != credentialstore.StatusDisabled {
		t.Fatalf("DisableSlot status: got %q want disabled", disabled.Status)
	}

	enabled, err := svc.EnableSlot(ctx, []byte(issued.RawToken), slot.ID, disabled.Revision)
	if err != nil {
		t.Fatalf("EnableSlot: %v", err)
	}
	if enabled.Status != credentialstore.StatusActive {
		t.Fatalf("EnableSlot status: got %q want active", enabled.Status)
	}

	rotated, err := svc.RotateSlot(ctx, []byte(issued.RawToken), RotateSlotInput{
		SlotID:         slot.ID,
		Revision:       enabled.Revision,
		ProviderSecret: []byte("new-secret-data"),
	})
	if err != nil {
		t.Fatalf("RotateSlot: %v", err)
	}
	if rotated.Revision != enabled.Revision+1 {
		t.Fatalf("RotateSlot revision: got %d want %d", rotated.Revision, enabled.Revision+1)
	}

	revoked, err := svc.RevokeSlot(ctx, []byte(issued.RawToken), slot.ID, rotated.Revision)
	if err != nil {
		t.Fatalf("RevokeSlot: %v", err)
	}
	if revoked.Status != credentialstore.StatusRevoked {
		t.Fatalf("RevokeSlot status: got %q want revoked", revoked.Status)
	}
	if revoked.RevokedAt == nil {
		t.Fatal("RevokeSlot must set RevokedAt")
	}

	slots, err := svc.ListSlots(ctx, []byte(issued.RawToken))
	if err != nil {
		t.Fatalf("ListSlots: %v", err)
	}
	if len(slots) != 1 {
		t.Fatalf("ListSlots count: got %d want 1", len(slots))
	}
	if slots[0].Status != credentialstore.StatusRevoked {
		t.Fatalf("ListSlots status: got %q want revoked", slots[0].Status)
	}
}

func TestServiceTokenCreateListLifecycle(t *testing.T) {
	svc, _, issued1 := newTestService(t, newFakeSealer(t))
	ctx := context.Background()

	token1 := []byte(issued1.RawToken)

	tok2, err := svc.CreateToken(ctx, token1)
	if err != nil {
		t.Fatalf("CreateToken 2: %v", err)
	}
	if tok2.RawToken == "" {
		t.Fatal("CreateToken must return raw token once")
	}

	tok3, err := svc.CreateToken(ctx, token1)
	if err != nil {
		t.Fatalf("CreateToken 3: %v", err)
	}
	if tok3.RawToken == "" {
		t.Fatal("CreateToken must return raw token once")
	}

	tokens, err := svc.ListTokens(ctx, token1)
	if err != nil {
		t.Fatalf("ListTokens: %v", err)
	}
	if len(tokens) != 3 {
		t.Fatalf("ListTokens count: got %d want 3", len(tokens))
	}
	for _, tok := range tokens {
		if tok.Status != credentialstore.StatusActive {
			t.Fatalf("token status: got %q want active", tok.Status)
		}
	}

	disabledTok2, err := svc.DisableToken(ctx, token1, tok2.Token.TokenRef, tok2.Token.Revision)
	if err != nil {
		t.Fatalf("DisableToken tok2: %v", err)
	}
	if disabledTok2.Status != credentialstore.StatusDisabled {
		t.Fatalf("DisableToken status: got %q want disabled", disabledTok2.Status)
	}

	_, err = svc.DisableToken(ctx, token1, tok2.Token.TokenRef, tok2.Token.Revision)
	if !errors.Is(err, ErrStaleRevision) {
		t.Fatalf("expected ErrStaleRevision for stale DisableToken, got: %v", err)
	}

	revokedTok2, err := svc.RevokeToken(ctx, token1, tok2.Token.TokenRef, disabledTok2.Revision)
	if err != nil {
		t.Fatalf("RevokeToken tok2: %v", err)
	}
	if revokedTok2.Status != credentialstore.StatusRevoked {
		t.Fatalf("RevokeToken status: got %q want revoked", revokedTok2.Status)
	}
	if revokedTok2.RevokedAt == nil {
		t.Fatal("RevokeToken must set RevokedAt")
	}

	_, err = svc.DisableToken(ctx, token1, issued1.Token.TokenRef, issued1.Token.Revision)
	if err != nil {
		t.Fatalf("DisableToken tok1: %v", err)
	}
	_, err = svc.ListSlots(ctx, token1)
	if !errors.Is(err, ErrUnauthorized) {
		t.Fatalf("expected ErrUnauthorized using disabled tok1, got: %v", err)
	}

	slotsTok3, err := svc.ListSlots(ctx, []byte(tok3.RawToken))
	if err != nil {
		t.Fatalf("ListSlots using active tok3: %v", err)
	}
	if len(slotsTok3) != 0 {
		t.Fatalf("expected 0 slots, got %d", len(slotsTok3))
	}
}

func TestServiceRejectsCrossPrincipalTokenReferences(t *testing.T) {
	svc, store, issued1 := newTestService(t, newFakeSealer(t))
	ctx := context.Background()

	issued2, err := store.CreatePrincipalWithToken(ctx, credentialstore.CreatePrincipalInput{Alias: "p2-principal"})
	if err != nil {
		t.Fatalf("create principal 2: %v", err)
	}

	token1 := []byte(issued1.RawToken)
	token2 := []byte(issued2.RawToken)

	tok1_2, err := svc.CreateToken(ctx, token1)
	if err != nil {
		t.Fatalf("CreateToken for p1: %v", err)
	}

	_, err = svc.DisableToken(ctx, token2, tok1_2.Token.TokenRef, tok1_2.Token.Revision)
	if !errors.Is(err, ErrNotFound) {
		t.Fatalf("expected ErrNotFound for cross-principal DisableToken, got: %v", err)
	}

	_, err = svc.RevokeToken(ctx, token2, tok1_2.Token.TokenRef, tok1_2.Token.Revision)
	if !errors.Is(err, ErrNotFound) {
		t.Fatalf("expected ErrNotFound for cross-principal RevokeToken, got: %v", err)
	}
}

func TestServiceRouteCreateUpdateLifecycle(t *testing.T) {
	svc, _, issued := newTestService(t, newFakeSealer(t))
	ctx := context.Background()

	token := []byte(issued.RawToken)
	slot, err := svc.CreateSlot(ctx, token, CreateSlotInput{
		Vendor:         "openai",
		CredentialKind: credentialstore.CredentialKindBearer,
		Alias:          "route-slot",
		ProviderSecret: []byte("secret-payload"),
	})
	if err != nil {
		t.Fatalf("CreateSlot: %v", err)
	}

	route, err := svc.CreateRoute(ctx, token, CreateRouteInput{
		SlotID:           slot.ID,
		Alias:            "route-alias",
		ProfileID:        "openai",
		UpstreamModel:    "gpt-4o",
		ResourceSelector: "default",
	})
	if err != nil {
		t.Fatalf("CreateRoute: %v", err)
	}
	if route.Alias != "route-alias" {
		t.Fatalf("Route alias mismatch: got %q want route-alias", route.Alias)
	}

	updatedRoute, err := svc.UpdateRoute(ctx, token, UpdateRouteInput{
		RouteID:          route.ID,
		CurrentRevision:  route.Revision,
		SlotID:           slot.ID,
		Alias:            "updated-route-alias",
		ProfileID:        "openai",
		UpstreamModel:    "gpt-4o-mini",
		ResourceSelector: "default",
	})
	if err != nil {
		t.Fatalf("UpdateRoute: %v", err)
	}
	if updatedRoute.Alias != "updated-route-alias" {
		t.Fatalf("Updated route alias: got %q want updated-route-alias", updatedRoute.Alias)
	}
	if updatedRoute.UpstreamModel != "gpt-4o-mini" {
		t.Fatalf("Updated route model: got %q want gpt-4o-mini", updatedRoute.UpstreamModel)
	}
	if updatedRoute.Revision != route.Revision+1 {
		t.Fatalf("Updated route revision: got %d want %d", updatedRoute.Revision, route.Revision+1)
	}

	_, err = svc.UpdateRoute(ctx, token, UpdateRouteInput{
		RouteID:          route.ID,
		CurrentRevision:  route.Revision,
		SlotID:           slot.ID,
		Alias:            "stale-update",
		ProfileID:        "openai",
		UpstreamModel:    "gpt-4o",
		ResourceSelector: "default",
	})
	if !errors.Is(err, ErrStaleRevision) {
		t.Fatalf("expected ErrStaleRevision on UpdateRoute with stale rev, got: %v", err)
	}
}

// ---------------------------------------------------------------------------
// API-1: Cross-principal denial
// ---------------------------------------------------------------------------

func TestServiceRejectsCrossPrincipalTargets(t *testing.T) {
	svc, store, issued1 := newTestService(t, newFakeSealer(t))
	ctx := context.Background()

	issued2, err := store.CreatePrincipalWithToken(ctx, credentialstore.CreatePrincipalInput{Alias: "other-principal"})
	if err != nil {
		t.Fatalf("create second principal: %v", err)
	}

	token1 := []byte(issued1.RawToken)
	token2 := []byte(issued2.RawToken)

	slot, err := svc.CreateSlot(ctx, token1, CreateSlotInput{
		Vendor:         "openai",
		CredentialKind: credentialstore.CredentialKindBearer,
		Alias:          "cross-slot",
		ProviderSecret: []byte("p1-secret"),
	})
	if err != nil {
		t.Fatalf("CreateSlot: %v", err)
	}

	route, err := svc.CreateRoute(ctx, token1, CreateRouteInput{
		SlotID:        slot.ID,
		Alias:         "cross-route",
		ProfileID:     "openai",
		UpstreamModel: "gpt-4o",
	})
	if err != nil {
		t.Fatalf("CreateRoute: %v", err)
	}

	_, err = svc.GetSlot(ctx, token2, slot.ID)
	if !errors.Is(err, ErrNotFound) {
		t.Fatalf("expected ErrNotFound for cross-principal GetSlot, got: %v", err)
	}

	_, err = svc.DisableSlot(ctx, token2, slot.ID, slot.Revision)
	if !errors.Is(err, ErrNotFound) {
		t.Fatalf("expected ErrNotFound for cross-principal DisableSlot, got: %v", err)
	}

	_, err = svc.RotateSlot(ctx, token2, RotateSlotInput{SlotID: slot.ID, Revision: slot.Revision, ProviderSecret: []byte("hack")})
	if !errors.Is(err, ErrNotFound) {
		t.Fatalf("expected ErrNotFound for cross-principal RotateSlot, got: %v", err)
	}

	slots, err := svc.ListSlots(ctx, token2)
	if err != nil {
		t.Fatalf("ListSlots for other principal: %v", err)
	}
	if len(slots) != 0 {
		t.Fatalf("expected empty list for cross-principal, got %d slots", len(slots))
	}

	_, err = svc.GetRoute(ctx, token2, route.ID)
	if !errors.Is(err, ErrNotFound) {
		t.Fatalf("expected ErrNotFound for cross-principal GetRoute, got: %v", err)
	}

	_, err = svc.UpdateRoute(ctx, token2, UpdateRouteInput{
		RouteID:         route.ID,
		CurrentRevision: route.Revision,
		SlotID:          slot.ID,
		Alias:           "p2-alias",
		ProfileID:       "openai",
		UpstreamModel:   "gpt-4o",
	})
	if !errors.Is(err, ErrNotFound) {
		t.Fatalf("expected ErrNotFound for cross-principal UpdateRoute, got: %v", err)
	}

	_, err = svc.CreateRoute(ctx, token2, CreateRouteInput{
		SlotID:        slot.ID,
		Alias:         "cross-bind",
		ProfileID:     "openai",
		UpstreamModel: "gpt-4o",
	})
	if !errors.Is(err, ErrNotFound) {
		t.Fatalf("expected ErrNotFound for cross-principal CreateRoute targeting p1 slot, got: %v", err)
	}
}

// ---------------------------------------------------------------------------
// API-1: Stale revision conflict
// ---------------------------------------------------------------------------

func TestServiceRejectsStaleRevision(t *testing.T) {
	svc, _, issued := newTestService(t, newFakeSealer(t))
	ctx := context.Background()

	token := []byte(issued.RawToken)
	slot, err := svc.CreateSlot(ctx, token, CreateSlotInput{
		Vendor:         "openai",
		CredentialKind: credentialstore.CredentialKindBearer,
		Alias:          "stale-slot",
		ProviderSecret: []byte("stale-secret"),
	})
	if err != nil {
		t.Fatalf("CreateSlot: %v", err)
	}
	route, err := svc.CreateRoute(ctx, token, CreateRouteInput{
		SlotID:        slot.ID,
		Alias:         "stale-route",
		ProfileID:     "openai",
		UpstreamModel: "gpt-4o",
	})
	if err != nil {
		t.Fatalf("CreateRoute: %v", err)
	}

	activeSlot, err := svc.GetSlot(ctx, token, slot.ID)
	if err != nil {
		t.Fatalf("GetSlot: %v", err)
	}

	disabledSlot, err := svc.DisableSlot(ctx, token, slot.ID, activeSlot.Revision)
	if err != nil {
		t.Fatalf("first disable: %v", err)
	}

	_, err = svc.DisableSlot(ctx, token, slot.ID, activeSlot.Revision)
	if !errors.Is(err, ErrStaleRevision) {
		t.Fatalf("expected ErrStaleRevision on second DisableSlot, got: %v", err)
	}

	_, err = svc.RotateSlot(ctx, token, RotateSlotInput{SlotID: slot.ID, Revision: activeSlot.Revision, ProviderSecret: []byte("new-sec")})
	if !errors.Is(err, ErrStaleRevision) {
		t.Fatalf("expected ErrStaleRevision on RotateSlot, got: %v", err)
	}

	enabledSlot, err := svc.EnableSlot(ctx, token, slot.ID, disabledSlot.Revision)
	if err != nil {
		t.Fatalf("EnableSlot: %v", err)
	}

	updatedRoute, err := svc.UpdateRoute(ctx, token, UpdateRouteInput{
		RouteID:         route.ID,
		CurrentRevision: route.Revision,
		SlotID:          enabledSlot.ID,
		Alias:           "updated-route",
		ProfileID:       "openai",
		UpstreamModel:   "gpt-4o-mini",
	})
	if err != nil {
		t.Fatalf("first UpdateRoute: %v", err)
	}
	_ = updatedRoute

	_, err = svc.UpdateRoute(ctx, token, UpdateRouteInput{
		RouteID:         route.ID,
		CurrentRevision: route.Revision,
		SlotID:          enabledSlot.ID,
		Alias:           "stale-update",
		ProfileID:       "openai",
		UpstreamModel:   "gpt-4o",
	})
	if !errors.Is(err, ErrStaleRevision) {
		t.Fatalf("expected ErrStaleRevision on UpdateRoute with stale rev, got: %v", err)
	}
}

// ---------------------------------------------------------------------------
// API-1: Missing sealer failure (fail-closed)
// ---------------------------------------------------------------------------

func TestServiceRequiresSealerForSecretMutation(t *testing.T) {
	ctx := context.Background()
	reg := credentialstore.EnvelopeKeyRegistry(newFakeKeyRegistryForService())
	dbPath := "file:iop_credentialops_nosealer_" + strings.ReplaceAll(t.Name(), "/", "_") + ".db?mode=memory&cache=shared"
	store, err := credentialstore.Open(ctx, dbPath, credentialstore.WithEnvelopeKeyRegistry(reg))
	if err != nil {
		t.Fatalf("open store: %v", err)
	}
	t.Cleanup(func() { _ = store.Close() })

	issued, err := store.CreatePrincipalWithToken(ctx, credentialstore.CreatePrincipalInput{Alias: "nosealer-principal"})
	if err != nil {
		t.Fatalf("create principal: %v", err)
	}

	capture := &logCapture{}
	core := zapcore.NewCore(zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig()), zapcore.AddSync(capture), zapcore.DebugLevel)
	logger := zap.New(core)

	svcWithoutSealer := NewService(store, logger, nil, nil)

	_, err = svcWithoutSealer.CreateSlot(ctx, []byte(issued.RawToken), CreateSlotInput{
		Vendor:         "openai",
		CredentialKind: credentialstore.CredentialKindBearer,
		Alias:          "nosealer-slot",
		ProviderSecret: []byte("nosealer-secret"),
	})
	if !errors.Is(err, ErrSealerUnavailable) {
		t.Fatalf("expected ErrSealerUnavailable on CreateSlot without sealer, got: %v", err)
	}

	slots, err := store.ListSlots(ctx, issued.Principal.ID)
	if err != nil {
		t.Fatalf("ListSlots: %v", err)
	}
	if len(slots) != 0 {
		t.Fatalf("expected 0 slots after failed CreateSlot, got %d", len(slots))
	}

	svcWithSealer := NewService(store, logger, newFakeSealer(t), nil)
	slot, err := svcWithSealer.CreateSlot(ctx, []byte(issued.RawToken), CreateSlotInput{
		Vendor:         "openai",
		CredentialKind: credentialstore.CredentialKindBearer,
		Alias:          "sealer-slot",
		ProviderSecret: []byte("sealer-secret"),
	})
	if err != nil {
		t.Fatalf("CreateSlot with sealer: %v", err)
	}

	_, err = svcWithoutSealer.RotateSlot(ctx, []byte(issued.RawToken), RotateSlotInput{
		SlotID:         slot.ID,
		Revision:       slot.Revision,
		ProviderSecret: []byte("new-secret"),
	})
	if !errors.Is(err, ErrSealerUnavailable) {
		t.Fatalf("expected ErrSealerUnavailable on RotateSlot without sealer, got: %v", err)
	}

	slotAfter, err := store.GetSlot(ctx, issued.Principal.ID, slot.ID)
	if err != nil {
		t.Fatalf("GetSlot: %v", err)
	}
	if slotAfter.Revision != slot.Revision {
		t.Fatalf("revision changed after failed RotateSlot: got %d want %d", slotAfter.Revision, slot.Revision)
	}
}

// ---------------------------------------------------------------------------
// API-1: Secret-blind responses & Redaction
// ---------------------------------------------------------------------------

func TestServiceResponsesAreSecretBlind(t *testing.T) {
	if _, ok := reflect.TypeOf(SlotRecord{}).FieldByName("Envelope"); ok {
		t.Fatal("secret-blind SlotRecord must not expose an envelope")
	}

	rawIOPTokenSentinel := "RAW_IOP_TOKEN_SENTINEL_998877"
	providerSecretSentinel := "PROVIDER_SECRET_SENTINEL_665544"
	ciphertextSentinel := "CIPHERTEXT_SENTINEL_332211"
	nonceSentinel := "NONCE_SENTINEL_009988"
	aadSentinel := "AAD_SENTINEL_776655"
	digestSentinel := digestOf([]byte(rawIOPTokenSentinel))

	fake := &fakeSealer{
		envelope: credentialstore.SecretEnvelope{
			Algorithm:  "AES-256-GCM",
			KeyID:      "fake-key",
			KeyVersion: 1,
			Nonce:      []byte(nonceSentinel),
			Ciphertext: []byte(ciphertextSentinel),
			AAD:        []byte(aadSentinel),
		},
	}

	svc, store, issued, capture := newTestServiceWithLogs(t, fake)
	ctx := context.Background()

	// Direct DB transaction to set digest sentinel on token row for auth test setup.
	err := store.RunInTransaction(ctx, func(ctx context.Context, tx *sql.Tx) error {
		_, err := tx.ExecContext(ctx, "UPDATE tokens SET digest=?, token_ref=? WHERE principal_id=?", digestSentinel, tokenRefForSentinel(digestSentinel), issued.Principal.ID)
		return err
	})
	if err != nil {
		t.Fatalf("update token digest sentinel: %v", err)
	}

	token := []byte(rawIOPTokenSentinel)
	slot, err := svc.CreateSlot(ctx, token, CreateSlotInput{
		Vendor:         "openai",
		CredentialKind: credentialstore.CredentialKindBearer,
		Alias:          "blind-slot",
		ProviderSecret: []byte(providerSecretSentinel),
	})
	if err != nil {
		t.Fatalf("CreateSlot: %v", err)
	}

	route, err := svc.CreateRoute(ctx, token, CreateRouteInput{
		SlotID:        slot.ID,
		Alias:         "blind-route",
		ProfileID:     "openai",
		UpstreamModel: "gpt-4o",
	})
	if err != nil {
		t.Fatalf("CreateRoute: %v", err)
	}

	activeSlot, err := svc.GetSlot(ctx, token, slot.ID)
	if err != nil {
		t.Fatalf("GetSlot: %v", err)
	}

	rotatedSlot, err := svc.RotateSlot(ctx, token, RotateSlotInput{
		SlotID:         slot.ID,
		Revision:       activeSlot.Revision,
		ProviderSecret: []byte("SECOND_SECRET_SENTINEL"),
	})
	if err != nil {
		t.Fatalf("RotateSlot: %v", err)
	}

	gotSlot, err := svc.GetSlot(ctx, token, slot.ID)
	if err != nil {
		t.Fatalf("GetSlot: %v", err)
	}
	listedSlots, err := svc.ListSlots(ctx, token)
	if err != nil {
		t.Fatalf("ListSlots: %v", err)
	}
	gotRoute, err := svc.GetRoute(ctx, token, route.ID)
	if err != nil {
		t.Fatalf("GetRoute: %v", err)
	}
	listedRoutes, err := svc.ListRoutes(ctx, token)
	if err != nil {
		t.Fatalf("ListRoutes: %v", err)
	}

	_, errNotFound := svc.GetSlot(ctx, token, "nonexistent-slot")

	var rendered strings.Builder
	rendered.WriteString(fmt.Sprintf("%+v\n", slot))
	rendered.WriteString(fmt.Sprintf("%+v\n", rotatedSlot))
	rendered.WriteString(fmt.Sprintf("%+v\n", gotSlot))
	rendered.WriteString(fmt.Sprintf("%+v\n", listedSlots))
	rendered.WriteString(fmt.Sprintf("%+v\n", gotRoute))
	rendered.WriteString(fmt.Sprintf("%+v\n", listedRoutes))
	if errNotFound != nil {
		rendered.WriteString(errNotFound.Error() + "\n")
	}
	rendered.WriteString(capture.String() + "\n")

	renderedStr := rendered.String()
	for _, forbidden := range []string{rawIOPTokenSentinel, providerSecretSentinel, ciphertextSentinel, nonceSentinel, aadSentinel, digestSentinel, "SECOND_SECRET_SENTINEL"} {
		if strings.Contains(renderedStr, forbidden) {
			t.Fatalf("rendered responses/errors/logs contains sensitive sentinel %q", forbidden)
		}
	}
}

func tokenRefForSentinel(digest string) string {
	if len(digest) > 16 {
		return "tok_" + digest[:16]
	}
	return "tok_" + digest
}

func TestServiceRedact(t *testing.T) {
	svc, _, issued := newTestService(t, newFakeSealer(t))
	ctx := context.Background()

	token := []byte(issued.RawToken)

	_, err := svc.GetSlot(ctx, token, "nonexistent")
	if err == nil {
		t.Fatal("expected error")
	}
	if strings.Contains(err.Error(), issued.RawToken) {
		t.Fatalf("error leaks raw token: %v", err)
	}
}

type retainingSealer struct {
	retained []byte
	envelope credentialstore.SecretEnvelope
	err      error
}

func (r *retainingSealer) Seal(_ context.Context, plaintext []byte, _ credentialseal.Context) (credentialstore.SecretEnvelope, error) {
	r.retained = plaintext
	return r.envelope, r.err
}

func TestServiceZeroizesOwnedProviderSecret(t *testing.T) {
	ctx := context.Background()
	validEnv := credentialstore.SecretEnvelope{
		Algorithm:  "AES-256-GCM",
		KeyID:      "fake-key",
		KeyVersion: 1,
		Nonce:      []byte("fake-nonce-01234"),
		Ciphertext: []byte("fake-ciphertext-val"),
	}

	t.Run("success paths zeroize owned and preserve caller", func(t *testing.T) {
		retSealer := &retainingSealer{envelope: validEnv}
		svc, _, issued := newTestService(t, retSealer)
		token := []byte(issued.RawToken)

		secret := []byte("super-secret-provider-key")
		secretCopy := append([]byte(nil), secret...)
		slot, err := svc.CreateSlot(ctx, token, CreateSlotInput{
			Vendor:         "openai",
			CredentialKind: credentialstore.CredentialKindBearer,
			Alias:          "zeroize-slot",
			ProviderSecret: secret,
		})
		if err != nil {
			t.Fatalf("CreateSlot: %v", err)
		}
		if len(retSealer.retained) == 0 {
			t.Fatal("retainingSealer did not capture plaintext slice")
		}
		for i, b := range retSealer.retained {
			if b != 0 {
				t.Fatalf("retained slice byte at index %d is non-zero (%d), expected zeroization", i, b)
			}
		}
		if !bytes.Equal(secret, secretCopy) {
			t.Fatalf("caller secret buffer mutated on CreateSlot: got %q want %q", secret, secretCopy)
		}

		retSealer.retained = nil
		rotateSecret := []byte("rotated-super-secret-key")
		rotateCopy := append([]byte(nil), rotateSecret...)
		_, err = svc.RotateSlot(ctx, token, RotateSlotInput{
			SlotID:         slot.ID,
			Revision:       slot.Revision,
			ProviderSecret: rotateSecret,
		})
		if err != nil {
			t.Fatalf("RotateSlot: %v", err)
		}
		if len(retSealer.retained) == 0 {
			t.Fatal("retainingSealer did not capture plaintext slice on rotate")
		}
		for i, b := range retSealer.retained {
			if b != 0 {
				t.Fatalf("retained slice byte at index %d on rotate is non-zero (%d), expected zeroization", i, b)
			}
		}
		if !bytes.Equal(rotateSecret, rotateCopy) {
			t.Fatalf("caller rotate secret buffer mutated on RotateSlot: got %q want %q", rotateSecret, rotateCopy)
		}
	})

	t.Run("failing paths zeroize owned and preserve caller", func(t *testing.T) {
		retSealer := &retainingSealer{
			envelope: validEnv,
			err:      errors.New("sealer error"),
		}
		svc, _, issued := newTestService(t, retSealer)
		token := []byte(issued.RawToken)

		failCreateSecret := []byte("fail-create-secret")
		failCreateCopy := append([]byte(nil), failCreateSecret...)
		_, err := svc.CreateSlot(ctx, token, CreateSlotInput{
			Vendor:         "openai",
			CredentialKind: credentialstore.CredentialKindBearer,
			Alias:          "fail-create-slot",
			ProviderSecret: failCreateSecret,
		})
		if err == nil {
			t.Fatal("expected error on CreateSlot with failing sealer")
		}
		if len(retSealer.retained) == 0 {
			t.Fatal("retainingSealer did not capture plaintext slice on failing CreateSlot")
		}
		for i, b := range retSealer.retained {
			if b != 0 {
				t.Fatalf("retained slice byte at index %d on failing CreateSlot is non-zero (%d), expected zeroization", i, b)
			}
		}
		if !bytes.Equal(failCreateSecret, failCreateCopy) {
			t.Fatalf("caller secret buffer mutated on failing CreateSlot: got %q want %q", failCreateSecret, failCreateCopy)
		}

		retSealer.err = nil
		retSealer.retained = nil
		validSlot, err := svc.CreateSlot(ctx, token, CreateSlotInput{
			Vendor:         "openai",
			CredentialKind: credentialstore.CredentialKindBearer,
			Alias:          "valid-slot-for-rotate",
			ProviderSecret: []byte("valid-secret"),
		})
		if err != nil {
			t.Fatalf("CreateSlot for valid slot: %v", err)
		}

		retSealer.err = errors.New("rotate sealer error")
		retSealer.retained = nil
		failRotateSecret := []byte("fail-rotate-secret")
		failRotateCopy := append([]byte(nil), failRotateSecret...)
		_, err = svc.RotateSlot(ctx, token, RotateSlotInput{
			SlotID:         validSlot.ID,
			Revision:       validSlot.Revision,
			ProviderSecret: failRotateSecret,
		})
		if err == nil {
			t.Fatal("expected error on RotateSlot with failing sealer")
		}
		if len(retSealer.retained) == 0 {
			t.Fatal("retainingSealer did not capture plaintext slice on failing RotateSlot")
		}
		for i, b := range retSealer.retained {
			if b != 0 {
				t.Fatalf("retained slice byte at index %d on failing RotateSlot is non-zero (%d), expected zeroization", i, b)
			}
		}
		if !bytes.Equal(failRotateSecret, failRotateCopy) {
			t.Fatalf("caller secret buffer mutated on failing RotateSlot: got %q want %q", failRotateSecret, failRotateCopy)
		}
	})
}

func TestServiceSecretHandlingFailureIsBlindAndDoesNotMutate(t *testing.T) {
	ctx := context.Background()

	plaintextSentinel := "REVIEWER_PLAINTEXT_SECRET_SENTINEL_12345"
	errorSentinel := "REVIEWER_SEALER_ERROR_SENTINEL_67890"
	keyIDSentinel := "REVIEWER_KEY_ID_SENTINEL_UNKNOWN_999"
	keyVersionSentinel := uint64(9998877)
	keyVersionSentinelStr := "9998877"
	ciphertextSentinel := "REVIEWER_CIPHERTEXT_SENTINEL_112233"
	nonceSentinel := "REVIEWER_NONCE_SENTINEL_445566"
	aadSentinel := "REVIEWER_AAD_SENTINEL_778899"

	forbiddenSentinels := []string{
		plaintextSentinel,
		errorSentinel,
		keyIDSentinel,
		keyVersionSentinelStr,
		ciphertextSentinel,
		nonceSentinel,
		aadSentinel,
	}

	validEnv := credentialstore.SecretEnvelope{
		Algorithm:  "AES-256-GCM",
		KeyID:      "fake-key",
		KeyVersion: 1,
		Nonce:      []byte("fake-nonce-01234"),
		Ciphertext: []byte("fake-ciphertext-val"),
	}

	mustGetSlot := func(t *testing.T, store *credentialstore.Store, pid, slotID string) *credentialstore.CredentialSlotRecord {
		t.Helper()
		s, err := store.GetSlot(ctx, pid, slotID)
		if err != nil {
			t.Fatalf("GetSlot: %v", err)
		}
		return s
	}

	mustListSlots := func(t *testing.T, store *credentialstore.Store, pid string) []credentialstore.CredentialSlotRecord {
		t.Helper()
		slots, err := store.ListSlots(ctx, pid)
		if err != nil {
			t.Fatalf("ListSlots: %v", err)
		}
		return slots
	}

	mustListSlotRevisions := func(t *testing.T, store *credentialstore.Store, pid, slotID string) []credentialstore.SlotRevisionRecord {
		t.Helper()
		revs, err := store.ListSlotRevisions(ctx, pid, slotID)
		if err != nil {
			t.Fatalf("ListSlotRevisions: %v", err)
		}
		return revs
	}

	mustProjectionGeneration := func(t *testing.T, store *credentialstore.Store) uint64 {
		t.Helper()
		gen, err := store.ProjectionGeneration(ctx)
		if err != nil {
			t.Fatalf("ProjectionGeneration: %v", err)
		}
		return gen
	}

	assertBlindAndNoSentinels := func(t *testing.T, err error, capture fmt.Stringer) {
		t.Helper()
		if !errors.Is(err, ErrSecretHandlingFailed) {
			t.Fatalf("expected ErrSecretHandlingFailed, got: %v", err)
		}
		errMsg := ""
		if err != nil {
			errMsg = err.Error()
		}
		logMsg := ""
		if capture != nil {
			logMsg = capture.String()
		}
		for _, s := range forbiddenSentinels {
			if s == "" {
				continue
			}
			if strings.Contains(errMsg, s) {
				t.Fatalf("error leaks sensitive sentinel %q: %v", s, err)
			}
			if strings.Contains(logMsg, s) {
				t.Fatalf("logs leak sensitive sentinel %q: %s", s, logMsg)
			}
		}
	}

	t.Run("CreateSlot failing sealer", func(t *testing.T) {
		failingEnvWithSentinels := credentialstore.SecretEnvelope{
			Algorithm:  "AES-256-GCM",
			KeyID:      keyIDSentinel,
			KeyVersion: keyVersionSentinel,
			Nonce:      []byte(nonceSentinel),
			Ciphertext: []byte(ciphertextSentinel),
			AAD:        []byte(aadSentinel),
		}
		retSealer := &retainingSealer{
			envelope: failingEnvWithSentinels,
			err:      fmt.Errorf("sealer failed with sensitive error %s, plaintext %s, key %s, ver %d, nonce %s, cipher %s, aad %s", errorSentinel, plaintextSentinel, keyIDSentinel, keyVersionSentinel, nonceSentinel, ciphertextSentinel, aadSentinel),
		}
		svc, store, issued, capture := newTestServiceWithLogs(t, retSealer)
		token := []byte(issued.RawToken)

		genBefore := mustProjectionGeneration(t, store)
		slotsBefore := mustListSlots(t, store, issued.Principal.ID)

		callerSecret := []byte("secret-payload-" + plaintextSentinel)
		callerCopy := append([]byte(nil), callerSecret...)

		_, err := svc.CreateSlot(ctx, token, CreateSlotInput{
			Vendor:         "openai",
			CredentialKind: credentialstore.CredentialKindBearer,
			Alias:          "failing-slot",
			ProviderSecret: callerSecret,
		})
		assertBlindAndNoSentinels(t, err, capture)

		if len(retSealer.retained) == 0 {
			t.Fatal("retainingSealer did not capture plaintext")
		}
		for i, b := range retSealer.retained {
			if b != 0 {
				t.Fatalf("retained slice byte at index %d is non-zero (%d)", i, b)
			}
		}
		if !bytes.Equal(callerSecret, callerCopy) {
			t.Fatalf("caller secret buffer mutated on failed CreateSlot")
		}

		slotsAfter := mustListSlots(t, store, issued.Principal.ID)
		if !reflect.DeepEqual(slotsAfter, slotsBefore) {
			t.Fatalf("slots mutated on failed CreateSlot: got %+v want %+v", slotsAfter, slotsBefore)
		}

		genAfter := mustProjectionGeneration(t, store)
		if genAfter != genBefore {
			t.Fatalf("ProjectionGeneration changed on failed CreateSlot: got %d want %d", genAfter, genBefore)
		}
	})

	t.Run("RotateSlot failing sealer", func(t *testing.T) {
		retSealer := &retainingSealer{envelope: validEnv}
		svc, store, issued, capture := newTestServiceWithLogs(t, retSealer)
		token := []byte(issued.RawToken)

		validSlot, err := svc.CreateSlot(ctx, token, CreateSlotInput{
			Vendor:         "openai",
			CredentialKind: credentialstore.CredentialKindBearer,
			Alias:          "valid-slot-for-rotate-failure",
			ProviderSecret: []byte("initial-secret"),
		})
		if err != nil {
			t.Fatalf("CreateSlot: %v", err)
		}

		genBefore := mustProjectionGeneration(t, store)
		slotBefore := mustGetSlot(t, store, issued.Principal.ID, validSlot.ID)
		historyBefore := mustListSlotRevisions(t, store, issued.Principal.ID, validSlot.ID)
		slotsBefore := mustListSlots(t, store, issued.Principal.ID)

		failingEnvWithSentinels := credentialstore.SecretEnvelope{
			Algorithm:  "AES-256-GCM",
			KeyID:      keyIDSentinel,
			KeyVersion: keyVersionSentinel,
			Nonce:      []byte(nonceSentinel),
			Ciphertext: []byte(ciphertextSentinel),
			AAD:        []byte(aadSentinel),
		}
		retSealer.envelope = failingEnvWithSentinels
		retSealer.err = fmt.Errorf("sealer rotate failed with sensitive error %s, plaintext %s, key %s, ver %d, nonce %s, cipher %s, aad %s", errorSentinel, plaintextSentinel, keyIDSentinel, keyVersionSentinel, nonceSentinel, ciphertextSentinel, aadSentinel)
		retSealer.retained = nil

		callerSecret := []byte("rotate-payload-" + plaintextSentinel)
		callerCopy := append([]byte(nil), callerSecret...)

		_, err = svc.RotateSlot(ctx, token, RotateSlotInput{
			SlotID:         validSlot.ID,
			Revision:       validSlot.Revision,
			ProviderSecret: callerSecret,
		})
		assertBlindAndNoSentinels(t, err, capture)

		if len(retSealer.retained) == 0 {
			t.Fatal("retainingSealer did not capture plaintext on failing RotateSlot")
		}
		for i, b := range retSealer.retained {
			if b != 0 {
				t.Fatalf("retained slice byte at index %d on failing RotateSlot is non-zero (%d)", i, b)
			}
		}
		if !bytes.Equal(callerSecret, callerCopy) {
			t.Fatalf("caller secret buffer mutated on failed RotateSlot")
		}

		slotAfter := mustGetSlot(t, store, issued.Principal.ID, validSlot.ID)
		if !reflect.DeepEqual(slotAfter, slotBefore) {
			t.Fatalf("slot mutated on failed RotateSlot: got %+v want %+v", slotAfter, slotBefore)
		}

		historyAfter := mustListSlotRevisions(t, store, issued.Principal.ID, validSlot.ID)
		if !reflect.DeepEqual(historyAfter, historyBefore) {
			t.Fatalf("slot revision history mutated on failed RotateSlot: got %+v want %+v", historyAfter, historyBefore)
		}

		slotsAfter := mustListSlots(t, store, issued.Principal.ID)
		if !reflect.DeepEqual(slotsAfter, slotsBefore) {
			t.Fatalf("slots mutated on failed RotateSlot: got %+v want %+v", slotsAfter, slotsBefore)
		}

		genAfter := mustProjectionGeneration(t, store)
		if genAfter != genBefore {
			t.Fatalf("ProjectionGeneration mutated on failed RotateSlot: got %d want %d", genAfter, genBefore)
		}
	})

	t.Run("CreateSlot unknown key ID", func(t *testing.T) {
		unknownEnv := credentialstore.SecretEnvelope{
			Algorithm:  "AES-256-GCM",
			KeyID:      keyIDSentinel,
			KeyVersion: keyVersionSentinel,
			Nonce:      []byte(nonceSentinel),
			Ciphertext: []byte(ciphertextSentinel),
			AAD:        []byte(aadSentinel),
		}
		retSealer := &retainingSealer{envelope: unknownEnv}
		svc, store, issued, capture := newTestServiceWithLogs(t, retSealer)
		token := []byte(issued.RawToken)

		genBefore := mustProjectionGeneration(t, store)
		slotsBefore := mustListSlots(t, store, issued.Principal.ID)

		callerSecret := []byte("secret-payload-" + plaintextSentinel)
		callerCopy := append([]byte(nil), callerSecret...)

		_, err := svc.CreateSlot(ctx, token, CreateSlotInput{
			Vendor:         "openai",
			CredentialKind: credentialstore.CredentialKindBearer,
			Alias:          "unknown-key-slot",
			ProviderSecret: callerSecret,
		})
		assertBlindAndNoSentinels(t, err, capture)

		if len(retSealer.retained) == 0 {
			t.Fatal("retainingSealer did not capture plaintext on unknown key CreateSlot")
		}
		for i, b := range retSealer.retained {
			if b != 0 {
				t.Fatalf("retained slice byte at index %d is non-zero (%d)", i, b)
			}
		}
		if !bytes.Equal(callerSecret, callerCopy) {
			t.Fatalf("caller secret buffer mutated on unknown key CreateSlot")
		}

		slotsAfter := mustListSlots(t, store, issued.Principal.ID)
		if !reflect.DeepEqual(slotsAfter, slotsBefore) {
			t.Fatalf("slots mutated on unknown key CreateSlot: got %+v want %+v", slotsAfter, slotsBefore)
		}

		genAfter := mustProjectionGeneration(t, store)
		if genAfter != genBefore {
			t.Fatalf("ProjectionGeneration changed on unknown key CreateSlot: got %d want %d", genAfter, genBefore)
		}
	})

	t.Run("RotateSlot unknown key ID", func(t *testing.T) {
		retSealer := &retainingSealer{envelope: validEnv}
		svc, store, issued, capture := newTestServiceWithLogs(t, retSealer)
		token := []byte(issued.RawToken)

		validSlot, err := svc.CreateSlot(ctx, token, CreateSlotInput{
			Vendor:         "openai",
			CredentialKind: credentialstore.CredentialKindBearer,
			Alias:          "valid-slot-for-unknown-key-rotate",
			ProviderSecret: []byte("initial-secret"),
		})
		if err != nil {
			t.Fatalf("CreateSlot: %v", err)
		}

		genBefore := mustProjectionGeneration(t, store)
		slotBefore := mustGetSlot(t, store, issued.Principal.ID, validSlot.ID)
		historyBefore := mustListSlotRevisions(t, store, issued.Principal.ID, validSlot.ID)
		slotsBefore := mustListSlots(t, store, issued.Principal.ID)

		unknownEnv := credentialstore.SecretEnvelope{
			Algorithm:  "AES-256-GCM",
			KeyID:      keyIDSentinel,
			KeyVersion: keyVersionSentinel,
			Nonce:      []byte(nonceSentinel),
			Ciphertext: []byte(ciphertextSentinel),
			AAD:        []byte(aadSentinel),
		}
		retSealer.envelope = unknownEnv
		retSealer.retained = nil

		callerSecret := []byte("rotate-payload-" + plaintextSentinel)
		callerCopy := append([]byte(nil), callerSecret...)

		_, err = svc.RotateSlot(ctx, token, RotateSlotInput{
			SlotID:         validSlot.ID,
			Revision:       validSlot.Revision,
			ProviderSecret: callerSecret,
		})
		assertBlindAndNoSentinels(t, err, capture)

		if len(retSealer.retained) == 0 {
			t.Fatal("retainingSealer did not capture plaintext on unknown key RotateSlot")
		}
		for i, b := range retSealer.retained {
			if b != 0 {
				t.Fatalf("retained slice byte at index %d is non-zero (%d)", i, b)
			}
		}
		if !bytes.Equal(callerSecret, callerCopy) {
			t.Fatalf("caller secret buffer mutated on unknown key RotateSlot")
		}

		slotAfter := mustGetSlot(t, store, issued.Principal.ID, validSlot.ID)
		if !reflect.DeepEqual(slotAfter, slotBefore) {
			t.Fatalf("slot mutated on unknown key RotateSlot: got %+v want %+v", slotAfter, slotBefore)
		}

		historyAfter := mustListSlotRevisions(t, store, issued.Principal.ID, validSlot.ID)
		if !reflect.DeepEqual(historyAfter, historyBefore) {
			t.Fatalf("slot revision history mutated on unknown key RotateSlot: got %+v want %+v", historyAfter, historyBefore)
		}

		slotsAfter := mustListSlots(t, store, issued.Principal.ID)
		if !reflect.DeepEqual(slotsAfter, slotsBefore) {
			t.Fatalf("slots mutated on unknown key RotateSlot: got %+v want %+v", slotsAfter, slotsBefore)
		}

		genAfter := mustProjectionGeneration(t, store)
		if genAfter != genBefore {
			t.Fatalf("ProjectionGeneration mutated on unknown key RotateSlot: got %d want %d", genAfter, genBefore)
		}
	})

	t.Run("CreateSlot invalid envelope variant", func(t *testing.T) {
		invalidEnv := credentialstore.SecretEnvelope{
			Algorithm:  "",
			KeyID:      keyIDSentinel,
			KeyVersion: keyVersionSentinel,
			Nonce:      []byte(nonceSentinel),
			Ciphertext: []byte(ciphertextSentinel),
			AAD:        []byte(aadSentinel),
		}
		retSealer := &retainingSealer{envelope: invalidEnv}
		svc, store, issued, capture := newTestServiceWithLogs(t, retSealer)
		token := []byte(issued.RawToken)

		genBefore := mustProjectionGeneration(t, store)
		slotsBefore := mustListSlots(t, store, issued.Principal.ID)

		callerSecret := []byte("secret-payload-" + plaintextSentinel)
		callerCopy := append([]byte(nil), callerSecret...)

		_, err := svc.CreateSlot(ctx, token, CreateSlotInput{
			Vendor:         "openai",
			CredentialKind: credentialstore.CredentialKindBearer,
			Alias:          "invalid-env-slot",
			ProviderSecret: callerSecret,
		})
		assertBlindAndNoSentinels(t, err, capture)

		if len(retSealer.retained) == 0 {
			t.Fatal("retainingSealer did not capture plaintext")
		}
		for i, b := range retSealer.retained {
			if b != 0 {
				t.Fatalf("retained slice byte at index %d is non-zero (%d)", i, b)
			}
		}
		if !bytes.Equal(callerSecret, callerCopy) {
			t.Fatalf("caller secret buffer mutated on invalid envelope CreateSlot")
		}

		slotsAfter := mustListSlots(t, store, issued.Principal.ID)
		if !reflect.DeepEqual(slotsAfter, slotsBefore) {
			t.Fatalf("slots mutated on invalid envelope CreateSlot: got %+v want %+v", slotsAfter, slotsBefore)
		}

		genAfter := mustProjectionGeneration(t, store)
		if genAfter != genBefore {
			t.Fatalf("ProjectionGeneration changed on invalid envelope CreateSlot: got %d want %d", genAfter, genBefore)
		}
	})

	t.Run("RotateSlot invalid envelope variant", func(t *testing.T) {
		retSealer := &retainingSealer{envelope: validEnv}
		svc, store, issued, capture := newTestServiceWithLogs(t, retSealer)
		token := []byte(issued.RawToken)

		validSlot, err := svc.CreateSlot(ctx, token, CreateSlotInput{
			Vendor:         "openai",
			CredentialKind: credentialstore.CredentialKindBearer,
			Alias:          "valid-slot-for-invalid-env-rotate",
			ProviderSecret: []byte("initial-secret"),
		})
		if err != nil {
			t.Fatalf("CreateSlot: %v", err)
		}

		genBefore := mustProjectionGeneration(t, store)
		slotBefore := mustGetSlot(t, store, issued.Principal.ID, validSlot.ID)
		historyBefore := mustListSlotRevisions(t, store, issued.Principal.ID, validSlot.ID)
		slotsBefore := mustListSlots(t, store, issued.Principal.ID)

		invalidEnv := credentialstore.SecretEnvelope{
			Algorithm:  "AES-256-GCM",
			KeyID:      keyIDSentinel,
			KeyVersion: keyVersionSentinel,
			Nonce:      nil,
			Ciphertext: []byte(ciphertextSentinel),
			AAD:        []byte(aadSentinel),
		}
		retSealer.envelope = invalidEnv
		retSealer.retained = nil

		callerSecret := []byte("rotate-payload-" + plaintextSentinel)
		callerCopy := append([]byte(nil), callerSecret...)

		_, err = svc.RotateSlot(ctx, token, RotateSlotInput{
			SlotID:         validSlot.ID,
			Revision:       validSlot.Revision,
			ProviderSecret: callerSecret,
		})
		assertBlindAndNoSentinels(t, err, capture)

		if len(retSealer.retained) == 0 {
			t.Fatal("retainingSealer did not capture plaintext")
		}
		for i, b := range retSealer.retained {
			if b != 0 {
				t.Fatalf("retained slice byte at index %d is non-zero (%d)", i, b)
			}
		}
		if !bytes.Equal(callerSecret, callerCopy) {
			t.Fatalf("caller secret buffer mutated on invalid envelope RotateSlot")
		}

		slotAfter := mustGetSlot(t, store, issued.Principal.ID, validSlot.ID)
		if !reflect.DeepEqual(slotAfter, slotBefore) {
			t.Fatalf("slot mutated on invalid envelope RotateSlot: got %+v want %+v", slotAfter, slotBefore)
		}

		historyAfter := mustListSlotRevisions(t, store, issued.Principal.ID, validSlot.ID)
		if !reflect.DeepEqual(historyAfter, historyBefore) {
			t.Fatalf("slot revision history mutated on invalid envelope RotateSlot: got %+v want %+v", historyAfter, historyBefore)
		}

		slotsAfter := mustListSlots(t, store, issued.Principal.ID)
		if !reflect.DeepEqual(slotsAfter, slotsBefore) {
			t.Fatalf("slots mutated on invalid envelope RotateSlot: got %+v want %+v", slotsAfter, slotsBefore)
		}

		genAfter := mustProjectionGeneration(t, store)
		if genAfter != genBefore {
			t.Fatalf("ProjectionGeneration mutated on invalid envelope RotateSlot: got %d want %d", genAfter, genBefore)
		}
	})
}

// ---------------------------------------------------------------------------
// API-3: Service construction has no network side effect
// ---------------------------------------------------------------------------

func TestServiceConstructionHasNoNetworkSideEffect(t *testing.T) {
	logger := zaptest.NewLogger(t)
	reg := credentialstore.EnvelopeKeyRegistry(newFakeKeyRegistryForService())
	dbPath := "file:iop_credentialops_no_net_" + strings.ReplaceAll(t.Name(), "/", "_") + ".db?mode=memory&cache=shared"
	store, err := credentialstore.Open(context.Background(), dbPath, credentialstore.WithEnvelopeKeyRegistry(reg))
	if err != nil {
		t.Fatalf("open store: %v", err)
	}
	t.Cleanup(func() { _ = store.Close() })

	svcWithSealer := NewService(store, logger, newFakeSealer(t), nil)
	if svcWithSealer == nil {
		t.Fatal("NewService returned nil with sealer")
	}

	svcWithoutSealer := NewService(store, logger, nil, nil)
	if svcWithoutSealer == nil {
		t.Fatal("NewService returned nil without sealer")
	}

	issued, err := store.CreatePrincipalWithToken(context.Background(), credentialstore.CreatePrincipalInput{Alias: "no-net-principal"})
	if err != nil {
		t.Fatalf("create principal: %v", err)
	}

	slots, err := svcWithoutSealer.ListSlots(context.Background(), []byte(issued.RawToken))
	if err != nil {
		t.Fatalf("ListSlots without wire server: %v", err)
	}
	if len(slots) != 0 {
		t.Fatalf("expected 0 slots, got %d", len(slots))
	}
}

// ---------------------------------------------------------------------------
// API-1: Authenticate rejects empty/invalid tokens
// ---------------------------------------------------------------------------

func TestServiceRejectsEmptyToken(t *testing.T) {
	svc, _, _ := newTestService(t, newFakeSealer(t))
	ctx := context.Background()

	_, err := svc.GetSlot(ctx, nil, "any-id")
	if !errors.Is(err, ErrUnauthorized) {
		t.Fatalf("expected ErrUnauthorized for nil token, got: %v", err)
	}

	_, err = svc.GetSlot(ctx, []byte{}, "any-id")
	if !errors.Is(err, ErrUnauthorized) {
		t.Fatalf("expected ErrUnauthorized for empty token, got: %v", err)
	}

	_, err = svc.ListSlots(ctx, []byte("nonexistent-token"))
	if !errors.Is(err, ErrUnauthorized) {
		t.Fatalf("expected ErrUnauthorized for unknown token, got: %v", err)
	}
}

// ---------------------------------------------------------------------------
// API-1: Concurrent access (race test)
// ---------------------------------------------------------------------------

func TestServiceConcurrentOperations(t *testing.T) {
	svc, _, issued := newTestService(t, newFakeSealer(t))
	ctx := context.Background()

	token := []byte(issued.RawToken)
	slot, err := svc.CreateSlot(ctx, token, CreateSlotInput{
		Vendor:         "openai",
		CredentialKind: credentialstore.CredentialKindBearer,
		Alias:          "concurrent-slot",
		ProviderSecret: []byte("concurrent-secret"),
	})
	if err != nil {
		t.Fatalf("CreateSlot: %v", err)
	}

	var wg sync.WaitGroup
	errs := make(chan error, 10)

	for range 5 {
		wg.Add(1)
		go func() {
			defer wg.Done()
			_, err := svc.GetSlot(ctx, token, slot.ID)
			if err != nil {
				errs <- err
			}
		}()
	}

	for range 5 {
		wg.Add(1)
		go func() {
			defer wg.Done()
			_, err := svc.ListSlots(ctx, token)
			if err != nil {
				errs <- err
			}
		}()
	}

	wg.Wait()
	close(errs)

	for err := range errs {
		t.Fatalf("concurrent error: %v", err)
	}
}

func TestServiceMapsStoreErrorsCorrectly(t *testing.T) {
	svc, _, issued := newTestService(t, newFakeSealer(t))
	ctx := context.Background()

	_, err := svc.GetSlot(ctx, []byte(issued.RawToken), "does-not-exist")
	if !errors.Is(err, ErrNotFound) {
		t.Fatalf("expected ErrNotFound, got: %v", err)
	}

	_, err = svc.GetRoute(ctx, []byte(issued.RawToken), "does-not-exist")
	if !errors.Is(err, ErrNotFound) {
		t.Fatalf("expected ErrNotFound for route, got: %v", err)
	}
}

func TestServiceAuthenticatesViaDigest(t *testing.T) {
	svc, store, issued := newTestService(t, newFakeSealer(t))
	ctx := context.Background()

	expectedDigest := digestOf([]byte(issued.RawToken))
	p, tkr, err := store.LookupTokenByDigest(ctx, expectedDigest)
	if err != nil {
		t.Fatalf("lookup by expected digest: %v", err)
	}
	if p.ID != issued.Principal.ID {
		t.Fatalf("principal ID mismatch: got %q want %q", p.ID, issued.Principal.ID)
	}
	if tkr.ID != issued.Token.ID {
		t.Fatalf("token ID mismatch: got %q want %q", tkr.ID, issued.Token.ID)
	}

	slot, err := svc.CreateSlot(ctx, []byte(issued.RawToken), CreateSlotInput{
		Vendor:         "openai",
		CredentialKind: credentialstore.CredentialKindBearer,
		Alias:          "digest-slot",
		ProviderSecret: []byte("digest-secret"),
	})
	if err != nil {
		t.Fatalf("CreateSlot: %v", err)
	}

	slots, err := svc.ListSlots(ctx, []byte(issued.RawToken))
	if err != nil {
		t.Fatalf("ListSlots with raw token: %v", err)
	}
	if len(slots) != 1 {
		t.Fatalf("expected 1 slot, got %d", len(slots))
	}
	if slots[0].ID != slot.ID {
		t.Fatalf("slot ID mismatch: got %q want %q", slots[0].ID, slot.ID)
	}
}

func TestServiceHasNoProtoDependency(t *testing.T) {
	svc, _, _ := newTestService(t, newFakeSealer(t))
	if svc == nil {
		t.Fatal("service must not be nil")
	}
}

func TestServiceImplementsExpectedInterface(t *testing.T) {
	var _ SecretSealer = (*fakeSealer)(nil)

	svc, _, _ := newTestService(t, nil)
	if svc == nil {
		t.Fatal("NewService must not return nil")
	}
}

// ---------------------------------------------------------------------------
// API-2: create-time AAD binds to the persisted slot id
// ---------------------------------------------------------------------------

func TestServiceCreateBindsSealContextToPersistedSlotID(t *testing.T) {
	fake := newFakeSealer(t)
	svc, _, issued := newTestService(t, fake)
	ctx := context.Background()

	created, err := svc.CreateSlot(ctx, []byte(issued.RawToken), CreateSlotInput{
		Vendor:         "openai",
		CredentialKind: credentialstore.CredentialKindBearer,
		Alias:          "bound-slot",
		ProviderSecret: []byte("secret"),
	})
	if err != nil {
		t.Fatalf("CreateSlot: %v", err)
	}
	if fake.callCount() != 1 {
		t.Fatalf("sealer call count: got %d want 1", fake.callCount())
	}
	if fake.calls[0].ctx_.SlotID == "" {
		t.Fatal("create-time seal context must carry a slot id")
	}
	if fake.calls[0].ctx_.SlotID != created.ID {
		t.Fatalf("seal context slot id mismatch: got %q want persisted %q", fake.calls[0].ctx_.SlotID, created.ID)
	}
	if fake.calls[0].ctx_.Kind != credentialstore.CredentialKindBearer {
		t.Fatalf("seal context kind mismatch: got %q", fake.calls[0].ctx_.Kind)
	}
}

// ---------------------------------------------------------------------------
// API-1/API-2: production keyring end-to-end at-rest encryption
// ---------------------------------------------------------------------------

func newKeyringForTest(t *testing.T) *credentialseal.Keyring {
	t.Helper()
	dir := t.TempDir()
	path := filepath.Join(dir, "manifest.yaml")
	material := base64.StdEncoding.EncodeToString(bytes.Repeat([]byte{0x5A}, 32))
	body := "keys:\n  - id: \"primary\"\n    version: 1\n    material: \"" + material + "\"\n"
	if err := os.WriteFile(path, []byte(body), 0o600); err != nil {
		t.Fatalf("write manifest: %v", err)
	}
	kr, err := credentialseal.LoadFile(credentialseal.FileConfig{KeyFile: path, ActiveKeyID: "primary", ActiveKeyVersion: 1})
	if err != nil {
		t.Fatalf("load keyring: %v", err)
	}
	return kr
}

func TestServiceKeyringStoresInspectableCiphertextAndDecrypts(t *testing.T) {
	ctx := context.Background()
	dir := t.TempDir()
	dbPath := filepath.Join(dir, "encrypted.db")
	keyring := newKeyringForTest(t)

	store, err := credentialstore.Open(ctx, dbPath, credentialstore.WithEnvelopeKeyRegistry(keyring))
	if err != nil {
		t.Fatalf("open store: %v", err)
	}
	logger := zaptest.NewLogger(t)
	svc := NewService(store, logger, keyring, nil)

	issued, err := store.CreatePrincipalWithToken(ctx, credentialstore.CreatePrincipalInput{Alias: "keyring-principal"})
	if err != nil {
		t.Fatalf("create principal: %v", err)
	}
	token := []byte(issued.RawToken)

	const secret1 = "PROVIDER_SECRET_SENTINEL_AAA_111"
	const secret2 = "PROVIDER_SECRET_SENTINEL_BBB_222"

	created, err := svc.CreateSlot(ctx, token, CreateSlotInput{
		Vendor:         "openai",
		CredentialKind: credentialstore.CredentialKindBearer,
		Alias:          "keyring-slot",
		ProviderSecret: []byte(secret1),
	})
	if err != nil {
		t.Fatalf("CreateSlot: %v", err)
	}

	rotated, err := svc.RotateSlot(ctx, token, RotateSlotInput{
		SlotID:         created.ID,
		Revision:       created.Revision,
		ProviderSecret: []byte(secret2),
	})
	if err != nil {
		t.Fatalf("RotateSlot: %v", err)
	}

	// Inspect the persisted row: only algorithm/key metadata/nonce/ciphertext/aad,
	// and no plaintext, are stored.
	var algorithm, keyID string
	var keyVersion uint64
	var nonce, ciphertext, aad []byte
	err = store.DB().QueryRowContext(ctx,
		`SELECT algorithm, key_id, key_version, nonce, ciphertext, aad FROM credential_slots WHERE id=?`, created.ID,
	).Scan(&algorithm, &keyID, &keyVersion, &nonce, &ciphertext, &aad)
	if err != nil {
		t.Fatalf("inspect slot row: %v", err)
	}
	if algorithm != credentialseal.AlgorithmAES256GCM {
		t.Fatalf("stored algorithm: got %q", algorithm)
	}
	if keyID != "primary" || keyVersion != 1 {
		t.Fatalf("stored key metadata: got id=%q version=%d", keyID, keyVersion)
	}
	if len(nonce) != 12 || len(ciphertext) == 0 || len(aad) == 0 {
		t.Fatalf("stored envelope shape: nonce=%d ciphertext=%d aad=%d", len(nonce), len(ciphertext), len(aad))
	}
	for _, blob := range [][]byte{nonce, ciphertext, aad} {
		if strings.Contains(string(blob), secret1) || strings.Contains(string(blob), secret2) {
			t.Fatal("stored envelope leaks plaintext secret")
		}
	}

	sealCtx := credentialseal.Context{PrincipalID: issued.Principal.ID, SlotID: created.ID, Kind: credentialstore.CredentialKindBearer}

	// Every historical revision decrypts to its original plaintext with the
	// exact context.
	revisions, err := store.ListSlotRevisions(ctx, issued.Principal.ID, created.ID)
	if err != nil {
		t.Fatalf("ListSlotRevisions: %v", err)
	}
	if len(revisions) != 2 {
		t.Fatalf("revision count: got %d want 2", len(revisions))
	}
	wantByRevision := map[int64]string{0: secret1, 1: secret2}
	for _, rev := range revisions {
		got, err := keyring.Open(ctx, rev.Envelope, sealCtx)
		if err != nil {
			t.Fatalf("decrypt revision %d: %v", rev.Revision, err)
		}
		if string(got) != wantByRevision[rev.Revision] {
			t.Fatalf("revision %d plaintext mismatch: got %q want %q", rev.Revision, got, wantByRevision[rev.Revision])
		}
	}

	// A swapped principal/slot/kind context cannot decrypt the current envelope.
	current, err := store.GetSlot(ctx, issued.Principal.ID, created.ID)
	if err != nil {
		t.Fatalf("GetSlot current: %v", err)
	}
	_ = rotated
	for _, wrong := range []credentialseal.Context{
		{PrincipalID: "other", SlotID: created.ID, Kind: credentialstore.CredentialKindBearer},
		{PrincipalID: issued.Principal.ID, SlotID: "other-slot", Kind: credentialstore.CredentialKindBearer},
		{PrincipalID: issued.Principal.ID, SlotID: created.ID, Kind: credentialstore.CredentialKindAPIKey},
	} {
		if _, err := keyring.Open(ctx, current.Envelope, wrong); !errors.Is(err, credentialseal.ErrOpenFailed) {
			t.Fatalf("expected ErrOpenFailed for swapped context, got: %v", err)
		}
	}

	// Close and reopen the DB with a freshly reloaded keyring holding the same
	// external material: the current revision still decrypts (restart + reload).
	if err := store.Close(); err != nil {
		t.Fatalf("close store: %v", err)
	}
	keyring2 := newKeyringForTest(t)
	store2, err := credentialstore.Open(ctx, dbPath, credentialstore.WithEnvelopeKeyRegistry(keyring2))
	if err != nil {
		t.Fatalf("reopen store: %v", err)
	}
	t.Cleanup(func() { _ = store2.Close() })

	reloaded, err := store2.GetSlot(ctx, issued.Principal.ID, created.ID)
	if err != nil {
		t.Fatalf("GetSlot after reopen: %v", err)
	}
	got, err := keyring2.Open(ctx, reloaded.Envelope, sealCtx)
	if err != nil {
		t.Fatalf("decrypt after reopen: %v", err)
	}
	if string(got) != secret2 {
		t.Fatalf("decrypt after reopen mismatch: got %q want %q", got, secret2)
	}
}

// ---------------------------------------------------------------------------
// REVIEW_API-1: canonical credential kind binds AAD to persisted kind
// ---------------------------------------------------------------------------

func TestServiceCreateCanonicalizesCredentialKindForAAD(t *testing.T) {
	ctx := context.Background()

	// Table-driven: each input kind normalizes to a canonical value.
	kindCases := []struct {
		name      string
		input     string
		canonical string
	}{
		{"bearer-lowercase", "bearer", credentialstore.CredentialKindBearer},
		{"bearer-uppercase", "BEARER", credentialstore.CredentialKindBearer},
		{"bearer-mixed-case", "BeArEr", credentialstore.CredentialKindBearer},
		{"bearer-leading-trailing-space", " bearer ", credentialstore.CredentialKindBearer},
		{"bearer-tabs-and-newlines", "\tbearer\n", credentialstore.CredentialKindBearer},
		{"api-key-lowercase", "api_key", credentialstore.CredentialKindAPIKey},
		{"api-key-uppercase", "API_KEY", credentialstore.CredentialKindAPIKey},
		{"api-key-mixed-case", "Api_Key", credentialstore.CredentialKindAPIKey},
		{"api-key-spaces", " api_key ", credentialstore.CredentialKindAPIKey},
	}

	for _, tc := range kindCases {
		t.Run(tc.name, func(t *testing.T) {
			subDir := t.TempDir()
			dbPath := filepath.Join(subDir, "canonical.db")
			keyring := newKeyringForTest(t)

			store, err := credentialstore.Open(ctx, dbPath, credentialstore.WithEnvelopeKeyRegistry(keyring))
			if err != nil {
				t.Fatalf("open store: %v", err)
			}
			t.Cleanup(func() { _ = store.Close() })

			logger := zaptest.NewLogger(t)
			svc := NewService(store, logger, keyring, nil)

			issued, err := store.CreatePrincipalWithToken(ctx, credentialstore.CreatePrincipalInput{Alias: "canonical-principal"})
			if err != nil {
				t.Fatalf("create principal: %v", err)
			}
			token := []byte(issued.RawToken)

			created, err := svc.CreateSlot(ctx, token, CreateSlotInput{
				Vendor:         "openai",
				CredentialKind: tc.input,
				Alias:          "canonical-" + tc.name,
				ProviderSecret: []byte("canonical-secret-payload"),
			})
			if err != nil {
				t.Fatalf("CreateSlot with kind %q: %v", tc.input, err)
			}

			// Persisted kind must equal the canonical value.
			if created.CredentialKind != tc.canonical {
				t.Fatalf("persisted CredentialKind: got %q want %q", created.CredentialKind, tc.canonical)
			}

			// Stored slot row must carry the canonical kind.
			stored, err := store.GetSlot(ctx, issued.Principal.ID, created.ID)
			if err != nil {
				t.Fatalf("GetSlot: %v", err)
			}
			if stored.CredentialKind != tc.canonical {
				t.Fatalf("stored CredentialKind: got %q want %q", stored.CredentialKind, tc.canonical)
			}

			// Initial envelope must open with the exact persisted context.
			sealCtx := credentialseal.Context{
				PrincipalID: issued.Principal.ID,
				SlotID:      created.ID,
				Kind:        stored.CredentialKind,
			}
			got, err := keyring.Open(ctx, stored.Envelope, sealCtx)
			if err != nil {
				t.Fatalf("open initial envelope with persisted context: %v", err)
			}
			if string(got) != "canonical-secret-payload" {
				t.Fatalf("initial envelope plaintext: got %q", got)
			}

			// Rotate with the same canonical kind.
			rotated, err := svc.RotateSlot(ctx, token, RotateSlotInput{
				SlotID:         created.ID,
				Revision:       created.Revision,
				ProviderSecret: []byte("canonical-rotated-secret"),
			})
			if err != nil {
				t.Fatalf("RotateSlot: %v", err)
			}
			if rotated.CredentialKind != tc.canonical {
				t.Fatalf("rotated CredentialKind: got %q want %q", rotated.CredentialKind, tc.canonical)
			}

			// All revisions must open with the persisted context.
			revisions, err := store.ListSlotRevisions(ctx, issued.Principal.ID, created.ID)
			if err != nil {
				t.Fatalf("ListSlotRevisions: %v", err)
			}
			for _, rev := range revisions {
				g, err := keyring.Open(ctx, rev.Envelope, sealCtx)
				if err != nil {
					t.Fatalf("open revision %d: %v", rev.Revision, err)
				}
				if rev.Revision == 0 && string(g) != "canonical-secret-payload" {
					t.Fatalf("revision 0 plaintext: got %q", g)
				}
				if rev.Revision == 1 && string(g) != "canonical-rotated-secret" {
					t.Fatalf("revision 1 plaintext: got %q", g)
				}
			}

			// Close and reopen: every revision must still decrypt with the row context.
			if err := store.Close(); err != nil {
				t.Fatalf("close store: %v", err)
			}
			keyring2 := newKeyringForTest(t)
			store2, err := credentialstore.Open(ctx, dbPath, credentialstore.WithEnvelopeKeyRegistry(keyring2))
			if err != nil {
				t.Fatalf("reopen store: %v", err)
			}
			t.Cleanup(func() { _ = store2.Close() })

			reloaded, err := store2.GetSlot(ctx, issued.Principal.ID, created.ID)
			if err != nil {
				t.Fatalf("GetSlot after reopen: %v", err)
			}
			if reloaded.CredentialKind != tc.canonical {
				t.Fatalf("reloaded CredentialKind: got %q want %q", reloaded.CredentialKind, tc.canonical)
			}
			reopenedCtx := credentialseal.Context{
				PrincipalID: issued.Principal.ID,
				SlotID:      created.ID,
				Kind:        reloaded.CredentialKind,
			}
			reopenedRevs, err := store2.ListSlotRevisions(ctx, issued.Principal.ID, created.ID)
			if err != nil {
				t.Fatalf("ListSlotRevisions after reopen: %v", err)
			}
			for _, rev := range reopenedRevs {
				g, err := keyring2.Open(ctx, rev.Envelope, reopenedCtx)
				if err != nil {
					t.Fatalf("decrypt revision %d after reopen: %v", rev.Revision, err)
				}
				if len(g) == 0 {
					t.Fatalf("empty plaintext after reopen for revision %d", rev.Revision)
				}
			}
		})
	}

	// Unknown kind must be rejected before the sealer is called.
	t.Run("unknown-kind-rejected-before-sealer", func(t *testing.T) {
		fake := newFakeSealer(t)
		svcFake, storeFake, issuedFake := newTestService(t, fake)

		credentialState := func(t *testing.T, store *credentialstore.Store, pid string) ([]credentialstore.CredentialSlotRecord, int, uint64) {
			t.Helper()
			slots, err := store.ListSlots(ctx, pid)
			if err != nil {
				t.Fatalf("ListSlots: %v", err)
			}
			var revCount int
			if err := store.DB().QueryRowContext(ctx, "SELECT COUNT(*) FROM credential_slot_revisions").Scan(&revCount); err != nil {
				t.Fatalf("QueryRowContext credential_slot_revisions count: %v", err)
			}
			gen, err := store.ProjectionGeneration(ctx)
			if err != nil {
				t.Fatalf("ProjectionGeneration: %v", err)
			}
			return slots, revCount, gen
		}

		slotsBefore, revisionsBefore, genBefore := credentialState(t, storeFake, issuedFake.Principal.ID)

		_, err := svcFake.CreateSlot(ctx, []byte(issuedFake.RawToken), CreateSlotInput{
			Vendor:         "openai",
			CredentialKind: "unknown_kind",
			Alias:          "unknown-kind-slot",
			ProviderSecret: []byte("unknown-secret"),
		})
		if !errors.Is(err, ErrInvalidCredentialKind) {
			t.Fatalf("expected ErrInvalidCredentialKind, got: %v", err)
		}
		if fake.callCount() != 0 {
			t.Fatalf("sealer must not be called for unknown kind, got %d calls", fake.callCount())
		}

		slotsAfter, revisionsAfter, genAfter := credentialState(t, storeFake, issuedFake.Principal.ID)
		if !reflect.DeepEqual(slotsAfter, slotsBefore) || revisionsAfter != revisionsBefore || genAfter != genBefore {
			t.Fatalf("unknown credential kind mutated durable state: slotsBefore=%+v slotsAfter=%+v revsBefore=%d revsAfter=%d genBefore=%d genAfter=%d",
				slotsBefore, slotsAfter, revisionsBefore, revisionsAfter, genBefore, genAfter)
		}
		if len(slotsAfter) != 0 || revisionsAfter != 0 {
			t.Fatalf("expected empty slots and zero revisions, got slots=%d revs=%d", len(slotsAfter), revisionsAfter)
		}
	})
}
