fix tests. new product advisories enhancements

This commit is contained in:
master
2026-01-25 19:11:36 +02:00
parent c70e83719e
commit 6e687b523a
504 changed files with 40610 additions and 3785 deletions

View File

@@ -664,24 +664,24 @@ CREATE TABLE IF NOT EXISTS policy.budget_ledger (
service_id VARCHAR(128) NOT NULL,
tenant_id VARCHAR(64),
tier INT NOT NULL DEFAULT 1,
window VARCHAR(16) NOT NULL,
"window" VARCHAR(16) NOT NULL,
allocated INT NOT NULL,
consumed INT NOT NULL DEFAULT 0,
status VARCHAR(16) NOT NULL DEFAULT 'green',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_budget_ledger_service_window UNIQUE (service_id, window)
CONSTRAINT uq_budget_ledger_service_window UNIQUE (service_id, "window")
);
CREATE INDEX idx_budget_ledger_service_id ON policy.budget_ledger (service_id);
CREATE INDEX idx_budget_ledger_tenant_id ON policy.budget_ledger (tenant_id);
CREATE INDEX idx_budget_ledger_window ON policy.budget_ledger (window);
CREATE INDEX idx_budget_ledger_window ON policy.budget_ledger ("window");
CREATE INDEX idx_budget_ledger_status ON policy.budget_ledger (status);
CREATE TABLE IF NOT EXISTS policy.budget_entries (
entry_id VARCHAR(64) PRIMARY KEY,
service_id VARCHAR(128) NOT NULL,
window VARCHAR(16) NOT NULL,
"window" VARCHAR(16) NOT NULL,
release_id VARCHAR(128) NOT NULL,
risk_points INT NOT NULL,
reason VARCHAR(512),
@@ -689,11 +689,11 @@ CREATE TABLE IF NOT EXISTS policy.budget_entries (
penalty_points INT NOT NULL DEFAULT 0,
consumed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
consumed_by VARCHAR(256),
CONSTRAINT fk_budget_entries_ledger FOREIGN KEY (service_id, window)
REFERENCES policy.budget_ledger (service_id, window) ON DELETE CASCADE
CONSTRAINT fk_budget_entries_ledger FOREIGN KEY (service_id, "window")
REFERENCES policy.budget_ledger (service_id, "window") ON DELETE CASCADE
);
CREATE INDEX idx_budget_entries_service_window ON policy.budget_entries (service_id, window);
CREATE INDEX idx_budget_entries_service_window ON policy.budget_entries (service_id, "window");
CREATE INDEX idx_budget_entries_release_id ON policy.budget_entries (release_id);
CREATE INDEX idx_budget_entries_consumed_at ON policy.budget_entries (consumed_at);
@@ -1219,7 +1219,7 @@ CREATE POLICY budget_entries_tenant_isolation ON policy.budget_entries
EXISTS (
SELECT 1 FROM policy.budget_ledger bl
WHERE bl.service_id = budget_entries.service_id
AND bl.window = budget_entries.window
AND bl."window" = budget_entries."window"
AND (bl.tenant_id = current_setting('app.tenant_id', TRUE) OR bl.tenant_id IS NULL)
)
);

View File

@@ -106,10 +106,10 @@ CREATE INDEX IF NOT EXISTS idx_gate_bypass_audit_image_digest
CREATE INDEX IF NOT EXISTS idx_gate_bypass_audit_bypass_type
ON policy.gate_bypass_audit(tenant_id, bypass_type);
-- Partial index for active time-limited bypasses
CREATE INDEX IF NOT EXISTS idx_gate_bypass_audit_active_bypasses
ON policy.gate_bypass_audit(tenant_id, expires_at)
WHERE expires_at IS NOT NULL AND expires_at > NOW();
-- Partial index for time-limited bypasses (filtered by non-null expires_at)
CREATE INDEX IF NOT EXISTS idx_gate_bypass_audit_active_bypasses
ON policy.gate_bypass_audit(tenant_id, expires_at)
WHERE expires_at IS NOT NULL;
-- ============================================================================
-- Row Level Security (RLS) Policies

View File

@@ -31,6 +31,11 @@ public sealed class ExceptionEntity
/// </summary>
public required Guid Id { get; init; }
/// <summary>
/// Human-readable unique exception identifier.
/// </summary>
public string ExceptionId { get; init; } = string.Empty;
/// <summary>
/// Tenant identifier.
/// </summary>

View File

@@ -23,11 +23,11 @@ public sealed class ExceptionRepository : RepositoryBase<PolicyDataSource>, IExc
{
const string sql = """
INSERT INTO policy.exceptions (
id, tenant_id, name, description, rule_pattern, resource_pattern,
id, exception_id, tenant_id, name, description, rule_pattern, resource_pattern,
artifact_pattern, project_id, reason, status, expires_at, metadata, created_by
)
VALUES (
@id, @tenant_id, @name, @description, @rule_pattern, @resource_pattern,
@id, @exception_id, @tenant_id, @name, @description, @rule_pattern, @resource_pattern,
@artifact_pattern, @project_id, @reason, @status, @expires_at, @metadata::jsonb, @created_by
)
RETURNING *
@@ -295,6 +295,11 @@ public sealed class ExceptionRepository : RepositoryBase<PolicyDataSource>, IExc
private static void AddExceptionParameters(NpgsqlCommand command, ExceptionEntity exception)
{
AddParameter(command, "id", exception.Id);
// Generate exception_id from Id if not provided
var exceptionId = string.IsNullOrEmpty(exception.ExceptionId)
? $"exc-{exception.Id:N}"[..24]
: exception.ExceptionId;
AddParameter(command, "exception_id", exceptionId);
AddParameter(command, "tenant_id", exception.TenantId);
AddParameter(command, "name", exception.Name);
AddParameter(command, "description", exception.Description);
@@ -312,6 +317,7 @@ public sealed class ExceptionRepository : RepositoryBase<PolicyDataSource>, IExc
private static ExceptionEntity MapException(NpgsqlDataReader reader) => new()
{
Id = reader.GetGuid(reader.GetOrdinal("id")),
ExceptionId = reader.GetString(reader.GetOrdinal("exception_id")),
TenantId = reader.GetString(reader.GetOrdinal("tenant_id")),
Name = reader.GetString(reader.GetOrdinal("name")),
Description = GetNullableString(reader, reader.GetOrdinal("description")),

View File

@@ -13,7 +13,7 @@
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Migrations\**\*.sql" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
<EmbeddedResource Include="Migrations\*.sql" />
</ItemGroup>
<ItemGroup>

View File

@@ -386,12 +386,18 @@ public sealed class SignatureRequiredGate : IPolicyGate
if (trusted.StartsWith("*@", StringComparison.Ordinal))
{
var domain = trusted[2..];
if (issuer.EndsWith($"@{domain}", StringComparison.OrdinalIgnoreCase))
if (!domain.Contains('*'))
{
return true;
// Simple wildcard: *@domain.com matches any local part with exact domain
if (issuer.EndsWith($"@{domain}", StringComparison.OrdinalIgnoreCase))
{
return true;
}
continue;
}
}
else if (trusted.Contains('*'))
if (trusted.Contains('*'))
{
// General wildcard pattern
var pattern = "^" + Regex.Escape(trusted).Replace("\\*", ".*") + "$";