1
0
mirror of https://github.com/bitwarden/server synced 2026-02-25 08:53:21 +00:00

Seeder simplifying and extending seeds (#7065)

This commit is contained in:
Mick Letofsky
2026-02-24 18:28:49 +01:00
committed by GitHub
parent 39f51974f6
commit 0d8b920550
36 changed files with 1588 additions and 367 deletions

View File

@@ -4,28 +4,35 @@ Hand-crafted JSON fixtures for Bitwarden Seeder test data.
## Quick Start
1. Copy template from `templates/` to appropriate `fixtures/` subfolder
2. Edit JSON (your editor validates against `$schema` automatically)
1. Create a JSON file in the right `fixtures/` subfolder
2. Add the `$schema` line — your editor picks up validation automatically
3. Build to verify: `dotnet build util/Seeder/Seeder.csproj`
## File Structure
## Writing Fixtures
```
Seeds/
├── fixtures/ Your seed data goes here
│ ├── ciphers/ Vault items
│ ├── organizations/ Organization definitions
│ ├── rosters/ Users, groups, collections, permissions
│ └── presets/ Complete seeding scenarios
├── schemas/ JSON Schema validation (auto-checked by editors)
├── templates/ Starter files - copy these
└── README.md This file
```
### Organizations
## Fixtures Overview
Just a name and domain. That's it.
Domains must use `.example` (RFC 2606 — guaranteed unresolvable, safe for QA email pipelines).
Plan type and seats are defined in presets, not here.
See: `fixtures/organizations/redwood-analytics.json`
### Rosters
Users, groups, and collections for an org.
- Users have a `firstName`, `lastName`, and `role` (`owner`, `admin`, `user`, `custom`)
- The Seeder pipeline builds emails as `firstName.lastName@domain`, so `"Family"` + `"Mom"` at domain `acme.example` becomes `family.mom@acme.example` or `a1b2c3d4+family.mom@acme.example` with mangling on
- Groups reference users by that same email prefix (e.g. `"family.mom"`)
- Collections assign permissions to groups or individual users (`readOnly`, `hidePasswords`, `manage` — all default false)
See: `starter-team.json` (minimal), `family.json` (groups + collections), `dunder-mifflin.json` (58-user enterprise)
### Ciphers
Vault items. Each item needs a `type` and `name`.
| Type | Required Object | Description |
| ------------ | --------------- | -------------------------- |
| `login` | `login` | Website credentials + URIs |
@@ -34,77 +41,56 @@ Seeds/
| `secureNote` | — | Uses `notes` field only |
| `sshKey` | `sshKey` | SSH key credentials |
**Schema**: `schemas/cipher.schema.json`
### Organizations
Organization identity definitions with name and domain. Plan type and seats are defined in presets, not org fixtures.
**Required fields**: `name`, `domain`
**Schema**: `schemas/organization.schema.json`
### Rosters
Complete user/group/collection structures with permissions. User emails auto-generated as `firstName.lastName@domain`.
**User roles**: `owner`, `admin`, `user`, `custom`
**Collection permissions**: `readOnly`, `hidePasswords`, `manage`
**Schema**: `schemas/roster.schema.json`
**Example**: See `fixtures/rosters/dunder-mifflin.json` for a complete 58-user example
See: `fixtures/ciphers/enterprise-basic.json`
### Presets
Combine organization, roster, and ciphers into complete scenarios. Presets can reference fixtures, generate data programmatically, or mix both approaches.
Presets **wire everything together**: org + roster + ciphers. You can reference fixtures by name or generate data with counts.
**Key features**:
Three styles:
- Reference existing fixtures by name
- Generate users, groups, collections, and ciphers with count parameters
- Add personal ciphers (user-owned, encrypted with user key, not in collections)
- Mix fixture references and generated data
- **Fixture-based**: `enterprise-basic.json` — references org, roster, and cipher fixtures
- **Generated**: `wonka-teams-small.json` — uses `count` parameters to create users, groups, collections, ciphers
- **Feature-specific**: `tde-enterprise.json`, `policy-enterprise.json` — adds SSO config, policies
**Schema**: `schemas/preset.schema.json`
**Examples**: See `fixtures/presets/` for complete examples including fixture-based, generated, and hybrid approaches
Presets can also define inline orgs (name + domain right in the preset) instead of referencing a fixture — see `large-enterprise.json`.
## Naming Conventions
| Element | Pattern | Example |
| ----------- | ------------------ | --------------------- |
| File names | kebab-case | `banking-logins.json` |
| Item names | Title case, unique | `Chase Bank Login` |
| User refs | firstName.lastName | `jane.doe` |
| Org domains | .example | `acme.example` |
## Validation
Modern editors validate against `$schema` automatically - errors appear as red squiggles.
Build errors catch schema violations:
Your editor validates against `$schema` automatically errors show up as red squiggles. Build also catches schema violations:
```bash
dotnet build util/Seeder/Seeder.csproj
```
## Naming Conventions
| Element | Pattern | Example |
| ----------- | ------------------ | ------------------------ |
| File names | kebab-case | `banking-logins.json` |
| Item names | Title case, unique | `Chase Bank Login` |
| User refs | firstName.lastName | `jane.doe` |
| Org domains | Realistic or .test | `acme.com`, `test.local` |
## QA Test Fixture Migration Matrix
These Seeds consolidate test data previously found across the `bitwarden/test` repo.
The table below maps existing QA fixtures to their Seeder equivalents.
| QA Source (`test/Bitwarden.Web.Tests/TestData/SetupData/`) | Used By | Seeder Preset | Org Fixture | Roster Fixture | Cipher Fixture |
| ---------------------------------------------------------- | --------------------------------- | ----------------------------------- | --------------------------- | ------------------------ | ------------------------ |
| `CollectionPermissionsOrg.json` | Web, Extension | `collection-permissions-enterprise` | `qa-collection-permissions` | `collection-permissions` | `collection-permissions` |
| `EnterpriseOrg.json` | Web, Extension, Android, iOS, CLI | `enterprise-basic` | `qa-enterprise` | `enterprise-basic` | `enterprise-basic` |
| `SsoOrg.json` | Web | `sso-enterprise` | `qa-sso-org` | `sso-basic` | `sso-vault` |
| `TDEOrg.json` | Web, Extension, Android, iOS | `tde-enterprise` | `qa-tde-org` | `tde-basic` | `tde-vault` |
| _(Confluence: Policy Org guide)_ | QA manual setup | `policy-enterprise` | `qa-policy-org` | `policy-org` | — |
| QA Source (`test/Bitwarden.Web.Tests/TestData/SetupData/`) | Used By | Seeder Preset | Org Fixture | Roster Fixture | Cipher Fixture |
| ---------------------------------------------------------- | --------------------------------- | ----------------------------------- | ------------------- | ------------------------ | ------------------------ |
| `CollectionPermissionsOrg.json` | Web, Extension | `collection-permissions-enterprise` | `cobalt-logistics` | `collection-permissions` | `collection-permissions` |
| `EnterpriseOrg.json` | Web, Extension, Android, iOS, CLI | `enterprise-basic` | `redwood-analytics` | `enterprise-basic` | `enterprise-basic` |
| `SsoOrg.json` | Web | `sso-enterprise` | `verdant-health` | `starter-team` | `sso-vault` |
| `TDEOrg.json` | Web, Extension, Android, iOS | `tde-enterprise` | `obsidian-labs` | `starter-team` | `tde-vault` |
| _(Confluence: Policy Org guide)_ | QA manual setup | `policy-enterprise` | `pinnacle-designs` | `starter-team` | — |
| `FamiliesOrg.json` | Web, Extension | `families-basic` | `adams-family` | `family` | — |
### Not Yet Migrated
| QA Source | Used By | Status |
| --------------------- | ---------------------------- | --------------------------------------------------------------------- |
| `FreeAccount.json` | All 7 platforms | Planned — `free-personal-vault` preset (separate PR due to file size) |
| `FamiliesOrg.json` | Web, Extension | Planned — `families-basic` preset |
| `PremiumAccount.json` | Web, Extension, Android, iOS | Planned — `premium-personal-vault` preset |
| `SecretsManager.json` | Web | Planned — `secrets-manager-enterprise` preset |
| `FreeOrg.json` | Web | Planned — `free-org-basic` preset |

View File

@@ -1,5 +1,5 @@
{
"$schema": "../../schemas/organization.schema.json",
"name": "TDE QA Org",
"domain": "qa-tde.test"
"name": "Adams Family",
"domain": "adams.example"
}

View File

@@ -0,0 +1,5 @@
{
"$schema": "../../schemas/organization.schema.json",
"name": "Cobalt Logistics",
"domain": "cobalt.example"
}

View File

@@ -1,5 +1,5 @@
{
"$schema": "../../schemas/organization.schema.json",
"name": "Dunder Mifflin",
"domain": "dundermifflin.com"
"domain": "dundermifflin.example"
}

View File

@@ -1,5 +1,5 @@
{
"$schema": "../../schemas/organization.schema.json",
"name": "Maple & Pine Trading Co",
"domain": "maplepine.com"
"domain": "maplepine.example"
}

View File

@@ -1,5 +1,5 @@
{
"$schema": "../../schemas/organization.schema.json",
"name": "SSO QA Org",
"domain": "qa-sso.test"
"name": "Obsidian Labs",
"domain": "obsidian.example"
}

View File

@@ -0,0 +1,5 @@
{
"$schema": "../../schemas/organization.schema.json",
"name": "Pinnacle Designs",
"domain": "pinnacle.example"
}

View File

@@ -1,5 +0,0 @@
{
"$schema": "../../schemas/organization.schema.json",
"name": "Collection Permissions QA Org",
"domain": "qa-collperms.test"
}

View File

@@ -1,5 +0,0 @@
{
"$schema": "../../schemas/organization.schema.json",
"name": "Enterprise QA Org",
"domain": "qa-enterprise.test"
}

View File

@@ -1,5 +0,0 @@
{
"$schema": "../../schemas/organization.schema.json",
"name": "Policy Testing Org",
"domain": "qa-policy.test"
}

View File

@@ -0,0 +1,5 @@
{
"$schema": "../../schemas/organization.schema.json",
"name": "Redwood Analytics",
"domain": "redwood.example"
}

View File

@@ -1,5 +1,5 @@
{
"$schema": "../../schemas/organization.schema.json",
"name": "Stark Industries",
"domain": "stark.dev"
"domain": "stark.example"
}

View File

@@ -0,0 +1,5 @@
{
"$schema": "../../schemas/organization.schema.json",
"name": "Verdant Health",
"domain": "verdant.example"
}

View File

@@ -1,5 +1,5 @@
{
"$schema": "../../schemas/organization.schema.json",
"name": "Wonka Confections",
"domain": "wonka.co"
"domain": "wonka.example"
}

View File

@@ -0,0 +1,5 @@
{
"$schema": "../../schemas/organization.schema.json",
"name": "Zero Knowledge Labs",
"domain": "zero-knowledge.example"
}

View File

@@ -1,7 +1,7 @@
{
"$schema": "../../schemas/preset.schema.json",
"organization": {
"fixture": "qa-collection-permissions",
"fixture": "cobalt-logistics",
"planType": "enterprise-annually",
"seats": 10
},

View File

@@ -1,7 +1,7 @@
{
"$schema": "../../schemas/preset.schema.json",
"organization": {
"fixture": "qa-enterprise",
"fixture": "redwood-analytics",
"planType": "enterprise-annually",
"seats": 10
},

View File

@@ -0,0 +1,19 @@
{
"$schema": "../../schemas/preset.schema.json",
"organization": {
"fixture": "adams-family",
"planType": "families-annually",
"seats": 6
},
"roster": {
"fixture": "family"
},
"folders": true,
"ciphers": {
"count": 150,
"assignFolders": true
},
"personalCiphers": {
"countPerUser": 65
}
}

View File

@@ -2,7 +2,7 @@
"$schema": "../../schemas/preset.schema.json",
"organization": {
"name": "Globex Corp",
"domain": "globex.com",
"domain": "globex.example",
"seats": 10000
},
"users": {

View File

@@ -1,11 +1,11 @@
{
"$schema": "../../schemas/preset.schema.json",
"organization": {
"fixture": "qa-policy-org",
"fixture": "pinnacle-designs",
"planType": "enterprise-annually"
},
"roster": {
"fixture": "policy-org"
"fixture": "starter-team"
},
"policies": {
"enableAll": true,

View File

@@ -1,12 +1,12 @@
{
"$schema": "../../schemas/preset.schema.json",
"organization": {
"fixture": "qa-sso-org",
"fixture": "verdant-health",
"planType": "enterprise-annually",
"seats": 10
},
"roster": {
"fixture": "sso-basic"
"fixture": "starter-team"
},
"ciphers": {
"fixture": "sso-vault"
@@ -15,7 +15,7 @@
"enable": ["requireSso"]
},
"sso": {
"identifier": "qa-sso-org",
"identifier": "verdant-health",
"encryptionType": "masterPassword",
"provider": "oidc"
}

View File

@@ -1,12 +1,12 @@
{
"$schema": "../../schemas/preset.schema.json",
"organization": {
"fixture": "qa-tde-org",
"fixture": "obsidian-labs",
"planType": "enterprise-annually",
"seats": 10
},
"roster": {
"fixture": "tde-basic"
"fixture": "starter-team"
},
"ciphers": {
"fixture": "tde-vault"
@@ -15,7 +15,7 @@
"enable": ["requireSso"]
},
"sso": {
"identifier": "qa-tde-org",
"identifier": "obsidian-labs",
"encryptionType": "trustedDevices",
"provider": "oidc"
}

View File

@@ -1,26 +0,0 @@
{
"$schema": "../../schemas/preset.schema.json",
"organization": {
"fixture": "wonka-confections",
"planType": "teams-annually",
"seats": 25
},
"users": {
"count": 10,
"realisticStatusMix": true
},
"groups": {
"count": 3
},
"collections": {
"count": 5
},
"folders": true,
"ciphers": {
"count": 50,
"assignFolders": true
},
"personalCiphers": {
"countPerUser": 20
}
}

View File

@@ -6,16 +6,21 @@
"seats": 25
},
"users": {
"count": 10,
"count": 25,
"realisticStatusMix": true
},
"groups": {
"count": 3
"count": 8
},
"collections": {
"count": 5
"count": 15
},
"folders": true,
"ciphers": {
"count": 100
"count": 250,
"assignFolders": true
},
"personalCiphers": {
"countPerUser": 25
}
}

View File

@@ -51,13 +51,23 @@
{ "name": "Collection-1892038", "groups": [{ "group": "All Members" }] },
{ "name": "Collection-1892039", "groups": [{ "group": "All Members" }] },
{ "name": "Collection-1892047-No-Access" },
{ "name": "Collection-1892047-View", "groups": [{ "group": "All Members", "readOnly": true }] },
{ "name": "Collection-1892047-Manage", "groups": [{ "group": "All Members", "manage": true }] },
{
"name": "Collection-1892047-View",
"groups": [{ "group": "All Members", "readOnly": true }]
},
{
"name": "Collection-1892047-Manage",
"groups": [{ "group": "All Members", "manage": true }]
},
{ "name": "Collection-2532597", "groups": [{ "group": "All Members" }] },
{ "name": "Collection-1793366", "groups": [{ "group": "All Members" }] },
{ "name": "Collection-3925894", "groups": [{ "group": "All Members" }] },
{ "name": "Collection-4204903", "groups": [{ "group": "All Members" }] },
{ "name": "Collection-5172094", "externalId": "Collection-5172094", "groups": [{ "group": "All Members" }] },
{
"name": "Collection-5172094",
"externalId": "Collection-5172094",
"groups": [{ "group": "All Members" }]
},
{ "name": "Collection-3392572", "groups": [{ "group": "All Members" }] },
{ "name": "Collection-3171087", "groups": [{ "group": "All Members" }] }
]

View File

@@ -0,0 +1,60 @@
{
"$schema": "../../schemas/roster.schema.json",
"users": [
{ "firstName": "Family", "lastName": "Mom", "role": "owner" },
{ "firstName": "Family", "lastName": "Dad", "role": "admin" },
{ "firstName": "Family", "lastName": "Son", "role": "user" },
{ "firstName": "Family", "lastName": "Daughter", "role": "user" },
{ "firstName": "Family", "lastName": "Grandpa", "role": "user" },
{ "firstName": "Family", "lastName": "Grandma", "role": "user" }
],
"groups": [
{
"name": "Everyone",
"members": [
"family.mom",
"family.dad",
"family.son",
"family.daughter",
"family.grandpa",
"family.grandma"
]
},
{
"name": "Parents",
"members": ["family.mom", "family.dad"]
},
{
"name": "Grandparents",
"members": ["family.grandpa", "family.grandma"]
}
],
"collections": [
{
"name": "Streaming",
"groups": [{ "group": "Everyone" }]
},
{
"name": "Banking",
"groups": [{ "group": "Parents", "manage": true }]
},
{
"name": "Wi-Fi & Home",
"groups": [{ "group": "Everyone" }]
},
{
"name": "School",
"users": [
{ "user": "family.son" },
{ "user": "family.daughter" }
]
},
{
"name": "Medical",
"groups": [
{ "group": "Parents" },
{ "group": "Grandparents" }
]
}
]
}

View File

@@ -1,9 +0,0 @@
{
"$schema": "../../schemas/roster.schema.json",
"users": [
{ "firstName": "Policy", "lastName": "Owner", "role": "owner" },
{ "firstName": "Policy", "lastName": "Admin", "role": "admin" },
{ "firstName": "Policy", "lastName": "Custom", "role": "custom" },
{ "firstName": "Policy", "lastName": "User", "role": "user" }
]
}

View File

@@ -1,8 +0,0 @@
{
"$schema": "../../schemas/roster.schema.json",
"users": [
{ "firstName": "Sso", "lastName": "Owner", "role": "owner" },
{ "firstName": "Sso", "lastName": "User", "role": "user" },
{ "firstName": "Sso", "lastName": "Provisioning", "role": "user" }
]
}

View File

@@ -0,0 +1,46 @@
{
"$schema": "../../schemas/roster.schema.json",
"users": [
{ "firstName": "StarterTeam", "lastName": "Owner", "role": "owner" },
{ "firstName": "StarterTeam", "lastName": "Admin", "role": "admin" },
{ "firstName": "StarterTeam", "lastName": "Custom", "role": "custom" },
{ "firstName": "StarterTeam", "lastName": "UserOne", "role": "user" },
{ "firstName": "StarterTeam", "lastName": "UserTwo", "role": "user" },
{ "firstName": "StarterTeam", "lastName": "UserThree", "role": "user" },
{ "firstName": "StarterTeam", "lastName": "UserFour", "role": "user" },
{ "firstName": "StarterTeam", "lastName": "Provisioning", "role": "user" },
{
"firstName": "StarterTeam",
"lastName": "Mp-Non-Trusted",
"role": "user"
},
{
"firstName": "StarterTeam",
"lastName": "No-Mp-Non-Trusted",
"role": "user"
}
],
"groups": [
{
"name": "Everyone",
"members": [
"starterteam.owner",
"starterteam.admin",
"starterteam.custom",
"starterteam.userone",
"starterteam.usertwo",
"starterteam.userthree",
"starterteam.userfour",
"starterteam.provisioning",
"starterteam.mp-non-trusted",
"starterteam.no-mp-non-trusted"
]
}
],
"collections": [
{
"name": "Default collection",
"users": [{ "user": "starterteam.no-mp-non-trusted", "manage": true }]
}
]
}

View File

@@ -1,16 +0,0 @@
{
"$schema": "../../schemas/roster.schema.json",
"users": [
{ "firstName": "Tde", "lastName": "Owner", "role": "owner" },
{ "firstName": "Tde", "lastName": "Mp-Non-Trusted", "role": "user" },
{ "firstName": "Tde", "lastName": "No-Mp-Non-Trusted", "role": "user" }
],
"collections": [
{
"name": "Default collection",
"users": [
{ "user": "tde.no-mp-non-trusted", "manage": true }
]
}
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,81 +0,0 @@
{
"$schema": "../schemas/cipher.schema.json",
"items": [
{
"type": "login",
"name": "Example Login",
"favorite": true,
"reprompt": 0,
"login": {
"username": "user@example.com",
"password": "ChangeMe123!",
"totp": "otpauth://totp/Example:user?secret=JBSWY3DPEHPK3PXP",
"uris": [
{
"uri": "https://example.com/login",
"match": "domain"
}
]
},
"fields": [
{
"name": "Recovery Code",
"value": "ABC-123-XYZ",
"type": "hidden"
},
{
"name": "Linked Username",
"type": "linked",
"linkedId": 100
}
],
"passwordHistory": [
{
"password": "OldPassword1!",
"lastUsedDate": "2024-01-15T00:00:00.000Z"
}
]
},
{
"type": "card",
"name": "Example Card",
"card": {
"cardholderName": "Jane Doe",
"brand": "Visa",
"number": "4111111111111111",
"expMonth": "12",
"expYear": "2030",
"code": "123"
}
},
{
"type": "identity",
"name": "Example Identity",
"identity": {
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@example.com",
"address1": "123 Main St",
"city": "Anytown",
"state": "CA",
"postalCode": "90210",
"country": "US"
}
},
{
"type": "secureNote",
"name": "Example Secure Note",
"notes": "This is a secure note with sensitive information."
},
{
"type": "sshKey",
"name": "Example SSH Key",
"reprompt": 1,
"sshKey": {
"privateKey": "-----BEGIN OPENSSH PRIVATE KEY-----\n...\n-----END OPENSSH PRIVATE KEY-----\n",
"publicKey": "ssh-ed25519 AAAAC3...",
"keyFingerprint": "SHA256:..."
}
}
]
}

View File

@@ -1,6 +0,0 @@
{
"$schema": "../schemas/organization.schema.json",
"name": "Acme Corporation",
"domain": "acme.example.com",
"seats": 10
}

View File

@@ -1,19 +0,0 @@
{
"$schema": "../schemas/preset.schema.json",
"organization": {
"name": "Acme Corporation",
"domain": "acme.example.com",
"seats": 50,
"planType": "enterprise-annually"
},
"roster": {
"fixture": "my-roster-fixture"
},
"ciphers": {
"fixture": "my-cipher-fixture"
},
"policies": {
"enableAll": true,
"except": ["requireSso"]
}
}

View File

@@ -1,87 +0,0 @@
{
"$schema": "../schemas/roster.schema.json",
"users": [
{
"firstName": "Alice",
"lastName": "Admin",
"title": "Administrator",
"role": "admin",
"branch": "Headquarters",
"department": "IT"
},
{
"firstName": "Bob",
"lastName": "User",
"title": "Developer",
"role": "user",
"status": "confirmed",
"branch": "Headquarters",
"department": "Engineering"
},
{
"firstName": "Dave",
"lastName": "Invited",
"role": "user",
"status": "invited",
"email": "dave.custom-email@external.com"
},
{
"firstName": "Carol",
"lastName": "Manager",
"title": "Engineering Manager",
"role": "admin",
"branch": "Headquarters",
"department": "Engineering"
}
],
"groups": [
{
"name": "Administrators",
"members": [
"alice.admin",
"carol.manager"
]
},
{
"name": "Engineering Team",
"externalId": "eng-team-001",
"members": [
"bob.user",
"carol.manager"
]
}
],
"collections": [
{
"name": "Company Shared",
"groups": [
{
"group": "Administrators",
"readOnly": false,
"hidePasswords": false,
"manage": true
}
],
"users": [
{
"user": "alice.admin",
"readOnly": false,
"hidePasswords": false,
"manage": true
}
]
},
{
"name": "Engineering/Development",
"externalId": "eng-dev-collection",
"groups": [
{
"group": "Engineering Team",
"readOnly": false,
"hidePasswords": false,
"manage": false
}
]
}
]
}

View File

@@ -19,10 +19,10 @@ dotnet run -- <command> [options]
```bash
# 100 users
dotnet run -- organization -n MyOrgNoCiphers -u 100 -d myorg-no-ciphers.com
dotnet run -- organization -n MyOrgNoCiphers -u 100 -d myorg-no-ciphers.example
# 10,000 users for load testing
dotnet run -- organization -n LargeOrgNoCiphers -u 10000 -d large-org-no-ciphers.test
dotnet run -- organization -n LargeOrgNoCiphers -u 10000 -d large-org-no-ciphers.example
```
### `seed` - Fixture-Based Seeding
@@ -49,33 +49,33 @@ dotnet run -- seed --preset dunder-mifflin-enterprise-full --password "MyTestPas
```bash
# Tiny org — quick sanity check
dotnet run -- vault-organization -n SmallOrg -d small.test -u 3 -c 10 -g 5 -o Traditional -m
dotnet run -- vault-organization -n SmallOrg -d small.example -u 3 -c 10 -g 5 -o Traditional -m
# Mid-size Traditional org with realistic status mix
dotnet run -- vault-organization -n MidOrg -d mid.test -u 50 -c 1000 -g 15 -o Traditional -m
dotnet run -- vault-organization -n MidOrg -d mid.example -u 50 -c 1000 -g 15 -o Traditional -m
# Mid-size with dense cipher-to-user ratio
dotnet run -- vault-organization -n DenseOrg -d dense.test -u 75 -c 650 -g 20 -o Traditional -m
dotnet run -- vault-organization -n DenseOrg -d dense.example -u 75 -c 650 -g 20 -o Traditional -m
# Large Modern org
dotnet run -- vault-organization -n LargeOrg -d large.test -u 500 -c 10000 -g 85 -o Modern -m
dotnet run -- vault-organization -n LargeOrg -d large.example -u 500 -c 10000 -g 85 -o Modern -m
# Stress test — massive Spotify-style org
dotnet run -- vault-organization -n StressOrg -d stress.test -u 8000 -c 100000 -g 125 -o Spotify -m
dotnet run -- vault-organization -n StressOrg -d stress.example -u 8000 -c 100000 -g 125 -o Spotify -m
# Regional data variants
dotnet run -- vault-organization -n EuropeOrg -d europe.test -u 10 -c 100 -g 5 --region Europe
dotnet run -- vault-organization -n ApacOrg -d apac.test -u 17 -c 600 -g 12 --region AsiaPacific
dotnet run -- vault-organization -n EuropeOrg -d europe.example -u 10 -c 100 -g 5 --region Europe
dotnet run -- vault-organization -n ApacOrg -d apac.example -u 17 -c 600 -g 12 --region AsiaPacific
# With ID mangling for test isolation (prevents collisions with existing data)
dotnet run -- vault-organization -n IsolatedOrg -d isolated.test -u 5 -c 25 -g 4 -o Spotify --mangle
dotnet run -- vault-organization -n IsolatedOrg -d isolated.example -u 5 -c 25 -g 4 -o Spotify --mangle
# With custom password for all accounts
dotnet run -- vault-organization -n CustomPwOrg -d custom-password-05.test -u 10 -c 100 -g 3 --password "MyTestPassword1" --plan-type teams-annually
dotnet run -- vault-organization -n CustomPwOrg -d custom-password-05.example -u 10 -c 100 -g 3 --password "MyTestPassword1" --plan-type teams-annually
# Free plan org (limited to 2 seats, 2 collections)
dotnet run -- vault-organization -n FreeOrg -d free.test -u 1 -c 10 -g 1 --plan-type free
dotnet run -- vault-organization -n FreeOrg -d free.example -u 1 -c 10 -g 1 --plan-type free
# Teams plan org
dotnet run -- vault-organization -n TeamsOrg -d teams.test -u 20 -c 200 -g 5 --plan-type teams-annually
dotnet run -- vault-organization -n TeamsOrg -d teams.example -u 20 -c 200 -g 5 --plan-type teams-annually
```