using System.Diagnostics.CodeAnalysis; namespace DodoSSH.Client.Domain; /// /// A folder hosts can be filed under, decrypted. /// /// /// /// One field, which makes this the smallest secret in the vault, and the small size is the feature. A group /// is a heading in a sidebar; everything else somebody might want from it — which hosts are in it, where it /// sits in a tree, what colour it is — was considered and left out, each for its own reason. /// /// /// No member list. Membership is a on each host, so filing two /// different hosts into one group on two machines is two writes to two items. Held here it would be two /// writes to one item, and has no set merge — the collision would resolve by one /// side winning outright and the other host silently leaving the group it was just put in. /// /// /// No parent. Groups are flat. Two clients can each re-parent A under B and B under A while offline, /// and a scalar merge accepts both: the result is a cycle that no reader can draw and that the server cannot /// even see, because it is inside the payload. One level of nesting is not worth a state with no repair path. /// /// public sealed record HostGroupSecret : IVaultSecret { /// What the group is called. The only name it has anywhere. public required string Label { get; init; } /// Whether this is storable, and why not if it is not. /// /// A blank name is refused rather than defaulted. A group is only ever a heading, so a nameless one is /// indistinguishable from the ungrouped heading it would sit next to — and a user cannot select what they /// cannot tell apart. /// public bool TryValidate([NotNullWhen(false)] out string? reason) { if (string.IsNullOrWhiteSpace(Label)) { reason = "A group needs a name."; return false; } reason = null; return true; } }