namespace WebDrop.Core; public sealed record Channel( Id16 Id, ChannelMode Mode, ChannelSettings Settings, byte[]? ReadHash, byte[]? WriteHash, byte[] OwnerHash, long CreatedAt, long ExpiresAt, long LastSeq, long CompactedThrough, long Bytes, string CreatorAccount, byte[]? JoinPasswordHash = null, byte[]? JoinPasswordSalt = null); public sealed record Share( Id16 Id, ShareSettings Settings, byte[] ReadHash, byte[]? OwnerHash, byte[]? CreatorEndpointHash, long CreatedAt, long ExpiresAt, long? SealedAt, Id16? ManifestItemId, long Bytes, string CreatorAccount) { public bool IsSealed => SealedAt is not null; } public sealed record ShareItem( Id16 ShareId, Id16 ItemId, FrameFlags Flags, long MaxDownloads, long Downloads, int FrameCount, long MaxIndex, long? FinalIndex, long Bytes, long CreatedAt, long ExpiresAt, long? CloseDeadline) { public bool IsGated => (Flags & FrameFlags.Gated) != 0; public bool IsSnapshot => (Flags & FrameFlags.Snapshot) != 0; public bool IsComplete => FinalIndex is { } f && FrameCount == f + 1; } public sealed record ShareFrame( Id16 ShareId, Id16 ItemId, uint Index, long AckSeq, int Length, byte[] Digest, byte[]? Inline, string? BlobKey); public sealed record Item( Id16 ChannelId, Id16 ItemId, byte[] AuthorHash, FrameFlags Flags, long MaxDownloads, long Downloads, int FrameCount, long MaxIndex, long? FinalIndex, long Bytes, long CreatedAt, long ExpiresAt, long? CloseDeadline, string? AuthorAccount) { public bool IsGated => (Flags & FrameFlags.Gated) != 0; public bool IsSnapshot => (Flags & FrameFlags.Snapshot) != 0; public bool IsComplete => FinalIndex is { } f && FrameCount == f + 1; } public sealed record Seat(byte[] EndpointHash, long JoinedAt, byte[]? Label, string? AccountName = null, string? AccountDeviceId = null); public sealed record ChannelInvitation(Id16 ChannelId, string Username, string Payload, long CreatedAt); public sealed record ChannelMember(string Username, string Role, long JoinedAt); public sealed record ChannelKeyPackage(Id16 ChannelId, string Username, string Role, string Payload, long CreatedAt); /// 已存储的一帧(完整封装)。Inline 与 BlobKey 二选一。 public sealed record StoredFrame( Id16 ChannelId, Id16 ItemId, uint Index, long Seq, int Length, byte[] Digest, byte[]? Inline, string? BlobKey); public sealed record LogEntry(long Seq, LogKind Kind, Id16 ItemId, uint FrameIndex, byte Aux, long CreatedAt); /// 一次请求验证通过后的身份。 public sealed record Principal(Role Role, byte[] EndpointHash, string? AccountName = null); /// 请求携带的凭据,尚未验证。 public sealed record Credentials(Role ClaimedRole, byte[]? Token, byte[] EndpointHash, string? AccountName = null, string? AccountDeviceId = null, bool RequireSignedContent = false);