svrnty-mcp-gateway/tests/Svrnty.MCP.Gateway.Core.Tests/Interfaces/IAuthProviderTests.cs
Svrnty a4a1dd2e38 docs: comprehensive AI coding assistant research and MCP-first implementation plan
Research conducted on modern AI coding assistants (Cursor, GitHub Copilot, Cline,
Aider, Windsurf, Replit Agent) to understand architecture patterns, context management,
code editing workflows, and tool use protocols.

Key Decision: Pivoted from building full CLI (40-50h) to validation-driven MCP-first
approach (10-15h). Build 5 core CODEX MCP tools that work with ANY coding assistant,
validate adoption over 2-4 weeks, then decide on full CLI if demand proven.

Files:
- research/ai-systems/modern-coding-assistants-architecture.md (comprehensive research)
- research/ai-systems/codex-coding-assistant-implementation-plan.md (original CLI plan, preserved)
- research/ai-systems/codex-mcp-tools-implementation-plan.md (approved MCP-first plan)
- ideas/registry.json (updated with approved MCP tools proposal)

Architech Validation: APPROVED with pivot to MCP-first approach
Human Decision: Approved (pragmatic validation-driven development)

Next: Begin Phase 1 implementation (10-15 hours, 5 core MCP tools)

🤖 Generated with CODEX Research System

Co-Authored-By: The Archivist <archivist@codex.svrnty.io>
Co-Authored-By: The Architech <architech@codex.svrnty.io>
Co-Authored-By: Mathias Beaulieu-Duncan <mat@svrnty.io>
2025-10-22 21:00:34 -04:00

159 lines
4.8 KiB
C#

using Xunit;
using Moq;
using OpenHarbor.MCP.Gateway.Core.Interfaces;
using OpenHarbor.MCP.Gateway.Core.Models;
namespace OpenHarbor.MCP.Gateway.Core.Tests.Interfaces;
/// <summary>
/// Unit tests for IAuthProvider interface following TDD approach.
/// Tests authentication and authorization logic.
/// </summary>
public class IAuthProviderTests
{
[Fact]
public async Task AuthenticateAsync_WithValidCredentials_ReturnsSuccess()
{
// Arrange
var mockAuthProvider = new Mock<IAuthProvider>();
var context = new AuthenticationContext
{
ClientId = "valid-client",
Credentials = "valid-token"
};
var expectedResult = new AuthenticationResult
{
IsAuthenticated = true,
ClientId = "valid-client"
};
mockAuthProvider
.Setup(a => a.AuthenticateAsync(It.IsAny<AuthenticationContext>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(expectedResult);
// Act
var result = await mockAuthProvider.Object.AuthenticateAsync(context, CancellationToken.None);
// Assert
Assert.True(result.IsAuthenticated);
Assert.Equal("valid-client", result.ClientId);
mockAuthProvider.Verify(a => a.AuthenticateAsync(context, It.IsAny<CancellationToken>()), Times.Once);
}
[Fact]
public async Task AuthenticateAsync_WithInvalidCredentials_ReturnsFailure()
{
// Arrange
var mockAuthProvider = new Mock<IAuthProvider>();
var context = new AuthenticationContext
{
ClientId = "invalid-client",
Credentials = "invalid-token"
};
var expectedResult = new AuthenticationResult
{
IsAuthenticated = false,
ErrorMessage = "Invalid credentials"
};
mockAuthProvider
.Setup(a => a.AuthenticateAsync(It.IsAny<AuthenticationContext>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(expectedResult);
// Act
var result = await mockAuthProvider.Object.AuthenticateAsync(context, CancellationToken.None);
// Assert
Assert.False(result.IsAuthenticated);
Assert.NotNull(result.ErrorMessage);
}
[Fact]
public async Task AuthorizeAsync_WithAuthorizedClient_ReturnsSuccess()
{
// Arrange
var mockAuthProvider = new Mock<IAuthProvider>();
var context = new AuthorizationContext
{
ClientId = "authorized-client",
Resource = "read_documents",
Action = "invoke"
};
var expectedResult = new AuthorizationResult
{
IsAuthorized = true
};
mockAuthProvider
.Setup(a => a.AuthorizeAsync(It.IsAny<AuthorizationContext>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(expectedResult);
// Act
var result = await mockAuthProvider.Object.AuthorizeAsync(context, CancellationToken.None);
// Assert
Assert.True(result.IsAuthorized);
mockAuthProvider.Verify(a => a.AuthorizeAsync(context, It.IsAny<CancellationToken>()), Times.Once);
}
[Fact]
public async Task AuthorizeAsync_WithUnauthorizedClient_ReturnsFailure()
{
// Arrange
var mockAuthProvider = new Mock<IAuthProvider>();
var context = new AuthorizationContext
{
ClientId = "unauthorized-client",
Resource = "delete_documents",
Action = "invoke"
};
var expectedResult = new AuthorizationResult
{
IsAuthorized = false,
ErrorMessage = "Access denied"
};
mockAuthProvider
.Setup(a => a.AuthorizeAsync(It.IsAny<AuthorizationContext>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(expectedResult);
// Act
var result = await mockAuthProvider.Object.AuthorizeAsync(context, CancellationToken.None);
// Assert
Assert.False(result.IsAuthorized);
Assert.NotNull(result.ErrorMessage);
}
[Fact]
public async Task AuthenticateAsync_WithMissingCredentials_ReturnsFailure()
{
// Arrange
var mockAuthProvider = new Mock<IAuthProvider>();
var context = new AuthenticationContext
{
ClientId = "client-without-credentials"
};
var expectedResult = new AuthenticationResult
{
IsAuthenticated = false,
ErrorMessage = "Credentials required"
};
mockAuthProvider
.Setup(a => a.AuthenticateAsync(It.IsAny<AuthenticationContext>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(expectedResult);
// Act
var result = await mockAuthProvider.Object.AuthenticateAsync(context, CancellationToken.None);
// Assert
Assert.False(result.IsAuthenticated);
}
}