Interview question
Test an endpoint capability matrix
Expresses allowed and denied capability combinations as one parameterized API integration test.
TL;DR
Expresses allowed and denied capability combinations as one parameterized API integration test.
Policy authorization, capability claims, 401 versus 403, parameterized cases, and regression-friendly access matrices.
Practice the problem like a real interview: restate, reason, implement, and test.
Use the test authentication scheme to send anonymous, ordinary-user, editor, and admin-capability requests. The matrix is the contract: anonymous gets 401, authenticated users without the capability get 403, and users with imports.preflight reach the endpoint.
Next in API Testing Labs: Ownership Boundary
An Editor role name alone does not guarantee access. The test passes only when the effective capability set includes imports.preflight.
I turn the policy into data rows so adding or removing one access path is obvious in review. Each request goes through the real authorization middleware. The success cases assert endpoint behavior too, preventing a false pass caused by an unrelated 404 or 500.
[Theory]
[InlineData(null, null, HttpStatusCode.Unauthorized)]
[InlineData("user", "suggestions.create", HttpStatusCode.Forbidden)]
[InlineData("editor", "content.read", HttpStatusCode.Forbidden)]
[InlineData("editor", "imports.preflight", HttpStatusCode.OK)]
[InlineData("admin", "imports.preflight", HttpStatusCode.OK)]
public async Task Import_preflight_enforces_capability(
string? userId,
string? capabilities,
HttpStatusCode expected)
{
await using var factory = new ApiTestFactory();
var client = factory.CreateClient();
if (userId is not null)
{
client.DefaultRequestHeaders.Add("X-Test-User", userId);
client.DefaultRequestHeaders.Add("X-Test-Capabilities", capabilities);
}
using var response = await client.PostAsJsonAsync(
"/api/admin/imports/preflight",
TestImports.MinimalValidPack());
Assert.Equal(expected, response.StatusCode);
}
The matrix is small and deterministic. It validates policy wiring, claim transformation, and endpoint authorization without importing content because the route is preflight-only and test services are isolated.
Spot a weak answer, missing edge case, or clearer explanation? Send it in.