namespace DodoSSH.Domain;
/// What a change did to an entity.
public enum ChangeOperation
{
/// Not a legal value.
Unspecified = 0,
/// Created or modified.
Upsert = 1,
/// Soft-deleted, leaving a tombstone.
Delete = 2,
}
/// The kind of item a change refers to. Mirrors the contract enum; append only.
public enum ChangeEntityType
{
/// Not a legal value.
Unspecified = 0,
/// An SSH host.
SshHost = 1,
/// A credential. M2.
Credential = 2,
/// An SSH key pair. M2.
SshKey = 3,
/// A host group. M2.
HostGroup = 4,
/// A tag. M2.
Tag = 5,
/// A host-to-tag association. M2.
HostTag = 6,
/// A host-to-credential association. M2.
HostCredential = 7,
/// A snippet. M2.
Snippet = 8,
/// A port forward. M2.
PortForward = 9,
/// A known SSH host key. M2.
KnownHostKey = 10,
/// One connection that was made, and how long it lasted. M2.
ConnectionLogEntry = 11,
/// One create, edit or delete of a vault item. M2.
ActivityLogEntry = 12,
/// An S3-compatible bucket, and the credentials that reach it. M2.
ObjectStore = 13,
/// A Spelunk API key, and the one Spelunk address it may be sent to.
SpelunkKey = 14,
}
///
/// One entry in a vault's change log, which is what delta sync reads.
///
///
///
/// comes from a bigserial, and that carries a trap worth stating
/// where the code lives: sequence values are handed out before commit. If transaction A
/// takes 5 and B takes 6 but B commits first, a reader that advances its cursor to 6 permanently
/// misses 5 — silent sync corruption that only appears under concurrent writes to one vault.
///
///
/// Every push therefore takes a per-vault transaction-scoped advisory lock as its first
/// statement, so sequence order equals commit order. See ADR 0003.
///
///
public sealed class VaultChange
{
/// Monotonic sequence. Database-generated.
public long Sequence { get; set; }
/// Owning vault. Cursors are scoped per vault.
public Guid VaultId { get; set; }
/// Kind of item.
public ChangeEntityType EntityType { get; set; }
/// The item.
public Guid EntityId { get; set; }
/// What happened.
public ChangeOperation Operation { get; set; }
/// The item's version after the change.
public int Revision { get; set; }
/// Who made the change.
public Guid ActorUserId { get; set; }
/// When it was recorded.
public DateTimeOffset OccurredAtUtc { get; set; }
}
///
/// Records that a client operation was applied, so a retry is a no-op.
///
///
/// Keyed on the client-generated operation id, which makes retries exactly-once at
/// operation granularity. A batch-level idempotency key alone would not: a client that
/// times out mid-push and retries with a partially overlapping batch would otherwise double-apply
/// the operations that did land.
///
public sealed class SyncOperationReceipt
{
/// The client-generated operation id. Primary key.
public Guid OperationId { get; set; }
/// Vault the operation targeted.
public Guid VaultId { get; set; }
/// Change-log sequence produced, when the operation was applied.
public long? AppliedChangeSequence { get; set; }
/// The item's version after the operation.
public int? ResultVersion { get; set; }
/// Creation timestamp.
public DateTimeOffset CreatedAtUtc { get; set; }
}