mirror of
https://github.com/bitwarden/server.git
synced 2026-06-01 01:55:55 -05:00
68 lines
4.1 KiB
Markdown
68 lines
4.1 KiB
Markdown
# Fixture & Preset Architecture
|
|
|
|
How the Seeder's JSON layers compose to create test data.
|
|
|
|
## The Core Rule
|
|
|
|
**Fixtures define what exists. Presets define how things relate.**
|
|
|
|
Fixtures are independent, reusable building blocks. They never reference each other. The preset is the only layer that sees all the pieces and defines cross-cutting relationships between them.
|
|
|
|
## Fixtures = Bricks
|
|
|
|
Each fixture type describes one category of entities:
|
|
|
|
| Fixture Type | What It Defines | Knows About |
|
|
| ---------------- | ---------------------------------------- | ------------------------------- |
|
|
| **Organization** | Name, domain | Nothing else |
|
|
| **Roster** | Users, groups, collections, permissions | Its own users (by email prefix) |
|
|
| **Ciphers** | Vault items (logins, cards, notes, etc.) | Nothing else |
|
|
|
|
Fixtures are stored under `fixtures/organizations/`, `fixtures/rosters/`, and `fixtures/ciphers/`. A roster knows about its own users (groups reference members by email prefix, collections reference groups and users) but has zero knowledge of which organization or ciphers it'll be paired with.
|
|
|
|
## Presets = Assembly Instructions
|
|
|
|
A preset picks one of each fixture (or generates data inline) and defines the relationships between them. It's the entry point for the `preset --name` CLI command.
|
|
|
|
There are three composition modes:
|
|
|
|
- **Fixture-based** — pointers to existing JSON files. See `presets/qa/enterprise-basic.json`.
|
|
- **Generation-based** — inline counts + density parameters, no fixtures. See `presets/scale/md-balanced-sterling-cooper.json`.
|
|
- **Hybrid** — mix of fixture and generated data. See `presets/qa/families-basic.json`.
|
|
|
|
The schemas are the source of truth for what fields are available: `schemas/preset.schema.json`, `schemas/roster.schema.json`, `schemas/cipher.schema.json`.
|
|
|
|
## Cross-Cutting Relationships
|
|
|
|
The preset owns all relationships that cross fixture boundaries. Three assignment types are supported:
|
|
|
|
### Collection Assignments (org-scoped)
|
|
|
|
`collectionAssignments` maps `(cipher, collection)` tuples — which ciphers belong in which collections. Collections are defined in the roster; ciphers are defined in the cipher fixture. When present, replaces the default round-robin cipher-to-collection assignment. Without it, `CreateCiphersStep` distributes ciphers across collections via round-robin.
|
|
|
|
### Folder Assignments (user-scoped)
|
|
|
|
Folder **declarations** go in the roster — each user can optionally declare a `folders` array of named folders. For individual user presets (no roster), folder declarations use the preset-level `folderNames` array instead. Folder **assignments** go in the preset — `folderAssignments` maps `(cipher, user, folder)` tuples, mirroring the `Cipher.Folders` JSON column: `{"USERID":"FOLDERID"}`.
|
|
|
|
### Favorite Assignments (user-scoped)
|
|
|
|
`favoriteAssignments` maps `(cipher, user)` tuples, mirroring `Cipher.Favorites`: `{"USERID":true}`.
|
|
|
|
See `presets/qa/zero-knowledge-labs-enterprise.json` for a working example with all three assignment types.
|
|
|
|
## Why This Design
|
|
|
|
1. **Honest to the data model** — assignment arrays mirror the actual DB relationships (`CollectionCipher`, `Cipher.Folders` JSON, `Cipher.Favorites` JSON)
|
|
2. **No mixed concerns** — roster owns entities, cipher fixture owns vault items, preset owns relationships
|
|
3. **Reusable bricks** — the same cipher fixture pairs with any roster and any assignment configuration
|
|
4. **Backward compatible** — presets without assignment arrays continue to use round-robin collection distribution and have no folder/favorite data
|
|
|
|
## The DB Analogy
|
|
|
|
| Fixture | Like This Table |
|
|
| ------------ | --------------------------------------------------- |
|
|
| Organization | `Organization` |
|
|
| Roster | `User` + `Group` + `Collection` + join tables |
|
|
| Ciphers | `Cipher` |
|
|
| Preset | The `JOIN` — picks tables and defines relationships |
|