Files
ScadaBridge/src/ZB.MOM.WW.ScadaBridge.InboundAPI/InboundApiOptions.cs
T
Joseph Doherty 0ffd4bdbea docs(src): fix CommentChecker findings across src/ — 1,032 → 5 (all false positives)
Comment/XML-doc changes only, no code logic:
- strip project-tracking references (WP*, P*-*, row-NN, #NN, Task N) from
  comments, keeping the explanatory rationale
- add missing summaries, <param>, <returns>, <typeparam> and <inheritdoc/>
- replace misused <inheritdoc/> with real docs; where <inheritdoc/> was
  combined with useful remarks, move the rationale into // comments
- drop stale replicationActor <param> on DeploymentManagerActor ctor

Remaining 5 are false positives (CWE-1236 x2, failures-1, year-0001, M365).
Build 0 errors / 0 warnings.
2026-10-07 14:12:25 -04:00

86 lines
4.8 KiB
C#

namespace ZB.MOM.WW.ScadaBridge.InboundAPI;
public class InboundApiOptions
{
/// <summary>
/// Default cap on the inbound API request body, in bytes.
/// </summary>
public const long DefaultMaxRequestBodyBytes = 1L * 1024 * 1024; // 1 MiB
/// <summary>Default timeout for inbound API method execution before the request is cancelled.</summary>
public TimeSpan DefaultMethodTimeout { get; set; } = TimeSpan.FromSeconds(30);
/// <summary>
/// Maximum accepted request body size for <c>POST /api/{methodName}</c>.
/// Requests whose body exceeds this are rejected with HTTP 413 before being
/// buffered into a <see cref="System.Text.Json.JsonDocument"/>. The inbound API
/// has no rate limiting (a deliberate design choice), so an explicit, modest cap
/// bounds per-request allocations.
/// </summary>
public long MaxRequestBodyBytes { get; set; } = DefaultMaxRequestBodyBytes;
/// <summary>
/// Server-side HMAC pepper for inbound-API bearer credentials, bound from
/// <c>ScadaBridge:InboundApi:ApiKeyPepper</c>.
/// <para>
/// Auth re-arch: the legacy SQL Server hashing path that consumed this
/// property was retired. The pepper itself is still required — the shared
/// ZB.MOM.WW.Auth.ApiKeys verifier reads the SAME configuration key
/// (<c>PepperSecretName</c> in the Host composition root points at it) to pepper
/// the SQLite-stored keys. It is a secret: supply a strong, random value
/// (≥ 16 characters), DIFFERENT per environment, via a secret store and never
/// hard-coded. This property is retained so the section still binds cleanly; the
/// value is consumed by the library verifier, not by <c>AddInboundAPI</c>.
/// </para>
/// </summary>
public string ApiKeyPepper { get; set; } = string.Empty;
/// <summary>
/// How long a resolved
/// <c>ApiMethod</c> row (found OR not-found) is served from <see cref="ApiMethodCache"/>
/// before the next request re-fetches it from the repository. The
/// <c>ScriptArtifactChangeSubscriber</c>/<c>IScriptArtifactChangeBus</c> pipeline
/// invalidates a specific method's entry immediately on a bundle-import change (the fast
/// path); this TTL is the self-healing fallback for changes the bus does not cover (e.g.
/// an operator edit via the Management API/UI, which does not publish a bus notification),
/// bounding staleness without requiring every mutation path to remember to invalidate.
/// Short by design — the whole point is to absorb repeated-request-storm SQL, not to
/// serve minutes-old method definitions.
/// </summary>
public TimeSpan ApiMethodCacheTtl { get; set; } = TimeSpan.FromSeconds(5);
/// <summary>
/// Standby-node forwarding (2026-08-28): the HTTP base URLs of the OTHER central
/// node(s) — e.g. <c>["http://scadabridge-central-b:5000"]</c> on central-a — that a
/// standby relays <c>POST /api/{methodName}</c> to instead of answering 503
/// <c>STANDBY_NODE</c>. Tried in order; the first peer that is not itself a standby
/// serves the call. Empty (the default) keeps the pre-forwarding behaviour: a standby
/// refuses with 503. Method scripts still execute only on the active node — the
/// standby is a pure relay (see <see cref="HttpStandbyRequestForwarder"/>). Each entry
/// must be an absolute <c>http</c>/<c>https</c> URL; never list this node's own address
/// (it would cost one wasted round-trip per call — the loop guard stops it bouncing).
/// </summary>
public List<string> StandbyForwardPeerEndpoints { get; set; } = new();
/// <summary>
/// End-to-end relay budget spanning connection, permitted standby retries and response
/// consumption. Size it for the longest method execution plus network overhead. A send
/// whose response is lost or times out returns OUTCOME_UNKNOWN and is never replayed.
/// Default 60 s.
/// </summary>
public TimeSpan StandbyForwardTimeout { get; set; } = TimeSpan.FromSeconds(60);
/// <summary>Default value of <see cref="MaxLogLinesPerRun"/>, also used when no options instance is available.</summary>
public const int DefaultMaxLogLinesPerRun = 200;
/// <summary>
/// Flow Debugger step logs (design 2026-09-09 D7): how many <c>Log.*</c> lines ONE traced
/// method execution may turn into <c>ScriptTrace/ScriptLog</c> audit rows. Past the cap the
/// lines are dropped from the trace — they still reach the node's <c>ILogger</c> — and the
/// run ends with a single runtime-sourced warning row naming the dropped count, so a
/// truncated trace is never silently short. Untraced executions emit no rows at all and are
/// therefore unaffected by this value. Must be greater than zero.
/// </summary>
public int MaxLogLinesPerRun { get; set; } = DefaultMaxLogLinesPerRun;
}