backend: require confirmation for signed channel updates [CI]
ci/woodpecker/pr/verify Pipeline failed
ci/woodpecker/pr/web-build unknown status

This commit is contained in:
justme committed 2026-10-07 12:57:20 +08:00
1 parent 7160de2a36
commit 84f9d211bc
62 files changed
+1717 -70

No files matched your search

@@ -53,10 +53,12 @@ public sealed class MoShiroNodeEventSink : INodeEventSink
private readonly AgentService _service;
private readonly NodeInfoService _nodes;
private readonly ReleaseService _releases;
private readonly IProbeStore _probes;
public MoShiroNodeEventSink(IAgentStore agents, AgentRuntime runtime, IEventStore events, LiveHub live, AgentService service, NodeInfoService nodes, ReleaseService releases)
public MoShiroNodeEventSink(IAgentStore agents, AgentRuntime runtime, IEventStore events, LiveHub live, AgentService service, NodeInfoService nodes, ReleaseService releases, IProbeStore probes)
{
_releases = releases;
_probes = probes;
_nodes = nodes;
_agents = agents;
_runtime = runtime;
@@ -130,6 +132,10 @@ public sealed class MoShiroNodeEventSink : INodeEventSink
{
ProbeHelloMeta? meta = raw.Deserialize(MoShiroJsonContext.Default.ProbeHelloMeta);
await _nodes.SetPlatformAsync(id.Value, NodeKinds.Probe, meta?.Platform, ct);
if (meta?.Ipv6 is { } ipv6)
{
await _probes.SetIpv6DiagnosticsAsync(id.Value, JsonSerializer.Serialize(ipv6, MoShiroJsonContext.Default.Ipv6Diagnostic), ct);
}
}
catch (JsonException)
{
@@ -146,7 +152,12 @@ public sealed class MoShiroNodeEventSink : INodeEventSink
case NodeEventKind.Heartbeat when nodeEvent.Extra is { } extra:
try
{
_releases.RecordStatus(id, extra.Deserialize(MoShiroJsonContext.Default.ProbeHeartbeatExtra)?.Update);
ProbeHeartbeatExtra? heartbeat = extra.Deserialize(MoShiroJsonContext.Default.ProbeHeartbeatExtra);
_releases.RecordStatus(id, heartbeat?.Update);
if (heartbeat?.Ipv6 is { } ipv6)
{
await _probes.SetIpv6DiagnosticsAsync(id.Value, JsonSerializer.Serialize(ipv6, MoShiroJsonContext.Default.Ipv6Diagnostic), ct);
}
}
catch (JsonException)
{
@@ -196,7 +207,8 @@ public sealed class MoShiroNodeEventSink : INodeEventSink
AgentRecord? before = await _agents.GetAsync(id, ct);
string? limitsJson = meta.LocalLimits is null ? null : JsonSerializer.Serialize(meta.LocalLimits, LocalLimitsJson.Default.LocalLimits);
await _agents.ApplyHelloAsync(id, new AgentHello(kinds, hello.NodeVersion, limitsJson, spki is { Length: 32 } ? spki : null, meta.ProbeTcpPort, meta.ProbeUdpPorts, meta.Ipv6Supported), ct);
string? ipv6Json = meta.Ipv6 is null ? null : JsonSerializer.Serialize(meta.Ipv6, MoShiroJsonContext.Default.Ipv6Diagnostic);
await _agents.ApplyHelloAsync(id, new AgentHello(kinds, hello.NodeVersion, limitsJson, spki is { Length: 32 } ? spki : null, meta.ProbeTcpPort, meta.ProbeUdpPorts, meta.Ipv6Supported, ipv6Json), ct);
// 端口或证书指纹变了,Probe 需要新的列表
AgentRecord? after = await _agents.GetAsync(id, ct);
@@ -128,6 +128,8 @@ public sealed partial class ProbeService
}
await _probes.RevokeAsync(id, _time.GetUtcNow().ToUnixTimeMilliseconds(), ct);
// 吊销会阻止未来认证;也断开当前直连 Backend 的长会话,不等待 Probe 心跳超时。
await _gateway.DisconnectAsync(new NodeId(id), "probe revoked", ct);
_gateway.NotifyAllTaskSetsChanged();
return Result<ProbeView>.Ok((await GetAsync(id, ct))!);
}