using System.Diagnostics.CodeAnalysis;
namespace DodoSSH.Client.Domain;
///
/// A saved command, decrypted.
///
///
///
/// is the field this type exists to get right. A terminal is one input
/// stream with no notion of "at a prompt": the remote may be inside vi, or at a sudo password
/// prompt with echo off, and without shell integration the client cannot tell. So inserting a snippet is
/// always "type this into whatever is there", never "run this command" — and whether a newline follows the
/// text is the difference between the user reading what appeared and deciding, and something happening.
/// It defaults to , which makes that decision the user's Enter key.
///
///
/// is stored verbatim. No trimming, no newline normalisation — the same rule
/// follows, for a related reason: a heredoc's trailing newline is
/// load-bearing, and a shell that receives a here-document terminator with the whitespace tidied off it hangs
/// waiting for one that never comes.
///
///
/// Deliberately not in this version, each with a reason rather than an omission: host scoping, which
/// needs a set merge that does not have; tags, which are their own reserved
/// item kind; and parameter substitution, which would make this a template language expanding into a
/// root shell — a second security surface for a feature whose first one is already the hard part.
///
///
public sealed record SnippetSecret : IVaultSecret
{
/// What the snippet is called. The only name it has anywhere.
public required string Label { get; init; }
/// The text to insert. May be several lines.
public required string Command { get; init; }
/// Free-text notes.
public string? Notes { get; init; }
///
/// Whether inserting this also presses Enter.
///
///
/// Off unless the user turns it on, per snippet. A vault-wide preference was the alternative and it is
/// worse: the setting belongs to the command, because ls -la and rm -rf /var/lib/postgresql
/// do not want the same answer, and a single switch would eventually be left on by whoever needed it for
/// the first of those.
///
public bool RunsOnInsert { get; init; }
/// Whether this is storable, and why not if it is not.
///
/// is checked for being blank but for nothing else. What makes a valid command is
/// the remote shell's business, this client does not know which shell that is, and a validator guessing
/// at it would refuse the legitimate cases — a bare \x03, a partial line meant to be completed by
/// hand — while catching nothing that matters.
///
public bool TryValidate([NotNullWhen(false)] out string? reason)
{
if (string.IsNullOrWhiteSpace(Label))
{
reason = "A snippet needs a name.";
return false;
}
if (string.IsNullOrEmpty(Command))
{
reason = "A snippet needs something to insert.";
return false;
}
reason = null;
return true;
}
}