歷史記錄 · 2026-08-02¶
重大重構里程碑¶
2026-08-02 ─ RoomId 房間實例識別(issue 000142)¶
決策檔:D-20260802-01
將既有六碼 roomCode 全面替換為 branded RoomId:canonical wire 形式為小寫 UUID v4,由 Web Crypto 產生、存活衝突時重生,每次建房均為新實例且不提供舊欄位相容層。識別已貫穿 matchmaking、Gossip discovery/presence、signaling room:<roomId> scope、room runtime、觀戰、聊天、摘要、providers 與 /room/:roomId;所有不可信邊界共用 parser fail-closed。matchId 推導維持 roster+startedAt+matchRules,不納入 RoomId。未來若需人類可讀邀請碼,須另建可輪換 alias,不能再充當 canonical identity。
2026-08-02 ─ GO 前全員 race-ready 屏障(issue 000133)¶
決策檔:D-20260802-02
正式 match 每回合新增綁定 match/round/roster 的有限單調 readiness:world-built → network-ready → presentation-ready。最後一階段只在場地、全車資產與實際 render 完成後回報;同賽道跨回合也重開世代。全 roster 未完成前不建立倒數或 frame pump;GO 前 peer 離開或 30 秒無嚴格進度則無懲罰取消,房主移除 missing 非 host、作廢舊 matchId,所有在線成員回原 RoomId 等待房重新 ready。
2026-08-02 ─ 三平面連線與分割安全定稿(issue 000139)¶
決策檔:D-20260802-03
room-control、race-mesh、spectator-stream 統一採 (peerId, plane, generation, status) 但資格完全隔離;舊 generation callback 不得污染新通道。race 逾 15 秒仍離線時,只有原 active roster 嚴格多數側可續賽;少數/平手側 partition-void。含 network removal 的 MatchResult signatures 改以原 roster 計門檻並兼作 removal certificate,故 4 人 2–2、2 人 1–1 都不能定稿;新增 conformance quorum 向量鎖定 3→2、4→3、2→2。
2026-08-02 ─ participantPassword 建房後不可變(issue 000141)¶
決策檔:D-20260802-04
participantPassword 限 Race Config 建房前設定;RoomPage 建房後只顯示有/無,若要更換必須關房並以新 RoomId 重建。密碼先在輸入端導成 verifier,HostRoom、RoomService 與 host succession 只保存 verifier/固定 policy epoch,public room-state 僅含 required/epoch;既有 seeded participant 繼任時仍免密重掛。spectatorPassword 保持獨立 waiting policy,留由 issue 000131 收斂。
2026-08-02 ─ spectator policy 建房與 waiting mutation(issue 000131)¶
決策檔:D-20260802-05
Race Config 新增 allowSpectators、0–50 容量與獨立 spectatorPassword 初值;RoomPage 對所有角色顯示政策,只有 host+waiting 可修改,match-start 後凍結。public Room 只含 allow/max/passwordRequired/policyEpoch,secret 留在 host RoomService。關閉觀戰或密碼新增/變更/移除會移除全部 spectator;縮容按 admission sequence 從最新者移除。密碼 mutation 以省略=保留、null=移除避免容量調整誤清 secret;受密碼保護房若 host succession 無法取得 secret,會關閉觀戰並提升 epoch,維持 fail-closed。
2026-08-02 ─ active + reserved 原子容量(issue 000132)¶
決策檔:D-20260802-06
新增共用 CapacityReservations<Key>,把非同步 admission 的容量條件固定為 active+reserved。SpectatorServer 在 openChannel 前取得 reservation,成功 commit、失敗或 dispose release、當前通道 close deactivate;相同 PeerId 滿房重連只替換、不多佔名額。maxPendingOpens 保留為獨立 DoS 背壓,後續 participant Quick Match 必須重用同一 primitive。
2026-08-02 ─ RoomSession 角色化 admission(issue 000130)¶
決策檔:D-20260802-07
participant/spectator 改由具名角色先進 room-control admission;spectator waiting 合法且不進 race roster。移除 discovery/WatchPage 密碼索源捷徑,stream 只接受已驗 spectator Peer,拒因端到端結構化;新增 room/role-admission conformance vectors。
2026-08-02 ─ Quick Match 加入既有公開房(issue 000138)¶
決策檔:D-20260802-08
Quick Match 改為從 rooms discovery 選擇既有 public、quick-match-enabled、無參賽密碼的 waiting 房,沿用原 host、RoomId、賽制與 access policy;房間公告明確投影最新容量、狀態、版本、模式/規則及 participant displayRating 中位數。選中後走一般 participant admission 並以 active+reserved 原子重驗最後席次;失敗持續搜尋至 timeout,絕不自動建房。移除 match-request/match-offer 與 MatchmakerPoller 接線,新增 room/quick-match-selection conformance vectors。
2026-08-02 ─ Race 與 Result 路由識別分層(issue 000140)¶
決策檔:D-20260802-09
共用頁路由收斂為 /race/:sessionId 與 /result/:resultId:正式 Race 以 RoomId 定位 RoomSession、正式 Result 以 64 位 matchId 查 ledger;本機則分別使用 local-session-<uuid> 與 local-result-<uuid>。四種格式 fail-closed 且互不冒充;移除 local-test sentinel、巢狀 result route 與舊 alias。本機摘要保存於 session-scoped 儲存以支援刷新,缺資料直接回 Race Config,絕不以 local id 查 ledger。
2026-08-02 ─ 持續 RoomSession 與共用 Race 生命週期(issue 000134)¶
決策檔:D-20260802-10
participant/spectator 共用 RoomPage 與 RacePage,角色由已驗 RoomSession 決定,不寫入 URL。RacePage 以 participant race session 或 SpectatorRaceAdapter 接上同一 viewport、HUD、聊天、離場與終局;移除 /watch route、safe-link 與 SEO metadata。sessionStorage 只保存最小 admission/active-match hint,刷新後必須向房主重做 admission,並以 live room 重算出同一 matchId 才能恢復;正常延遲訂閱不會被誤當成 recovery。
2026-08-02 ─ 觀戰可驗結果與共用 Result 生命週期(issue 000137)¶
決策檔:D-20260802-11
正常完賽改由鏈上確認後的 result-ready { matchId, roomId } 驅動;兩個 id 都須通過 wire 格式與目前 RoomSession 比對,transport 不攜帶或授權 MatchSummary。spectator ResultPage 只讀 verified MatchRecord,等待時不顯示 provisional result,查無/驗證失敗回原房;participant 保留再戰、spectator 只手動回房。新 RoundResult 將 endReason 納入多簽,歷史 TrueSkill delta 由 settlement base 重播既有決定性轉換。
2026-08-02 ─ 觀戰公開報廢 presentation 快照(issue 000135)¶
決策檔:D-20260802-12
10Hz SpectatorVehicleState 新增必填 brokenPartIds 與 eliminated;廣播端只從 StepOutput 投影公開顯示鍵與致命破壞結果,不傳耐久、溫度、電量或技能。wire 對每車 64 鍵、每鍵 128 字元、去重遞增排序與 boolean 型別 fail-closed;位姿連續插值,報廢欄在 next snapshot 邊界切換。已淘汰車因此可留在固定車序並顯示報廢,但這份 snapshot 仍只是 presentation,不是物理、賽果或結算權威。
2026-08-02 ─ 共用三模式相機與場內巡禮(issue 000129)¶
共用 RacePage 新增 CameraController 與 TourDirector,產品只顯示跟車、自由、巡禮。participant 在 readiness barrier 預設局部巡禮,每回合 countdown 開始一次切跟自己;外部 spectator 初始自由。淘汰或完賽不自動切鏡,且車仍留在首幀固定的跟車序列,只跳過離線缺席者。巡禮以局部車群展開度取景、以場地 ray collision 避讓,不以全場 bounds fit;與 D-20260802-10 的 participant/spectator 共用生命週期對齊,不在 RoomPage 建第二個巡禮場景。
2026-08-02 ─ Arena PBR 環境可讀性(issue 000125)¶
Race arena 新增離線程序 RoomEnvironment → PMREM image-based lighting,補足大型 canonical/UGC 高金屬度 PBR 場地缺少環境反射而近黑的問題。環境只在 race 場景持有,換場景/銷毀會釋放 render target,建立失敗則沿用原有主題燈光;不下載 HDRI、不修改創作者材質,主題 profile 的方向光、環境色、rim、背景與霧仍維持原責任。
2026-08-02 ─ 真實 GLB checkpoint E2E 契約收斂(issue 000147)¶
opt-in 真實 GLB E2E 改為斷言 D-20260802-09 的 local-session-<uuid>/local-result-<uuid> 路由,並在接受 checkpoint 前比較 storageState IndexedDB origin 與本次 baseURL,避免跨 E2E port 誤判可恢復。大型 urban GLB 在受限 headless Chromium 實測可低至約 0.1 倍速,故自然 60 秒賽程採 900 秒上限且驗證時關閉 retry,避免舊 360 秒門檻反覆產生假失敗。
2026-08-02 ─ 起跑跟車 self 事件順序修復(issue 000148)¶
CameraController 保存 countdown 已開始但 selfPeerId 尚未到達的 pending follow-self 意圖;首個 participant HUD 設定 self 後只完成一次跟車並清除 pending。修正 HUD/countdown callback 無固定順序時仍停在巡禮的競態,後續 HUD、淘汰或完賽不會再次自動切鏡。
2026-08-02 ─ Spectator participant-source 自動接替(issue 000136)¶
決策檔:D-20260802-03
觀戰來源從 host 單點改為固定 participant roster 選舉:初次取第一位在線者,stream 失效後從上一來源之後循環,spectator 永不候選。每位 participant 都維持 deterministic presentation broadcaster/server;room-state.spectators 同步已通過 room-control admission 的 PeerId,讓替代來源守住資格邊界。每次成功索源遞增 sourceEpoch,通道一進 reconnecting 即拒絕舊 generation 訊息;賽中 host control link 消失仍保留 active match、presence 與來源服務,不改 race roster。只有無在線 participant 或重撥失敗才以 host-disconnect 終止觀戰。
2026-08-02 ─ 瀏覽器 Helia UGC 貢獻保留(issue 000152)¶
決策檔:D-20260802-13
舊 { enabled, quotaGb } 與不可到達的 local Kubo provider 改為裝置級
ugcContribution.level = off | standard | generous;三階在 desktop/non-iOS 使用
0.70→0.60、0.80→0.70、0.85→0.75,在 iOS/iPadOS 使用 0.50→0.40、0.60→0.50、
0.70→0.60。standard/generous 必須有 persistent storage,否則保存 off;公開設定頁保存
不啟動 P2P。狀態明示 inactive、runtime-not-started、storage-not-persistent、active,而非 provider
health。警告依目前 level:超 trigger 的離線清理延後、在線 GC 後仍高於 target 或失敗才警告;啟動
critical 維持嚴格 >0.9。本機只延長既有 LRU UGC 保留,active app 的已持有 CID 可能讓目前連線 peer
走既有 Bitswap 取得,非 Kubo、全域 seed 或 CSP 擴張;不新增共識 rule ID。
2026-08-02 ─ 本機 Helia Storage Authority(issue 000152)¶
決策檔:D-20260802-14
修正 D-20260802-13 的 storage lifetime:AppShell 在未登入/離線也可由正常 lifecycle single-flight
建立唯一 networkless Helia authority,持有 Ledger content storage、pin datastore、local CID reader
與 LRU;公開設定保存仍是純 action,不建立或重試任何 service。authenticated online generation
只新增 libp2p/Bitswap/Orbit/transport,並以 non-owning adapter 借用同一 storage identity;所有
block、pin、batch mutation 與 GC 共用 origin-exclusive Web Lock,只有 authority 可 GC。離線啟動
嚴格 >0.9 可 forced cleanup,離線降級仍 deferred;final disposal 先 drain race lease,再關 online
generation、LRU、authority,獨立錯誤繼續清理後彙整。沒有 Kubo、port、CSP、共識、global seed 或
background service 變更,issue 000153 仍獨立。