Linxira 的软件生态有多个入口:安装器的软件选择、Welcome 的推荐链接、图形化的软件管理。这些入口如果各维护一份软件清单,必然走向漂移——安装器里有的,欢迎页没有;欢迎页推荐的,软件管理器不显示。catalog 就是回答这个问题的架构:所有入口共享同一份经过审核的元数据。本文讲清楚 catalog v2 与 v3 的关系,以及「GUI 只规划、后端执行」的设计。
展开技术细节之前先给一个框架:对用户来说,软件生态不是「一个包管理器加几份清单」——它是整个发行版最可见的表面。用户在安装时选择它、装完后浏览它、靠它判断这台机器是否适合自己的工作。如果这个表面不一致,发行版给人的感觉就是坏的,任何特性清单都无法弥补;catalog 就是维持这个表面一致性的承重结构。
一个发行版与软件生态的接触面比看起来多得多:安装时要选装什么、装完后欢迎页推荐什么、图形软件管理器展示什么、精选应用怎么分类。如果每个接触面各自维护一份软件清单,后果是必然的:数据不一致。同一个软件在这份清单里有、在那份清单里没有;同一个分类在这里叫这个名字、在那里叫另一个名字;更新一份清单时漏掉另一份。
更隐蔽的问题是信任不一致:一份清单经过审核、另一份没有,用户无法判断「官方推荐」到底意味着什么。catalog 的出发点就是:把「哪些软件可用、它们是什么、为什么被推荐」收敛成一份数据,让所有入口读同一份,从结构上消灭漂移。
举个具体的漂移例子:假设安装器为「科学计算」分类维护了一份清单,Welcome 又各自维护了一份。某个软件被新版本替换、某个软件因许可证问题下架——改了一处、漏了另一处,用户就会在安装器里看到它、在欢迎页里找不到它。更糟的是没有人会意识到这是错误,因为两份清单看起来都「挺完整」。数据共享从结构上消除了这一类错误:改一处,处处生效。维护负担也随之缩小:只需审核更新一份清单,而不是手工同步好几份。
catalog 还回答了维护侧的问题:谁来决定推荐什么?有了单一审核数据集,答案很明确——一个审核流程、一个应用进入或离开的入口、一条审计线索。新应用通过审核进入目录,下架通过审核移出目录。「推荐」是目录的属性,而不是某个恰好列出该应用的页面的属性。
catalog v2 是审核配置的载体:Welcome、Calamares(安装器)、Config Hub 与 Shelly 的推荐链接都读取同一份经过审核的 catalog v2。安装时从 catalog v2 选择可选的审核配置并创建用户账户;装完后欢迎页与软件管理器的推荐来自同一份来源。
v2 的角色是「兼容保留」:它继续作为安装器与推荐链接的共同数据源工作,不因 v3 的到来而废弃。对既有用户而言,v2 的行为没有任何变化;它被保留,是为了让安装流程与推荐链路不必跟着架构升级一起迁移。
「审核配置」在安装场景里的含义是:安装器展示给用户的不是原始包名列表,而是经过审核、有说明、可勾选的配置项——用户在选择「科学计算」或「开发工具」时,实际是在选择一组审核过的软件集合,而不是逐个判断每个包要不要装。这份数据同时被 Welcome 与 Shelly 的推荐链接读取,保证安装时看到的选择与装完后看到的一致。
catalog v3 是新的应用 / 组件 / 能力图,由四类实体构成:desktops(桌面环境)、applications(应用)、components(组件)、bundles(组合包)。它不只是「一份应用列表」,而是描述应用、组件与能力之间关系的结构化数据——一个应用属于哪个分类、依赖哪些组件、捆绑在哪个组合里,都在同一份图里表达。
审查覆盖三个维度:许可证(能否随 Linxira 分发)、来源(来自官方仓库还是第三方、是否可复现)、可用性(在当前架构与基线里是否真正可用)。审查通过的精选应用按 14 个分类组织,共 93 个;外部生态(AUR 等)默认关闭,必须由用户显式启用。对用户的直接体现是:软件生态 页面里的 93 个应用、应用 文档里的分类,背后都是同一份 v3 数据。
四类实体的分工值得展开:desktops 描述可选的桌面环境及其审核配置;applications 是最终用户看到的应用及其分类;components 是应用背后的能力包、运行时与工具链(它们不一定是「应用」,却是应用能否工作的前提);bundles 把应用与组件组合成面向场景的集合——比如「科学计算」捆绑可以一次带上它依赖的全部组件。分类树、组件依赖、场景捆绑,都在这一张图里表达,而不是散落在各处的硬编码。
catalog 只是元数据——它不安装任何东西。真正动系统的是后端,而 GUI 与后端的职责被严格分开:界面负责展示与规划,系统修改由受控后端以确定性事务执行。
这个原则在几个工具里各有体现:Shelly(安装后的图形软件管理器)只执行获准的软件包操作,不参与安装器事务——安装器的事务由 Calamares 与配套后端负责,两者互不交叉;Package Center(精选应用安装)把安装拆成 plan / confirm / apply 三步事务——先规划出将执行的包操作,用户确认后才应用;Component Manager(组件选择)用三态树(required / recommended / optional)表达选择,且仅安装、不支持卸载,把「规划」与「执行」的边界钉死。
底层支撑是 linxira-components 后端:目录绑定的 pacman 事务规划与 receipt 后端——确定性 plan、SHA-256 规范 JSON 摘要、root-only pacman、持久 receipt,通过 D-Bus 服务 org.linxira.Components1 暴露。GUI 永远不直接碰 pacman;它向后端提交规划,后端以确定性的方式执行并留下可审计的记录。
「确定性」在这里是具体的技术含义:同样的目录与同样的选择,永远规划出同样的事务,产出的摘要可复算、可比对。持久 receipt 意味着系统里留有「装了什么、按什么规划装的」的机器可读记录——不仅用户能查,后续的工具也能基于它做增量操作,而不是重新猜测系统状态。
plan / confirm / apply 三步事务对用户的实际感受值得直说:从 Package Center 安装时,界面先展示规划——将执行的精确包操作——然后请求确认,最后才应用。GUI 永远不会在后台还在决定时声称「我已经装好了」;任何东西碰到系统之前,用户一定先看到规划。这一个交互决策,就是整套只读/规划模型的可见面孔。
「审核目录」与「塞满 ISO」是两种相反的思路。塞满 ISO 的诱惑是直观的:预装得越多,「开箱即用」的感觉越强。但代价是实打实的:ISO 体积膨胀、维护面变大、每个预装软件的许可证与来源都要长期负责,而且用户卸载不掉的预装软件会变成负担。
审核目录的取舍是相反的:默认只装审核过的子集,其余软件按需通过目录安装;未审核的 AUR 配方不会被当作官方软件展示——它们可以存在、可以被用户显式启用,但不会出现在官方推荐里。结果是:官方软件列表始终是「我们审核过、能负责」的列表,而不是「互联网上所有能装的软件」的列表。
这个取舍让「官方软件」这个词重新有了意义。配置中心的更多细节见 配置中心 文档,catalog 的应用侧数据见 软件生态 与 应用。
为什么默认关闭外部生态而不是默认开放?因为「开放」的成本不是用户装了什么,而是用户信任了什么——默认开放的生态会稀释「官方推荐」的语义,让用户无法区分审核与未审核的来源。默认关闭 + 显式启用保留了选择的自由,同时保住了官方列表的语义纯净:需要 AUR 的用户一条命令即可打开,不需要的用户永远不会在推荐里看到未审核的配方。