namespace DodoSSH.Api.Features.Teams;

/// <summary>
/// A team create or membership change was structurally unacceptable.
/// </summary>
/// <remarks>
/// The message is returned to the caller. Keep it about the shape of their own request, and never
/// about accounts or teams they cannot already see — "no such user" is safe when the caller supplied
/// the id from a directory lookup they just made, and is an enumeration oracle everywhere else.
/// </remarks>
internal sealed class TeamInvalidException(string message) : Exception(message);

/// <summary>The requested slug is already in use.</summary>
/// <remarks>
/// Its own type because it is the one create failure the caller could not have predicted from their
/// own input, and the only one whose remedy is choosing a different value rather than fixing one.
/// </remarks>
internal sealed class TeamSlugTakenException(string message) : Exception(message);

/// <summary>The change would leave a team with no owner.</summary>
/// <remarks>
/// Refused rather than allowed: a team with no owner has nobody who can appoint one, so the only
/// route back would be an operator editing the database by hand.
/// </remarks>
internal sealed class LastTeamOwnerException(string message) : Exception(message);

/// <summary>
/// A vault key grant was rejected.
/// </summary>
/// <remarks>
/// Never about the wrapped key's contents. The server cannot open it, so a grant sealing garbage is
/// accepted here and fails at the recipient as a tag failure, with the signature naming who issued
/// it. See docs/crypto.md §6.
/// </remarks>
internal sealed class VaultGrantInvalidException(string message) : Exception(message);
