news 2026/9/13 3:52:39

Bitwarden Server Seeder 数据密度验证:verification.md 的 Q0–Q11 SQL 查询与预设期望值详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Bitwarden Server Seeder 数据密度验证:verification.md 的 Q0–Q11 SQL 查询与预设期望值详解

Bitwarden Server Seeder 数据密度验证:verification.md 的 Q0–Q11 SQL 查询与预设期望值详解

【免费下载链接】serverBitwarden infrastructure/backend (API, database, Docker, etc).项目地址: https://gitcode.com/GitHub_Trending/ser/server

本文以 Bitwarden 开源仓库中util/Seeder/Seeds/docs/verification.md为主体,讲解如何用手写 SQL 查询(Q0–Q11)验证 Seeder 密度算法(density modeling)的输出是否符合预设(Scale 与 Validation 预设)的期望分布,并完整覆盖文档中 9 个 Scale 预设与 4 个 Validation 预设的逐项期望值。读完本文,你将能够:对任意一个dotnet run -- preset --name {name} --mangle生成的组织,独立跑通整套验证查询、对照期望值做 pass/fail 判定,并理解每条查询背后对应哪一条密度参数(membership.shapecollectionFanOutdirectAccessRatiocipherAssignment.*等)。

文档定位:谁来用、什么时候用

verification.md开头就明确了自己的读者画像:面向开发者(Developer-facing),用于在跑完某个 Scale 或 Validation 预设后,核对数据库中的实际分布与预设 JSON 中声明的密度参数是否一致,"正常 Seeder 用户无需关心"。文档推荐的两种使用方式:

  • 手动模式(Manual Usage):先执行 Q0 按组织名查出 Organization ID,再把该 ID 粘贴进其余查询。
  • 让 Claude Code 代跑:文档给出的标准三步——
    1. 播种预设:dotnet run -- preset --name scale.md-balanced-sterling-cooper --mangle
    2. 把 Seeder 输出(含 Org ID)贴给 Claude Code,并要求"对 Org ID {id} 执行 Q1–Q8,并与 verification.md 中 Sterling Cooper 的期望值对比";
    3. Claude Code 逐条执行查询、输出 pass/fail 表格并标记超差项。

文档特别指出:密度算法最初就是这样被验证的——Claude Code 跑完所有查询、对照期望值逐项判定,当场暴露出若干分布 bug 并在同一会话中被修复。因此这套查询同时充当了回归检查手册的角色。

验证查询全集(Q0–Q11)

所有查询都带NOLOCK提示、使用@OrgId UNIQUEIDENTIFIER变量,直接面向 SQL Server 的dboschema 表(OrganizationGroupGroupUserCollectionCollectionGroupCollectionUserCollectionCipherCipherOrganizationUser)。以下按文档顺序完整列出。

Q0:找到 Organization ID

SELECT Id, [Name] FROM [dbo].[Organization] WITH (NOLOCK) WHERE [Name] = 'PASTE_ORG_NAME_HERE';

拿到Id后,把下面所有查询里的PASTE_ORG_ID_HERE替换掉即可。

Q1:Group 成员分布

验证membership.shapemembership.skew。成员计数应体现 Uniform(大致均等)、PowerLaw(递减)或 MegaGroup(一个占绝对多数)三种形态之一:

DECLARE @OrgId UNIQUEIDENTIFIER = 'PASTE_ORG_ID_HERE'; SELECT G.[Name], COUNT(GU.OrganizationUserId) AS Members FROM [dbo].[Group] G WITH (NOLOCK) LEFT JOIN [dbo].[GroupUser] GU WITH (NOLOCK) ON G.Id = GU.GroupId WHERE G.OrganizationId = @OrgId GROUP BY G.[Name] ORDER BY Members DESC;

Q2:CollectionGroup 记录总数

验证collectionFanOut。总数应落在collections * mincollections * max之间:

DECLARE @OrgId UNIQUEIDENTIFIER = 'PASTE_ORG_ID_HERE'; SELECT COUNT(*) AS CollectionGroupCount FROM [dbo].[CollectionGroup] CG WITH (NOLOCK) INNER JOIN [dbo].[Collection] C WITH (NOLOCK) ON CG.CollectionId = C.Id WHERE C.OrganizationId = @OrgId;

Q3:权限分布

验证permissions权重;零权重权限必须产生零条记录。查询用UNION ALLCollectionUserCollectionGroup两个来源合并统计,ReadWrite 定义为三个标志位全 0:

DECLARE @OrgId UNIQUEIDENTIFIER = 'PASTE_ORG_ID_HERE'; SELECT 'CollectionUser' AS [Source], COUNT(*) AS Total, SUM(CASE WHEN CU.ReadOnly = 1 THEN 1 ELSE 0 END) AS ReadOnly, SUM(CASE WHEN CU.Manage = 1 THEN 1 ELSE 0 END) AS Manage, SUM(CASE WHEN CU.HidePasswords = 1 THEN 1 ELSE 0 END) AS HidePasswords, SUM(CASE WHEN CU.ReadOnly = 0 AND CU.Manage = 0 AND CU.HidePasswords = 0 THEN 1 ELSE 0 END) AS ReadWrite FROM [dbo].[CollectionUser] CU WITH (NOLOCK) INNER JOIN [dbo].[OrganizationUser] OU WITH (NOLOCK) ON CU.OrganizationUserId = OU.Id WHERE OU.OrganizationId = @OrgId UNION ALL SELECT 'CollectionGroup', COUNT(*), SUM(CASE WHEN CG.ReadOnly = 1 THEN 1 ELSE 0 END), SUM(CASE WHEN CG.Manage = 1 THEN 1 ELSE 0 END), SUM(CASE WHEN CG.HidePasswords = 1 THEN 1 ELSE 0 END), SUM(CASE WHEN CG.ReadOnly = 0 AND CG.Manage = 0 AND CG.HidePasswords = 0 THEN 1 ELSE 0 END) FROM [dbo].[CollectionGroup] CG WITH (NOLOCK) INNER JOIN [dbo].[Collection] C WITH (NOLOCK) ON CG.CollectionId = C.Id WHERE C.OrganizationId = @OrgId;

Q4:孤儿 Cipher(Orphan Ciphers)

验证cipherAssignment.orphanRate。孤儿指没有任何CollectionCipher分配的 cipher:

DECLARE @OrgId UNIQUEIDENTIFIER = 'PASTE_ORG_ID_HERE'; SELECT COUNT(*) AS TotalCiphers, SUM(CASE WHEN CC.CipherId IS NULL THEN 1 ELSE 0 END) AS Orphans FROM [dbo].[Cipher] CI WITH (NOLOCK) LEFT JOIN (SELECT DISTINCT CipherId FROM [dbo].[CollectionCipher] WITH (NOLOCK)) CC ON CI.Id = CC.CipherId WHERE CI.OrganizationId = @OrgId;

Q5:Direct Access 比例

验证directAccessRatio。文档强调计算式为int(userCount * directAccessRatio) / userCount,因此小组织会出现截断误差;注意总用户数只统计[Status] = 2(Confirmed):

DECLARE @OrgId UNIQUEIDENTIFIER = 'PASTE_ORG_ID_HERE'; SELECT TotalOrgUsers, UsersWithDirectAccess, CAST(UsersWithDirectAccess AS FLOAT) / NULLIF(TotalOrgUsers, 0) AS DirectAccessRatio FROM ( SELECT (SELECT COUNT(*) FROM [dbo].[OrganizationUser] WITH (NOLOCK) WHERE OrganizationId = @OrgId AND [Status] = 2) AS TotalOrgUsers, (SELECT COUNT(DISTINCT CU.OrganizationUserId) FROM [dbo].[CollectionUser] CU WITH (NOLOCK) INNER JOIN [dbo].[OrganizationUser] OU WITH (NOLOCK) ON CU.OrganizationUserId = OU.Id WHERE OU.OrganizationId = @OrgId) AS UsersWithDirectAccess ) T;

Q6:Cipher 分布形态

验证cipherAssignment.skew。变异系数 CV 接近 0 表示 uniform,CV 偏高表示 heavyRight:

DECLARE @OrgId UNIQUEIDENTIFIER = 'PASTE_ORG_ID_HERE'; SELECT COUNT(*) AS Collections, MIN(CipherCount) AS MinCiphers, MAX(CipherCount) AS MaxCiphers, AVG(CipherCount) AS AvgCiphers, CASE WHEN AVG(CipherCount) > 0 THEN STDEV(CipherCount) / AVG(CipherCount) ELSE 0 END AS CoefficientOfVariation FROM ( SELECT C.Id, COUNT(CC.CipherId) AS CipherCount FROM [dbo].[Collection] C WITH (NOLOCK) LEFT JOIN [dbo].[CollectionCipher] CC WITH (NOLOCK) ON C.Id = CC.CollectionId WHERE C.OrganizationId = @OrgId GROUP BY C.Id ) T;

Q7:每用户 Collection 数分布

验证userCollections。CV 接近 0 = uniform,CV > 0.5 = power-law:

DECLARE @OrgId UNIQUEIDENTIFIER = 'PASTE_ORG_ID_HERE'; SELECT COUNT(*) AS UsersWithDirectAccess, MIN(CollectionCount) AS MinCollections, MAX(CollectionCount) AS MaxCollections, AVG(CollectionCount) AS AvgCollections, CASE WHEN AVG(CollectionCount) > 0 THEN STDEV(CollectionCount) / AVG(CollectionCount) ELSE 0 END AS CoefficientOfVariation FROM ( SELECT CU.OrganizationUserId, COUNT(DISTINCT CU.CollectionId) AS CollectionCount FROM [dbo].[CollectionUser] CU WITH (NOLOCK) INNER JOIN [dbo].[OrganizationUser] OU WITH (NOLOCK) ON CU.OrganizationUserId = OU.Id WHERE OU.OrganizationId = @OrgId GROUP BY CU.OrganizationUserId ) T;

Q8:多 Collection Cipher 比例

验证cipherAssignment.multiCollectionRate,比例应近似配置值:

DECLARE @OrgId UNIQUEIDENTIFIER = 'PASTE_ORG_ID_HERE'; SELECT COUNT(*) AS TotalAssignedCiphers, SUM(CASE WHEN CollectionCount > 1 THEN 1 ELSE 0 END) AS MultiCollectionCiphers, MAX(CollectionCount) AS MaxCollectionsPerCipher FROM ( SELECT CC.CipherId, COUNT(DISTINCT CC.CollectionId) AS CollectionCount FROM [dbo].[CollectionCipher] CC WITH (NOLOCK) INNER JOIN [dbo].[Cipher] CI WITH (NOLOCK) ON CC.CipherId = CI.Id WHERE CI.OrganizationId = @OrgId GROUP BY CC.CipherId ) T;

Q9:已删除的组织 Cipher

验证cipherAssignment.deletedRatemaxDeletedCiphers,适用于所有 Scale 预设的组织 cipher:

DECLARE @OrgId UNIQUEIDENTIFIER = 'PASTE_ORG_ID_HERE'; SELECT COUNT(*) AS TotalOrgCiphers, SUM(CASE WHEN DeletedDate IS NOT NULL THEN 1 ELSE 0 END) AS DeletedCiphers FROM [dbo].[Cipher] WITH (NOLOCK) WHERE OrganizationId = @OrgId;

Q10:个人池中的 Archived/Deleted Cipher

验证cipherAssignment.archivedRatedeletedRatearchivedAndDeletedOverlapRate,但对象是个人(非组织)cipher 池——仅适用于配置了density.personalCiphers的预设(Sterling Cooper、Wayne Enterprises、Weyland-Yutani)。由于个人 cipher 不挂OrganizationId,查询通过OrganizationUser限定到被播种组织的用户;归档判定复用dbo.CipherDetails中计算ArchivedDate的同款 JSON 路径模式(Archives列中按大写 UserId 取值):

DECLARE @OrgId UNIQUEIDENTIFIER = 'PASTE_ORG_ID_HERE'; SELECT COUNT(*) AS TotalPersonalCiphers, SUM(CASE WHEN JSON_VALUE(C.[Archives], CONCAT('$."', UPPER(CONVERT(VARCHAR(36), C.UserId)), '"')) IS NOT NULL THEN 1 ELSE 0 END) AS ArchivedCiphers, SUM(CASE WHEN C.DeletedDate IS NOT NULL THEN 1 ELSE 0 END) AS DeletedCiphers, SUM(CASE WHEN C.DeletedDate IS NOT NULL AND JSON_VALUE(C.[Archives], CONCAT('$."', UPPER(CONVERT(VARCHAR(36), C.UserId)), '"')) IS NOT NULL THEN 1 ELSE 0 END) AS BothArchivedAndDeleted FROM [dbo].[Cipher] C WITH (NOLOCK) WHERE C.OrganizationId IS NULL AND C.UserId IN ( SELECT OU.UserId FROM [dbo].[OrganizationUser] OU WITH (NOLOCK) WHERE OU.OrganizationId = @OrgId );

Q11:组织池中的 Archived/Deleted Cipher

同样验证三个 rate,但对象是组织 cipher,适用于每个Scale 预设。文档解释:组织 cipher 的归档是"独立"于个人池的,且归档对象是轮询(round-robin)选出的某位组织成员(见GenerateCiphersStep),因此只需检查Archives列是否非空,无需像 Q10 那样限定到具体用户:

DECLARE @OrgId UNIQUEIDENTIFIER = 'PASTE_ORG_ID_HERE'; SELECT COUNT(*) AS TotalOrgCiphers, SUM(CASE WHEN Archives IS NOT NULL THEN 1 ELSE 0 END) AS ArchivedCiphers, SUM(CASE WHEN DeletedDate IS NOT NULL THEN 1 ELSE 0 END) AS DeletedCiphers, SUM(CASE WHEN DeletedDate IS NOT NULL AND Archives IS NOT NULL THEN 1 ELSE 0 END) AS BothArchivedAndDeleted FROM [dbo].[Cipher] WITH (NOLOCK) WHERE OrganizationId = @OrgId;

源码侧印证:期望值从哪里来

文档中的每个"Check"都对应预设 JSON 里density块的一个参数。以 Sterling Cooper 预设 为例,其density块是:

"density": { "membership": { "shape": "powerLaw", "skew": 0.6 }, "collectionFanOut": { "min": 1, "max": 5, "shape": "powerLaw", "emptyGroupRate": 0.1 }, "directAccessRatio": 0.5, "permissions": { "readOnly": 0.55, "readWrite": 0.20, "manage": 0.15, "hidePasswords": 0.10 }, "cipherAssignment": { "skew": "heavyRight", "orphanRate": 0.08, "multiCollectionRate": 0.20, "maxCollectionsPerCipher": 3, "deletedRate": 0.03, "archivedRate": 0.06, "archivedAndDeletedOverlapRate": 0.02 }, "userCollections": { "min": 1, "max": 10, "shape": "powerLaw", "skew": 0.5 }, "personalCiphers": { "shape": "realistic" } }

与 verification.md 中 Sterling Cooper 的期望值表逐行对应:PowerLaw(skew 0.6) 的 50 组 → Q1;fan-out 1–5 × 500 个 collection → Q2 的 500–2,500 区间;directAccessRatio 0.5→ Q5;四档权限权重 → Q3;orphanRate 0.08× 5,000 → Q4 的约 400 条孤儿;archivedRate 0.06(=300)被钳制到上限 50 → Q11 的 50 条归档。再看 Initech 预设:directAccessRatio: 1.0解释了为什么该预设 Q2 期望 0 条 CollectionGroup("DirectAccessRatio 是 1.0,CollectionGroup 生成被整体跳过"),orphanRate: 0.85解释了 Q4 期望 85% 孤儿。

从源码结构看,这些参数由util/Seeder/Steps/下的步骤消费:CreateGroupsStep(成员分布)、CreateCollectionsStep(fan-out)、CreateCipherCollectionsStepGenerateCiphersStep(cipher 分配、归档/删除,Q11 注释即指向GenerateCiphersStep)。参数与实现的映射关系是文档中每条期望值"可复算"的根本原因——这也是 Q0–Q11 能充当回归检查的前提。

Scale 预设期望值(9 个预设全量)

以下完整继承 verification.md 的期望值表。判定标准:与预设 JSON 的density参数对照,容差内视为 pass。

1. Central Perk(XS)

CheckExpected
Membership shapeUniform — 2 组,每组约 3 人。
CollectionGroups10–20 条记录。每 collection 1–2 组的 uniform fan-out。
Permissions约 50% Manage、40% ReadWrite、10% ReadOnly、0% HidePasswords。
Orphan ciphers0 / 200(0% 孤儿率)。
Direct access ratio0.8 —— 约 80% 的访问路径是直接 CollectionUser。
Collections per userUniform 1–3。Min=1,Max=3,Avg=2。
Multi-collection rate200 个非孤儿 cipher 中 20% 位于 2 个 collection,约 40 条。
Archived org ciphers约 8 / 200(4% 率,低于 50 上限)。
Deleted org ciphers约 4 / 200(2% 率,低于 25 上限);其中约 2 条同时归档(1% 重叠),约 2 条仅删除。

2. Planet Express(SM)

CheckExpected
Membership shapePowerLaw(skew 0.4) —— 首组最大,8 组间温和递减。
CollectionGroups200–400 条。每 collection 2–4 组的 uniform fan-out。
Permissions约 40% ReadOnly、30% ReadWrite、25% Manage、5% HidePasswords。
Orphan ciphers约 37 / 750(5%)。
Direct access ratio0.7。
Collections per userPowerLaw 1–5(skew 0.3)。首用户最多 5 个,多数 1–2。CV > 0.3。
Multi-collection rate约 713 个非孤儿 cipher 中 15% 位于 2 个 collection,约 107 条。
Archived org ciphers约 45 / 750(6%)。
Deleted org ciphers约 22 / 750(3%);约 15 条同时归档(2% 重叠),约 7 条仅删除。

3. Bluth Company(SM)

CheckExpected
Membership shapePowerLaw(skew 0.7) —— 4 组间陡降,首组占绝对多数。
CollectionGroups25–125 条。每 collection 1–5 组的 PowerLaw fan-out。
Permissions约 82% ReadOnly、9% ReadWrite、5% Manage、4% HidePasswords。
Orphan ciphers约 75 / 500(15%)。
Direct access ratio0.6。
Collections per userUniform 1–3。Min=1,Max=3,Avg=2。
Multi-collection rate约 425 个非孤儿 cipher 中 10%,约 42 条。
Archived org ciphers约 40 / 500(8%)。
Deleted org ciphers约 20 / 500(4%);约 15 条同时归档(3% 重叠),约 5 条仅删除。

4. Sterling Cooper(MD)

CheckExpected
Membership shapePowerLaw(skew 0.6) —— 50 组间中度递减。
CollectionGroups500–2,500 条。每 collection 1–5 个活跃组的 PowerLaw fan-out。
Permissions约 55% ReadOnly、20% ReadWrite、15% Manage、10% HidePasswords。
Orphan ciphers约 400 / 5,000(8%)。
Direct access ratio0.5 —— 直接访问与组中介访问大致各半。
Empty group rate约 26% —— 50 组中约 13 组因幂律尾部截断而 0 成员。
Collections per userPowerLaw 1–10(skew 0.5)。首用户最多 10 个,多数 1–2。CV > 0.5。
Multi-collection rate约 4,600 个非孤儿 cipher 中 20% 位于 2–3 个 collection,单 cipher 最多 3 个。
Archived org ciphers50 / 5,000(6% = 300,钳制到 50 上限)。
Deleted org ciphers25 / 5,000(3% = 150,钳制到 25 上限)。25 条全部同时归档(2% 重叠 = 100,钳制后)——0 条仅删除。
Archived personal ciphers约 3,638 个个人 cipher 中的 50 个(6% = 约 218,钳制到 50)。
Deleted personal ciphers约 3,638 中的 25 个(3% 钳制到 25)。25 条全部同时归档(2% 重叠 = 约 73,钳制到min(archivedTarget, maxDeletedCiphers)= 25)——0 条仅删除。该钳制可对照ArchiveAndDeleteRateTests.BothTarget_NeverExceedsMaxDeletedCiphers_EvenWhenArchivedCeilingIsHigher单测。Sterling Cooper 的归档/删除项同时落在组织池与个人池,因为archivedRate/deletedRate/archivedAndDeletedOverlapRate对两个池分别独立生效。

5. Umbrella Corp(MD)

CheckExpected
Membership shapeMegaGroup(skew 0.5) —— 组 1 约 72% 成员,其余 7 组平分剩余。
CollectionGroups800–2,400 条。每 collection 1–3 组的 FrontLoaded fan-out。
Permissions约 50% ReadWrite、20% Manage、20% ReadOnly、10% HidePasswords。
Orphan ciphers约 600 / 3,000(20%)。
Direct access ratio0.9。
Collections per userPowerLaw 1–15(skew 0.6)。CV > 0.5。
Multi-collection rate约 2,400 个非孤儿 cipher 中 25% 位于 2–3 个 collection,单 cipher 最多 3 个。
Archived org ciphers50 / 3,000(8% = 240,钳制到 50)。
Deleted org ciphers25 / 3,000(4% = 120,钳制到 25)。25 条全部同时归档(3% 重叠 = 90,钳制后)——0 条仅删除。

6. Wayne Enterprises(LG)

CheckExpected
Membership shapePowerLaw(skew 0.7) —— 100 组间陡降,首几组明显更大。
CollectionGroups2,000–10,000 条。每 collection 1–5 个活跃组的 PowerLaw fan-out。
Permissions约 82% ReadOnly、9% ReadWrite、5% Manage、4% HidePasswords。
Orphan ciphers约 1,000 / 10,000(10%)。
Direct access ratio0.5。
Empty group rate约 30% —— 100 组中约 30 组 0 成员(幂律尾部截断)。
Collections per userPowerLaw 1–25(skew 0.6)。CV > 0.5。
Multi-collection rate约 9,000 个非孤儿 cipher 中 25% 位于 2–4 个 collection,单 cipher 最多 4 个。
Archived org ciphers50 / 10,000(6% = 600,钳制到 50)。
Deleted org ciphers25 / 10,000(3% = 300,钳制到 25)。25 条全部同时归档(2% 重叠 = 200,钳制后)——0 条仅删除。
Archived personal ciphers约 14,525 个个人 cipher 中的 50 个(6% = 约 872,钳制到 50)。
Deleted personal ciphers约 14,525 中的 25 个(3% 钳制到 25)。25 条全部同时归档(2% 重叠,钳制方式同 Sterling Cooper)——0 条仅删除。Wayne Enterprises 的组织池与个人池都播种归档/删除项。

7. Tyrell Corp(LG)

CheckExpected
Membership shapePowerLaw(skew 0.8) —— 75 组间极陡递减,首组非常大。
CollectionGroups4,600–18,400 条。每 collection 2–8 个活跃组的 PowerLaw fan-out。
Permissions约 82% ReadOnly、9% ReadWrite、5% Manage、4% HidePasswords。
Orphan ciphers约 2,550 / 17,000(15%)。
Direct access ratio0.6。
Empty group rate20% —— 75 组中约 15 组 0 成员。
Collections per userPowerLaw 1–30(skew 0.7)。CV > 0.5。
Multi-collection rate约 14,450 个非孤儿 cipher 中 30% 位于 2–4 个 collection,单 cipher 最多 4 个。
Archived org ciphers50 / 17,000(8% = 1,360,钳制到 50)。
Deleted org ciphers25 / 17,000(4% = 680,钳制到 25)。25 条全部同时归档(3% 重叠 = 510,钳制后)——0 条仅删除。

8. Weyland-Yutani(XL)

CheckExpected
Membership shapePowerLaw(skew 0.8) —— 500 组间极陡递减,长尾小群体。
CollectionGroups1,200–3,600 条。每 collection 1–3 个活跃组的 PowerLaw fan-out。
Permissions约 55% ReadWrite、25% ReadOnly、10% Manage、10% HidePasswords。
Orphan ciphers约 1,500 / 15,000(10%)。
Direct access ratio0.4 —— 多数访问经组中介。
Empty group rate约 68% —— 500 组中约 341 组 0 成员(幂律尾部截断)。
Collections per userPowerLaw 1–50(skew 0.8)。CV > 0.5。
Multi-collection rate约 13,500 个非孤儿 cipher 中 30% 位于 2–5 个 collection,单 cipher 最多 5 个。
Archived org ciphers50 / 15,000(4% = 600,钳制到 50)。
Deleted org ciphers25 / 15,000(3% = 450,钳制到 25)。25 条全部同时归档(1% 重叠 = 150,钳制后)——0 条仅删除。
Archived personal ciphers约 11,000 个个人 cipher 中的 50 个(4% = 440,钳制到 50)。
Deleted personal ciphers约 11,000 中的 25 个(3% 钳制到 25)。25 条全部同时归档(1% 重叠 = 110,同式钳制)——0 条仅删除。Weyland-Yutani 同样在组织池与个人池双池播种归档/删除项。

9. Initech(XL)

CheckExpected
Membership shapeMegaGroup(skew 0.95) —— 组 1 约 93% 成员,其余 4 组平分剩余。
CollectionGroups0 条记录。DirectAccessRatio 是 1.0,CollectionGroup 生成被整体跳过。
Permissions约 30% Manage、30% ReadWrite、30% ReadOnly、10% HidePasswords。
Orphan ciphers约 12,750 / 15,000(85%)。
Direct access ratio1.0 —— 100% 直接 CollectionUser 访问。
Collections per userPowerLaw 1–20(skew 0.5)。首用户最多 20 个,多数 1 个。CV > 0.2。
Multi-collection rate约 2,250 个非孤儿 cipher 中 15% 位于 2–3 个 collection,单 cipher 最多 3 个。
Archived org ciphers50 / 15,000(8% = 1,200,钳制到 50)。
Deleted org ciphers25 / 15,000(5% = 750,钳制到 25)。25 条全部同时归档(3% 重叠 = 450,钳制后)——0 条仅删除。

Validation 预设期望值(4 个预设全量)

Validation 预设用于 Seeder 开发阶段的算法验证(非通用用途),逐个跑--mangle后对照下表的"Check/Expected"判定。

1. Power-Law Distribution

dotnet run -- preset --name validation.density-modeling-power-law-test --mangle
CheckExpected
Groups10 组。首组约 50 人,递减到 1;最后 2 组 0 成员(20% 空组率)。
CollectionGroups> 0 条。靠前 collection 分到的组更多(PowerLaw fan-out)。
Permissions约 50% ReadOnly、30% ReadWrite、15% Manage、5% HidePasswords。
Orphan ciphers约 50 / 500(10%)。
DirectAccessRatio0.6。

2. MegaGroup Distribution

dotnet run -- preset --name validation.density-modeling-mega-group-test --mangle
CheckExpected
Groups5 组。组 1 约 90 人(90.5%);组 2–5 平分约 10 人。
CollectionUsers0 条。DirectAccessRatio 为 0.0 —— 全部访问经组。
CollectionGroups> 0。前 10 个 collection 各得 3 组(FrontLoaded),其余各 1 组。
PermissionsReadOnly / ReadWrite / Manage / HidePasswords 各 25%(均匀切分)。

3. Empty Groups

dotnet run -- preset --name validation.density-modeling-empty-groups-test --mangle
CheckExpected
Groups共 10 组:5 组各约 10 人,5 组 0 人(50% 空组)。
CollectionGroups只引用那 5 个非空组。
DirectAccessRatio0.5 —— 约一半用户获得直接 CollectionUser 记录。

4. No Density(Baseline,基线)

dotnet run -- preset --name validation.density-modeling-no-density-test --mangle
CheckExpected
Groups5 组,每组约 10 人(uniform round-robin)。
CollectionGroups0 条。无 density = 不生成 CollectionGroup。
Permissions每用户首次分配为 Manage,之后为 ReadOnly(原始轮转模式)。
Orphan ciphers0。每个 cipher 至少分配进一个 collection。

延伸阅读路径

  • 预设目录与各预设组成(org + roster + ciphers 的装配方式):presets.md,其中 Scale 表列出了 9 个预设的 Users/Groups/Collections/Ciphers 规模,与本文期望值表相互印证;
  • 密度参数 JSON Schema(字段取值范围的权威定义):util/Seeder/Seeds/schemas/preset.schema.json(在 presets.md 中被声明为 source of truth);
  • Fixture 与 Preset 的分层架构:architecture.md;
  • Seeder 使用入口与 Quick Start:util/Seeder/Seeds/README.md 与 util/Seeder/README.md。

适用前提:本文所有查询面向 SQL Server 的dboschema 与NOLOCK语义,验证对象为通过dotnet run -- preset --name {name} --mangle播种的 Bitwarden Seeder 数据;--mangle会改写组织名以避免与既有数据冲突,因此 Q0 应按 Seeder 实际打印的组织名检索。

【免费下载链接】serverBitwarden infrastructure/backend (API, database, Docker, etc).项目地址: https://gitcode.com/GitHub_Trending/ser/server

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 3:46:07

lo 库 Fill 函数深度解析:基于 Go 1.18+ 泛型的切片克隆填充

lo 库 Fill 函数深度解析:基于 Go 1.18 泛型的切片克隆填充 【免费下载链接】lo 💥 A Lodash-style Go library based on Go 1.18 Generics (map, filter, contains, find...) 项目地址: https://gitcode.com/GitHub_Trending/lo/lo Fill 是 lo 库…

作者头像 李华
网站建设 2026/9/13 3:45:02

如何为 p5.js 新方法添加参数校验的友好错误消息?

如何为 p5.js 新方法添加参数校验的友好错误消息? 【免费下载链接】p5.js p5.js is a client-side JS platform that empowers artists, designers, students, and anyone to learn to code and express themselves creatively on the web. It is based on the core…

作者头像 李华
网站建设 2026/9/13 3:45:00

Web教师成果管理系统开发:Vue+SpringBoot实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 3:43:58

Android面试能力解码:基础穿透力与场景决策力实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 3:43:42

树莓派Pico呼吸灯:MicroPython硬件PWM与伽马校正实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华