권한 규칙 호환성 확장: @/|/() 패턴 파싱 및 체인 회귀 강화
Some checks failed
Release Gate / gate (push) Has been cancelled
Some checks failed
Release Gate / gate (push) Has been cancelled
- AgentContext 권한 규칙 파서가 tool@pattern 외 tool|pattern, tool(pattern) 표기를 해석하도록 확장 - deny 우선순위 체인은 유지하면서 claw-code 계열 표기 차이로 인한 규칙 누락을 방지 - OperationModePolicyTests에 파이프/함수형 패턴 및 deny 우선 회귀 테스트 추가 - README/DEVELOPMENT에 2026-04-04 14:55(KST) 기준 이력 동기화
This commit is contained in:
@@ -120,6 +120,40 @@ public class OperationModePolicyTests
|
||||
context.GetEffectiveToolPermission("process", "git push origin main").Should().Be("Deny");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AgentContext_GetEffectiveToolPermission_SupportsPipePatternSyntax()
|
||||
{
|
||||
var context = new AgentContext
|
||||
{
|
||||
Permission = "Default",
|
||||
ToolPermissions = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["process|git *"] = "acceptedits",
|
||||
["process|git push *"] = "deny",
|
||||
}
|
||||
};
|
||||
|
||||
context.GetEffectiveToolPermission("process", "git status").Should().Be("Default");
|
||||
context.GetEffectiveToolPermission("process", "git push origin main").Should().Be("Deny");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AgentContext_GetEffectiveToolPermission_SupportsFunctionPatternSyntax()
|
||||
{
|
||||
var context = new AgentContext
|
||||
{
|
||||
Permission = "Default",
|
||||
ToolPermissions = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["process(git *)"] = "dontask",
|
||||
["process(git push *)"] = "deny",
|
||||
}
|
||||
};
|
||||
|
||||
context.GetEffectiveToolPermission("process", "git status").Should().Be("DontAsk");
|
||||
context.GetEffectiveToolPermission("process", "git push origin main").Should().Be("Deny");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AgentContext_GetEffectiveToolPermission_AcceptEditsAllowsWriteButKeepsProcessPrompted()
|
||||
{
|
||||
|
||||
@@ -330,12 +330,30 @@ public class AgentContext
|
||||
|
||||
var trimmed = key.Trim();
|
||||
var at = trimmed.IndexOf('@');
|
||||
if (at <= 0 || at == trimmed.Length - 1)
|
||||
return false;
|
||||
if (at > 0 && at < trimmed.Length - 1)
|
||||
{
|
||||
ruleTool = trimmed[..at].Trim();
|
||||
rulePattern = trimmed[(at + 1)..].Trim();
|
||||
return !string.IsNullOrWhiteSpace(ruleTool) && !string.IsNullOrWhiteSpace(rulePattern);
|
||||
}
|
||||
|
||||
ruleTool = trimmed[..at].Trim();
|
||||
rulePattern = trimmed[(at + 1)..].Trim();
|
||||
return !string.IsNullOrWhiteSpace(ruleTool) && !string.IsNullOrWhiteSpace(rulePattern);
|
||||
var pipe = trimmed.IndexOf('|');
|
||||
if (pipe > 0 && pipe < trimmed.Length - 1)
|
||||
{
|
||||
ruleTool = trimmed[..pipe].Trim();
|
||||
rulePattern = trimmed[(pipe + 1)..].Trim();
|
||||
return !string.IsNullOrWhiteSpace(ruleTool) && !string.IsNullOrWhiteSpace(rulePattern);
|
||||
}
|
||||
|
||||
var open = trimmed.IndexOf('(');
|
||||
if (open > 0 && trimmed.EndsWith(")", StringComparison.Ordinal))
|
||||
{
|
||||
ruleTool = trimmed[..open].Trim();
|
||||
rulePattern = trimmed[(open + 1)..^1].Trim();
|
||||
return !string.IsNullOrWhiteSpace(ruleTool) && !string.IsNullOrWhiteSpace(rulePattern);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool WildcardMatch(string input, string pattern)
|
||||
|
||||
Reference in New Issue
Block a user