Samples
Catalog and matrix samples
Three artifacts as they ship: a behavior-catalog excerpt with its migration decisions, an enforcement-matrix excerpt with its three cell classes, and the coverage boundary. The rows come from the Bugzilla teardown, so the cited source is public and checkable.
Artifact · Behavior catalog
Catalog excerpt, with migration decisions
Each behavior carries typed semantics, a provenance citation into Bugzilla's source, its epistemic tier, and the decision made when the system was rebuilt. On a rebuild engagement, the migration column is part of what you approve before construction starts.
| ID | Behavior | Kind | Result | Provenance | Tier |
|---|---|---|---|---|---|
| attachment.create-attachment.happy-path | Authenticated user who can see the bug and has product edit access uploads a file attachment | happy-path | emits AttachmentCreated | Bugzilla/Attachment.pm Attachment creation and field validation | Traced in source Read from code, not yet run against a live system. |
| attachment.create-attachment.empty-description | Attachment creation requires a non-empty description | validation | rejects · MISSING_ATTACHMENT_DESCRIPTION | Bugzilla/Attachment.pm ATT-DR-7 — description must be non-empty | Traced in source Read from code, not yet run against a live system. |
| attachment.create-attachment.authorization-denied | User without permission to see the bug or edit the product is denied attachment creation | authorization | rejects · PERMISSION_DENIED | Bugzilla/Attachment.pm ATT-DR-1 — requires can_see_bug and can_edit_product | Traced in source Read from code, not yet run against a live system. |
| attachment.create-attachment.patch-forces-text-plain | When isPatch is true, the MIME type is forced to text/plain regardless of user input | business-rule | emits AttachmentCreated | Bugzilla/Attachment.pm ATT-DR-4 — patch attachments force text/plain | Traced in source Read from code, not yet run against a live system. |
| bug.add-bug-group.happy-path | User with editbugs/assignee/QA role adds a group restriction to a bug | happy-path | emits BugGroupAdded | Bugzilla/Bug.pm AddBugGroup command - group restriction addition | Traced in source Read from code, not yet run against a live system. |
| bug.add-bug-group.invalid-group-for-product | Cannot add a group that is not valid for the bug's product | validation | rejects · INVALID_GROUP | Bugzilla/Bug.pm Group validation via GroupControlMapReadModel | Traced in source Read from code, not yet run against a live system. |
| bug.add-bug-group.authorization-denied | User without editbugs/assignee/QA role cannot add group restrictions | authorization | rejects · PERMISSION_DENIED | Bugzilla/Bug.pm AddBugGroup requires editbugs/assignee/QA role | Traced in source Read from code, not yet run against a live system. |
| bug.add-bug-group.already-member | Adding a group the bug already has is a no-op or returns success idempotently | business-rule | returns success without duplicating the group | Bugzilla/Bug.pm Group addition idempotency | Traced in source Read from code, not yet run against a live system. |
| notification.get-notification-preferences.happy-path | An authenticated user retrieves their own notification preference matrix, including email-disabled flag, ignored bug IDs, and the full role × change-type preference matrix | happy-path | returns the preference matrix | Bugzilla/BugMail.pm Notification preference resolution for bugmail recipients | Traced in source Read from code, not yet run against a live system. |
| notification.get-notification-log.filter-by-date-range | Notification log query supports optional date range filtering to narrow results to a specific time window | validation | returns records within the date range | Bugzilla/BugMail.pm Notification log filtering by date | Traced in source Read from code, not yet run against a live system. |
| notification.get-notification-preferences.unauthorized | A user without notifications:read permission is denied access to notification preferences | authorization | rejects · PERMISSION_DENIED | Bugzilla/User.pm Authorization gate for user notification preferences | Traced in source Read from code, not yet run against a live system. |
| notification.get-notification-preferences.owns-preferences-policy | A user can only retrieve their own notification preferences; attempting to read another user's preferences is denied by OwnsPreferencesPolicy | business-rule | rejects · PERMISSION_DENIED | Bugzilla/User.pm OwnsPreferencesPolicy — users can only read their own preferences | Traced in source Read from code, not yet run against a live system. |
| product.create-component.happy-path | A user with components:manage permission successfully creates a new component under a product | happy-path | emits ComponentCreated | Bugzilla/Component.pm Component creation logic and required fields | Traced in source Read from code, not yet run against a live system. |
| product.create-component.name-required | Component creation fails when name is empty or blank | validation | rejects · component_blank_name | Bugzilla/Component.pm _check_name validator rejects empty strings with component_blank_name | Traced in source Read from code, not yet run against a live system. |
| product.create-component.unauthorized-caller | Component creation is denied when caller lacks components:manage permission | authorization | rejects · PERMISSION_DENIED | Bugzilla/User.pm check_can_admin_product method gates component management | Traced in source Read from code, not yet run against a live system. |
| product.create-component.name-unique-per-product | Component creation fails when name already exists within the same product | business-rule | rejects · component_name_not_unique | Bugzilla/Component.pm _check_name validator checks uniqueness within product via name collision detection | Traced in source Read from code, not yet run against a live system. |
| user.create-user.happy-path | Admin creates a new user account with a unique email and valid password | happy-path | emits UserCreated | Bugzilla/User.pm User creation logic, email uniqueness validation, password complexity check | Traced in source Read from code, not yet run against a live system. |
| user.create-user.email-not-unique | Cannot create user with an email that already belongs to an active user | validation | rejects · email_already_exists | Bugzilla/User.pm Email uniqueness validation on create — INV-1 | Traced in source Read from code, not yet run against a live system. |
| user.create-user.unauthorized | User without users:create permission cannot create users | authorization | rejects · PERMISSION_DENIED | Bugzilla/User.pm Layer 1 permission: users:create required on CreateUser command | Traced in source Read from code, not yet run against a live system. |
| user.update-user-profile.disabled-user-self-modify | Disabled users cannot update their own profile through self-service | business-rule | rejects · account_disabled | Bugzilla/User.pm INV-6: Disabled accounts cannot self-modify — admin override allowed | Traced in source Read from code, not yet run against a live system. |
Artifact · Enforcement matrix
Enforcement-matrix excerpt
The matrix crosses every frontend gate against every backend guard and classes each rule. Most rules land in both layers, which is the point: the control group is what makes the exceptions findings rather than noise. These rows come from the rebuilt Bugzilla stack.
- Both layers
- The control group: the rule holds wherever you hit it.
- UI only
- The finding class: the frontend promises what the backend never checks.
- Backend only
- The inverse: the server refuses what the UI lets you attempt.
| Rule | Frontend gate | Backend guard | Class |
|---|---|---|---|
| Summary required to file a bug | frontend/src/views/BugCreate/BugCreate.tsx | services/service-bug/service/src/commands/create-bugHandler.ts | Both layers |
| Attachment size limit | frontend/src/views/BugDetail/BugDetail.tsx | services/service-attachment/service/src/commands/create-attachment-Handler.ts | Both layers |
| Comment length capped at 65,535 characters | frontend/src/views/BugDetail/BugDetail.tsx | services/service-bug/service/src/commands/add-commentHandler.ts | Both layers |
| Duplicate id must reference a different, existing bug No backend guard found at generation time; flagged, then fixed in the same run. | frontend/src/views/BugDetail/BugDetail.tsx | none found | UI only |
| Target milestone limited to the product's milestones The select constrains the value; the command accepted any string. | frontend/src/views/BugDetail/BugDetail.tsx | none found | UI only |
| Reassignment restricted to editbugs members The UI shows the assignee field to every signed-in user; the server refuses. | none found | services/service-bug/service/src/commands/assign-bug-Handler.ts | Backend only |
| Security-group changes restricted to members of the group The checkboxes render for everyone; the command rejects non-members. | none found | services/service-bug/service/src/commands/add-bug-groupHandler.ts | Backend only |
The finding class on a client estate, redacted
Probe candidate Needs a live environment to settle. Never presented as a confirmed defect.
The same UI-only class as it appears in practice: a rule the frontend promises at
serverless-████-service/███Form.tsxPath partially redacted. with no corresponding
backend guard found. It stays a probe candidate, with the exact API call that settles it,
until it's run against a live environment.
Artifact · Coverage boundary
The boundary, as it ships
Every catalog ends with this block: what was read, what wasn't, and what that means for the findings. It's rendered below exactly as a client receives it, populated from the Bugzilla teardown.