using System.Text.Json;
using Fleet.Core;
using Fleet.Rpc;
namespace Fleet.Server;
public sealed record EnrollmentContext(string? RemoteIp, JsonElement? ProductMeta);
///
/// 节点的真实来源地址:前面有反向代理时,套接字上只有代理的地址,产品在这里决定信不信转发头。
/// 没有注册就用套接字地址。
///
public interface IClientAddressSource
{
/// 套接字上看到的对端地址。
/// 按名字取请求头的所有值。
string? Resolve(System.Net.IPAddress? socket, Func> header);
}
///
/// 服务器的身份密钥:操作员用 passkey 把它的公钥签进操作员集合。有它的时候,认证挑战会带上服务器的签名,节点据此确认对面是真的服务器,
/// 并在这条链路上用应用层加密。没有注册就是旧的行为(没有服务器身份)。
///
public interface IServerIdentity
{
byte[] PublicKeySpki { get; }
/// 对一段内容签名(Fleet.Identity.ServerHello.Payload 给出的)。
byte[] Sign(ReadOnlySpan payload);
}
/// 操作员集合的链(passkey 签的,创世在前)。没有初始化信任根时是空的。节点注册时用它确认「这个面板确实是我的操作员的」。
public interface IOperatorTrustSource
{
ValueTask> ChainAsync(CancellationToken ct);
}
/// 产品挂钩:节点注册成功之后调用。
public interface IEnrollmentHook
{
ValueTask OnEnrolledAsync(NodeRecord node, EnrollmentContext context, CancellationToken ct);
}
public enum NodeEventKind
{
Online,
Offline,
Hello,
Heartbeat,
}
/// 这条连接的来源地址(经过 );没有就是 null。
public sealed record NodeEvent(NodeEventKind Kind, NodeRecord Node, long AtMs, HelloParams? Hello = null, JsonElement? Extra = null, string? Reason = null, string? RemoteIp = null);
public interface INodeEventSink
{
ValueTask OnEventAsync(NodeEvent nodeEvent, CancellationToken ct);
}
/// 期望状态提供者:为每个节点计算期望状态的完整快照(天然幂等)。
public interface IStateProvider
{
/// 状态文档类型,例如 task_set。
string Type { get; }
ValueTask GetAsync(NodeRecord node, CancellationToken ct);
/// 节点应用之后回调,rejected[] 带结构化原因。
ValueTask OnAppliedAsync(NodeRecord node, long version, StateSyncResult result, CancellationToken ct);
}
public sealed record StateDocument(long Version, JsonElement Doc);
public enum InboxOutcome
{
Stored,
Duplicate,
Rejected,
}
/// 收件箱:持久化之后才返回 Stored,框架随后才回复 ACK。
public interface IInbox
{
byte Channel { get; }
ValueTask HandleAsync(NodeRecord node, Guid msgId, ReadOnlyMemory payload, CancellationToken ct);
}
/// 通知 Fleet:某个节点的期望状态变了,需要重新计算并推送。
public interface IStateNotifier
{
void NotifyChanged(NodeId node);
void NotifyAllChanged();
}