w4c-workflows-api/Services/Security/PolicyDecision.cs
Vitali sharp8n 42ffcb9adc workflows
2026-09-13 19:28:47 +03:00

53 lines
2.2 KiB
C#

namespace w4c_workflows.Services.Security;
/// <summary>
/// The result of evaluating a target against any of the execution policies
/// (egress, node permissions). A denied decision carries a stable
/// <see cref="Code"/> for failure routing and tests plus a human-readable
/// <see cref="Reason"/> that is safe to surface to the workflow author.
///
/// The egress and node-permission layers used to define byte-identical records
/// (<c>EgressDecision</c> / <c>NodePermissionDecision</c>); this is the single
/// shape so callers can treat a policy result uniformly.
///
/// <para>
/// The four independent layers that gate a node run, in the order they apply:
/// <list type="number">
/// <item><description>
/// <b>Egress</b> (<see cref="EgressPolicy"/> + <see cref="EgressGuard"/>) —
/// every outbound target (HTTP node, REST connector, credential test) is
/// vetted per hop; credentials are dropped on a cross-host redirect.
/// </description></item>
/// <item><description>
/// <b>Node permission</b> (<see cref="NodePermissionPolicy"/>) — which
/// blueprint types/kinds/origins may run, enforced at the palette, the
/// compiler and the run kernel.
/// </description></item>
/// <item><description>
/// <b>Node request budget</b> (Nodes/NodeRequestBudget) — a per-run cap on
/// outbound requests and response size, guarding against a runaway loop or an
/// oversized body. Resource governance, not authorization.
/// </description></item>
/// <item><description>
/// <b>Tenant run quota</b> (<see cref="Quota.WorkflowQuotaService"/>) — the
/// monthly run allowance per tenant.
/// </description></item>
/// </list>
/// </para>
/// </summary>
public sealed record PolicyDecision
{
public required bool Allowed { get; init; }
/// <summary>Stable machine code, e.g. <c>host_blocked</c> or <c>node_type_blocked</c>.</summary>
public string? Code { get; init; }
/// <summary>Human-readable explanation, safe to surface to the workflow author.</summary>
public string? Reason { get; init; }
public static PolicyDecision Permit() => new() { Allowed = true };
public static PolicyDecision Deny(string code, string reason)
=> new() { Allowed = false, Code = code, Reason = reason };
}