架構與通訊協定 v1
儲存
資料庫結構由 header、state 與 checkpoints 組成。除了格式中繼資料、鹽值及資料列序號之外,所有值都是經過驗證的密文。日誌也包含密文。系統沒有持久化的明文 FTS 索引。經授權的一般記憶會切分為相互重疊、可安全處理 Unicode 的區塊,並使用 Jieba 斷詞,再放入記憶體中的 SQLite FTS5 索引。快取以保管庫的政策/修訂/隔離狀態作為索引鍵,在查詢之間重複使用;編輯、同步與政策變更會使其失效,鎖定則會清除快取。SQLite 暫存刻意限定只使用記憶體。向量會正規化,且僅快取於記憶體;明文索引與嵌入向量都不會進入備份或同步酬載。
由密碼衍生的金鑰會包裝隨機主金鑰;主金鑰用於加密狀態及本機檢查點。每個權限世代都有一把保管庫金鑰,每個修訂則有一把隨機資料金鑰,並由所屬世代金鑰包裝。內容經序列化後,切分為個別驗證的 256 KiB 區塊,區塊位置與總數都會繫結至關聯資料。修訂簽章涵蓋資產 ID、父修訂、政策頂端、墓碑旗標、密文及裝置憑證。
異動會在複製的狀態上準備,再以 synchronous=FULL 在單一 SQLite 交易中,連同加密狀態及檢查點一起提交。讀取與執行意圖會在交付前提交。因此,磁碟故障會拒絕交付;意圖提交後若發生當機,結果可能無法確定。
獨占的作業系統鎖允許一個遵守鎖定協定的本機寫入者。初始化會在相同目錄中建立完整資料庫,關閉並同步後,再發布到目的地,且不覆寫既有目的地。暫存作業中斷不會阻止重試。每個裝置都需要自己的本機儲存區;透過雲端同步用戶端複製使用中的 SQLite 檔案,無法提供多裝置交易安全性。
身分與傳輸
使用者 Ed25519 金鑰為裝置 Ed25519 簽署金鑰及裝置 X25519 交換金鑰簽發憑證。只有憑證還不夠:每個保管庫政策都必須明確授權裝置。裝置金鑰彼此獨立,包括屬於同一使用者的裝置。初始使用者簽署權限會透過經驗證、以收件者金鑰加密的封包,交付給核准的個人裝置;裝置撤銷後,該權限無法繞過保管庫的裝置允許清單。
信封包含格式版本、傳送裝置金鑰、收件者交換金鑰、暫時性 X25519 公開金鑰、AEAD 酬載及 Ed25519 簽章。HKDF 用於衍生傳輸金鑰。收件者身分及暫時性金鑰都經過驗證。加入的裝置使用有期限的簽署請求,並明確釘選核准裝置的公開金鑰;請求僅在成功提交後才會消耗。
第一版使用請求/核准字串與檔案,而非相機 QR 掃描。指紋是完整的 SHA-256 摘要;清單中顯示的縮短值,絕不能作為唯一的核准檢查依據。
政策與合併
保管庫政策是經簽署的線性歷程,包含成員資格、角色、裝置允許清單、只增不減的裝置撤銷集合及世代。角色檢查使用前一個政策。一般使用者可以為自己的身分授權其他裝置,而不變更成員資格。Admin 可以變更 Admin、Editor 與 Reader 的成員資格,並授權成員的裝置。Admin 不能新增、移除或變更 Owner、撤銷裝置,或轉移擁有權;Owner 才能執行這些操作。擁有權轉移會保留恰好一位 Owner。
資產歷程形成依內容定址的 DAG,供所有可編輯種類共用(記憶、卡片——包括知識、腦、人格及受保護卡片中繼資料——檔案與憑證)。每次儲存都附加一個經簽署的修訂;沒有獨立的 wiki 專用歷程儲存區,也不會自動修剪。history 列出修訂及其作者與摘要;diff 傳回兩個修訂之間,或某修訂與目前 HEAD 之間的統一文字投影(標題、結構化中繼資料、內文)。檔案差異不包含二進位酬載;憑證的機密內文仍無法透過讀取/差異取得。同一資產若有多個尚未被後續修訂消耗的修訂,即為衝突;解決修訂會列出所有可見的父修訂。墓碑會將資產從目前檢視移除,但不刪除歷程。
同步會先驗證完整的政策、修訂及稽核歷程,再合併至候選狀態。來自已被取代世代的未知寫入會被隔離。若傳入的較新政策快照未包含本機離線寫入,這些寫入也會被隔離。隔離只能在本機審查/重新套用,不能由不受信任的傳入欄位清除。
權限分支需要擁有者針對選定頂端及整條捨棄的政策鏈簽署。簽署者必須在兩條分支上都是擁有者。捨棄的政策仍可用於驗證歷史/隔離修訂。成功解決會推進選定政策並輪替其金鑰。相互競爭或不相容的解決方案會採取封閉式失敗,拒絕處理。
本機 API
service::Request 是共用的型別化操作介面,以 snake case 的 op 識別欄位序列化。未知的頂層欄位會被拒絕。本機 IPC 使用以大端序 32 位元長度為前綴的 JSON 訊框(版本 1 的 Wire 包裝)。選用的 HTTP/WebSocket 監聽與中繼 RPC,在權杖驗證後使用相同的 WebSocket 二進位 JSON 訊框(先 AuthFrame,再 Wire)。MCP 能力會在分派前獨立檢查。RunBound 與 RemoteExec 的分派方式相同:run_bound_prepare 在服務鎖內授權並解密,IPC 執行緒在未持鎖時執行程式,run_bound_finish 則稽核結果。執行繫結存放在裝置本機的 State.run_bindings,不在保管庫內。
網路傳輸可承載經權杖驗證的訊框化 Requests。權杖僅來自旗標/環境變數(絕不來自 TOML),以固定時間比較,並在儲存區鎖定時清除。遠端呼叫者使用穩定的提權命名空間(ws:remote/relay:remote),不繼承本機的 cli:{pid} 提權;透過遠端連接進行解鎖與 sudo,會提升該命名空間的權限,讓 CLI 單次連線維持提權。桌面 HTTP/中繼主機分派完整的 handle_client 操作介面(與本機 IPC 相同的提權門檻)。行動版 FFI 與 Share 保留平台拒絕清單,不會在手機上建立桌面專屬功能。HTTP 監聽預設使用 loopback;非 loopback 繫結需要 --allow-non-loopback 並顯示警告。一般 HTTP/WS 不需要憑證;--tls-cert/--tls-key 啟用 HTTPS/WSS。中繼 RPC 在信任邊界外使用 WSS,搭配高熵房間 id 與權杖;保管庫同步保留 /v1/channel。WebUI 提供唯讀狀態投影及受限的一般卡片編輯器,不是 Request 傳輸通道。請參閱遠端常駐程式及 SECURITY.md。
選用的授權 Center(設定中的 [[centers]])禁止本機自行啟動信任及本機簽發 MCP 授權;註冊與授權會以 Center 簽署的票證分發,並明確指定範圍(allow_all/read/write/read_write/read_write_delete)。請參閱 Center。
選用的 Center 託管模式(--data DIR)在 DIR/store/ 下持有獨立的常駐程式格式加密 Store,使用由操作人員持有的伺服器密碼開啟。其 HTTP 內容 RPC 使用 Service 中封閉、依保管庫授權的分派器;操作範圍內的提權涵蓋受保護/私密內容及附件,不變更常駐程式的 MCP 授權。這是伺服器端加密,不是用戶端端對端加密。獨立的管理 HTTP 路由管理託管鎖定/解鎖,以及僅擁有者可存取的 DIR/members.json 中持久化的具名授權。經簽署的解鎖票證僅授權本機裝置以密碼解鎖;裝置金鑰絕不會送到僅處理票證的 Center。單一 [[centers]] 項目設定 mode = "saas",會使常駐程式的內容 RPC 使用該託管後端及其環境 bearer 權杖,而不提供平行的本機內容路徑或 MCP 能力提權。裝置/管理控制不屬於授權內容介面。邊界與移轉資訊請參閱 Center 託管保管庫。
行動版 ABI 宣告於 crates/ffi/memories.h。控制代碼是登錄表中的數值 ID,不是原始 Rust 指標。每個傳回的字串都必須使用 memories_free 釋放一次。無效 JSON 會產生一般錯誤,不回顯輸入。memories_lock_all 在進入背景時推進全域鎖定世代,並抑制延遲抵達的進行中回應。登錄表儲存以參考計數管理的個別控制代碼服務鎖;網路作業不持有登錄表鎖或寫入鎖。忙碌的控制代碼會在下一個請求前套用待處理的鎖定。行動版排除程序執行及 MCP 授權建立。
Flutter 模式選擇器(mobile/lib/app_mode.dart)將 Standalone 導向本機函式庫,將 Center/SaaS 導向 HostedCenterPage。此處的 Center 指具備託管儲存區的自架伺服器;SaaS 則選取固定的 https://memories.ivjn.us 端點。兩者都使用相同的 Rust hosted_* FFI 操作及 HostedClient;選擇模式不會修改常駐程式 TOML、註冊受票證管理的裝置,或在儲存區之間移動資料。
所選模式是不含機密的偏好設定。Center 與 SaaS 各自在平台安全儲存區中存放一組 URL/權杖設定檔。切換時會鎖定本機服務、停止分享,並釋放託管頁面/工作階段。進入背景會清除託管內容,並使延遲回應失效;返回時必須明確重新連線。設定檔索引鍵及升級行為請參閱行動版設定,使用者操作步驟請參閱行動版指南。
桌面系統匣與狀態投影
Request::DesktopStatus 傳回初始化/鎖定狀態、函式庫與連線數量、已設定提供者種類,以及同步佇列數量的型別化投影。它在未鎖定操作分派前執行,不會複製或提交加密狀態、觸碰閒置/提權計時器,或公開識別碼、帳號摘要、內容或憑證。鎖定時的回應不包含詳細資料。現有的 MCP 允許清單拒絕此請求。
CLI 函式庫提供本機儀表板及 Windows/macOS 系統匣。memories tray 與獨立的 memories-tray 啟動器都使用原生主執行緒事件迴圈。HTTP 伺服器及具有界限的狀態探測工作執行緒分開執行,因此忙碌的常駐程式不會阻塞系統匣或瀏覽器。探測使用一般作業系統驗證 IPC 呼叫同目錄的 CLI,並設有期限及子程序清理。HTTP 介面提供內嵌資產、固定的狀態投影,以及明確的一般卡片/類型編輯允許清單。它不能解鎖、提權、揭露機密或分派任意服務請求。權杖及瀏覽器來源邊界請參閱 SECURITY.md,另請參閱桌面使用方式。
檢索與模型協調
search::Cache 最多持有兩個保管庫索引,每個索引限制為 10,000 個區塊、16 MiB 來源文字/中繼資料及 32 MiB 向量。建立索引前會排除私密、憑證、檔案、已刪除、隔離及衝突內容。BM25 對標題/內文/中繼資料的權重為 5/1/2。向量搜尋使用餘弦相似度;混合搜尋以倒數排名融合結合兩種排名。預設重新排序會在有界限的候選集合內,提高查詢涵蓋率及精確詞組相符項目的權重。已設定的模型端點可執行學習式重新排序。
Retrieve、RagIndex、RagStatus 與 RagAsk 保留保管庫授權及 MCP 授權範圍限制。IPC 在服務互斥鎖外執行模型作業,並於外部作業前後及交付前,重新檢查解鎖世代、授權有效性、存取權及來源修訂戳記。經簽署的意圖先於推論/匯出提交;成功/失敗及已交付的來源 ID 都會接受稽核,但不包含提示詞或金鑰。來源資產/修訂參照使用共用的短 ID 投影;區塊雜湊及 [S1] 引用標籤不是資產 ID。
rag::Runtime 延遲載入原生 ONNX 推論及釘選的 EmbeddingGemma Q4 資產,或呼叫已設定的 Gemini/相容嵌入 URL。它也支援已設定的生成與重新排序 URL、以環境變數參照的 API 金鑰、代理伺服器及重試。原生模型檔案是公開模型資料;加密的使用者紀錄絕不會成為模型權重。生成提示詞中的檢索文字被視為不受信任的資料,傳回的引用 ID 會對照所選來源驗證。這會驗證參照,不會驗證模型生成文字的事實正確性。
行動版 FFI 可使用改進的詞彙搜尋,並支援 BM25 retrieve。模型支援的操作目前使用已設定的桌面常駐程式;本版不在 Flutter 新增模型設定或模型推論 UI。
桌面密碼學工作
jobs::Job 描述工具、釘選的輸入檔案/目錄樹、憑證繫結、有序步驟、清理及新的輸出路徑。CLI 的 crypto 配方會為 S/MIME/OpenPGP 及 Android/iOS 簽署建立此計畫。核准會在解析短 ID 前檢查,因此其摘要精確繫結呼叫者所見的參照。服務檢查本機提權及保管庫存取權,只解析憑證資產,提交執行意圖,再呼叫共用核心執行器。
執行器重新檢查工具、複製並驗證輸入,在私密工作區中實體化憑證,不透過 shell 執行命令、抑制其輸出,並且只發布成功的產物。預留位置展開只替換路徑,不會遞迴解譯路徑內容。MCP 允許清單及行動版 FFI 拒絕程序工作。既有 run 語意不變。
AI 用戶端技能
memories inject 是僅限 CLI 的安裝操作。skills.rs 將有版本的 crates/cli/skills/memories/SKILL.md 內嵌於執行檔,並安裝到文件所列的 Codex、OpenCode 或 Claude Code 技能探索目錄。它在建立資料主目錄前執行,絕不開啟儲存區或呼叫常駐程式。使用者與專案範圍共用相同指示文字;不會插入儲存區路徑、保管庫 ID、授權權杖或機密材料。
安裝器會預先檢查所有目標、保留內容相同的檔案,對不同內容要求 --force,拒絕連結的技能檔案/目錄,並透過目的地目錄中已同步的暫存檔發布每個檔案。新檔案發布時不會覆寫同時建立的檔案。這是單一檔案的原子性,不是跨用戶端的交易。既有同層資源及用戶端設定都會保留。技能透過既有 MCP 或 CLI 介面導向一般搜尋、附引用的檢索、已設定的回答及寫入;不新增授權能力。
雲端授權
桌面 CLI 使用 PKCE、loopback 回呼及固定提供者端點,執行瀏覽器 OAuth。CloudBegin 在 sudo 下建立有期限、繫結呼叫者/提供者/用戶端的票證。網路請求在常駐程式外執行;CloudComplete 在提交前檢查票證及目前授權。鎖定、登出及重新啟動會使待處理票證失效,避免延遲結果恢復登入。
State.cloud_accounts 在本機裝置上加密儲存權杖。狀態僅傳回帳號中繼資料;備份、配對、保管庫同步及 MCP 都排除權杖。登入不會建立保管庫成員資格。
雲端物件同步
State.cloud_sync 在相同的加密狀態 blob 中持有持久化的寄件匣/收件匣收據。CloudSyncEnqueue 在任何傳輸 I/O 前,寫入精確的序列化信封位元組及經簽署的描述項。物件 ID 是這些位元組的 SHA-256;重試會重複使用相同 ID。CloudSyncWork 傳回密文及列舉游標,不包含 OAuth 權杖。sync::execute 在不持有服務互斥鎖的情況下執行有界限的 put/get/list。CloudSyncAck 檢查程序本機的工作階段世代,再一起提交上傳旗標、已發現 ID、下載位元組及保管庫合併。早於物件抵達的描述項會保持待處理。鎖定、解鎖及登出會遞增工作階段,因此延遲確認無法匯入。memories cloud sync 要求常駐程式透過 OneDrive 或 Google Drive 應用程式資料夾更新權杖、上傳及下載;該 HTTP 作業在寫入鎖外執行。權杖絕不透過 IPC 傳回。測試也使用 MemoryTransport 及 loopback Graph/Drive 測試環境。已完成佇列酬載會壓縮為雜湊收據及依提供者/收件者區分的發布戳記。收據保留於本機,不會刪除雲端歷程。遺失的物件使用持久化的指數延遲重試;待處理容量會對列舉施加背壓。提供者工作執行緒依帳號序列化執行,並拒絕來自失效工作階段的更新/匯入結果。IPC 分派最多使用 16 個並行連線。
遠端工作階段
桌面常駐程式持有 SSH、FTP、TCP、MySQL、Redis 及 PostgreSQL 連線。RemoteOpen 驗證憑證主機允許清單、記錄連線意圖,再於寫入鎖外連線。SSH 使用密碼憑證或匯入的 OpenSSH 私密金鑰驗證,也可選擇搭配 OpenSSH 憑證。CredentialGenerate 在 sudo 下建立 SSH 金鑰與 TLS 憑證;私密金鑰會儲存為憑證,絕不傳回。CredentialPublic 從儲存的材料衍生 SSH 公開金鑰或 PEM 憑證。資料庫工作階段預設啟用 TLS,可選擇將 PEM CA 憑證(tls_ca)加入用戶端信任儲存區。必須驗證主機名稱;尚未實作憑證釘選。每個指令都會提出為票證,其指紋涵蓋工作階段、序號及標準化指令。RemoteApprove 為單次使用,且繫結至已提權呼叫者;RemoteExec 僅在既有工作階段執行該票證。鎖定、閒置到期及登出會捨棄即時連線與待處理票證。檔案操作使用 FTP;SSH 與資料庫工作階段接受 exec/query。
ProxyStart 在完成與 RemoteOpen 相同的憑證及主機允許清單檢查後,繫結 loopback 監聽器。本機用戶端不需機密即可連線;常駐程式持有上游 SSH 或資料庫驗證資料。proxy.start 在繫結前記錄連線意圖;proxy.stop 記錄停止意圖。已繫結的 socket 直接移交 Tokio,不存在關閉/重新繫結的空窗。PostgreSQL SSLRequest 與 MySQL SSLRequest 先於 TLS 升級;Redis 使用直接 TLS。PostgreSQL SCRAM 同時檢查 nonce 及伺服器簽章。MySQL 支援 native 及 caching-SHA-256 驗證,包括外掛切換;完整密碼交換需要 TLS。資料庫交握有 30 秒期限、64 KiB 封包界限,以及每個監聽器 16 個用戶端的限制。
本機至代理的資料庫傳輸為明文,登入/資料庫啟動欄位不會覆寫已設定的上游身分。本機用戶端可在該帳號權限內授權不受限制的遠端指令。Loopback 不提供個別使用者驗證。鎖定、保管庫閒置到期、明確停止及服務釋放會取消監聽器及使用中的工作階段。代理最長存續時間為 30 分鐘;流量不會延長保管庫解鎖時間。MCP 不能管理代理。
服務持有每個代理工作執行緒,並在停止/鎖定時等待其結束,因此成功回應不會與仍在轉送指令的連線發生競爭。
設定檔執行
memories file exec 結合既有的授權 Read 請求、CLI 本機檔案實體化及程序監督。它不引入新的服務請求、檔案種類、密碼學機制或行動版/MCP 執行權限。常駐程式使用既有讀取路徑稽核檔案交付,接著 CLI 執行前景子程序,不占用服務鎖。CLI 在直接子程序結束前持有暫時明文快照;後續保管庫變更或鎖定,不會變更/撤銷該已交付快照。
復原
備份在獨立的 Argon2id/AEAD 信封下包含經簽署的本機狀態及機密復原材料。復原會產生新的裝置金鑰並建立獨立的保管庫 ID,保留目前有效內容及衝突頂端。原始簽署歷程保留於加密的唯讀封存。復原不宣稱歷史上的共用成員資格仍然有效。僅限裝置的保管庫、雲端授權及雲端寄件匣/收件匣收據都會排除;每個復原裝置都必須個別登入雲端提供者。
卡片與安全投影
Kind::Card 共用一般記憶授權,型別化中繼資料儲存在加密修訂內。CardLink 新增同一保管庫內的有向邊。圖譜只投影目前明確且可見的節點,以及兩端都可見的邊。搜尋使用前述有界限的記憶體 FTS5 快取,涵蓋一般內文、標籤/來源及允許清單中的受保護卡片中繼資料。憑證內文絕不進入此索引。搜尋/清單/圖譜公開安全的 summary 投影;卡片讀取保留不透明的憑證參照,但絕不解析其值。
protected_card 驗證 account/env/token/TOTP/HOTP 輸入(包括 otpauth URI 匯入),將憑證與其卡片寫入同一候選狀態,並一起提交。通用 put 不能附加或替換受保護參照。機密操作解析目前的憑證修訂並驗證其種類。otp_code 實作 RFC 6238(TOTP)及 RFC 4226(HOTP),在相同提交中推進 HOTP 計數器,並在傳回代碼前記錄交付意圖。HTTP 標頭建構將 bearer/cookie 值標記為敏感,停用重新導向並抑制回應。
記憶及卡片內容也可以攜帶 secrets 對應,將穩定標籤對應至標準憑證資產 ID。protect_secret 將內文中完全相符的內容替換為 {{secret:LABEL}},並在相同交易中建立憑證。通用 put 要求既有對應保持不變,不能新增或重新指定其目標。CLI 與行動版編輯會沿用既有對應。MCP card_write 省略該對應,因此更新具有機密參照的卡片會驗證失敗。用戶端投影只縮短型別化憑證 ID,保持內文標記穩定。備份復原保留明確的資產 ID,因此對應可在復原後保留。credential_copy 直接解析標籤、受保護卡片或憑證,要求本機提權,並在將 UTF-8 明文傳回剪貼簿用戶端前提交稽核意圖。MCP 拒絕這兩個新操作。任何通用讀取、搜尋或圖譜操作都不會解析機密。替換不會改變經簽署的歷史內文;請參閱 SECURITY.md 中的 wiki 與剪貼簿限制。
服務僅向經授權的本機複製呼叫者傳回 {"secret":"..."}。CLI 在 clipboard.rs 中使用此回應,僅在剪貼簿寫入成功後,才於一般輸出信封內傳回 {"copied":true}。行動版使用 Flutter 的剪貼簿通道,並在交付前檢查其生命週期世代。稽核記錄的是帶有 delivery_intent 的 credential.copy,不是作業系統剪貼簿成功收據。請參閱使用指南。
State.local_vaults 在加密的本機狀態內標記僅限裝置的保管庫。local_config 將用戶端收集的版本及目錄中繼資料記錄在其中一個保管庫內。裝置核准會過濾掉這些保管庫;直接成員資格匯出及同步會被拒絕;store::backup 會從匯出快照移除它們。明確的資產 ID 在復原至新保管庫後仍會保留,維持圖譜及卡片至憑證的參照,同時將原始簽署歷程保留於封存中。