跳轉到

部署資訊

本檔角色:Pinning / Signaling 自架、PWA 離線、SEO、域名遷移。第一次部署要填的實際值與單機拓撲見 部署實際值與初始拓撲.md。 對應模組(實作):程式架構/pinning-service.md / 程式架構/signaling-service.md / 程式架構/pwa-offline.md / 程式架構/seo.md

1. 部署架構總覽

open4wd.org(主站 canonical origin;GitHub Pages 純靜態 hosting)
  ↓
玩家瀏覽器(PWA + Service Worker)
  ↓
連向:
  - Signaling provider(玩家手動/接受的 session route/community registry)
  - Pinning provider(玩家選取的有限集合;write 逐 provider 授權)
  - ICE / TURN provider(玩家手動/配對 signaling/接受的 session route,§4.3)
  - libp2p DHT(直接 P2P)
  - 其他玩家(mesh WebRTC)

核心特性:唯一公共 Ledger address 與 genesis governance signer set 是網路信任根; signaling/pinning/bootstrap/relay/ICE·TURN 都是可替換 runtime provider,不是專案營運權威。 任何 provider 全失都不得阻止 client 啟動、讀取本地資料或驗證 Ledger。

1.1 權威與用語

  • project-maintained:主 client、specs、releases、conformance vectors 與主 repo 收錄資產。
  • community-listed:上次檢核時技術上可發現,不代表 endorsement、信任或持續可用。
  • operator:對一個 deployment 負責的人或組織。
  • provider:提供一項 runtime capability 的 endpoint。
  • self-hosted:由玩家或社群自行營運的 deployment。

公版 Template repo 共通模型open-4wd-pinningopen-4wd-signalingopen-4wd-turn 只提供 reusable implementation/設定/manifests/驗證;repo 本體不部署且 不存營運 secrets。Operator 自行決定是否建立 deployment、名稱、可見性、endpoint 與可用性 政策;主專案不建立官方 deployment、不發布預設 endpoint,也不因使用公版內容而背書。

主 repo registry、*.open4wd.org 子域名與 project-maintained release 都不授予 provider officialtrustedrecommendedprimaryfallbackverified 地位。

2. 主站部署(open4wd.org)

項目 細節
主站 URL https://open4wd.org/已購入;第一個公開 production origin)
防禦性別名 https://open4wd.com/ 只做 path-preserving 301 到 .org,不承載獨立 app、SW 或 origin-bound 資料
Pages preview https://xjustloveux.github.io/open-4wd/ 僅作顯式 preview/回復 hosting target,不作 private 期或正式期 canonical origin
Hosting GitHub Pages(純靜態;custom domain)
Build GitHub Actions → Pages artifact → actions/deploy-pages(不要求 gh-pages 分支)
升級流程 PR 合併進 master → CI → deploy(禁直推,見 流程/升版.md §8.2

GitHub Pages 無法設自訂 HTTP header → CSP 在 prerender 後依每份 HTML 的 inline bytes 逐頁生成並注入 <meta>資安規範.md §4);主站無 frame-ancestors / X-Frame-Options(風險接受——無 cookie / 無跨源授權狀態);HTTPS 由 github.io HSTS preload / custom domain enforce-HTTPS 保證。

詳見本檔 §9 CI/CD。

2.1 主 repo 可見性生命週期(private 開發期 → public 上線)

策略:主 repo private 起手、本機測試完備後轉 public;這裡的 private 期間不發布 GitHub Pages,專指主 open-4wd client。open-4wd-specs 與可索引的 docs.open4wd.org專案生命週期 刻意較早同批公開,不代表遊戲 runtime 已上線。主 repo 成功轉 public 時,runtime_phase 立即由 pre_launch 進入 live,再啟用主站 Pages;open4wd.org 仍是遊戲 runtime 的第一個公開 production origin,不先以 github.io 建立公開 origin。

Private 期間的四個現實

項目 影響與對策
無 GitHub Pages 開發期以本地 serve/build 測試;root target (/) 與 Pages preview target (/open-4wd/) 都在本機驗證,hosting 面(DNS/TLS//version.json/SW)於首次 public deploy 做 bounded smoke
Community registry 無法下載 依序使用最後成功快取與 build snapshot;兩者皆不可用時保持本地模式,允許玩家手動輸入或接受 session route
Actions 免費 2000 分鐘/月 完整 CI(Playwright 跨瀏覽器矩陣)吃額度——開發期先跑 lint+unit、矩陣省用或本地跑;public 後無限、CI 全量
branch protection 免費方案僅 public 可用 「master 禁直推」(流程/升版.md §8.2)private 期無法平台強制、自律走 PR;切 public 當天必開

同一份本機或已上線 build 可用 URL query 明示 runtime 測試策略:?runtime=local 完全不啟動網路 assembly,只建立 storage-only local-ready?runtime=network 要求網路 assembly 成功,失敗即讓登入嘗試 fail-closed;省略或 ?runtime=auto 是正式預設,連線失敗時安全降級本機模式。未知、重複或內部 policy 名稱一律回到 auto,query 不寫入玩家設定或持久資料。

鐵則:從第一個 commit 起當作已 public——翻 public 時全部歷史可見:零 secrets 入庫(主 repo 設計本為零 secrets——LEDGER_DB_ADDRESS/genesis signers/bootstrap 清單皆公開常數)、commit 訊息乾淨、(可選)commit email 用 GitHub noreply。

切 public checklist:① 掃歷史確認無敏感資訊 → ②Settings 改 public(成功即觸發 live)→ ③ 開 branch protection → ④ GitHub Pages 直接設定 open4wd.org custom domain、Enforce HTTPS → ⑤以 root build 發布 → ⑥CI 全量與首次公開 smoke。因先前沒有 public runtime origin,本次走 §8.1,不跑既有 origin 遷移程序。跨 repo 前置順序、雙 SHA 與公開後 remote provenance gate 以 專案生命週期 為準。

週邊 repo 一律採 §1.1 的公版 Template 共通模型;主專案不預告或要求 維護者建立 private -deploy repo。

3. Pinning Service 自架

Repo 層規格(目錄結構 / 部署變數 /CI/ 自架指南 /runbook)見 部署資訊/open-4wd-pinning.md。 定位:主專案不營運、不指定也不預設任何 pinning 節點。玩家自行設定/發現節點;各節點只對自己的儲存、供應與選配法遵流程負責。

詳見 程式架構/pinning-service.md;repo 層規格見 部署資訊/open-4wd-pinning.md,共通部署模型依 §1.1

3.1 用途

  • IPFS 多副本加速層(非單點權威)
  • 玩家可選任一節點 / 自架 / 不選(直接 P2P)
  • 初期允許 1 個 OrbitDB/pinning 節點啟動;3 個獨立故障域是公開服務的建議耐久目標。單機三副本不等於三故障域。

3.2 已交付部署模板

Provider 流程
Docker Compose 填妥 config/secrets 後啟動 base compose;資源限制從 compose.resources.example.yml 複製成 operator override,依 deploy/sizing/README.md 實測調整
Kubernetes 以營運者 fork 的 overlay/secret 覆寫 base manifests;可從 k8s/overlays/sizing-example/ 複製 resources patch,禁止把範例值當容量保證

目前沒有 Fly.io/Render one-click 模板,也不能只用單一 docker run 啟動 app image: pinning 的正式最小拓撲仍需要 app、kubo、cluster 三個服務。

3.3 Pinning Server 安全 Header

詳見 資安規範.md §7

3.4 與 ledger 整合

Pinning Server 負責:

  • IPFS GLB 內容快取 + 提供
  • OrbitDB peer(同步事件鏈)+ 訂閱檢查點自動 pin(帳本完整性)
  • 下架與拒服務(仲裁黑名單 CID unpin+拒重 pin/provider-scoped DMCA 下架/Repeat Infringer 拒 pin,程式架構/pinning-service.md §9
  • DMCA 後端 API(可選)
  • 設定頁顯示連線狀態

4. Signaling Service 自架

Repo 層規格見 部署資訊/open-4wd-signaling.md

詳見 程式架構/signaling-service.md

4.1 用途

  • WebRTC handshake 中介(exchange SDP / ICE candidates)
  • 連線後直接 P2P(不再經 signaling)

4.2 多 Transport

Transport 執行期行為 伺服器端
WSS 先依服務模式限制來源,再按玩家手動、接受的 session route、community registry 順序嘗試 同一 Signaling v1 協議;Cloudflare Worker 與 Node adapter 是地位相同的 reusable 實作
GossipSub 與 WSS rendezvous 同時開始;建房端維持第一個可註冊 WSS,加入端跳過只含本機的空 roster 並續試候選;冷啟動 WSS roster 無目標時走 Gossip,跨 transport 以 signed nonce 去重 純 P2P、無 signaling server;實作位於主 repo(程式架構/peer-discovery.md

4.3 TURN + STUN(coturn,open-4wd-turn repo)

open-4wd-turn 提供 coturn 設定模板、k8s manifests 與驗證 CI;共通部署模型依 §1.1,repo 層規格見 部署資訊/open-4wd-turn.md。 coturn 同一 daemon 同時提供兩種協議:

  • STUN(無認證、無狀態、幾個封包即退場):由玩家手動設定、ice.json 或已接受的 session ICE configuration 提供;不硬編碼永久公網保底。
  • TURN(打洞失敗時中繼、流量計費):需憑證——TURN_TOKEN_TTL_SEC: 300,token 由 配對的 signaling provider 發放、coturn 以 shared secret(REST API auth)驗證。不得任意 混用不同 operator/provider 的 signaling token 與 TURN deployment。

k8s 跑 coturn 需 UDP + relay port range(hostNetwork / NodePort range),manifests 模板內建。

5. Bootstrap Nodes(peer-discovery)

詳見 程式架構/peer-discovery.md

參數
公開啟動硬下限 0(保持本地模式)
LEDGER_PROVIDER_FAULT_DOMAINS_RECOMMENDED 3(bootstrap 獨立 provider 故障域少於此值只告警)
BOOTSTRAP_DIAL_TIMEOUT_MS 15_000

Bootstrap 使用 communitymanual-onlyoffline 三種玩家模式。Community 模式可合併 玩家手動 entry、已接受的 session multiaddr 與 public/community/bootstrap.json;registry 失敗依序使用最後成功快取與 build snapshot。所有候選失敗時使用既有 peer cache,仍無連線 就保持本地模式,不把 provider 可用性當作 release gate。

Circuit Relay 與 bootstrap 分開選擇;只有玩家手動、已接受 session route 或 relay.json 明確宣告 relay capability 的候選能進入,bootstrap listing 不會自動授予 relay 能力。 client 只在直接連線全失,或冷啟動 15 秒後仍為零連線時嘗試 relay;每個線上 generation 只建立並重用一個 circuit listener,不在啟動時預撥所有候選。公版未部署值保持空陣列。

6. PWA 離線

詳見 程式架構/pwa-offline.md

6.1 PWA Manifest

{
  "name": "Open4WD",
  "short_name": "Open4WD",
  "start_url": "./",
  "display": "standalone",
  "theme_color": "#0B0C0E",
  "icons": [/* 多 size */],
  "categories": ["games", "entertainment"]
}

start_url 用相對路徑——base path 隨部署位置變(project pages = /open-4wd/、custom domain = /),寫死 / 會在 project pages 跳出 PWA scope。

6.2 Service Worker 快取策略

導航 / HTML = Network-first(離線 fallback cache);JS / CSS / WASM / 靜態圖 = Cache-first(含 version hash);/api/* / /version.json = Network-only;IPFS GLB 由 Helia 管。完整快取分路表以 程式架構/pwa-offline.md §2 為準

6.3 離線可玩

完全離線下可:

  • 進 /garage 看本地 loadout
  • 使用 bytes 完整的正式 / 本機測試車位與本機測試場地進行 local-test
  • 不可:配對 / 多人或正式比賽 / 上鏈

6.4 升版整合

詳見 版本規範.md §8

7. SEO

詳見 程式架構/seo.md

7.1 靜態 metadata

元素 內容
<title> 各頁面動態(i18n)
<meta description> 各頁面動態
<meta keywords> 主關鍵字
OpenGraph og:title / og:description / og:image / og:url
Twitter Card summary_large_image
canonical URL 各頁面對應 base URL

7.2 i18n hreflang

每頁面對應 hreflang 連結(各語系 → 路徑前綴對照)。HREFLANG_MAP 常數值見 ui.md §16(本檔不重列,避免漂移)。

7.3 OG 圖

OpenGraph 分享圖:固定封面圖 + 標準 1200×630 尺寸。OG_IMAGE_PATH / OG_IMAGE_WIDTH / OG_IMAGE_HEIGHT 常數值見 ui.md §16(本檔不重列,避免漂移)。

7.4 sitemap.xml

首發 sitemap 只由 route manifest、公告 build snapshot 與同一 build 的靜態輸入決定性生成;不連 provider 或 OrbitDB,也不宣稱 UGC Top-N。Optional UGC 接縫與日後啟用前提見 程式架構/seo.md §4

SEO 生成器不得單獨改寫 /version.json(commit_hash);任何 sitemap/robots 變更隨正常 build 驗證與發布,避免製造沒有 client bytes 變更的假升版通知。

7.5 JSON-LD

首頁 @graph:VideoGame + WebSite(SearchAction);公告詳情為 Article。UGC track/part 與 creator 的 client-side metadata 接縫分別使用 Game/CreativeWork/Person;首發不承諾其 prerender 或 sitemap 收錄——詳 程式架構/seo.md §3

7.6 SSG / 預渲染

Angular SSG/prerender 的 route 名錄、靜態範圍與 optional UGC 接縫只由 程式架構/seo.md §6 定義;本檔不另列第二份清單。

7.7 Lighthouse CI

PR 跑 Lighthouse CI;門檻與跑法見 程式架構/seo.md §7(本檔不重列,避免漂移)

8. 首次域名啟用與日後遷移

第一個公開 production origin 直接使用 open4wd.org。本節其餘遷移程序保留給未來「已有公開使用者的 origin A → origin B」。

8.1 首次公開不是遷移

private 開發期沒有 GitHub Pages 公開站,也沒有既有 public client、搜尋索引或 origin-bound 玩家資料。首次公開因此直接部署 root base path (/) 的 custom-domain build;只需驗 DNS/TLS、PWA scope、canonical URL、deep link、/version.json 與部署服務 smoke。不需要 30 天 banner、major 過渡或 301 herding。

/open-4wd/ 仍是獨立 GitHub Pages preview build target,用於本機/CI 驗證 project-pages 相容性;它不是 production canonical origin。

8.2 日後遷移性質

無資料搬運步驟。主站只發靜態 code(發行渠道、非資料端點);全域狀態(帳本 + GLB)住 libp2p / IPFS / pinning、以內容定址(CID / OrbitDB address 不含域名字串),cutover 前後是同一張活網路——新 origin client 走「新玩家首次同步」既有路徑從 pinning / DHT 重建副本,不存在「轉移中資料又更新」競態(沒有複製步驟可被競態;事件只存在暗 peer 的形狀被首播 ±30s 收件驗證封死,程式架構/ledger-admission.md §1)。

瀏覽器儲存(IndexedDB / localStorage / Cache Storage / SW 註冊 / 已安裝 PWA)全部 origin-bound、不可轉移(同源政策無跨 origin 讀取 API;custom domain 一設,舊 origin 即 301、頁面永久載不進)。各項命運:

資料 cutover 後 動手者
OrbitDB 帳本副本 / DerivedState 快取 從 pinning / DHT 自動重 sync(副本 = 快取、非本體) app 自動
Helia GLB 快取 / 縮圖 / LRU meta 玩到再抓、重新累積 app 自動
SW cache + SW 註冊 新 origin 首次載入自動重建 瀏覽器自動
已安裝 PWA 舊圖示成殭屍(由 §8.6 herding 趕到新站);重新加入主畫面 玩家一鍵
encrypted-keys(身分) 備份碼 + 新 PIN 重入;本機資料包不含 key,無備份碼仍永久遺失身分 玩家
身分 container/設定/本機測試資產 cutover 前匯出 .open4wd-backup,新 origin 驗證預覽後匯入 玩家

8.3 預告期(≥ 30 天、banner 常駐)

  1. 確認助記詞備份(核心訊息,對應唯一不可逆損失點)
  2. 匯出加密 .open4wd-backup,包含所選身分資料、設定與本機測試資產;密碼遺失無法復原
  3. 遷移日期與新 origin 匯入步驟

banner 觸及不了長期離線玩家——底線保障 = 助記詞備份本就是 onboarding 強制項(流程/玩家整體旅程.md §5 抄寫驗證),banner 屬 best-effort 加強、非唯一防線。

8.4 技術前置檢核(維護者)

  1. pinning 帳本完整性驗證:log head = 最新 LedgerCheckpointEvent、pinned CID 抽驗可取。pinning 為持續訂閱自動 pin(程式架構/pinning-service.md),此為健康抽查閘、凍結快照——flip 前後新事件照常流入。
  2. 無識別子綁主站 origin 檢核(CI 不變式):①OrbitDB address / pubsub topic = 純內容派生、不含任何域名、不得從 location.origin 派生;②bootstrap / signaling / pinning 端點 hostname 與主站 origin 解耦——端點是 multiaddr / wss URL、本就含自有 DNS hostname,要求是主站換域時不需改動任何端點——「不用遷移」是設計不變式而非自動性質,此為其證明義務。
  3. DNS CNAME 提前(T−1 日)設好待傳播(此時尚無人使用新域名、傳播延遲無感)。

8.5 cutover 日(低流量時段)

  1. Deploy 遷移版 build:major bump,將 UI.seo.CANONICAL_BASE_URL 明確改為目標 origin(robots / sitemap / hreflang 隨 build 切換)。build 先在舊 origin 上線、功能不受影響(canonical 僅 SEO);新舊版配對互擋 = 標準 major 過渡。
  2. 複驗 pinning(8.4-1)。
  3. repo 設 custom domain → GitHub 開始新域名服務 + github.io 自動 301 + TLS 憑證簽發。
  4. 唯一抖動窗 = TLS 憑證簽發(分鐘級~1h):期間 reload 者可能見憑證錯誤、重試即可——可用性小抖動、非資料事件;已開 tab 與 P2P 網路不受影響(賽中受 idle guard 保護不 reload,版本規範.md §8.2)。
  5. 驗證:https 新站載入 + Enforce HTTPS + 從舊 origin fetch('/version.json') follow-301 可讀(herding 生效前提——跨源讀取依賴 GH Pages 回應帶 Access-Control-Allow-Origin: *;CSP https: scheme 已放行)→ 公告。
  6. Abort path:移除 custom domain 設定 → github.io 恢復直接服務(§13 災難表)——全程無資料搬運、回退成本近零。

8.6 T+ 收尾

  • Search Console 改址;監看 pinning 節點同步負載(大量 client 同時重 sync 的流量尖峰)。
  • 舊 origin 殭屍 client 自動收斂(301 herding):github.io 301 為 path-preserving → 舊 client 下次 fetch /version.json follow 301 拿到新站的檔 → commit_hash 不符 → 既有強制升版機制 reload 落到新 origin(§10);major 另擋配對雙保險。

9. CI/CD 流程

Developer 合併 PR 進 master
  ↓
GitHub Actions:
  - Build(Angular production build)
  - 依每份 prerender HTML 的 inline bytes 逐頁生成並注入 CSP `<meta>`(資安規範.md §4)
  - Test(Vitest + Playwright)
  - 不變式檢查
  - Lighthouse CI(門檻見 seo.md §7)
  - SRI hash 生成
  ↓
Pages artifact:
  - actions/configure-pages
  - actions/upload-pages-artifact
  ↓
Deploy job 以 OIDC 執行 actions/deploy-pages
  ↓
GitHub Pages 發佈
  ↓
Service Worker 啟動升版檢查

sitemap、robots 與 SSG routes 由同一生成器隨相關 build 產生(§7.4),不另設 會在沒有 client release 時改寫公開產物的每日 workflow。

10. 版本擴散

詳見 版本規範.md §10 升版檢查 API

新版本 deploy 後:
  - 玩家 SW 啟動 fetch /version.json(network-only;勿與 PWA manifest.json 混淆)
  - commit_hash 不一致 → 通知玩家升版
  - 24 小時軟性升級寬限後強制升版(major bump 立即)
  - 套用受 idle guard:比賽 / 房間 / Stage 2 編輯中不 reload、延後至離開後(版本規範 §8.2)

11. Client build-time 設定

瀏覽器 bundle 不在 runtime 讀 process.env。正式端點與 trust roots 依部署階段分成 deployment-values.development.jsondeployment-values.private-playtest.jsondeployment-values.public.json;Angular build configuration 選入對應唯讀 profile, check:deployment --profile <name> 直接驗證同一份值,且內嵌 stage 不一致時拒絕:

欄位/來源 用途
stagebasePath 部署階段與 Project Pages base path
ledgerAddressgenesisTimestampgovernanceSigners 帳本 trust root;timestamp 必須逐字取自 genesis receipt
legalAgentContact public release 法律聯絡資料
src/system-constants/network/versioning.ts client_version 等協定版本常數
Pages workflow 產出的 version.json commit_hashbuild_timestamp;CI 在 build 後寫入

Build profile 只保存主站與 Ledger/genesis project trust root,不保存 provider 清單。五類 runtime provider 由玩家設定、已接受的 session route 與受檢 registry 產生;空 registry 與 全部 provider unavailable 都不得讓 project release validation 失敗。

12. 監控與 Telemetry

設計選擇:不蒐集遠端 telemetry(保護玩家隱私)。

  • 本地錯誤日誌 buffer 收 console.error(不接 Sentry 等遠端錯誤服務);與 資安規範.md §9 安全事件記錄同一 local-only 模式
  • 玩家可在設定頁手動匯出 debug log
  • 公開的 GitHub Issues 接收 bug report
  • 同一立場的延伸:營運資金 = 捐助制、不掛第三方廣告(權威 = 總覽.md 專案定位——廣告聯播網 = 第三方 script+ 追蹤,與本節及資安鐵則不相容)

此限制不排除服務端自身的低基數基礎設施 metrics。Pinning 公版可選配 Prometheus,labels 不得含 PeerId、IP、CID、RoomId、DMCA 案件或其他玩家/內容識別值;營運者自行決定 raw metrics、Grafana 與告警的私有存取。本檔不指定域名或通知供應商,完整契約見 pinning-service §10open-4wd-pinning §6

13. 災難復原

災難 復原
GitHub Pages down 玩家 PWA 離線仍可進 /garage / 本機測試
Signaling 所有 provider down 配對失敗;遊戲不可開始;玩家可換 provider
玩家選取的 Pinning provider 全 down 遠端持久供應暫不可用;本機 cache、CAR、Bitswap 與其他玩家 peer 照常,client 可改選 provider
Bootstrap 節點全 down 玩家於設定頁自填 bootstrap(§5);已建立的 session 不受影響(既有 DHT 連線)
Custom domain 失效(DNS 到期 / 設定錯誤) 維護者移除 repo custom domain 設定 → github.io 原址恢復直接服務(注意:設定仍在時 github.io 會 301 到失效域名,自動 fallback);CANONICAL_BASE_URL 退回 github.io
OrbitDB Sync 異常 從最近帳本檢查點重 sync
Service Worker 卡死 /reset/ 逃生口
經濟機制壞損(參數 / 規則 bug / exploit) 復原階梯:治理回滾 → 修法+全網重算(derive_logic major)——經濟系統.md §2.1
帳本壞損(事件史不可解讀) 鏈重生:自最後良好帳本檢查點起新鏈(新位址、client major 出貨)——資料系統.md §19

14. 跨模組對接

模組 內容
程式架構/pinning-service.md 自架部署模板 + 管理 API + IPFS Cluster + 訂閱檢查點自動 pin
程式架構/signaling-service.md 自架部署模板 + 多 provider fallback(TURN·STUN = open-4wd-turn repo,§4.3
部署資訊/ 三 repo 規格(pinningsignalingturn repo 層:目錄結構 / 部署變數 / CI / 自架指南 / runbook
程式架構/pwa-offline.md PWA + SW 快取分路 + 升版整合 + UGC 快取 LRU
程式架構/seo.md metadata / sitemap / JSON-LD
程式架構/dmca.md Provider-scoped DMCA 受理、私有案卷與 uploader inbox;pinning 執行層 = 程式架構/pinning-service.md §9
程式架構/peer-discovery.md bootstrap / DHT / GossipSub / Peer Scoring
程式架構/versioning.md 升版流程