You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Maka should have one peer reachability and connection-recovery foundation shared by Peer Mesh, direct Runtime Host profiles, and Session collaboration.
That foundation must converge automatically whenever enough reachability information still exists, and it must report an explicit repair state when automatic convergence is impossible. It must not hide a missing rendezvous path behind retries, long spinners, stale online indicators, or Session-specific workarounds.
This issue follows the completed Peer Mesh tracker #3842 and the WebRTC direct-path tracker #4382. Those projects supplied membership, signed Mesh routes, Circuit Relay v2 coordination, bounded member transit, QUIC/DCUtR, and WebRTC ICE. The remaining problem is that these capabilities do not yet form one durable recovery model.
The liveness boundary
A PeerId authenticates a peer; it does not locate that peer.
Two peers can rediscover each other after both have been offline and their addresses have changed only if at least one of the following remains true:
one cached locator is still usable;
a peer reacquires a coordination anchor whose address the other peer still knows; or
a reachable third member or rendezvous service knows a current locator.
If all three are false, retries, a longer TTL, random DHT walks, DCUtR, WebRTC, and more UI waiting cannot create a first packet path. The correct state is needs_repair, followed by a fresh invitation or another explicit bootstrap path. Repair updates reachability for the existing identity and membership; it must not create a duplicate Mesh or silently replace authority.
This is the central invariant of the proposal. Any stronger availability claim requires an explicit rendezvous service and its accompanying privacy, abuse, operations, and SLA commitments.
Problems this model resolves
A Mesh invitation usually works because it contains fresh bootstrap routes, while a later Session invitation can fail after routes or relay reservations change.
Two members that go offline past route expiry can become a zombie Mesh if both addresses change and neither can reacquire a known relay anchor.
Route refresh currently sits in front of some connection attempts, so discovery latency delays useful dialing instead of contributing candidates concurrently.
Reconnect backoff is not always woken by a new route revision, network resume, or an already-restored peer path; switching Sessions can therefore recover faster than waiting.
Generic reachability facts currently share a record with Mesh presentation and transit fields. This couples unrelated lifecycles and prevents one resolver from serving Host profiles, Mesh control, and collaboration.
Collaboration credential finalization intentionally requires a second authenticated Runtime Host stream, but the UI presents it as a second full network preparation and can let the Owner appear finished before the Guest is ready.
Route expiry is sometimes perceived as membership expiry even though authorization and reachability are different facts.
Non-negotiable boundaries
One peer endpoint and one PeerId per endpoint.native/runtime-host-peer remains the production connection authority. WebRTC does not introduce a JS sidecar, second Swarm, second reconnect loop, or second identity.
Connectivity grants no Runtime Host authority. Mesh membership, Runtime Host credential/Root ID validation, and Session grants remain separate authorities.
Membership is durable; reachability is leased. Losing every current route never removes membership or changes identity.
One application protocol. QUIC, TCP, WebRTC, and approved member transit all terminate in the existing authenticated Runtime Host protocol.
Public relays are coordination-only. Dynamically discovered or manually configured external Circuit Relay v2 nodes may carry Mesh control and direct-upgrade signaling, but never Runtime Host application traffic. Only an explicitly approved Mesh member may provide application transit.
No silent mutation replay. Reconnection restores subscriptions and projections. It does not resend an operation whose outcome is unknown.
A device is not an identity shortcut. Desktop Client and Runtime Host endpoints may live on the same computer but have different identities, lifecycles, and authority. UX may group them; the protocol must not merge them implicitly.
Target model
1. A reusable signed reachability lease
Introduce one peer-owned, self-signed PeerReachabilityLease independent of Mesh and Runtime Host application state:
The route classes are explicit. A coordination-relay route cannot accidentally become an application-capable route.
The lease contains no Mesh ID, display name, endpoint kind, transit policy, Runtime Host Root ID, credential, Session ID, or grant. A recipient verifies the signature, PeerId, revision, bounds, and expiry before treating it as current. Historical leases may be retained for a bounded recovery horizon as low-priority bootstrap hints, but they are never displayed as online or accepted as current truth.
This remains a Maka-typed signed record. A plain libp2p Signed Peer Record carries signed addresses, but does not express issuer expiry or the distinction between direct and coordination-only routes. We can adapt the Maka lease at a future rendezvous boundary without weakening the internal contract.
2. Mesh-specific member metadata stays Mesh-specific
The authority-signed Mesh roster remains the only membership authority. A separate peer-signed MeshMemberAdvertisement may carry the member alias, endpoint kind, and bounded capabilities for one Mesh.
Transit permission remains explicit Mesh policy. It must not be embedded in generic reachability or leak from one Mesh into another. A peer must be in the current roster before it can receive route or member-advertisement updates.
3. Persist coordination anchors, not reservations
For each persistent PeerId, remember a bounded set of previously successful relay addresses. On restart:
apply manual relay configuration first;
try to reacquire reservations on remembered successful anchors;
use public IPFS Amino discovery only to replenish failed or missing slots;
publish a relay route only after the main peer endpoint receives reservation acceptance.
The persisted fact is “this relay accepted us before,” not “the old reservation is still valid.” Reservation lifetime remains owned by the running endpoint.
Selection should be stable rather than RTT-churned: acquire a replacement before a planned release, apply bounded exponential backoff after refusal, and obey relay limits. The default active reservation count is a resource budget and redundancy policy, not a liveness proof. Increasing it may improve probability but also consumes third-party relay capacity; it should be changed from evidence, not intuition.
IPFS Amino remains an experimental, replaceable source of ordinary relay candidates. Maka does not publish peer presence to the public IPFS DHT and does not pretend that the DHT has a standard “find relays” or “find this Maka peer” query.
4. Symmetric, bounded anti-entropy
Mesh route exchange remains authenticated point-to-point anti-entropy, not Gossipsub:
every active member, including the authority, initiates reconciliation;
a replica prioritizes the authority and rotates through other current members;
the authority rotates through current members instead of waiting passively;
a material reachability revision, accepted/lost relay reservation, network resume, or successful repair triggers immediate bounded sync;
a low-frequency periodic pass handles missed events;
only current-roster peers exchange fresh state;
duplicate or older revisions are ignored;
expired signed routes may be tried only as rate-limited identity-verified bootstrap hints within the recovery horizon.
This is sufficient for small private Meshes and keeps message volume bounded. Gossipsub would still need discovery and would add overlay maintenance, scoring, and duplicate state without solving the zero-locator case.
5. One event-fed connection attempt authority
Host profiles, Mesh control, and Session invitations all use the same resolver and attempt lifecycle:
cached / invitation / historical hints ──┐
fresh Mesh anti-entropy updates ─────────┤
reacquired relay anchors ────────────────┼──> one fenced attempt
direct observation and upgrades ─────────┘ │
├── QUIC/TCP direct
├── QUIC + DCUtR
├── WebRTC + ICE
└── approved member transit
Known routes are dialed immediately. Discovery and anti-entropy run concurrently and feed newly verified candidates into the same target-bound attempt. There is no serial “discover for N seconds, then start connecting” gate.
The attempt has one immutable expected PeerId, one deadline, one cancellation source, one winner, and stale-result fencing. A route revision, network resume, explicit retry, or restored underlying peer connection wakes recovery immediately instead of waiting for an old backoff timer. Backoff still protects unavailable peers and resources when no new evidence exists.
The winner only provides transport. The existing Runtime Host handshake must still validate the expected PeerId, Root ID, compatibility, and credential before application use.
6. Session collaboration uses current reachability, not a frozen invitation
A Session invitation remains an application-authority payload plus bounded bootstrap hints. It identifies the target Runtime Host PeerId/Root ID and Guest credential flow, but it is not a permanent route snapshot.
On initial join and every later reconnect, the Guest asks the shared resolver for the target peer's current verified routes from direct profile state and any joined Mesh. Route changes do not require resharing the Session. Mesh removal does not revoke Session authority, and Session revocation does not remove Mesh membership.
The collaboration security flow remains two application-authentication phases:
a narrowly scoped pending credential claims and binds the invitation;
a fresh Runtime Host stream authenticates the active, client-bound Guest credential and catches up the shared projection.
This must not become two network acquisitions. The underlying authenticated peer connection is retained when healthy; only the Runtime Host stream is reopened. UX presents one continuous join with honest sub-states such as “Securing access to this device” and “Loading shared task.” The Owner may show “Guest admitted” after finalization, but “Guest ready” is not true until the second stream is authenticated and transcript catch-up reaches its watermark.
7. Explicit recovery state
Expose a small product state machine rather than protocol trivia:
connecting → reachable
│ │
├── new evidence wakes attempt
├── transient loss → reconnecting
└── no locator after bounded recovery → needs_repair
“Direct,” “WebRTC,” relay reservation counts, STUN, and failure reason codes belong in progressive diagnostics. Normal UX answers: is the peer available, is Maka trying, or does the user need a new invitation/bootstrap action?
Closing, leaving, cancelling, and discarding pairing must remain locally responsive. A remote acknowledgement may complete later, but a missing remote path must not trap local state behind an indefinite modal or lock.
Why not the tempting alternatives?
Deterministic PeerId → DHT region → common relay: DHT topology, relay admission, and time windows do not guarantee that two peers select the same usable relay. It is a heuristic, not a liveness foundation.
Publish Maka presence in the public IPFS DHT: this expands metadata leakage and abuse surface while still providing no project-controlled availability guarantee.
Gossipsub: it distributes data after peers meet; it does not provide the missing first locator.
Treat expired routes as dead membership: this destroys durable authority because of a temporary network fact.
Persist reservation state: a reservation belongs to a live connection and can be refused after restart. Only the anchor address and success history are reusable.
Wait for discovery before dialing: it increases latency and makes slow discovery indistinguishable from a hung connection.
Merge Desktop and Runtime Host identities: it couples different authority and lifecycle domains and makes remote Host ownership ambiguous.
A production js-libp2p sidecar: it duplicates identity, Swarm, lifecycle, resource limits, packaging, and recovery ownership. JavaScript remains an interoperability oracle only.
A mandatory central service now: it would offer stronger rendezvous guarantees, but it is a separate product and operations commitment. We should add it only when we choose that SLA explicitly.
Availability claim
This design guarantees bounded behavior and convergence under stated preconditions, not universal connectivity:
With a usable cached route, a reacquired remembered anchor, or a reachable current member, peers converge without a new invitation.
If direct punching fails, an explicitly approved member may carry application traffic.
If every shared locator is gone, Maka reaches needs_repair promptly and preserves identity, membership, and grants for repair.
Guaranteed recovery after arbitrary simultaneous downtime and total address churn requires a stable rendezvous service. Standard libp2p Rendezvous is currently a Working Draft and leaves deployment/abuse policy to operators, so adopting it is a later explicit decision rather than a hidden dependency.
Security and privacy properties
Every reachability lease is self-signed and target PeerId authentication still occurs on connection.
Mesh roster validation precedes state exchange; removed peers receive no new routes.
Historical hints are bounded, rate-limited, and cannot establish identity by themselves.
Routes are network metadata and are shared only through explicit invitations or authenticated Mesh control; diagnostics redact them by default.
Public relay discovery sees the discovery Swarm's temporary identity, while reservation and publication remain owned by the real peer endpoint.
External Circuit Relay v2 nodes never become application authorities and never receive Runtime Host plaintext/application streams.
Reconnect and path changes never weaken credential, Root ID, grant, or plaintext policy.
Delivery plan
This feature has not shipped, so prefer a clean internal model over dual-read/dual-write compatibility paths.
Reachability domain split — introduce the reusable lease, move Mesh presentation/transit fields to Mesh-specific state, and make every consumer use typed direct vs coordination routes.
Stable anchor recovery — persist bounded successful relay anchors per PeerId, reacquire them before public discovery, and publish native reachability revisions.
Convergent Mesh control — make anti-entropy symmetric and event-driven, add bounded historical bootstrap hints, and define needs_repair plus invitation-based repair of existing membership.
Unified recovery and collaboration — feed route revisions into one connection attempt/reconnect lifecycle, reuse the underlying peer connection across Guest finalization, and project authoritative readiness states to both Owner and Guest.
Each layer should be independently reviewable, but the acceptance matrix below is the release gate for the whole model.
High-value acceptance matrix
Keep tests small and decision-relevant:
Remembered-anchor convergence: two peers stop, direct addresses change, both restart, and at least one advertised relay anchor can be reacquired. They rediscover each other and refresh signed leases without a new invitation.
Third-member convergence: the authority has no usable route to a replica, but another current member has a fresher signed lease. Bounded anti-entropy restores contact without granting that member authority.
Honest zero-locator failure and repair: all cached routes and anchors are unusable and no third member exists. Recovery reaches needs_repair within a bound; a fresh invitation repairs the existing membership/identity rather than creating a duplicate.
Event-driven Session recovery: a Guest loses its path, a new signed route arrives, and recovery wakes immediately. Subscription catch-up reaches one canonical watermark, no accepted mutation is replayed, and Owner/Guest agree on admitted/ready/terminal state.
Single visible join: collaboration credential finalization opens a second Runtime Host stream over the existing peer connection. The UI does not repeat network preparation, and “ready” is emitted only after authenticated catch-up.
Resource and authority bounds: candidate, route, historical-hint, connection-attempt, and backoff limits hold under churn; removed members cannot pull routes; public relays carry no Runtime Host application bytes.
The controlled NAT harness from #4382 should exercise topology-dependent behavior outside ordinary CI. Deterministic unit/integration tests cover state, fencing, recovery wakeups, and authorization. Public-network success rates must not become flaky merge gates.
libp2p Rendezvous specification — useful future adapter, but currently a Working Draft and not a membership or operations policy
Definition of done
The issue is complete when Peer Mesh, direct Host profiles, and Session collaboration consume one reachability/recovery model; automatic reconnection converges whenever the liveness precondition holds; impossible recovery becomes a prompt, bounded needs_repair state; and the security, resource, no-replay, and cross-platform acceptance matrix passes without introducing a second network authority.
简体中文
核心结论
Maka 需要一套统一的 peer 可达性与连接恢复基座,让 Peer Mesh、Runtime Host 直连配置和 Session 协作都走同一套模型。
English
Thesis
Maka should have one peer reachability and connection-recovery foundation shared by Peer Mesh, direct Runtime Host profiles, and Session collaboration.
That foundation must converge automatically whenever enough reachability information still exists, and it must report an explicit repair state when automatic convergence is impossible. It must not hide a missing rendezvous path behind retries, long spinners, stale online indicators, or Session-specific workarounds.
This issue follows the completed Peer Mesh tracker #3842 and the WebRTC direct-path tracker #4382. Those projects supplied membership, signed Mesh routes, Circuit Relay v2 coordination, bounded member transit, QUIC/DCUtR, and WebRTC ICE. The remaining problem is that these capabilities do not yet form one durable recovery model.
The liveness boundary
A PeerId authenticates a peer; it does not locate that peer.
Two peers can rediscover each other after both have been offline and their addresses have changed only if at least one of the following remains true:
If all three are false, retries, a longer TTL, random DHT walks, DCUtR, WebRTC, and more UI waiting cannot create a first packet path. The correct state is
needs_repair, followed by a fresh invitation or another explicit bootstrap path. Repair updates reachability for the existing identity and membership; it must not create a duplicate Mesh or silently replace authority.This is the central invariant of the proposal. Any stronger availability claim requires an explicit rendezvous service and its accompanying privacy, abuse, operations, and SLA commitments.
Problems this model resolves
Non-negotiable boundaries
native/runtime-host-peerremains the production connection authority. WebRTC does not introduce a JS sidecar, second Swarm, second reconnect loop, or second identity.Target model
1. A reusable signed reachability lease
Introduce one peer-owned, self-signed
PeerReachabilityLeaseindependent of Mesh and Runtime Host application state:The route classes are explicit. A coordination-relay route cannot accidentally become an application-capable route.
The lease contains no Mesh ID, display name, endpoint kind, transit policy, Runtime Host Root ID, credential, Session ID, or grant. A recipient verifies the signature, PeerId, revision, bounds, and expiry before treating it as current. Historical leases may be retained for a bounded recovery horizon as low-priority bootstrap hints, but they are never displayed as online or accepted as current truth.
This remains a Maka-typed signed record. A plain libp2p Signed Peer Record carries signed addresses, but does not express issuer expiry or the distinction between direct and coordination-only routes. We can adapt the Maka lease at a future rendezvous boundary without weakening the internal contract.
2. Mesh-specific member metadata stays Mesh-specific
The authority-signed Mesh roster remains the only membership authority. A separate peer-signed
MeshMemberAdvertisementmay carry the member alias, endpoint kind, and bounded capabilities for one Mesh.Transit permission remains explicit Mesh policy. It must not be embedded in generic reachability or leak from one Mesh into another. A peer must be in the current roster before it can receive route or member-advertisement updates.
3. Persist coordination anchors, not reservations
For each persistent PeerId, remember a bounded set of previously successful relay addresses. On restart:
The persisted fact is “this relay accepted us before,” not “the old reservation is still valid.” Reservation lifetime remains owned by the running endpoint.
Selection should be stable rather than RTT-churned: acquire a replacement before a planned release, apply bounded exponential backoff after refusal, and obey relay limits. The default active reservation count is a resource budget and redundancy policy, not a liveness proof. Increasing it may improve probability but also consumes third-party relay capacity; it should be changed from evidence, not intuition.
IPFS Amino remains an experimental, replaceable source of ordinary relay candidates. Maka does not publish peer presence to the public IPFS DHT and does not pretend that the DHT has a standard “find relays” or “find this Maka peer” query.
4. Symmetric, bounded anti-entropy
Mesh route exchange remains authenticated point-to-point anti-entropy, not Gossipsub:
This is sufficient for small private Meshes and keeps message volume bounded. Gossipsub would still need discovery and would add overlay maintenance, scoring, and duplicate state without solving the zero-locator case.
5. One event-fed connection attempt authority
Host profiles, Mesh control, and Session invitations all use the same resolver and attempt lifecycle:
Known routes are dialed immediately. Discovery and anti-entropy run concurrently and feed newly verified candidates into the same target-bound attempt. There is no serial “discover for N seconds, then start connecting” gate.
The attempt has one immutable expected PeerId, one deadline, one cancellation source, one winner, and stale-result fencing. A route revision, network resume, explicit retry, or restored underlying peer connection wakes recovery immediately instead of waiting for an old backoff timer. Backoff still protects unavailable peers and resources when no new evidence exists.
The winner only provides transport. The existing Runtime Host handshake must still validate the expected PeerId, Root ID, compatibility, and credential before application use.
6. Session collaboration uses current reachability, not a frozen invitation
A Session invitation remains an application-authority payload plus bounded bootstrap hints. It identifies the target Runtime Host PeerId/Root ID and Guest credential flow, but it is not a permanent route snapshot.
On initial join and every later reconnect, the Guest asks the shared resolver for the target peer's current verified routes from direct profile state and any joined Mesh. Route changes do not require resharing the Session. Mesh removal does not revoke Session authority, and Session revocation does not remove Mesh membership.
The collaboration security flow remains two application-authentication phases:
This must not become two network acquisitions. The underlying authenticated peer connection is retained when healthy; only the Runtime Host stream is reopened. UX presents one continuous join with honest sub-states such as “Securing access to this device” and “Loading shared task.” The Owner may show “Guest admitted” after finalization, but “Guest ready” is not true until the second stream is authenticated and transcript catch-up reaches its watermark.
7. Explicit recovery state
Expose a small product state machine rather than protocol trivia:
“Direct,” “WebRTC,” relay reservation counts, STUN, and failure reason codes belong in progressive diagnostics. Normal UX answers: is the peer available, is Maka trying, or does the user need a new invitation/bootstrap action?
Closing, leaving, cancelling, and discarding pairing must remain locally responsive. A remote acknowledgement may complete later, but a missing remote path must not trap local state behind an indefinite modal or lock.
Why not the tempting alternatives?
Availability claim
This design guarantees bounded behavior and convergence under stated preconditions, not universal connectivity:
needs_repairpromptly and preserves identity, membership, and grants for repair.Security and privacy properties
Delivery plan
This feature has not shipped, so prefer a clean internal model over dual-read/dual-write compatibility paths.
needs_repairplus invitation-based repair of existing membership.Each layer should be independently reviewable, but the acceptance matrix below is the release gate for the whole model.
High-value acceptance matrix
Keep tests small and decision-relevant:
needs_repairwithin a bound; a fresh invitation repairs the existing membership/identity rather than creating a duplicate.The controlled NAT harness from #4382 should exercise topology-dependent behavior outside ordinary CI. Deterministic unit/integration tests cover state, fencing, recovery wakeups, and authorization. Public-network success rates must not become flaky merge gates.
Related evidence and specifications
Definition of done
The issue is complete when Peer Mesh, direct Host profiles, and Session collaboration consume one reachability/recovery model; automatic reconnection converges whenever the liveness precondition holds; impossible recovery becomes a prompt, bounded
needs_repairstate; and the security, resource, no-replay, and cross-platform acceptance matrix passes without introducing a second network authority.简体中文
核心结论
Maka 需要一套统一的 peer 可达性与连接恢复基座,让 Peer Mesh、Runtime Host 直连配置和 Session 协作都走同一套模型。
只要网络里还留着足够的信息,系统就应该自己重新收敛;如果客观上已经没有任何见面的路径,就要尽快告诉用户“需要修复”,而不是一直重试、转圈、显示过期的在线状态,或者在 Session 功能里再补一套临时逻辑。
这个 issue 承接已经完成的 Peer Mesh #3842 和 WebRTC 直连 #4382。前面的工作已经有了成员关系、签名路由、Circuit Relay v2 协调、受控的成员转发、QUIC/DCUtR 和 WebRTC ICE。现在缺的不是再加一种传输协议,而是把这些能力收进一套可靠的恢复模型。
先把能力边界说清楚
PeerId 能证明“对面是谁”,但不能告诉我们“对面在哪儿”。
两个节点都离线过、地址也变了以后,想自动重新找到彼此,至少要满足下面一条:
如果三条都不成立,那么加大重试次数、延长 TTL、随机扫 DHT、跑 DCUtR 或 WebRTC 都不会凭空变出第一条链路。此时正确行为是进入
needs_repair,让用户用新邀请或其他明确入口补回 bootstrap 信息。修复的是原来的身份和成员关系,不能偷偷新建一个重复 Mesh,也不能换掉原来的 authority。这是整套设计最重要的不变量。如果我们以后承诺“无论双方离线多久、地址怎么变都能自动回来”,那就必须明确引入一个稳定 rendezvous 服务,并正面承担隐私、滥用防护、运维和 SLA,而不能把这份承诺藏在客户端算法里。
这套模型要解决什么
不能破坏的边界
native/runtime-host-peer继续拥有生产连接。WebRTC 不能带来 JS sidecar、第二个 Swarm、第二套重连循环或第二个身份。目标模型
1. 一份真正通用的签名可达租约
增加 peer 自己签名的
PeerReachabilityLease,只描述“如何找到这个 PeerId”,不掺 Mesh 和 Runtime Host 业务状态:两类 route 必须在类型上分开,不能让协调 relay 地址误入应用流量路径。
这份租约不带 Mesh ID、别名、节点类型、transit 策略、Runtime Host Root ID、credential、Session ID 或 grant。接收方验证签名、PeerId、revision、数量边界和有效期以后,才能把它当成当前事实。过期租约可以在一个有限恢复窗口内作为低优先级 bootstrap 线索,但绝不能因此显示“在线”,也不能把旧信息冒充新状态。
内部继续使用 Maka 自己定义的签名 record。libp2p 的 Signed Peer Record 能签地址,但没有 issuer expiry,也表达不了“直连地址”和“仅协调地址”的区别。以后接入 rendezvous 时可以做适配,没有必要为了表面标准化削弱内部契约。
2. Mesh 的信息留在 Mesh 里
authority 签名的 roster 继续是唯一成员 authority。每个 peer 可以另外签一份
MeshMemberAdvertisement,只放这个 Mesh 里的别名、endpoint 类型和少量能力信息。transit 是否允许属于 Mesh policy,不能塞进通用 reachability,更不能从一个 Mesh 泄漏到另一个 Mesh。只有当前 roster 里的成员,才有资格收发新的路由和成员信息。
3. 记住协调锚点,不假装 reservation 永久有效
每个持久 PeerId 记住少量曾经成功过的 relay 地址。进程重启后按下面顺序恢复:
持久化的是“这台 relay 以前接受过我”,不是“上次 reservation 现在还活着”。reservation 始终属于当前运行中的 endpoint。
选 relay 应该以稳定为主,不要为了几十毫秒 RTT 反复换节点。计划替换时先拿到新的再放旧的;遭到拒绝后做有界指数退避;尊重对方资源限制。默认保留几条 active reservation 是资源预算和冗余策略,不是可用性证明。数量更多可能提高概率,也会消耗第三方容量,应该拿数据决定,而不是凭感觉堆数量。
IPFS Amino 只是一种可替换的实验性 relay 候选来源。Maka 不把自己的在线位置发布到公共 IPFS DHT,也不虚构 DHT 存在“查找所有 relay”或“查找某个 Maka peer”的标准接口。
4. 双向、有界的 anti-entropy
Mesh 继续使用认证后的点对点同步,不上 Gossipsub:
小型私有 Mesh 用这套办法已经够了,而且消息量有明确上界。Gossipsub 仍然要先解决 peer discovery,还会带来 overlay、scoring 和消息去重状态,并不能解决“双方一个地址都没有”的根问题。
5. 一个可以持续吃进新证据的 connection attempt
Host profile、Mesh control 和 Session invitation 全部使用同一个 resolver 和 attempt lifecycle:
手里已有的地址立即拨号,discovery 和 anti-entropy 同时跑,后续拿到的新候选直接喂给同一个 target-bound attempt。不能再有“先 discovery 十秒,再开始连接”的串行门。
一次 attempt 只有一个 immutable expected PeerId、一个 deadline、一个取消源、一个 winner,并且拒绝旧 attempt 的迟到结果。route revision、网络唤醒、用户重试或底层 peer connection 恢复时,recovery 要立即醒来,不能继续睡在旧 backoff 里。没有任何新证据时,backoff 仍负责保护不可达 peer 和本机资源。
winning path 只解决 transport。真正交给应用前,现有 Runtime Host handshake 仍要验证 expected PeerId、Root ID、compatibility 和 credential。
6. Session 协作永远解析当前路由
Session invitation 仍然包含应用 authority payload 和少量 bootstrap hints,但不能成为永久路由快照。它标出目标 Runtime Host 的 PeerId/Root ID,并携带 Guest credential 流程所需信息;以后每次重连都要按目标 PeerId 向统一 resolver 查询当前可用路由,包括 direct profile 和已经加入的 Mesh。
这样,路由变了不需要重新分享 Session。退出 Mesh 不会自动撤销 Session 权限,撤销 Session 也不会把节点踢出 Mesh。
协作认证保留两段式:
这是两次应用认证,不应该变成两次找网络。底层 peer connection 健康时要直接复用,只重开 Runtime Host stream。UI 把它表现成一个连续过程,例如“正在保护此设备的访问权限”然后“正在载入共享任务”,不能再完整跑两遍“准备可用路径”。Owner 在 finalization 后可以看到“Guest 已准入”,但第二条 stream 完成认证、transcript 追到 watermark 以前,不能显示“Guest 已就绪”。
7. 明确的恢复状态
普通用户只需要理解一个小状态机:
Direct、WebRTC、reservation 数量、STUN 和具体错误码放进渐进式诊断。主界面只回答三个问题:现在能不能用、Maka 是否正在恢复、是否需要用户提供一份新邀请或 bootstrap。
关闭、退出、取消和放弃配对必须优先完成本地动作。远端确认可以稍后补齐,不能因为对面联系不上,就把用户困在无法关闭的弹窗或本地锁里。
为什么不选那些看起来更省事的方案
我们实际承诺什么
这套设计承诺的是“在条件成立时自动收敛、条件不成立时有界失败”,不是万能网络:
needs_repair,同时保留身份、membership 和 grant,等待修复。安全与隐私
落地顺序
这组功能尚未正式发布,因此优先得到干净模型,不为内部半成品增加双读、双写和长期兼容层。
needs_repair,支持新邀请修复原 membership。每层都可以单独 review,但下面的验收矩阵必须整体通过,才能认为模型完成。
少量、高价值验收
needs_repair;粘贴新邀请后修复原 membership/identity,不产生重复项。#4382 的受控 NAT harness 用于验证依赖 topology 的行为,不塞进普通 CI。普通单元/集成测试只锁定状态机、fence、recovery wakeup 和授权。公网成功率不能变成不稳定的合并门槛。
相关证据与规范
完成标准
当 Peer Mesh、Host 直连配置和 Session 协作都消费同一套 reachability/recovery 模型;满足可达前提时能自动收敛;客观无法恢复时能快速、准确地进入可修复状态;并且安全、资源上界、禁止重放和跨平台验收全部通过,同时没有引入第二个网络 authority,这个 issue 才算完成。