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>
153 lines
4.0 KiB
C#
153 lines
4.0 KiB
C#
using Xunit;
|
|
using OpenHarbor.MCP.Gateway.Core.Configuration;
|
|
|
|
namespace OpenHarbor.MCP.Gateway.Core.Tests.Configuration;
|
|
|
|
/// <summary>
|
|
/// Unit tests for SecurityConfig following TDD approach.
|
|
/// Tests security configuration and validation.
|
|
/// </summary>
|
|
public class SecurityConfigTests
|
|
{
|
|
[Fact]
|
|
public void SecurityConfig_DefaultValues_DisablesAuthentication()
|
|
{
|
|
// Arrange & Act
|
|
var config = new SecurityConfig();
|
|
|
|
// Assert
|
|
Assert.False(config.EnableAuthentication);
|
|
Assert.False(config.EnableAuthorization);
|
|
}
|
|
|
|
[Fact]
|
|
public void SecurityConfig_WithApiKeyAuth_StoresCorrectly()
|
|
{
|
|
// Arrange & Act
|
|
var config = new SecurityConfig
|
|
{
|
|
EnableAuthentication = true,
|
|
AuthenticationScheme = "ApiKey",
|
|
ApiKeys = new List<string> { "key1", "key2", "key3" }
|
|
};
|
|
|
|
// Assert
|
|
Assert.True(config.EnableAuthentication);
|
|
Assert.Equal("ApiKey", config.AuthenticationScheme);
|
|
Assert.NotNull(config.ApiKeys);
|
|
Assert.Equal(3, config.ApiKeys.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void SecurityConfig_WithJwtAuth_StoresCorrectly()
|
|
{
|
|
// Arrange & Act
|
|
var config = new SecurityConfig
|
|
{
|
|
EnableAuthentication = true,
|
|
AuthenticationScheme = "JWT",
|
|
JwtSecret = "my-secret-key",
|
|
JwtIssuer = "gateway.example.com",
|
|
JwtAudience = "mcp-clients"
|
|
};
|
|
|
|
// Assert
|
|
Assert.Equal("JWT", config.AuthenticationScheme);
|
|
Assert.Equal("my-secret-key", config.JwtSecret);
|
|
Assert.Equal("gateway.example.com", config.JwtIssuer);
|
|
Assert.Equal("mcp-clients", config.JwtAudience);
|
|
}
|
|
|
|
[Fact]
|
|
public void SecurityConfig_WithAuthorization_StoresClientPermissions()
|
|
{
|
|
// Arrange & Act
|
|
var config = new SecurityConfig
|
|
{
|
|
EnableAuthorization = true,
|
|
ClientPermissions = new Dictionary<string, List<string>>
|
|
{
|
|
{ "client-1", new List<string> { "read", "write" } },
|
|
{ "client-2", new List<string> { "read" } }
|
|
}
|
|
};
|
|
|
|
// Assert
|
|
Assert.True(config.EnableAuthorization);
|
|
Assert.NotNull(config.ClientPermissions);
|
|
Assert.Equal(2, config.ClientPermissions.Count);
|
|
Assert.Contains("write", config.ClientPermissions["client-1"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void SecurityConfig_WithRateLimiting_StoresCorrectly()
|
|
{
|
|
// Arrange & Act
|
|
var config = new SecurityConfig
|
|
{
|
|
EnableRateLimiting = true,
|
|
RequestsPerMinute = 60,
|
|
BurstSize = 10
|
|
};
|
|
|
|
// Assert
|
|
Assert.True(config.EnableRateLimiting);
|
|
Assert.Equal(60, config.RequestsPerMinute);
|
|
Assert.Equal(10, config.BurstSize);
|
|
}
|
|
|
|
[Fact]
|
|
public void SecurityConfig_Validate_WithApiKeyButNoKeys_ReturnsFalse()
|
|
{
|
|
// Arrange
|
|
var config = new SecurityConfig
|
|
{
|
|
EnableAuthentication = true,
|
|
AuthenticationScheme = "ApiKey",
|
|
ApiKeys = new List<string>()
|
|
};
|
|
|
|
// Act
|
|
var isValid = config.Validate();
|
|
|
|
// Assert
|
|
Assert.False(isValid);
|
|
}
|
|
|
|
[Fact]
|
|
public void SecurityConfig_Validate_WithJwtButNoSecret_ReturnsFalse()
|
|
{
|
|
// Arrange
|
|
var config = new SecurityConfig
|
|
{
|
|
EnableAuthentication = true,
|
|
AuthenticationScheme = "JWT",
|
|
JwtSecret = null
|
|
};
|
|
|
|
// Act
|
|
var isValid = config.Validate();
|
|
|
|
// Assert
|
|
Assert.False(isValid);
|
|
}
|
|
|
|
[Fact]
|
|
public void SecurityConfig_Validate_WithValidApiKeyConfig_ReturnsTrue()
|
|
{
|
|
// Arrange
|
|
var config = new SecurityConfig
|
|
{
|
|
EnableAuthentication = true,
|
|
AuthenticationScheme = "ApiKey",
|
|
ApiKeys = new List<string> { "valid-key" }
|
|
};
|
|
|
|
// Act
|
|
var isValid = config.Validate();
|
|
|
|
// Assert
|
|
Assert.True(isValid);
|
|
}
|
|
}
|