namespace ZB.MOM.WW.OtOpcUa.Configuration.Entities; /// /// One OPC UA data-plane API key. The OPC UA data plane is machine-to-machine, so a /// consuming system authenticates with a key rather than an LDAP user, and the key resolves to a /// that rows grant permissions to. /// /// /// /// One principal per key, deliberately. The reason to separate keys from principals is so /// that many keys can share one grant set and rotating a key never touches an ACL row — and that /// holds with a single principal per key, because nothing stops two keys naming the same /// principal. A key belonging to several principals at once (union of grants) buys little and /// costs a join table, so it is not modelled. UserAuthorizationState.Principals is still a /// list, so adding it later needs no change on the ACL side. /// /// /// The secret is never stored. holds a peppered HMAC-SHA256 of the /// secret half only; the plaintext is shown once at creation and is unrecoverable afterwards. /// /// /// ⚠️ Revocation requires a deploy. Phase 4 leaves driver-only nodes with no ConfigDb, so /// keys reach them inside the deployment artifact exactly as rows do. /// Setting to false takes effect on a node only once a new artifact reaches /// it. This is an operational sharp edge, not an oversight. /// /// public sealed class ApiKey { /// Gets or sets the database row ID for this key. public Guid ApiKeyRowId { get; set; } /// /// Gets or sets the public key id — the middle segment of otua_<keyId>_<secret>. /// Carried in the clear so verification is an index seek rather than a scan over every stored hash. /// public required string ApiKeyId { get; set; } /// Gets or sets the human-readable label, e.g. the consuming system's name. public required string Name { get; set; } /// /// Gets or sets the base64 peppered HMAC-SHA256 of the key's secret segment. Never the secret. /// public required string SecretHash { get; set; } /// /// Gets or sets the principal this key authenticates as. rows /// naming this value grant it permissions. /// public required string Principal { get; set; } /// Gets or sets whether the key may authenticate. See the revocation caveat on the type. public bool Enabled { get; set; } = true; /// Gets or sets when the key was created (UTC). public DateTime CreatedUtc { get; set; } /// Gets or sets when the key expires (UTC); null never expires. public DateTime? ExpiresUtc { get; set; } /// Gets or sets optional operator notes. public string? Notes { get; set; } /// Optimistic concurrency token, matching the rest of the live-edit config model. public byte[] RowVersion { get; set; } = Array.Empty(); }