
Friend 项目 INV-DATA-1 数据面连续性不变式生产家族身份、路由权威矩阵与多层守护机制解析【免费下载链接】FriendAI that sees your screen, listens to your conversations and tells you what to do项目地址: https://gitcode.com/GitHub_Trending/fr/Friend导读本文围绕 FriendOmi仓库中已锁定locked的 INV-DATA-1 生产家族客户数据面连续性不变式 展开系统讲解生产家族production-family产物如何在不同平台、不同发布通道之间共享同一套客户身份与数据面移动端Stable / Beta / 内部 / alpha / TestFlight / Play Internal、macOS 端 Stable 与 Beta都必须使用生产 Firebase Auth 与 Firestorebased-hardware保持同一 UID、录音、会话、集成与同步状态。读完本文你将掌握该不变式的权威矩阵、唯一允许的服务面serving-plane拆分、local_prod开发者例外、外部预览的 fail-closed 机制以及从启动路由校验到 CI 静态守卫、再到生产 Firebase 探针的整套守护测试体系并能在提交涉及路由相关路径的 PR 时正确引用INV-DATA-1。一、不变式核心一个客户身份一个数据面Statement不变式声明任何生产家族产物都只能保留一个规范的客户身份/数据面customer identity/data plane。具体而言移动端Stable、Beta、内部构建、alpha、TestFlight、Play Internal 通道发布的包全部使用生产 Firebase Auth 与 Firestore项目based-hardware并保留相同的 UID、录音recordings、会话conversations、集成integrations与同步状态sync state。macOS 端Stable 的身份是com.omi.computer-macosBeta 是可独立安装的com.omi.computer-macos.beta狗粮dogfood身份。Beta 拥有独立的本地存储是刻意设计的隔离拥有自己的 UserDefaults 域、TCC 授权、Keychain ACL 与单实例锁可同时与 Stable 并行运行但它不是独立的云账户或独立的 Firestore 宇宙。这一设计意味着发布通道release channel只能控制资格eligibility、灰度曝光rollout exposure、诊断diagnostics与功能可用性feature availability绝不允许通过通道切换不同的账户或客户数据宇宙。TestFlight 检测、Android 的 dart define、更新通道偏好、启动环境或打包进产物里的环境文件都不是把生产家族包重定向到其他环境的授权依据。二、路由权威矩阵谁是唯一的权威文档以一张矩阵形式给出了生产家族路由的唯一权威这也是排查任何路由漂移问题的第一参照表SurfaceProduction-family authorityFlutter APIhttps://api.omi.me/macOS Stable Python / desktop APIhttps://api.omi.me//https://desktop-backend-hhibjajaja-uc.a.run.app/macOS Beta Python / desktop APIhttps://api.omiapi.com//https://desktop-backend-dt5lrfkkoa-uc.a.run.app/macOS Beta OAuth APIhttps://api.omi.me/macOS production identitiesStable:com.omi.computer-macos; Beta:com.omi.computer-macos.betamacOS Firebase/Firestore configthe shipped production customer project (based-hardware)从表中可以提炼出两个关键结论服务面serving plane只允许这一个拆分Stable 固定在生产 Python 与桌面 APIBeta 固定在开发 Pythonapi.omiapi.com与开发桌面后端desktop-backend-dt5lrfkkoa——但 Beta 的OAuth 权威仍然是生产api.omi.me。除此之外不得再选择任何其他 Firebase 项目、账户宇宙或任意端点。数据面data plane不允许任何拆分无论是 Stable 还是 BetaFirebase/Firestore 一律指向生产项目based-hardware。这一服务面可拆、数据面不可拆的不对称设计是理解整个守护体系的关键Beta 的隔离是存储与身份维度上的本地隔离 服务路由维度上的固定开发端点但云端的用户数据永远在生产宇宙内。三、平台实现移动端 profile 体系与启动路由校验3.1 四个受支持的 profile移动端的数据/信任面trust plane在 app/lib/env/environment_profile.dart 中以枚举形式显式建模每个 profile 在构建时被选定Profile默认 API Base URLFirebase 项目Auth 回调 schemeFirebase Auth 模拟器允许生产数据local_devhttp://127.0.0.1:8000/demo-omi-localomi-dev是否local_prodhttp://127.0.0.1:8000/based-hardwareomi否是mobile_betahttps://api.omiapi.com/based-hardwareomi-beta否是productionhttps://api.omi.me/based-hardwareomi否是其中local_dev面向本地模拟器不允许访问生产数据allowsProductionData: falsemobile_beta是唯一把生产 Firebase 身份与开发服务面显式配对的正规 profilelocal_prod则是文档强调的仅限 debug 的开发者工作流例外用显式的OMI_APP_PROFILElocal_proddart-define 把生产 Firebase 身份与开发者自选的本地后端端点配对。profile 的选择入口在 app/lib/env/environment_profile.dart#L56-L69 的AppEnvironmentProfile.forFlavor读取String.fromEnvironment(OMI_APP_PROFILE)为空时按 flavor 回退prod环境 →production否则 →local_dev非空时必须命中local_dev/mobile_beta/production之一否则抛StateError。3.2 启动路由校验网络服务启动前的硬闸门app/lib/startup_routing.dart 提供validateApplicationStartupRouting在main中任何网络化服务启动前执行env_test.dart#L254-L261 以静态接线测试钉死了该校验必须先于ServiceManager.init()的调用顺序。其底层 Env.validateStartupRouting 按 profile 分支处理local_dev只接受回环或私网端点判定逻辑_isLocalDevelopmentApi覆盖localhost、host.docker.internal、::1、10/8、172.16/12、192.168/16并特意放行 RFC 6598 的100.64.0.0/10CGNATTailscale 分配的网段——注释说明这是物理设备访问开发者本机 harness 的唯一路径同时严格拒绝100.63.x与100.128.x等网段边缘外的地址防止放行 100.x退化成放行任意公网地址local_prod在 release 构建中直接抛StateError(Profile local_prod is only available in debug builds.)——这是任何已发布产物都无法选中它的实现保证debug 构建下要求合法的 http(s) 端点production/mobile_beta要求归一化后的 API Base URL 与 profile 默认值精确相等mobile_beta为https://api.omiapi.com/否则抛错。配套的 profile 配对约束validateProfilePairing与 Firebase 项目校验validateFirebaseProject要求实际初始化的项目 ID 必须等于 profile 的firebaseProjectId即based-hardware或demo-omi-local进一步收紧了防线。3.3 OAuth 固定在生产身份面值得单独强调 Env.authApiBaseUrlForProfile当 profile 为mobile_beta时OAuth/认证 API 无条件返回生产https://api.omi.me/。这正是文档矩阵中Beta OAuth 权威仍是生产的移动端实现并由 env_test.dart#L68-L73 用断言钉死——即使服务面指向api.omiapi.com认证仍留在生产身份面。四、macOS 实现身份即路由环境变量无法越权4.1 AppBuildbundle 身份是路由的第一判据macOS 侧的路由决策不依赖环境变量而是以 bundle 身份为锚。在 desktop/macos/Desktop/Sources/AppBuild.swift 中productionBundleIdentifier com.omi.computer-macosbetaProductionBundleIdentifier com.omi.computer-macos.beta二者组成productionFamilyBundleIdentifiersBeta 的独立 bundle id 带来独立的 UserDefaults 域、TCC 授权、Keychain ACL 与单实例锁从而可与 Stable 并行共存注释明确要求与DesktopStorageIdentity.betaProductionBundleIdentifier保持同步并有单元测试断言更新通道Sparkle是身份绑定的currentUpdateChannel对 Beta 恒为beta、对 Stable 恒为stable——Beta 永久是 beta 通道客户端Stable.app 永远不会消费 beta 通道防止残留的update_channel设置把用户拖入针对生产 API 的更新mayRunLegacyStableAppCleanup只允许 Stable 身份执行旧包清理避免 Beta 或开发包误杀用户正在运行的 Stable 应用manualDownloadURL对 Beta 强制携带identitybeta参数保证 Beta 应用永远下载回自己的身份而不是 Stable 应用。4.2 DesktopBackendEnvironment固定端点的 fail-closed 决策链desktop/macos/Desktop/Sources/DesktopBackendEnvironment.swift 定义了四个固定端点常量路由决策由shouldUseDevelopmentBackends触发外部预览bundle id 前缀com.omi.preview.必须通过签名元数据显式选择后端缺失或畸形元数据时externalPreviewBackend返回nil路由fail closed 到生产绝不继承本地开发默认值Betacom.omi.computer-macos.beta无条件返回开发服务面api.omiapi.com/desktop-backend-dt5lrfkkoa-uc.a.run.app同时shouldUseProductionAuth恒为 true保证 Auth/Firebase/Firestore 仍在生产其他非生产家族身份默认开发后端且只有这类身份才允许环境变量OMI_PYTHON_API_URL/OMI_DESKTOP_API_URL/OMI_AUTH_API_URL覆盖生产家族身份Stable / BetashouldUseProductionAuth为 true 时pythonBaseURL、authBaseURL、rustBackendURL全部锁定生产常量——启动环境或打包配置不能切换其客户数据面applyReleaseChannelDefaults也只为缺失的 URL 补齐默认值不会覆盖既有权威。注意authBaseURL的注释桌面 Apple 登录使用共享 Services ID注册的 web 回调在api.omi.me因此 Beta 绝不能把 OAuth 继承到开发数据后端主机——这与文档Beta 必须忽略OMI_AUTH_API_URL的要求完全一致。五、外部预览保留身份 签名元数据畸形即关闭文档对外部预览external preview的约束是不允许外部预览使用生产家族身份发布。外部预览需要一个保留的预览身份com.omi.preview.前缀见 AppBuild.swift显式选择其许可数据面的签名元数据OMIExternalPreview标记 OMIExternalPreviewBackend值取值production或development畸形元数据 fail closed 到生产面。源码中的三重保障可以印证这一设计AppBuild.isExternalPreviewBundleIdentifier用保留前缀 非空后缀界定预览身份即使打包漏写标记身份本身仍受限AppBuild.Configuration.hasValidExternalPreviewConfiguration要求是预览 ⇒ 必须有标记且后端非空而DesktopBackendEnvironment.shouldUseDevelopmentBackends中预览分支只对externalPreviewBackend .development返回 true其余一律落到生产。六、MUST NOT五条不可逾越的红线原文档的 MUST NOT 清单必须原样继承这是评审任何涉及路由 PR 的判据不得通过 build define、CI 变量、运行时偏好、更新通道、进程环境或打包.env值把 Stable、移动端或其他生产家族产物路由到开发、staging、beta API 或任意端点——Beta 的两个固定开发服务权威与仅限 debug 的local_prod开发者 profile 是仅有的例外不得把 Beta 的 OAuth、Firebase Auth、Firebase API-key 绑定或 Firestore 路由到开发项目或端点——Beta 必须忽略OMI_AUTH_API_URL不得把OMI_BETA_RELEASE_RING、STAGING_API_URL、api-beta.omi.me或等价的 beta/staging 选择器当作生产家族路由机制不得以生产家族身份发布外部预览预览需保留身份 显式选择数据面的签名元数据畸形元数据 fail closed 到生产面不得把受保护的权威或 Firebase/Firestore 项目当作发布流水线的附带工作随意更改。七、刻意迁移例外迁移不是 beta 灰度文档强调客户数据面迁移不是 beta 灰度。一次真正的数据面迁移必须同时满足在 PR 中显式引用INV-DATA-1通过架构评审与产品评审提供身份/数据连续性证据identity/data continuity evidence有回滚计划rollback plan在发布前提供产物级断言锁定新的不可变权威immutable authority。而Beta 的固定服务面拆分本身不是客户数据面迁移。独立的开发/测试 app 身份与测试凭据可以使用非生产服务但不得复用生产家族身份——这条边界把开发测试与生产狗粮严格区分开来。八、守护测试体系从单元测试到生产探针的四层防线原文档列出的守护测试构成了启动即校验 → 桌面路由单测 → 外部预览单测 → CI 静态守卫 → 生产探针的多层防线逐层对应如下源码第一层移动端启动路由单元测试 app/test/unit/env_test.dart生产启动接受https://api.omi.me/TestFlight 与 Android 两分支mobile_beta接受开发服务面但要求生产身份配对生产启动拒绝api-beta.omi.me、api.omi.dev、staging.example.test、任意端点见 L133-L146local_dev放行全部私网与 CGNAT 范围、拒绝公网端点及 CGNAT 边缘之外L148-L192local_prod在 debug 下接受回环/私网/隧道端点在 release 构建下必抛错畸形端点必抛错L194-L231静态接线测试钉死main中启动路由校验先于ServiceManager.init()L254-L261并验证 Firebase 项目校验挂在ensureFirebaseApp()的所有路径上。第二层macOS 桌面路由测试APIClientRoutingTests.swift验证 Stable 保持生产路由Beta 在污染值contaminated values存在时仍只解析固定的开发服务端点与生产 AuthExternalPreviewBuildTests.swift预览身份必须有签名后端元数据且fail closed。第三层CI 静态守卫 .github/scripts/check-mobile-production-routing.py该脚本以任何生产家族客户端一旦离开其数据面即失败为目标检查codemagic.yaml中 7 个生产工作流ios-internal-auto、android-internal-auto、ios-prod-testflight、android-prod-internal、ios-prod-patch、android-prod-patch、macos-prod-appstore必须且只能各含恰好一条API_BASE_URLhttps://api.omi.me/的不可变赋值桌面工作流omi-desktop-swift-release必须恰好一条BUNDLE_IDcom.omi.computer-macos、一条OMI_PYTHON_API_URLhttps://api.omi.me、一条OMI_DESKTOP_API_URLhttps://desktop-backend-hhibjajaja-uc.a.run.app/保护路径codemagic.yaml、app/lib/env/dev_env.dart、app/lib/env/prod_env.dart、app/lib/main.dart、app/lib/utils/environment_detector.dart、DesktopBackendEnvironment.swift中不得出现OMI_BETA_RELEASE_RING、api-beta.omi.me、STAGING_API_URL等遗留路由令牌AppBuild.swift中出现的 macOS 生产 bundle 身份只允许com.omi.computer-macos与com.omi.computer-macos.beta两个受认可值SANCTIONED_MACOS_PRODUCTION_BUNDLE_IDENTIFIERS任何新增的发散身份都会被拒绝退役的 GKE desktop-backend 图表backend/charts、desktop/macos/charts中带desktop-api.omi.me/desktop-backend标记的清单与 GKE 部署工作流不得回归生产桌面后端已迁移到 Cloud Run。其变异契约测试 test_check_mobile_production_routing.py 覆盖缺失、冲突、staging、任意与遗留赋值的各类突变场景确保守卫本身不被绕过。第四层生产 Firebase 探针 backend/scripts/probe_beta_uid_continuity.py这是文档强调的非人工non-human生产探针它以based-hardware生产项目为目标创建一个有界的哨兵记录sentinelPROBE_UIDuuid4随机标记通过生产写入然后通过Beta 的固定开发 Python 端点https://api.omiapi.com/读取同一条记录来证明 UID 连续性最后在finally块中通过生产删除该记录。只有这条探针链路通过Beta 才有资格被晋升qualification can promote Beta。探针同时校验生产 Firebase JWT 声明validate_production_firebase_claims任何一步失败都会以ContinuityProbeError终止。文档还提醒签名后的移动端与桌面产物冒烟artifact smoke仍是发布证据静态 CI 守卫只是绊线tripwires不能替代产物级验证。九、受保护路径清单与 PR 规则文档给出了变更即触发评审的路径 globs本文保持完整codemagic.yamlapp/lib/env/env.dartapp/lib/main.dartapp/lib/startup_routing.dartapp/lib/utils/environment_detector.dartapp/lib/firebase_options*.dartapp/android/**/google-services.jsonapp/ios/**/GoogleService-Info.plistdesktop/macos/Desktop/Sources/AppBuild.swiftdesktop/macos/Desktop/Sources/DesktopBackendEnvironment.swiftdesktop/macos/Desktop/Sources/GoogleService-Info*.plistbackend/charts/desktop-backend/**已退役此图表不得回归.github/workflows/gcp_*.yml已退役任何 GKE desktop-backend 部署权威不得回归.github/workflows/desktop_backend_*.yml.github/scripts/check-mobile-production-routing.py.github/scripts/test_check_mobile_production_routing.pybackend/docs/runbooks/desktop-backend-cloud-run-ownership.mdPR 规则任何改动上述路径的 PR必须在 PR 描述中写明INV-DATA-1并明确声明该改动是保持既有权威还是显式迁移例外。这条规则把不变式从文档层面落到了日常工程协作流程。十、小结INV-DATA-1 的核心可以用一句话概括服务面可以且只允许有一条固定拆分Beta → 开发 Python/桌面端点数据面在任何情况下都只有一条生产based-hardware身份bundle id / UID / Firebase 项目是路由的最终判据环境变量、更新通道与打包配置均无越权资格。Friend 仓库通过移动端 profile 枚举 启动硬校验、macOS 身份绑定路由 fail-closed 决策链、CI 静态守卫含变异契约测试与生产 Firebase 哨兵探针这四层防线把这个不变式变成了可在每次发布前机器验证的工程事实。对于任何需要改动上述路径的开发者和评审者本文提供的权威矩阵、MUST NOT 红线、迁移例外条件与守护测试清单可以作为直接的引用与检查依据。【免费下载链接】FriendAI that sees your screen, listens to your conversations and tells you what to do项目地址: https://gitcode.com/GitHub_Trending/fr/Friend创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考