package core

import (
	"bytes"
	"context"
	"crypto/sha256"
	"encoding/hex"
	"io"
	"net/http"
	"net/http/httptest"
	"strings"
	"sync"
	"testing"
	"time"

	"github.com/stephnangue/warden/internal/namespace"
	"github.com/stephnangue/warden/logical"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

// TestHandleRequest_SealedCore tests that requests are rejected when core is sealed
func TestHandleRequest_SealedCore(t *testing.T) {
	core := createTestCore(t)

	// Seal the core
	core.Seal()

	req := &logical.Request{
		Path:        "sys/mounts",
		Operation:   logical.ReadOperation,
		HTTPRequest: httptest.NewRequest(http.MethodGet, "/v1/sys/mounts", nil),
	}

	resp, err := core.HandleRequest(context.Background(), req)
	require.NoError(t, err)
	require.NotNil(t, resp)
	assert.Equal(t, http.StatusServiceUnavailable, resp.StatusCode)
}

// TestHandleRequest_StandbyNode tests that requests return ErrStandby when the
// node has transitioned to standby and the active context is canceled.
func TestHandleRequest_StandbyNode(t *testing.T) {
	core := createTestCore(t)

	// Simulate standby transition: cancel active context, set standby flag
	ctx, cancel := context.WithCancel(context.Background())
	cancel()
	core.activeContext = ctx
	core.standby.Store(true)

	req := &logical.Request{
		Path:        "sys/mounts",
		Operation:   logical.ReadOperation,
		HTTPRequest: httptest.NewRequest(http.MethodGet, "/v1/sys/mounts", nil),
	}

	resp, err := core.HandleRequest(context.Background(), req)
	assert.Nil(t, resp)
	assert.ErrorIs(t, err, ErrStandby)
}

// TestCheckToken_StandbyNode tests that CheckToken returns ErrStandby when a
// token lookup fails on a standby node.
func TestCheckToken_StandbyNode(t *testing.T) {
	core := createTestCore(t)

	// Set node to standby
	core.standby.Store(true)

	req := &logical.Request{
		Path:        "sys/mounts",
		Operation:   logical.ReadOperation,
		ClientToken: "invalid-token-that-will-fail-lookup",
	}

	ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)
	_, _, _, err := core.CheckToken(ctx, req, false)
	assert.ErrorIs(t, err, ErrStandby)
}

// TestHandleRequest_NamespaceNotFound tests that requests fail when namespace is not found
func TestHandleRequest_NamespaceNotFound(t *testing.T) {
	core := createTestCore(t)

	req := &logical.Request{
		Path:        "nonexistent-ns/sys/mounts",
		Operation:   logical.ReadOperation,
		HTTPRequest: httptest.NewRequest(http.MethodGet, "/v1/nonexistent-ns/sys/mounts", nil),
	}

	resp, err := core.HandleRequest(context.Background(), req)
	require.NoError(t, err)
	require.NotNil(t, resp)
	assert.Equal(t, http.StatusNotFound, resp.StatusCode)
}

// TestHandleRequest_NoHandlerForPath tests that requests fail when no backend handles the path
func TestHandleRequest_NoHandlerForPath(t *testing.T) {
	core := createTestCore(t)

	req := &logical.Request{
		Path:        "nonexistent/path",
		Operation:   logical.ReadOperation,
		HTTPRequest: httptest.NewRequest(http.MethodGet, "/v1/nonexistent/path", nil),
	}

	resp, err := core.HandleRequest(context.Background(), req)
	require.NoError(t, err)
	require.NotNil(t, resp)
	assert.Equal(t, http.StatusNotFound, resp.StatusCode)
}

// TestHandleRequest_RestrictedSysAPIs tests that restricted sys APIs are blocked in non-root namespaces
func TestHandleRequest_RestrictedSysAPIs(t *testing.T) {
	core := createTestCore(t)
	ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)

	// First create a child namespace
	childNs := &namespace.Namespace{
		Path: "child/",
	}
	err := core.namespaceStore.SetNamespace(ctx, childNs)
	require.NoError(t, err)

	// Try to access restricted API in child namespace
	req := &logical.Request{
		Path:        "child/sys/seal",
		Operation:   logical.UpdateOperation,
		HTTPRequest: httptest.NewRequest(http.MethodPost, "/v1/child/sys/seal", nil),
	}

	resp, err := core.HandleRequest(context.Background(), req)
	require.NoError(t, err)
	require.NotNil(t, resp)
	assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
}

// TestHandleRequest_NamespaceHeader tests that X-Warden-Namespace header is respected
func TestHandleRequest_NamespaceHeader(t *testing.T) {
	core := createTestCore(t)
	ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)

	// Create a child namespace
	testNs := &namespace.Namespace{
		Path: "test-ns/",
	}
	err := core.namespaceStore.SetNamespace(ctx, testNs)
	require.NoError(t, err)

	// Request with namespace header - sys/namespaces requires auth
	httpReq := httptest.NewRequest(http.MethodGet, "/v1/sys/namespaces", nil)
	httpReq.Header.Set("X-Warden-Namespace", "test-ns")

	req := &logical.Request{
		Path:        "sys/namespaces",
		Operation:   logical.ListOperation,
		HTTPRequest: httpReq,
	}

	resp, err := core.HandleRequest(context.Background(), req)
	// The request should be processed (namespace header respected)
	// It may fail with permission denied since we don't have a token
	// The key thing is that the namespace was resolved correctly
	require.NotNil(t, resp)
	// Either succeeds, permission denied, or error - all are acceptable
	// as long as we didn't get "namespace not found"
	assert.NotEqual(t, http.StatusNotFound, resp.StatusCode,
		"namespace should have been found via header")
	_ = err // err may contain permission denied
}

// TestSynthesizeGatewayPath covers the normalization rules for the
// X-Warden-Provider header value and the role-empty / role-present
// branches of the path-synthesis helper.
func TestSynthesizeGatewayPath(t *testing.T) {
	cases := []struct {
		name     string
		provider string
		role     string
		apiPath  string
		want     string
		wantErr  bool
	}{
		// Successful normalisations.
		{"single segment", "github", "repo-reader", "repos/org/repo", "github/role/repo-reader/gateway/repos/org/repo", false},
		{"trailing slash stripped", "github/", "repo-reader", "repos/org/repo", "github/role/repo-reader/gateway/repos/org/repo", false},
		{"leading slash stripped", "/github", "repo-reader", "repos/org/repo", "github/role/repo-reader/gateway/repos/org/repo", false},
		{"multi-segment mount", "gitlab/prod", "ci", "api/v4/projects/1", "gitlab/prod/role/ci/gateway/api/v4/projects/1", false},
		{"multi-segment with trailing slash", "gitlab/prod/", "ci", "api/v4/projects/1", "gitlab/prod/role/ci/gateway/api/v4/projects/1", false},
		{"role empty", "github", "", "repos/org/repo", "github/gateway/repos/org/repo", false},
		{"api path with leading slash", "github", "r", "/repos/org/repo", "github/role/r/gateway/repos/org/repo", false},
		{"double-dot infix is OK", "gitlab/..eu-west", "r", "p", "gitlab/..eu-west/role/r/gateway/p", false},

		// Malformed values that must error.
		{"empty provider", "", "r", "p", "", true},
		{"slash only", "/", "r", "p", "", true},
		{"empty middle segment", "gitlab//prod", "r", "p", "", true},
		{"bare double-dot", "..", "r", "p", "", true},
		{"trailing double-dot", "gitlab/..", "r", "p", "", true},
		{"whitespace only passes synthesis", "   ", "r", "p", "   /role/r/gateway/p", false},
	}
	// Whitespace is not stripped or rejected per-segment; the helper trusts
	// that no real mount has whitespace-only names, so the request lands on
	// the existing 404 path rather than 400. The case above documents that.

	for _, tc := range cases {
		tc := tc
		t.Run(tc.name, func(t *testing.T) {
			got, err := synthesizeGatewayPath(tc.provider, tc.role, tc.apiPath)
			if tc.wantErr {
				require.Error(t, err)
				return
			}
			require.NoError(t, err)
			assert.Equal(t, tc.want, got)
		})
	}
}

// TestHandleRequest_ProviderHeader_SysRejected verifies that a request
// carrying X-Warden-Provider against a /v1/sys/... URL is rejected with
// 400, regardless of whether the named mount exists.
func TestHandleRequest_ProviderHeader_SysRejected(t *testing.T) {
	core := createTestCore(t)

	httpReq := httptest.NewRequest(http.MethodGet, "/v1/sys/mounts", nil)
	httpReq.Header.Set("X-Warden-Provider", "github")

	req := &logical.Request{
		Path:        "sys/mounts",
		Operation:   logical.ReadOperation,
		HTTPRequest: httpReq,
	}

	resp, err := core.HandleRequest(context.Background(), req)
	require.NoError(t, err)
	require.NotNil(t, resp)
	assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
}

// TestHandleRequest_ProviderHeader_SysRejected_WithNamespace confirms the
// sys-backend exclusion fires after namespace strip, not just when the raw
// URL begins with /v1/sys/.
func TestHandleRequest_ProviderHeader_SysRejected_WithNamespace(t *testing.T) {
	core := createTestCore(t)
	ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)

	childNs := &namespace.Namespace{Path: "tenant-a/"}
	require.NoError(t, core.namespaceStore.SetNamespace(ctx, childNs))

	httpReq := httptest.NewRequest(http.MethodGet, "/v1/tenant-a/sys/mounts", nil)
	httpReq.Header.Set("X-Warden-Provider", "github")

	req := &logical.Request{
		Path:        "tenant-a/sys/mounts",
		Operation:   logical.ReadOperation,
		HTTPRequest: httpReq,
	}

	resp, err := core.HandleRequest(context.Background(), req)
	require.NoError(t, err)
	require.NotNil(t, resp)
	assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
}

// TestHandleRequest_ProviderHeader_Malformed verifies that a structurally
// malformed X-Warden-Provider value returns 400 (not 404).
func TestHandleRequest_ProviderHeader_Malformed(t *testing.T) {
	core := createTestCore(t)

	httpReq := httptest.NewRequest(http.MethodGet, "/v1/repos/org/repo", nil)
	httpReq.Header.Set("X-Warden-Provider", "gitlab/..")

	req := &logical.Request{
		Path:        "repos/org/repo",
		Operation:   logical.ReadOperation,
		HTTPRequest: httpReq,
	}

	resp, err := core.HandleRequest(context.Background(), req)
	require.NoError(t, err)
	require.NotNil(t, resp)
	assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
}

// TestHandleRequest_ProviderHeader_NoSuchMount verifies that a well-formed
// X-Warden-Provider value naming an unmounted provider returns 404, not 400.
// This is the error-class split: 400 = malformed header, 404 = unknown mount.
func TestHandleRequest_ProviderHeader_NoSuchMount(t *testing.T) {
	core := createTestCore(t)

	httpReq := httptest.NewRequest(http.MethodGet, "/v1/repos/org/repo", nil)
	httpReq.Header.Set("X-Warden-Provider", "doesnotexist")

	req := &logical.Request{
		Path:        "repos/org/repo",
		Operation:   logical.ReadOperation,
		HTTPRequest: httpReq,
	}

	resp, err := core.HandleRequest(context.Background(), req)
	require.NoError(t, err)
	require.NotNil(t, resp)
	assert.Equal(t, http.StatusNotFound, resp.StatusCode)
}

// TestHandleRequest_ProviderHeader_SigV4Rejected verifies that combining
// X-Warden-Provider with a SigV4-shaped Authorization header is rejected
// with 400. The synthesis rewrites URL.Path, which would silently invalidate
// the client's signature under SigV4 — better to fail loudly with a clear
// error than to surface as a confusing 401.
func TestHandleRequest_ProviderHeader_SigV4Rejected(t *testing.T) {
	core := createTestCore(t)

	cases := []struct{ name, authz string }{
		{"AWS SigV4", "AWS4-HMAC-SHA256 Credential=anything/20260101/us-east-1/sts/aws4_request, SignedHeaders=host;x-amz-date, Signature=deadbeef"},
		{"Alicloud ACS3", "ACS3-HMAC-SHA256 Credential=anything,SignedHeaders=host,Signature=deadbeef"},
	}
	for _, tc := range cases {
		tc := tc
		t.Run(tc.name, func(t *testing.T) {
			httpReq := httptest.NewRequest(http.MethodPost, "/v1/sts/", nil)
			httpReq.Header.Set("X-Warden-Provider", "aws")
			httpReq.Header.Set("Authorization", tc.authz)

			req := &logical.Request{
				Path:        "sts/",
				Operation:   logical.CreateOperation,
				HTTPRequest: httpReq,
			}

			resp, err := core.HandleRequest(context.Background(), req)
			require.NoError(t, err)
			require.NotNil(t, resp)
			assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
		})
	}
}

// TestApplyRoleHeader covers the role-segment rewrite used in path-routing
// mode when X-Warden-Role is set.
func TestApplyRoleHeader(t *testing.T) {
	cases := []struct {
		name string
		path string
		role string
		want string
	}{
		{"rewrites mount-level role segment", "vault/role/old/gateway/v1/secret", "new", "vault/role/new/gateway/v1/secret"},
		{"multi-segment mount path", "gitlab/prod/role/old/gateway/api/v4/projects", "new", "gitlab/prod/role/new/gateway/api/v4/projects"},
		{"no role segment is a no-op", "vault/gateway/v1/secret", "new", "vault/gateway/v1/secret"},
		{"empty role is a no-op", "vault/role/old/gateway/v1/secret", "", "vault/role/old/gateway/v1/secret"},
		{"only the leftmost segment is rewritten", "vault/role/old/gateway/role/embedded/gateway/api", "new", "vault/role/new/gateway/role/embedded/gateway/api"},
		{"role without /gateway/ suffix is a no-op", "vault/role/whatever/other", "new", "vault/role/whatever/other"},
	}
	for _, tc := range cases {
		tc := tc
		t.Run(tc.name, func(t *testing.T) {
			got := applyRoleHeader(tc.path, tc.role)
			assert.Equal(t, tc.want, got)
		})
	}
}

// TestHandleRequest_RoleHeaderRewritesPath verifies that in path-routing
// mode (no X-Warden-Provider), an X-Warden-Role header rewrites the role
// segment of req.Path AND the underlying HTTPRequest.URL.Path so the
// streaming backend's path-based role parser sees the same role the auth
// resolver chooses.
func TestHandleRequest_RoleHeaderRewritesPath(t *testing.T) {
	core := createTestCore(t)

	httpReq := httptest.NewRequest(http.MethodGet, "/v1/somemount/role/old-role/gateway/v1/secret/data/foo", nil)
	httpReq.Header.Set("X-Warden-Role", "new-role")

	req := &logical.Request{
		Path:        "somemount/role/old-role/gateway/v1/secret/data/foo",
		Operation:   logical.ReadOperation,
		HTTPRequest: httpReq,
	}

	// We only care that the path rewrite occurred; the mount doesn't exist so
	// the request lands on the 404 path, but req.Path / URL.Path are mutated
	// before the lookup.
	_, _ = core.HandleRequest(context.Background(), req)

	assert.Equal(t, "somemount/role/new-role/gateway/v1/secret/data/foo", req.Path,
		"req.Path should carry the header role after rewrite")
	assert.Equal(t, "/v1/somemount/role/new-role/gateway/v1/secret/data/foo", req.HTTPRequest.URL.Path,
		"HTTPRequest.URL.Path should be realigned with req.Path")
}

// TestHandleRequest_RoleHeader_NoOpWhenPathHasNoRoleSegment confirms that
// the rewrite is idempotent: when the URL has no role/<x>/gateway/ segment,
// req.Path and URL.Path are left untouched and the header role flows
// through the auth resolver instead.
func TestHandleRequest_RoleHeader_NoOpWhenPathHasNoRoleSegment(t *testing.T) {
	core := createTestCore(t)

	httpReq := httptest.NewRequest(http.MethodGet, "/v1/somemount/gateway/v1/secret/data/foo", nil)
	httpReq.Header.Set("X-Warden-Role", "new-role")

	req := &logical.Request{
		Path:        "somemount/gateway/v1/secret/data/foo",
		Operation:   logical.ReadOperation,
		HTTPRequest: httpReq,
	}

	_, _ = core.HandleRequest(context.Background(), req)

	assert.Equal(t, "somemount/gateway/v1/secret/data/foo", req.Path,
		"req.Path should be unchanged when there is no role segment to rewrite")
	assert.Equal(t, "/v1/somemount/gateway/v1/secret/data/foo", req.HTTPRequest.URL.Path,
		"URL.Path should be unchanged when there is no role segment to rewrite")
}

// TestParseRequestBody tests the parseRequestBody function
func TestParseRequestBody(t *testing.T) {
	core := createTestCore(t)

	t.Run("nil HTTPRequest", func(t *testing.T) {
		req := &logical.Request{}
		err := core.parseRequestBody(req)
		require.NoError(t, err)
		assert.Nil(t, req.Data)
	})

	t.Run("query params only", func(t *testing.T) {
		httpReq := httptest.NewRequest(http.MethodGet, "/v1/test?foo=bar&baz=qux", nil)
		req := &logical.Request{
			HTTPRequest: httpReq,
		}
		err := core.parseRequestBody(req)
		require.NoError(t, err)
		assert.Equal(t, "bar", req.Data["foo"])
		assert.Equal(t, "qux", req.Data["baz"])
	})

	t.Run("multiple values for same param", func(t *testing.T) {
		httpReq := httptest.NewRequest(http.MethodGet, "/v1/test?tags=a&tags=b&tags=c", nil)
		req := &logical.Request{
			HTTPRequest: httpReq,
		}
		err := core.parseRequestBody(req)
		require.NoError(t, err)
		tags, ok := req.Data["tags"].([]string)
		require.True(t, ok)
		assert.Equal(t, []string{"a", "b", "c"}, tags)
	})

	t.Run("GET request ignores body", func(t *testing.T) {
		body := `{"should": "be ignored"}`
		httpReq := httptest.NewRequest(http.MethodGet, "/v1/test?query=value", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/json")
		req := &logical.Request{
			HTTPRequest: httpReq,
		}
		err := core.parseRequestBody(req)
		require.NoError(t, err)
		assert.Equal(t, "value", req.Data["query"])
		assert.Nil(t, req.Data["should"])
	})

	t.Run("DELETE request ignores body", func(t *testing.T) {
		body := `{"should": "be ignored"}`
		httpReq := httptest.NewRequest(http.MethodDelete, "/v1/test", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/json")
		req := &logical.Request{
			HTTPRequest: httpReq,
		}
		err := core.parseRequestBody(req)
		require.NoError(t, err)
		assert.Nil(t, req.Data["should"])
	})

	t.Run("POST request parses JSON body", func(t *testing.T) {
		body := `{"name": "test", "value": 123}`
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/test", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/json")
		req := &logical.Request{
			HTTPRequest: httpReq,
		}
		err := core.parseRequestBody(req)
		require.NoError(t, err)
		assert.Equal(t, "test", req.Data["name"])
		assert.Equal(t, float64(123), req.Data["value"])
	})

	t.Run("PUT request parses JSON body", func(t *testing.T) {
		body := `{"key": "updated"}`
		httpReq := httptest.NewRequest(http.MethodPut, "/v1/test", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/json")
		req := &logical.Request{
			HTTPRequest: httpReq,
		}
		err := core.parseRequestBody(req)
		require.NoError(t, err)
		assert.Equal(t, "updated", req.Data["key"])
	})

	t.Run("body overwrites query params", func(t *testing.T) {
		body := `{"name": "from-body"}`
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/test?name=from-query", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/json")
		req := &logical.Request{
			HTTPRequest: httpReq,
		}
		err := core.parseRequestBody(req)
		require.NoError(t, err)
		assert.Equal(t, "from-body", req.Data["name"])
	})

	t.Run("empty body is OK", func(t *testing.T) {
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/test", strings.NewReader(""))
		httpReq.Header.Set("Content-Type", "application/json")
		req := &logical.Request{
			HTTPRequest: httpReq,
		}
		err := core.parseRequestBody(req)
		require.NoError(t, err)
	})

	t.Run("form-urlencoded content type is parsed", func(t *testing.T) {
		body := `name=test&value=123`
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/test", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
		req := &logical.Request{
			HTTPRequest: httpReq,
		}
		err := core.parseRequestBody(req)
		require.NoError(t, err)
		assert.Equal(t, "test", req.Data["name"])
		assert.Equal(t, "123", req.Data["value"])
	})

	t.Run("form-urlencoded multi-value fields", func(t *testing.T) {
		body := `tag=a&tag=b&tag=c`
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/test", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
		req := &logical.Request{
			HTTPRequest: httpReq,
		}
		err := core.parseRequestBody(req)
		require.NoError(t, err)
		tags, ok := req.Data["tag"].([]string)
		require.True(t, ok)
		assert.Equal(t, []string{"a", "b", "c"}, tags)
	})

	t.Run("form-urlencoded body is restored after parsing", func(t *testing.T) {
		body := `key=value`
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/test", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
		req := &logical.Request{
			HTTPRequest: httpReq,
		}
		err := core.parseRequestBody(req)
		require.NoError(t, err)
		restoredBody, err := io.ReadAll(req.HTTPRequest.Body)
		require.NoError(t, err)
		assert.Equal(t, body, string(restoredBody))
	})

	t.Run("form-urlencoded overwrites query params", func(t *testing.T) {
		body := `name=from-body`
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/test?name=from-query", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
		req := &logical.Request{
			HTTPRequest: httpReq,
		}
		err := core.parseRequestBody(req)
		require.NoError(t, err)
		assert.Equal(t, "from-body", req.Data["name"])
	})

	t.Run("binary content type skips body parsing", func(t *testing.T) {
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/test", strings.NewReader("binary data"))
		httpReq.Header.Set("Content-Type", "application/octet-stream")
		req := &logical.Request{
			HTTPRequest: httpReq,
		}
		err := core.parseRequestBody(req)
		require.NoError(t, err)
		// Data map is initialized (for query params) but body is not parsed into it
		assert.Empty(t, req.Data)
	})

	t.Run("xml content type skips body parsing", func(t *testing.T) {
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/test", strings.NewReader("<root/>"))
		httpReq.Header.Set("Content-Type", "application/xml")
		req := &logical.Request{
			HTTPRequest: httpReq,
		}
		err := core.parseRequestBody(req)
		require.NoError(t, err)
		// Data map is initialized (for query params) but body is not parsed into it
		assert.Empty(t, req.Data)
	})

	t.Run("invalid JSON returns error", func(t *testing.T) {
		body := `{"invalid json`
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/test", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/json")
		req := &logical.Request{
			HTTPRequest: httpReq,
		}
		err := core.parseRequestBody(req)
		require.Error(t, err)
	})

	t.Run("body is restored after reading", func(t *testing.T) {
		body := `{"test": "data"}`
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/test", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/json")
		req := &logical.Request{
			HTTPRequest: httpReq,
		}
		err := core.parseRequestBody(req)
		require.NoError(t, err)

		// Body should be re-readable
		restoredBody, err := io.ReadAll(req.HTTPRequest.Body)
		require.NoError(t, err)
		assert.Equal(t, body, string(restoredBody))
	})
}

// TestParseJSONBody tests the parseJSONBody function
func TestParseJSONBody(t *testing.T) {
	core := createTestCore(t)

	t.Run("nil body", func(t *testing.T) {
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/test", nil)
		req := &logical.Request{
			HTTPRequest: httpReq,
			Data:        make(map[string]any),
		}
		err := core.parseJSONBody(req)
		require.NoError(t, err)
	})

	t.Run("complex JSON object is flattened", func(t *testing.T) {
		body := `{
			"string": "value",
			"number": 42,
			"float": 3.14,
			"bool": true,
			"null": null,
			"array": [1, 2, 3],
			"nested": {"key": "value"}
		}`
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/test", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/json")
		req := &logical.Request{
			HTTPRequest: httpReq,
			Data:        make(map[string]any),
		}
		err := core.parseJSONBody(req)
		require.NoError(t, err)

		// Scalar leaf values are unchanged
		assert.Equal(t, "value", req.Data["string"])
		assert.Equal(t, float64(42), req.Data["number"])
		assert.Equal(t, 3.14, req.Data["float"])
		assert.Equal(t, true, req.Data["bool"])
		assert.Nil(t, req.Data["null"])
		// Arrays are treated as leaf values
		assert.Equal(t, []interface{}{float64(1), float64(2), float64(3)}, req.Data["array"])
		// Nested maps are preserved as-is for TypeMap field support
		assert.Equal(t, map[string]interface{}{"key": "value"}, req.Data["nested"])
	})

	t.Run("deep nesting is preserved", func(t *testing.T) {
		body := `{"a": {"b": {"c": "deep"}}}`
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/test", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/json")
		req := &logical.Request{
			HTTPRequest: httpReq,
			Data:        make(map[string]any),
		}
		err := core.parseJSONBody(req)
		require.NoError(t, err)

		nested := req.Data["a"].(map[string]interface{})
		inner := nested["b"].(map[string]interface{})
		assert.Equal(t, "deep", inner["c"])
	})

	t.Run("mixed flat and nested keys", func(t *testing.T) {
		body := `{"ttl": "1h", "data": {"username": "admin", "password": "secret"}}`
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/test", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/json")
		req := &logical.Request{
			HTTPRequest: httpReq,
			Data:        make(map[string]any),
		}
		err := core.parseJSONBody(req)
		require.NoError(t, err)

		assert.Equal(t, "1h", req.Data["ttl"])
		nested := req.Data["data"].(map[string]interface{})
		assert.Equal(t, "admin", nested["username"])
		assert.Equal(t, "secret", nested["password"])
	})

	t.Run("empty nested object is preserved", func(t *testing.T) {
		body := `{"a": {}, "b": "kept"}`
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/test", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/json")
		req := &logical.Request{
			HTTPRequest: httpReq,
			Data:        make(map[string]any),
		}
		err := core.parseJSONBody(req)
		require.NoError(t, err)

		assert.Equal(t, map[string]interface{}{}, req.Data["a"])
		assert.Equal(t, "kept", req.Data["b"])
		assert.Equal(t, 2, len(req.Data))
	})

	t.Run("array of objects is a leaf value", func(t *testing.T) {
		body := `{"messages": [{"role": "user", "content": "hello"}], "model": "test"}`
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/test", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/json")
		req := &logical.Request{
			HTTPRequest: httpReq,
			Data:        make(map[string]any),
		}
		err := core.parseJSONBody(req)
		require.NoError(t, err)

		assert.Equal(t, "test", req.Data["model"])
		// Array is preserved as-is, not flattened
		msgs, ok := req.Data["messages"].([]interface{})
		require.True(t, ok)
		assert.Len(t, msgs, 1)
	})
}

// TestIsStreamingRequest tests the isStreamingRequest function
func TestIsStreamingRequest(t *testing.T) {
	core := createTestCore(t)
	ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)

	// Mount a backend with streaming paths
	backend := &mockBackendWithStreamingPaths{}
	entry := &MountEntry{
		Path:        "aws/",
		Type:        "aws",
		Class:       mountClassProvider,
		UUID:        "aws-uuid",
		Accessor:    "aws_12345678",
		NamespaceID: namespace.RootNamespaceID,
		namespace:   namespace.RootNamespace,
	}
	view := &mockBarrierView{prefix: "provider/aws-uuid/"}
	err := core.router.Mount("aws/", backend, entry, view)
	require.NoError(t, err)

	t.Run("streaming path returns true", func(t *testing.T) {
		isStreaming := core.isStreamingRequest(ctx, "aws/gateway/s3/bucket")
		assert.True(t, isStreaming)
	})

	t.Run("non-streaming path returns false", func(t *testing.T) {
		isStreaming := core.isStreamingRequest(ctx, "aws/config")
		assert.False(t, isStreaming)
	})

	t.Run("non-existent path returns false", func(t *testing.T) {
		isStreaming := core.isStreamingRequest(ctx, "nonexistent/path")
		assert.False(t, isStreaming)
	})
}

// TestCheckToken_UnauthenticatedRequest tests CheckToken with unauthenticated requests
func TestCheckToken_UnauthenticatedRequest(t *testing.T) {
	core := createTestCore(t)
	ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)

	t.Run("unauthenticated without token succeeds", func(t *testing.T) {
		req := &logical.Request{
			Path:      "auth/jwt/login",
			Operation: logical.UpdateOperation,
		}
		auth, cbp, te, err := core.CheckToken(ctx, req, true)
		require.NoError(t, err)
		require.NotNil(t, auth)
		assert.Nil(t, cbp)
		assert.Nil(t, te)
	})
}

// TestCheckToken_MissingToken tests CheckToken when token is required but missing
func TestCheckToken_MissingToken(t *testing.T) {
	core := createTestCore(t)
	ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)

	req := &logical.Request{
		Path:        "sys/mounts",
		Operation:   logical.ReadOperation,
		ClientToken: "",
	}
	_, _, _, err := core.CheckToken(ctx, req, false)
	require.Error(t, err)
}

// TestPopulateTokenEntry tests the PopulateTokenEntry function
func TestPopulateTokenEntry(t *testing.T) {
	core := createTestCore(t)
	ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)

	t.Run("empty token does nothing", func(t *testing.T) {
		req := &logical.Request{
			ClientToken: "",
		}
		err := core.PopulateTokenEntry(ctx, req)
		require.NoError(t, err)
		assert.Empty(t, req.ClientTokenAccessor)
		assert.Empty(t, req.ClientTokenID)
	})

	t.Run("invalid token does not error", func(t *testing.T) {
		req := &logical.Request{
			ClientToken: "invalid-token",
		}
		err := core.PopulateTokenEntry(ctx, req)
		require.NoError(t, err)
		// Token entry not found, but no error
	})
}

// TestLoginCreateToken tests the LoginCreateToken function
func TestLoginCreateToken(t *testing.T) {
	core := createTestCore(t)
	ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)

	t.Run("root token rejected", func(t *testing.T) {
		resp := &logical.Response{
			Auth: &logical.Auth{
				Policies: []string{"root"},
			},
		}
		result, err := core.LoginCreateToken(ctx, resp)
		require.Error(t, err)
		require.NotNil(t, result)
		assert.Equal(t, http.StatusForbidden, result.StatusCode)
	})

	t.Run("non-assignable policy rejected", func(t *testing.T) {
		resp := &logical.Response{
			Auth: &logical.Auth{
				Policies: []string{"response-wrapping"},
			},
		}
		result, err := core.LoginCreateToken(ctx, resp)
		require.Error(t, err)
		require.NotNil(t, result)
		// Should be forbidden (403) for policy rejection
		assert.True(t, result.StatusCode == http.StatusForbidden || result.StatusCode == http.StatusInternalServerError,
			"expected Forbidden or InternalServerError, got %d", result.StatusCode)
	})
}

// TestHandleLoginRequest tests the handleLoginRequest function
func TestHandleLoginRequest(t *testing.T) {
	core := createTestCore(t)
	ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)

	t.Run("sets unauthenticated flag", func(t *testing.T) {
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/auth/test/login", bytes.NewReader([]byte(`{}`)))
		httpReq.Header.Set("Content-Type", "application/json")
		req := &logical.Request{
			Path:        "sys/namespaces",
			Operation:   logical.ListOperation,
			HTTPRequest: httpReq,
		}

		resp, auth, err := core.handleLoginRequest(ctx, req, false)
		// The path might not exist, but we're testing that Unauthenticated is set
		assert.True(t, req.Unauthenticated)
		// Response depends on whether the path exists
		_ = resp
		_ = auth
		_ = err
	})
}

// TestHandleNonLoginRequest_ParsesBody tests that handleNonLoginRequest parses body before CheckToken
func TestHandleNonLoginRequest_ParsesBody(t *testing.T) {
	core := createTestCore(t)
	ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)

	body := `{"key": "value"}`
	httpReq := httptest.NewRequest(http.MethodPost, "/v1/sys/test", strings.NewReader(body))
	httpReq.Header.Set("Content-Type", "application/json")
	req := &logical.Request{
		Path:        "sys/test",
		Operation:   logical.CreateOperation,
		HTTPRequest: httpReq,
	}

	// This will fail due to missing token, but req.Data should be populated
	_, _, _ = core.handleNonLoginRequest(ctx, req)

	// Verify body was parsed
	assert.Equal(t, "value", req.Data["key"])
}

// TestMintCredentialForRequest tests the mintCredentialForRequest function
func TestMintCredentialForRequest(t *testing.T) {
	core := createTestCore(t)
	ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)

	t.Run("nil token entry returns 500", func(t *testing.T) {
		req := &logical.Request{}
		err := core.mintCredentialForRequest(ctx, req, nil)
		require.Error(t, err)
		assert.Equal(t, http.StatusInternalServerError, logical.GetErrorCode(err))
		assert.Nil(t, req.Credential)
	})

	t.Run("empty credential spec returns 400", func(t *testing.T) {
		req := &logical.Request{}
		te := &logical.TokenEntry{
			ID:             "test-token",
			CredentialSpec: "",
		}
		err := core.mintCredentialForRequest(ctx, req, te)
		require.Error(t, err)
		assert.Equal(t, http.StatusBadRequest, logical.GetErrorCode(err))
		assert.Nil(t, req.Credential)
	})
}

// TestLogical_ErrorResponse_StatusCodes tests that ErrorResponse returns correct status codes
func TestLogical_ErrorResponse_StatusCodes(t *testing.T) {
	testCases := []struct {
		name           string
		err            error
		expectedStatus int
	}{
		{
			name:           "service unavailable",
			err:            logical.ErrServiceUnavailable("service down"),
			expectedStatus: http.StatusServiceUnavailable,
		},
		{
			name:           "not found",
			err:            logical.ErrNotFound("not found"),
			expectedStatus: http.StatusNotFound,
		},
		{
			name:           "bad request",
			err:            logical.ErrBadRequest("invalid input"),
			expectedStatus: http.StatusBadRequest,
		},
		{
			name:           "forbidden",
			err:            logical.ErrForbidden("access denied"),
			expectedStatus: http.StatusForbidden,
		},
		{
			name:           "internal error",
			err:            logical.ErrInternal("internal error"),
			expectedStatus: http.StatusInternalServerError,
		},
		{
			name:           "conflict",
			err:            logical.ErrConflict("conflict"),
			expectedStatus: http.StatusConflict,
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			resp := logical.ErrorResponse(tc.err)
			assert.Equal(t, tc.expectedStatus, resp.StatusCode)
		})
	}
}

// TestRestrictedSysAPIs_Paths tests that restrictedSysAPIs contains expected paths
func TestRestrictedSysAPIs_Paths(t *testing.T) {
	restrictedPaths := []string{
		"seal",
		"unseal",
		"init",
		"audit",
		"key-status",
		"rotate",
	}

	for _, path := range restrictedPaths {
		t.Run(path, func(t *testing.T) {
			assert.True(t, restrictedSysAPIs.HasPathSegments(path),
				"path %s should be restricted", path)
		})
	}
}

// TestRestrictedSysAPIs_AllowedPaths tests that non-restricted paths are allowed
func TestRestrictedSysAPIs_AllowedPaths(t *testing.T) {
	allowedPaths := []string{
		"namespaces",
		"providers",
		"auth",
		"policies",
		"credentials",
	}

	for _, path := range allowedPaths {
		t.Run(path, func(t *testing.T) {
			assert.False(t, restrictedSysAPIs.HasPathSegments(path),
				"path %s should be allowed", path)
		})
	}
}

// mockTransparentModeProvider implements both logical.Backend and logical.TransparentModeProvider
type mockTransparentModeProvider struct {
	mockProvider
	transparentMode bool
	autoAuthPath    string
	defaultAuthRole string
}

func (m *mockTransparentModeProvider) IsTransparentMode() bool {
	return m.transparentMode
}

func (m *mockTransparentModeProvider) GetAutoAuthPath() string {
	return m.autoAuthPath
}

func (m *mockTransparentModeProvider) GetAuthRole(path string, _ *logical.Request) string {
	// Simple pattern matching for testing: role/{role}/gateway...
	if strings.HasPrefix(path, "role/") {
		parts := strings.Split(path, "/")
		if len(parts) >= 3 && parts[2] == "gateway" {
			return parts[1]
		}
	}
	return m.defaultAuthRole
}

func (m *mockTransparentModeProvider) IsTransparentPath(path string) bool {
	return strings.HasPrefix(path, "gateway") || strings.Contains(path, "/gateway")
}

func (m *mockTransparentModeProvider) IsUnauthenticatedPath(path string) bool {
	return false
}

func (m *mockTransparentModeProvider) SpecialPaths() *logical.Paths {
	return &logical.Paths{
		Stream: []string{
			"gateway/*",
			"role/*/gateway/*",
		},
	}
}

// TestIsTransparentRequest tests the isTransparentRequest function
func TestIsTransparentRequest(t *testing.T) {
	core := createTestCore(t)

	t.Run("returns false for backend without TransparentModeProvider", func(t *testing.T) {
		backend := &mockProvider{}
		req := &logical.Request{Path: "role/terraform/gateway/v1/secret"}

		isTransparent, role := core.isTransparentRequest(req, backend)
		assert.False(t, isTransparent)
		assert.Empty(t, role)
	})

	t.Run("returns false when auth config is not set", func(t *testing.T) {
		backend := &mockTransparentModeProvider{
			transparentMode: false,
			autoAuthPath:    "auth/jwt/",
			defaultAuthRole: "default",
		}
		req := &logical.Request{Path: "role/terraform/gateway/v1/secret"}

		isTransparent, role := core.isTransparentRequest(req, backend)
		assert.False(t, isTransparent)
		assert.Empty(t, role)
	})

	t.Run("returns false when path does not match transparent pattern", func(t *testing.T) {
		backend := &mockTransparentModeProvider{
			transparentMode: true,
			autoAuthPath:    "auth/jwt/",
			defaultAuthRole: "", // No default role
		}
		req := &logical.Request{Path: "config"}

		isTransparent, role := core.isTransparentRequest(req, backend)
		assert.False(t, isTransparent)
		assert.Empty(t, role)
	})

	t.Run("returns true with role for matching path", func(t *testing.T) {
		backend := &mockTransparentModeProvider{
			transparentMode: true,
			autoAuthPath:    "auth/jwt/",
		}
		req := &logical.Request{Path: "role/terraform/gateway/v1/secret/data/foo"}

		isTransparent, role := core.isTransparentRequest(req, backend)
		assert.True(t, isTransparent)
		assert.Equal(t, "terraform", role)
	})

	t.Run("returns true with default role when path does not match but default is set", func(t *testing.T) {
		backend := &mockTransparentModeProvider{
			transparentMode: true,
			autoAuthPath:    "auth/jwt/",
			defaultAuthRole: "default-role",
		}
		req := &logical.Request{Path: "gateway/v1/secret"}

		isTransparent, role := core.isTransparentRequest(req, backend)
		assert.True(t, isTransparent)
		assert.Equal(t, "default-role", role)
	})

	t.Run("returns header role when no URL role prefix", func(t *testing.T) {
		backend := &mockTransparentModeProvider{
			transparentMode: true,
			autoAuthPath:    "auth/jwt/",
		}
		httpReq := httptest.NewRequest(http.MethodGet, "/v1/vault/gateway/v1/secret", nil)
		httpReq.Header.Set("X-Warden-Role", "terraform")
		req := &logical.Request{
			Path:        "gateway/v1/secret",
			HTTPRequest: httpReq,
		}

		isTransparent, role := core.isTransparentRequest(req, backend)
		assert.True(t, isTransparent)
		assert.Equal(t, "terraform", role)
	})

	t.Run("header role overrides URL role", func(t *testing.T) {
		// This is a behavior change from earlier versions: X-Warden-Role
		// previously yielded to a role embedded in the URL. The two headers
		// (provider, role) now obey the same rule — header wins.
		backend := &mockTransparentModeProvider{
			transparentMode: true,
			autoAuthPath:    "auth/jwt/",
		}
		httpReq := httptest.NewRequest(http.MethodGet, "/v1/vault/role/terraform/gateway/v1/secret", nil)
		httpReq.Header.Set("X-Warden-Role", "operator")
		req := &logical.Request{
			Path:        "role/terraform/gateway/v1/secret",
			HTTPRequest: httpReq,
		}

		isTransparent, role := core.isTransparentRequest(req, backend)
		assert.True(t, isTransparent)
		assert.Equal(t, "operator", role)
	})

	t.Run("header role takes precedence over default role", func(t *testing.T) {
		backend := &mockTransparentModeProvider{
			transparentMode: true,
			autoAuthPath:    "auth/jwt/",
			defaultAuthRole: "fallback",
		}
		httpReq := httptest.NewRequest(http.MethodGet, "/v1/vault/gateway/v1/secret", nil)
		httpReq.Header.Set("X-Warden-Role", "terraform")
		req := &logical.Request{
			Path:        "gateway/v1/secret",
			HTTPRequest: httpReq,
		}

		isTransparent, role := core.isTransparentRequest(req, backend)
		assert.True(t, isTransparent)
		assert.Equal(t, "terraform", role)
	})
}

// TestHandleTransparentAuth tests the handleTransparentAuth function
func TestHandleTransparentAuth(t *testing.T) {
	core := createTestCore(t)
	ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)

	t.Run("returns error when no credential provided", func(t *testing.T) {
		backend := &mockTransparentModeProvider{
			transparentMode: true,
			autoAuthPath:    "auth/jwt/",
		}
		req := &logical.Request{
			ClientToken: "",
		}

		err := core.handleTransparentAuth(ctx, req, backend, "terraform")
		require.Error(t, err)
		assert.Contains(t, err.Error(), "no valid credential")
	})

	t.Run("returns error for non-JWT non-cert token", func(t *testing.T) {
		backend := &mockTransparentModeProvider{
			transparentMode: true,
			autoAuthPath:    "auth/jwt/",
		}
		req := &logical.Request{
			ClientToken: "cws.not-a-jwt-token",
		}

		err := core.handleTransparentAuth(ctx, req, backend, "terraform")
		require.Error(t, err)
		assert.Contains(t, err.Error(), "no valid credential")
	})

	t.Run("uses existing JWT token when found in cache", func(t *testing.T) {
		// Create a JWT token using GenerateToken with the jwt_role type
		sampleJWT := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0LXVzZXIifQ.test-sig"

		authData := &AuthData{
			TokenValue:     sampleJWT,
			RoleName:       "terraform",
			PrincipalID:    "test-user",
			ExpireAt:       time.Now().Add(24 * time.Hour),
			Policies:       []string{"default"},
			CredentialSpec: "test-spec",
		}
		te, err := core.tokenStore.GenerateToken(ctx, TypeJWTRole, authData)
		require.NoError(t, err)
		require.NotNil(t, te)

		backend := &mockTransparentModeProvider{
			transparentMode: true,
			autoAuthPath:    "auth/jwt/",
		}
		req := &logical.Request{
			ClientToken: sampleJWT,
		}

		err = core.handleTransparentAuth(ctx, req, backend, "terraform")
		require.NoError(t, err)
		assert.NotNil(t, req.TokenEntry())
		assert.Equal(t, te.ID, req.TokenEntry().ID)
	})

	t.Run("returns error when implicit auth fails - auth backend not mounted", func(t *testing.T) {
		backend := &mockTransparentModeProvider{
			transparentMode: true,
			autoAuthPath:    "auth/jwt/",
		}
		// Use a JWT that won't be found in the token store
		req := &logical.Request{
			ClientToken: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.signature",
			HTTPRequest: httptest.NewRequest(http.MethodPost, "/v1/vault/role/terraform/gateway", nil),
		}

		err := core.handleTransparentAuth(ctx, req, backend, "terraform")
		// Should fail because the auth backend is not mounted
		require.Error(t, err)
	})
}

// TestHandleTransparentAuth_Singleflight tests that concurrent requests with the same JWT token
// all resolve to the same cached token entry
func TestHandleTransparentAuth_Singleflight(t *testing.T) {
	core := createTestCore(t)
	ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)

	// Create a JWT token using GenerateToken
	sampleJWT := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzaW5nbGVmbGlnaHQtdXNlciJ9.test-sig"

	authData := &AuthData{
		TokenValue:     sampleJWT,
		RoleName:       "terraform",
		PrincipalID:    "test-user-singleflight",
		ExpireAt:       time.Now().Add(24 * time.Hour),
		Policies:       []string{"default"},
		CredentialSpec: "test-spec",
	}
	te, err := core.tokenStore.GenerateToken(ctx, TypeJWTRole, authData)
	require.NoError(t, err)
	require.NotNil(t, te)

	backend := &mockTransparentModeProvider{
		transparentMode: true,
		autoAuthPath:    "auth/jwt/",
	}

	// Simulate multiple concurrent requests with the same JWT token
	const numGoroutines = 10
	var wg sync.WaitGroup
	results := make(chan *TokenEntry, numGoroutines)
	errors := make(chan error, numGoroutines)

	for i := 0; i < numGoroutines; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			req := &logical.Request{
				ClientToken: sampleJWT,
			}
			err := core.handleTransparentAuth(ctx, req, backend, "terraform")
			if err != nil {
				errors <- err
				return
			}
			results <- req.TokenEntry()
		}()
	}

	wg.Wait()
	close(results)
	close(errors)

	// Check no errors occurred
	for err := range errors {
		t.Errorf("unexpected error: %v", err)
	}

	// All requests should get the same token (verified by ID and accessor)
	var firstTE *TokenEntry
	resultCount := 0
	for result := range results {
		resultCount++
		if firstTE == nil {
			firstTE = result
		} else {
			// Check same ID - proves all requests resolved to the same token
			assert.Equal(t, firstTE.ID, result.ID, "all requests should get the same token ID")
			assert.Equal(t, firstTE.Accessor, result.Accessor, "all requests should get the same token accessor")
		}
	}

	// Verify we got results from all goroutines
	assert.Equal(t, numGoroutines, resultCount, "should have received results from all goroutines")
}

// TestHandleTransparentAuth_JWTDifferentRoles tests that the same JWT with different roles
// produces different tokens, preventing JWT+Role1 from being reused for JWT+Role2
func TestHandleTransparentAuth_JWTDifferentRoles(t *testing.T) {
	core := createTestCore(t)
	ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)

	// Sample JWT for testing (format is valid but signature is not verified in tests)
	sampleJWT := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.signature"

	t.Run("same JWT with different roles should produce different token IDs", func(t *testing.T) {
		jwtType := &JWTRoleTokenType{}

		// Create token for JWT + Role1
		entry1 := &TokenEntry{
			Data: map[string]string{},
		}
		authData1 := &AuthData{
			TokenValue:  sampleJWT,
			RoleName:    "role1",
			PrincipalID: "test-user",
			ExpireAt:    time.Now().Add(1 * time.Hour),
			Policies:    []string{"policy1"},
		}
		_, err := jwtType.Generate(context.Background(), authData1, entry1)
		require.NoError(t, err)
		id1 := jwtType.ComputeID(entry1.Data["jwt"])

		// Create token for JWT + Role2
		entry2 := &TokenEntry{
			Data: map[string]string{},
		}
		authData2 := &AuthData{
			TokenValue:  sampleJWT,
			RoleName:    "role2",
			PrincipalID: "test-user",
			ExpireAt:    time.Now().Add(1 * time.Hour),
			Policies:    []string{"policy2"},
		}
		_, err = jwtType.Generate(context.Background(), authData2, entry2)
		require.NoError(t, err)
		id2 := jwtType.ComputeID(entry2.Data["jwt"])

		// The token IDs should be different
		assert.NotEqual(t, id1, id2, "Same JWT with different roles should have different token IDs")
	})

	t.Run("LookupJWTTokenWithRole returns error for non-existent token", func(t *testing.T) {
		sampleJWT2 := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.test"

		// Looking up a token that doesn't exist should return an error
		_, err := core.LookupJWTTokenWithRole(ctx, sampleJWT2, "terraform")
		assert.Error(t, err, "Looking up non-existent JWT token should return error")

		// Looking up with different role should also fail
		_, err = core.LookupJWTTokenWithRole(ctx, sampleJWT2, "different-role")
		assert.Error(t, err, "Looking up with different role should not find the token")
	})

	t.Run("ComputeData and ComputeID match token creation ID", func(t *testing.T) {
		jwtType := &JWTRoleTokenType{}

		// Simulate token creation: Generate stores hash of JWT+role in entry.Data["jwt"]
		entry := &TokenEntry{
			Data: map[string]string{},
		}
		authData := &AuthData{TokenValue: sampleJWT, RoleName: "terraform"}
		jwtType.Generate(context.Background(), authData, entry)

		// Verify the stored value is a hash of JWT+role (not raw value)
		expectedHash := sha256.Sum256([]byte(sampleJWT + ":terraform"))
		assert.Equal(t, hex.EncodeToString(expectedHash[:]), entry.Data["jwt"])

		// Token ID is computed from the stored hash
		tokenID := jwtType.ComputeID(entry.Data["jwt"])

		// Lookup: hash first, then compute ID - should match
		lookupHash := jwtType.ComputeData(sampleJWT, "terraform")
		lookupID := jwtType.ComputeID(lookupHash)

		assert.Equal(t, tokenID, lookupID, "Token creation and lookup should produce same ID")
	})
}

// mockStreamBodyParserBackend implements logical.Backend and logical.StreamBodyParser
type mockStreamBodyParserBackend struct {
	mockBackendWithStreamingPaths
	parseStreamBody bool
}

func (m *mockStreamBodyParserBackend) ShouldParseStreamBody() bool {
	return m.parseStreamBody
}

// TestHandleNonLoginRequest_StreamingBodyParsing tests opt-in body parsing for streaming requests
func TestHandleNonLoginRequest_StreamingBodyParsing(t *testing.T) {
	core := createTestCore(t)
	ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)

	// Mount backend that opts into stream body parsing
	backend := &mockStreamBodyParserBackend{parseStreamBody: true}
	entry := &MountEntry{
		Path:        "vault/",
		Type:        "vault",
		Class:       mountClassProvider,
		UUID:        "vault-uuid",
		Accessor:    "vault_12345678",
		NamespaceID: namespace.RootNamespaceID,
		namespace:   namespace.RootNamespace,
	}
	view := &mockBarrierView{prefix: "provider/vault-uuid/"}
	err := core.router.Mount("vault/", backend, entry, view)
	require.NoError(t, err)

	t.Run("streaming request with JSON body populates req.Data", func(t *testing.T) {
		body := `{"key": "value", "ttl": "1h"}`
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/vault/gateway/v1/pki/issue/my-role", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/json")
		httpReq.Header.Set("X-Vault-Token", "test-token")
		req := &logical.Request{
			Path:        "vault/gateway/v1/pki/issue/my-role",
			Operation:   logical.CreateOperation,
			HTTPRequest: httpReq,
		}

		// Will fail auth, but req.Data should be populated before that
		_, _, _ = core.handleNonLoginRequest(ctx, req)
		assert.True(t, req.Streamed)
		assert.Equal(t, "value", req.Data["key"])
		assert.Equal(t, "1h", req.Data["ttl"])
	})

	t.Run("streaming request with form-urlencoded body populates req.Data", func(t *testing.T) {
		body := `name=test&ttl=2h`
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/vault/gateway/v1/secret/data/mykey", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
		httpReq.Header.Set("X-Vault-Token", "test-token")
		req := &logical.Request{
			Path:        "vault/gateway/v1/secret/data/mykey",
			Operation:   logical.CreateOperation,
			HTTPRequest: httpReq,
		}

		_, _, _ = core.handleNonLoginRequest(ctx, req)
		assert.True(t, req.Streamed)
		assert.Equal(t, "test", req.Data["name"])
		assert.Equal(t, "2h", req.Data["ttl"])
	})

	t.Run("streaming request body is restored after parsing", func(t *testing.T) {
		body := `{"key": "value"}`
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/vault/gateway/test", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/json")
		httpReq.Header.Set("X-Vault-Token", "test-token")
		req := &logical.Request{
			Path:        "vault/gateway/test",
			Operation:   logical.CreateOperation,
			HTTPRequest: httpReq,
		}

		_, _, _ = core.handleNonLoginRequest(ctx, req)
		restoredBody, err := io.ReadAll(req.HTTPRequest.Body)
		require.NoError(t, err)
		assert.Equal(t, body, string(restoredBody))
	})

	t.Run("streaming request with binary content type skips parsing", func(t *testing.T) {
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/vault/gateway/upload", strings.NewReader("binary data"))
		httpReq.Header.Set("Content-Type", "application/octet-stream")
		httpReq.Header.Set("X-Vault-Token", "test-token")
		req := &logical.Request{
			Path:        "vault/gateway/upload",
			Operation:   logical.CreateOperation,
			HTTPRequest: httpReq,
		}

		_, _, _ = core.handleNonLoginRequest(ctx, req)
		assert.True(t, req.Streamed)
		// Data map is initialized (for query params) but binary body is not parsed into it
		assert.Empty(t, req.Data)
	})
}

// TestCheckToken_ConcurrentRequests tests that multiple concurrent requests
// with the same valid root token all succeed. This reproduces a bug where
// only the first concurrent request succeeds and subsequent ones get 403.
func TestCheckToken_ConcurrentRequests(t *testing.T) {
	core := createTestCore(t)
	ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)

	// Generate root token
	rootToken, err := core.tokenStore.GenerateRootToken()
	require.NoError(t, err)
	require.NotEmpty(t, rootToken)

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

	for i := 0; i < numGoroutines; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			req := &logical.Request{
				Path:        "sys/providers",
				Operation:   logical.ReadOperation,
				ClientToken: rootToken,
			}
			_, _, _, err := core.CheckToken(ctx, req, false)
			if err != nil {
				errs <- err
			}
		}()
	}

	wg.Wait()
	close(errs)

	for err := range errs {
		t.Errorf("concurrent CheckToken failed: %v", err)
	}
}

// TestHandleRequest_ConcurrentWithRootToken tests that concurrent HandleRequest
// calls with a valid root token all succeed end-to-end through the HTTP pipeline.
func TestHandleRequest_ConcurrentWithRootToken(t *testing.T) {
	core := createTestCore(t)

	// Generate root token
	rootToken, err := core.tokenStore.GenerateRootToken()
	require.NoError(t, err)

	const numGoroutines = 10
	var wg sync.WaitGroup
	results := make(chan int, numGoroutines) // collect status codes

	for i := 0; i < numGoroutines; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			httpReq := httptest.NewRequest(http.MethodGet, "/v1/sys/providers?warden-list=true", nil)
			httpReq.Header.Set("X-Warden-Token", rootToken)
			req := &logical.Request{
				Path:        "sys/providers",
				Operation:   logical.ListOperation,
				HTTPRequest: httpReq,
			}
			resp, err := core.HandleRequest(context.Background(), req)
			if err != nil {
				results <- -1
				return
			}
			if resp == nil {
				results <- 0
				return
			}
			results <- resp.StatusCode
		}()
	}

	wg.Wait()
	close(results)

	failures := 0
	for code := range results {
		// 200 or 0 (StatusCode not explicitly set = OK) are acceptable
		if code != http.StatusOK && code != 0 {
			failures++
			t.Errorf("concurrent HandleRequest returned unexpected status: %d", code)
		}
	}
	if failures > 0 {
		t.Errorf("%d out of %d concurrent requests failed", failures, numGoroutines)
	}
}

// TestTransparentOps_NonStreamingPath tests transparent operations on non-gateway endpoints
func TestTransparentOps_NonStreamingPath(t *testing.T) {
	core := createTestCore(t)
	ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)

	t.Run("X-Warden-Token skips transparent ops", func(t *testing.T) {
		// When X-Warden-Token is set, transparent ops should be skipped entirely,
		// even if namespace has auto_auth_path configured.
		rootToken, err := core.tokenStore.GenerateRootToken()
		require.NoError(t, err)

		httpReq := httptest.NewRequest(http.MethodGet, "/v1/sys/providers?warden-list=true", nil)
		httpReq.Header.Set("X-Warden-Token", rootToken)
		httpReq.Header.Set("X-Warden-Role", "operator")
		req := &logical.Request{
			Path:        "sys/providers",
			Operation:   logical.ListOperation,
			HTTPRequest: httpReq,
		}

		resp, _, err := core.handleNonLoginRequest(ctx, req)
		// Should succeed with root token — transparent ops was skipped
		assert.Nil(t, err)
		if resp != nil {
			assert.NotEqual(t, http.StatusUnauthorized, resp.StatusCode)
		}
		// Transparent flag should NOT be set
		assert.False(t, req.Transparent)
	})

	t.Run("no auth path means normal flow - Bearer treated as Warden token", func(t *testing.T) {
		// No X-Warden-Token, no namespace auto_auth_path.
		// Authorization: Bearer should be treated as a Warden token (normal flow).
		httpReq := httptest.NewRequest(http.MethodGet, "/v1/sys/providers", nil)
		httpReq.Header.Set("Authorization", "Bearer some-warden-token")
		req := &logical.Request{
			Path:        "sys/providers",
			Operation:   logical.ReadOperation,
			HTTPRequest: httpReq,
		}

		_, _, _ = core.handleNonLoginRequest(ctx, req)
		// Should NOT be marked transparent
		assert.False(t, req.Transparent)
		// ClientToken should be the Bearer value (extracted by extractToken)
		assert.Equal(t, "some-warden-token", req.ClientToken)
	})

	t.Run("JWT transparent ops with namespace auto_auth_path triggers implicit auth", func(t *testing.T) {
		// Sends Authorization: Bearer <JWT> with namespace auto_auth_path configured.
		// Since the auth backend isn't actually mounted, this will fail — but it
		// proves transparent ops was triggered (req.Transparent is set).
		sampleJWT := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0LXVzZXIifQ.test-sig-ops"

		ns := &namespace.Namespace{
			ID:   "test-ns-trigger",
			Path: "trigger/",
			CustomMetadata: map[string]string{
				"auto_auth_path": "auth/jwt/",
			},
		}
		nsCtx := namespace.ContextWithNamespace(context.Background(), ns)

		httpReq := httptest.NewRequest(http.MethodGet, "/v1/sys/cred/sources", nil)
		httpReq.Header.Set("Authorization", "Bearer "+sampleJWT)
		httpReq.Header.Set("X-Warden-Role", "operator")
		req := &logical.Request{
			Path:        "sys/cred/sources",
			Operation:   logical.ReadOperation,
			HTTPRequest: httpReq,
		}

		resp, _, _ := core.handleNonLoginRequest(nsCtx, req)
		// Should fail because auth backend is not mounted, but transparent flag is set
		require.NotNil(t, resp)
		assert.True(t, req.Transparent, "request should be marked as transparent")
	})

	t.Run("JWT transparent ops with cached token succeeds", func(t *testing.T) {
		// Pre-create a cached token in root namespace, then verify transparent ops finds it.
		sampleJWT := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjYWNoZWQtdXNlciJ9.cached-sig"

		authData := &AuthData{
			TokenValue:     sampleJWT,
			RoleName:       "ops-reader",
			PrincipalID:    "cached-user",
			ExpireAt:       time.Now().Add(24 * time.Hour),
			Policies:       []string{"default"},
			CredentialSpec: "test-spec",
		}
		te, err := core.tokenStore.GenerateToken(ctx, TypeJWTRole, authData)
		require.NoError(t, err)
		require.NotNil(t, te)

		// Use root namespace with auto_auth_path to trigger transparent ops
		rootWithAuth := &namespace.Namespace{
			ID:   namespace.RootNamespaceID,
			Path: "",
			CustomMetadata: map[string]string{
				"auto_auth_path": "auth/jwt/",
			},
		}
		nsCtx := namespace.ContextWithNamespace(context.Background(), rootWithAuth)

		httpReq := httptest.NewRequest(http.MethodGet, "/v1/sys/cred/sources", nil)
		httpReq.Header.Set("Authorization", "Bearer "+sampleJWT)
		httpReq.Header.Set("X-Warden-Role", "ops-reader")
		req := &logical.Request{
			Path:        "sys/cred/sources",
			Operation:   logical.ReadOperation,
			HTTPRequest: httpReq,
		}

		_, _, _ = core.handleNonLoginRequest(nsCtx, req)
		assert.True(t, req.Transparent)
		assert.NotNil(t, req.TokenEntry())
		assert.Equal(t, te.ID, req.TokenEntry().ID)
	})

	t.Run("no credential with auto_auth_path returns auth error", func(t *testing.T) {
		// No JWT, no cert — namespace has auto_auth_path but no credential
		ns := &namespace.Namespace{
			ID:   "test-ns-nocred",
			Path: "nocred/",
			CustomMetadata: map[string]string{
				"auto_auth_path": "auth/cert/",
			},
		}
		nsCtx := namespace.ContextWithNamespace(context.Background(), ns)

		httpReq := httptest.NewRequest(http.MethodGet, "/v1/sys/cred/sources", nil)
		httpReq.Header.Set("X-Warden-Role", "agent")
		req := &logical.Request{
			Path:        "sys/cred/sources",
			Operation:   logical.ReadOperation,
			HTTPRequest: httpReq,
		}

		resp, _, _ := core.handleNonLoginRequest(nsCtx, req)
		require.NotNil(t, resp)
		assert.True(t, req.Transparent)
		assert.NotNil(t, resp.Err)
		assert.Contains(t, resp.Err.Error(), "no valid credential")
	})

	t.Run("namespace auto_auth_path triggers transparent ops", func(t *testing.T) {
		// Create a namespace with auto_auth_path in custom_metadata
		ns := &namespace.Namespace{
			ID:   "test-ns-id",
			Path: "team-a/",
			CustomMetadata: map[string]string{
				"auto_auth_path": "auth/jwt/",
			},
		}
		nsCtx := namespace.ContextWithNamespace(context.Background(), ns)

		sampleJWT := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJucy11c2VyIn0.ns-sig"

		httpReq := httptest.NewRequest(http.MethodGet, "/v1/sys/cred/sources", nil)
		httpReq.Header.Set("Authorization", "Bearer "+sampleJWT)
		httpReq.Header.Set("X-Warden-Role", "operator")
		req := &logical.Request{
			Path:        "sys/cred/sources",
			Operation:   logical.ReadOperation,
			HTTPRequest: httpReq,
		}

		_, _, _ = core.handleNonLoginRequest(nsCtx, req)
		assert.True(t, req.Transparent)
	})

	t.Run("role query param takes precedence over X-Warden-Role header", func(t *testing.T) {
		sampleJWT := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJwcmVjLXVzZXIifQ.prec-sig"

		// Pre-create cached tokens for both roles
		for _, roleName := range []string{"from-query", "from-header"} {
			authData := &AuthData{
				TokenValue:     sampleJWT,
				RoleName:       roleName,
				PrincipalID:    "prec-user",
				ExpireAt:       time.Now().Add(24 * time.Hour),
				Policies:       []string{"default"},
				CredentialSpec: "test-spec",
			}
			_, err := core.tokenStore.GenerateToken(ctx, TypeJWTRole, authData)
			require.NoError(t, err)
		}

		ns := &namespace.Namespace{
			ID:   "test-ns-prec",
			Path: "prec/",
			CustomMetadata: map[string]string{
				"auto_auth_path": "auth/jwt/",
			},
		}
		nsCtx := namespace.ContextWithNamespace(context.Background(), ns)

		httpReq := httptest.NewRequest(http.MethodGet, "/v1/sys/cred/sources?role=from-query", nil)
		httpReq.Header.Set("Authorization", "Bearer "+sampleJWT)
		httpReq.Header.Set("X-Warden-Role", "from-header")
		req := &logical.Request{
			Path:        "sys/cred/sources",
			Operation:   logical.ReadOperation,
			HTTPRequest: httpReq,
		}

		_, _, _ = core.handleNonLoginRequest(nsCtx, req)
		assert.True(t, req.Transparent)
		require.NotNil(t, req.TokenEntry())
		assert.Equal(t, "from-query", req.TokenEntry().RoleName)
	})

	t.Run("X-Warden-Role header used when no role query param", func(t *testing.T) {
		sampleJWT := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJmYWxsYmFjay11c2VyIn0.fallback-sig"

		authData := &AuthData{
			TokenValue:     sampleJWT,
			RoleName:       "from-header",
			PrincipalID:    "fallback-user",
			ExpireAt:       time.Now().Add(24 * time.Hour),
			Policies:       []string{"default"},
			CredentialSpec: "test-spec",
		}
		_, err := core.tokenStore.GenerateToken(ctx, TypeJWTRole, authData)
		require.NoError(t, err)

		ns := &namespace.Namespace{
			ID:   "test-ns-fallback",
			Path: "fallback/",
			CustomMetadata: map[string]string{
				"auto_auth_path": "auth/jwt/",
			},
		}
		nsCtx := namespace.ContextWithNamespace(context.Background(), ns)

		httpReq := httptest.NewRequest(http.MethodGet, "/v1/sys/cred/sources", nil)
		httpReq.Header.Set("Authorization", "Bearer "+sampleJWT)
		httpReq.Header.Set("X-Warden-Role", "from-header")
		req := &logical.Request{
			Path:        "sys/cred/sources",
			Operation:   logical.ReadOperation,
			HTTPRequest: httpReq,
		}

		_, _, _ = core.handleNonLoginRequest(nsCtx, req)
		assert.True(t, req.Transparent)
		require.NotNil(t, req.TokenEntry())
		assert.Equal(t, "from-header", req.TokenEntry().RoleName)
	})
}

// TestHandleNonLoginRequest_StreamingWithoutBodyParsing tests that backends without
// StreamBodyParser do not get body parsing on streaming requests
func TestHandleNonLoginRequest_StreamingWithoutBodyParsing(t *testing.T) {
	core := createTestCore(t)
	ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace)

	// Mount backend that does NOT opt into stream body parsing (default)
	backend := &mockBackendWithStreamingPaths{}
	entry := &MountEntry{
		Path:        "aws/",
		Type:        "aws",
		Class:       mountClassProvider,
		UUID:        "aws-uuid-2",
		Accessor:    "aws_87654321",
		NamespaceID: namespace.RootNamespaceID,
		namespace:   namespace.RootNamespace,
	}
	view := &mockBarrierView{prefix: "provider/aws-uuid-2/"}
	err := core.router.Mount("aws/", backend, entry, view)
	require.NoError(t, err)

	t.Run("streaming request without opt-in does not parse body", func(t *testing.T) {
		body := `{"key": "value"}`
		httpReq := httptest.NewRequest(http.MethodPost, "/v1/aws/gateway/test", strings.NewReader(body))
		httpReq.Header.Set("Content-Type", "application/json")
		req := &logical.Request{
			Path:        "aws/gateway/test",
			Operation:   logical.CreateOperation,
			HTTPRequest: httpReq,
		}

		_, _, _ = core.handleNonLoginRequest(ctx, req)
		assert.True(t, req.Streamed)
		// req.Data should be nil - body was NOT parsed
		assert.Nil(t, req.Data)
	})
}

func TestValidActorSubject(t *testing.T) {
	cases := []struct {
		name  string
		input string
		want  bool
	}{
		{"empty rejected", "", false},
		{"simple alpha", "agent-alpha", true},
		{"namespaced path", "agents/alpha", true},
		{"email-ish", "alpha@pod-xyz", true},
		{"colon ok", "kind:agent-alpha", true},
		{"plus ok", "alpha+test", true},
		{"dot ok", "alpha.bot", true},
		{"underscore ok", "agent_alpha", true},
		{"comma rejected (single-actor enforcement)", "alpha,beta", false},
		{"space rejected", "alpha beta", false},
		{"CR rejected", "alpha\rinjected", false},
		{"LF rejected", "alpha\ninjected", false},
		{"tab rejected", "alpha\tbeta", false},
		{"unicode rejected", "agent-α", false},
		{"at-256-bytes accepted", strings.Repeat("a", 256), true},
		{"over-256-bytes rejected", strings.Repeat("a", 257), false},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			assert.Equal(t, tc.want, validActorSubject(tc.input))
		})
	}
}
