feat!: genesis-pinned operator set, server identity with an encrypted control link, key-less join codes; release key continuity
ci/woodpecker/tag/gitea-release Pipeline is pending
ci/woodpecker/tag/linux-release Pipeline failed
ci/woodpecker/tag/windows-release Pipeline was canceled

Join codes need no passkey touch and carry only public values (genesis
fingerprint, owner credentials, installer hashes). Nodes pin the genesis and
owners at enrollment and only follow passkey-signed operator set versions.
The panel's server key is listed in the set; pinned nodes require its
signature and run the control link under AES-256-GCM. Password sessions carry
no capabilities. The updater adopts a next_key from a signed manifest.

Bump version to 0.2.0. [CI SKIP]
This commit is contained in:
justme committed 2026-10-08 03:21:44 +08:00
1 parent 9bb6841dce
commit a2f88a344b
89 files changed
+2145 -1195

No files matched your search

@@ -1,6 +1,5 @@
using System.Text.Json;
using Fleet.Hosting;
using Fleet.Identity;
using Fleet.Core;
using Fleet.Rpc;
using MoShiro.Measurement;
@@ -102,22 +101,14 @@ public sealed class TaskManager
_ = ct;
var result = new StateSyncResult { AppliedVersion = version };
// 固定了操作员创世的节点:先验面板带来的操作员集合链(从固定的创世出发),再要求每个 Probe 带着操作员批准的证明。
// 面板自己改名册、塞进自己的 Probe 公钥是过不了这一关的:它签不出操作员的委托。
// 固定了操作员创世的节点:面板带来的新版本操作员集合,从固定的创世验过才采用(名册本身由面板决定)
_trust.Update(set.TrustChain);
var peers = new Dictionary<string, byte[]>(StringComparer.Ordinal);
foreach (PeerSpec peer in set.Peers)
{
try
{
byte[] key = Convert.FromBase64String(peer.PublicKey);
if (_trust.VerifyPeer(peer.Proof, key, "probe") != TrustFailure.None)
{
result.Rejected.Add(new RejectedItem { Id = peer.ProbeId.Value, Reason = RejectReasons.PolicyDenied });
continue;
}
peers[peer.ProbeId.Value] = key;
peers[peer.ProbeId.Value] = Convert.FromBase64String(peer.PublicKey);
}
catch (FormatException)
{