moose-inventory 2.0 → 2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +2 -0
  3. data/.gitignore +2 -1
  4. data/.rubocop.yml +21 -0
  5. data/BACKLOG.md +630 -8
  6. data/Gemfile +2 -0
  7. data/Gemfile.lock +1 -1
  8. data/README.md +315 -39
  9. data/Rakefile +2 -0
  10. data/bin/moose-inventory +2 -1
  11. data/docs/architecture/architecture-and-trust-boundaries.md +444 -0
  12. data/docs/compatibility/cli-output-compatibility.md +76 -0
  13. data/docs/governance/approval-register.md +37 -0
  14. data/docs/maintenance/database-backup-restore-guidance.md +162 -0
  15. data/docs/maintenance/package-maintenance-and-agent-boundaries.md +260 -0
  16. data/docs/process/conformance-gap-analysis-2026-05-28.md +192 -0
  17. data/docs/product/product-brief.md +161 -0
  18. data/docs/product/requirements-baseline.md +477 -0
  19. data/docs/qa/qa-documentation-and-release-gates.md +283 -0
  20. data/docs/release/package-provenance-hardening.md +126 -0
  21. data/docs/release/publishing.md +11 -3
  22. data/docs/release/release-environment-protection.md +70 -0
  23. data/docs/release/release-readiness.md +23 -4
  24. data/docs/security/accepted-risk-register.md +84 -0
  25. data/docs/security/security-privacy-process.md +287 -0
  26. data/docs/security-audit-2026-05-26-rerun.md +2 -2
  27. data/docs/ux/cli-workflow-notes.md +287 -0
  28. data/examples/ansible/ansible.cfg +3 -0
  29. data/examples/ansible/inventory/moose_inventory.yml +5 -0
  30. data/examples/ansible/inventory_plugins/moose_inventory.py +100 -0
  31. data/examples/ci/README.md +16 -0
  32. data/examples/ci/github-actions/inventory-review.yml +38 -0
  33. data/examples/ci/inventory/example-snapshot.yml +19 -0
  34. data/examples/ci/scripts/validate-inventory-snapshot.sh +30 -0
  35. data/lib/moose_inventory/cli/application.rb +133 -5
  36. data/lib/moose_inventory/cli/association_rendering.rb +74 -0
  37. data/lib/moose_inventory/cli/association_rendering_support.rb +89 -0
  38. data/lib/moose_inventory/cli/audit.rb +62 -0
  39. data/lib/moose_inventory/cli/audit_recording.rb +40 -0
  40. data/lib/moose_inventory/cli/child_relation_rendering.rb +110 -0
  41. data/lib/moose_inventory/cli/console.rb +135 -0
  42. data/lib/moose_inventory/cli/db.rb +64 -0
  43. data/lib/moose_inventory/cli/factory.rb +28 -0
  44. data/lib/moose_inventory/cli/formatter.rb +8 -12
  45. data/lib/moose_inventory/cli/group.rb +5 -2
  46. data/lib/moose_inventory/cli/group_add.rb +11 -9
  47. data/lib/moose_inventory/cli/group_addchild.rb +23 -65
  48. data/lib/moose_inventory/cli/group_addhost.rb +16 -67
  49. data/lib/moose_inventory/cli/group_addvar.rb +27 -47
  50. data/lib/moose_inventory/cli/group_get.rb +8 -42
  51. data/lib/moose_inventory/cli/group_list.rb +7 -40
  52. data/lib/moose_inventory/cli/group_listvars.rb +9 -55
  53. data/lib/moose_inventory/cli/group_rm.rb +12 -10
  54. data/lib/moose_inventory/cli/group_rmchild.rb +26 -82
  55. data/lib/moose_inventory/cli/group_rmhost.rb +18 -53
  56. data/lib/moose_inventory/cli/group_rmvar.rb +30 -41
  57. data/lib/moose_inventory/cli/group_tags.rb +33 -0
  58. data/lib/moose_inventory/cli/helpers.rb +68 -1
  59. data/lib/moose_inventory/cli/host.rb +6 -3
  60. data/lib/moose_inventory/cli/host_add.rb +69 -29
  61. data/lib/moose_inventory/cli/host_addgroup.rb +22 -58
  62. data/lib/moose_inventory/cli/host_addvar.rb +28 -52
  63. data/lib/moose_inventory/cli/host_get.rb +9 -37
  64. data/lib/moose_inventory/cli/host_list.rb +24 -21
  65. data/lib/moose_inventory/cli/host_listvars.rb +9 -62
  66. data/lib/moose_inventory/cli/host_rm.rb +60 -42
  67. data/lib/moose_inventory/cli/host_rmgroup.rb +25 -44
  68. data/lib/moose_inventory/cli/host_rmvar.rb +31 -45
  69. data/lib/moose_inventory/cli/host_tags.rb +33 -0
  70. data/lib/moose_inventory/cli/listvars_support.rb +55 -0
  71. data/lib/moose_inventory/cli/plan_rendering.rb +50 -0
  72. data/lib/moose_inventory/cli/relation_transaction_support.rb +51 -0
  73. data/lib/moose_inventory/cli/tag_support.rb +97 -0
  74. data/lib/moose_inventory/cli/variable_rendering.rb +67 -0
  75. data/lib/moose_inventory/config/config.rb +185 -108
  76. data/lib/moose_inventory/db/db.rb +170 -195
  77. data/lib/moose_inventory/db/exceptions.rb +6 -3
  78. data/lib/moose_inventory/db/models.rb +16 -0
  79. data/lib/moose_inventory/db/schema_migrations.rb +248 -0
  80. data/lib/moose_inventory/inventory_context.rb +68 -2
  81. data/lib/moose_inventory/operations/add_associations.rb +20 -16
  82. data/lib/moose_inventory/operations/add_groups.rb +21 -13
  83. data/lib/moose_inventory/operations/add_hosts.rb +30 -17
  84. data/lib/moose_inventory/operations/add_variables.rb +77 -0
  85. data/lib/moose_inventory/operations/entity_variable_operation_support.rb +46 -0
  86. data/lib/moose_inventory/operations/group_child_relations.rb +23 -16
  87. data/lib/moose_inventory/operations/group_cleanup.rb +23 -8
  88. data/lib/moose_inventory/operations/import_inventory_snapshot.rb +41 -0
  89. data/lib/moose_inventory/operations/inventory_doctor.rb +172 -0
  90. data/lib/moose_inventory/operations/inventory_snapshot.rb +60 -0
  91. data/lib/moose_inventory/operations/inventory_snapshot_applier.rb +112 -0
  92. data/lib/moose_inventory/operations/inventory_snapshot_preview.rb +174 -0
  93. data/lib/moose_inventory/operations/inventory_snapshot_validator.rb +134 -0
  94. data/lib/moose_inventory/operations/operation_event_support.rb +27 -0
  95. data/lib/moose_inventory/operations/query_inventory/base_query.rb +24 -0
  96. data/lib/moose_inventory/operations/query_inventory/group_queries.rb +86 -0
  97. data/lib/moose_inventory/operations/query_inventory/host_queries.rb +106 -0
  98. data/lib/moose_inventory/operations/query_inventory.rb +47 -0
  99. data/lib/moose_inventory/operations/remove_associations.rb +30 -18
  100. data/lib/moose_inventory/operations/remove_groups.rb +12 -12
  101. data/lib/moose_inventory/operations/remove_hosts.rb +68 -0
  102. data/lib/moose_inventory/operations/remove_variables.rb +67 -0
  103. data/lib/moose_inventory/runtime_options.rb +31 -0
  104. data/lib/moose_inventory/version.rb +3 -1
  105. data/lib/moose_inventory.rb +10 -7
  106. data/moose-inventory.gemspec +19 -35
  107. data/scripts/check.sh +1 -0
  108. data/scripts/ci/check_generated_artifacts.sh +41 -0
  109. data/scripts/ci/check_permissions.sh +2 -0
  110. data/scripts/ci/check_rubocop.sh +30 -25
  111. data/scripts/files.rb +5 -4
  112. data/spec/examples/ci_examples_spec.rb +37 -0
  113. data/spec/lib/moose_inventory/ansible_plugin_examples_spec.rb +29 -0
  114. data/spec/lib/moose_inventory/cli/application_doctor_spec.rb +50 -0
  115. data/spec/lib/moose_inventory/cli/application_import_export_spec.rb +100 -0
  116. data/spec/lib/moose_inventory/cli/application_spec.rb +25 -15
  117. data/spec/lib/moose_inventory/cli/audit_spec.rb +56 -0
  118. data/spec/lib/moose_inventory/cli/cli_spec.rb +15 -19
  119. data/spec/lib/moose_inventory/cli/console_spec.rb +98 -0
  120. data/spec/lib/moose_inventory/cli/factory_spec.rb +27 -0
  121. data/spec/lib/moose_inventory/cli/formatter_spec.rb +95 -3
  122. data/spec/lib/moose_inventory/cli/group_add_spec.rb +140 -116
  123. data/spec/lib/moose_inventory/cli/group_addchild_spec.rb +89 -35
  124. data/spec/lib/moose_inventory/cli/group_addhost_spec.rb +81 -84
  125. data/spec/lib/moose_inventory/cli/group_addvar_spec.rb +65 -68
  126. data/spec/lib/moose_inventory/cli/group_get_spec.rb +17 -33
  127. data/spec/lib/moose_inventory/cli/group_list_spec.rb +16 -38
  128. data/spec/lib/moose_inventory/cli/group_listvar_spec.rb +33 -40
  129. data/spec/lib/moose_inventory/cli/group_rm_spec.rb +136 -96
  130. data/spec/lib/moose_inventory/cli/group_rmchild_spec.rb +66 -41
  131. data/spec/lib/moose_inventory/cli/group_rmhost_spec.rb +76 -78
  132. data/spec/lib/moose_inventory/cli/group_rmvar_spec.rb +57 -63
  133. data/spec/lib/moose_inventory/cli/group_spec.rb +2 -0
  134. data/spec/lib/moose_inventory/cli/helpers_spec.rb +146 -0
  135. data/spec/lib/moose_inventory/cli/host_add_spec.rb +170 -116
  136. data/spec/lib/moose_inventory/cli/host_addgroup_spec.rb +100 -83
  137. data/spec/lib/moose_inventory/cli/host_addvar_spec.rb +92 -74
  138. data/spec/lib/moose_inventory/cli/host_get_spec.rb +14 -33
  139. data/spec/lib/moose_inventory/cli/host_list_spec.rb +41 -33
  140. data/spec/lib/moose_inventory/cli/host_listvar_spec.rb +45 -53
  141. data/spec/lib/moose_inventory/cli/host_rm_spec.rb +66 -48
  142. data/spec/lib/moose_inventory/cli/host_rmgroup_spec.rb +73 -83
  143. data/spec/lib/moose_inventory/cli/host_rmvar_spec.rb +56 -63
  144. data/spec/lib/moose_inventory/cli/host_spec.rb +2 -0
  145. data/spec/lib/moose_inventory/cli/tags_spec.rb +81 -0
  146. data/spec/lib/moose_inventory/config/config_spec.rb +41 -3
  147. data/spec/lib/moose_inventory/db/db_spec.rb +396 -36
  148. data/spec/lib/moose_inventory/db/exceptions_spec.rb +18 -0
  149. data/spec/lib/moose_inventory/db/models_spec.rb +7 -3
  150. data/spec/lib/moose_inventory/db_lifecycle_spec.rb +73 -0
  151. data/spec/lib/moose_inventory/inventory_context_spec.rb +10 -0
  152. data/spec/lib/moose_inventory/operations/add_associations_spec.rb +34 -0
  153. data/spec/lib/moose_inventory/operations/add_groups_spec.rb +15 -0
  154. data/spec/lib/moose_inventory/operations/add_hosts_spec.rb +13 -0
  155. data/spec/lib/moose_inventory/operations/add_variables_spec.rb +103 -0
  156. data/spec/lib/moose_inventory/operations/group_child_relations_spec.rb +46 -0
  157. data/spec/lib/moose_inventory/operations/import_inventory_snapshot_spec.rb +226 -0
  158. data/spec/lib/moose_inventory/operations/inventory_doctor_spec.rb +77 -0
  159. data/spec/lib/moose_inventory/operations/inventory_snapshot_spec.rb +50 -0
  160. data/spec/lib/moose_inventory/operations/operation_event_support_spec.rb +78 -0
  161. data/spec/lib/moose_inventory/operations/query_inventory_spec.rb +146 -0
  162. data/spec/lib/moose_inventory/operations/remove_associations_spec.rb +35 -0
  163. data/spec/lib/moose_inventory/operations/remove_groups_spec.rb +21 -0
  164. data/spec/lib/moose_inventory/operations/remove_hosts_spec.rb +55 -0
  165. data/spec/lib/moose_inventory/operations/remove_variables_spec.rb +83 -0
  166. data/spec/shared/shared_config_setup.rb +4 -3
  167. data/spec/spec_helper.rb +50 -40
  168. data/spec/support/cli_harness.rb +33 -0
  169. metadata +80 -41
@@ -0,0 +1,283 @@
1
+ # Moose Inventory QA, Documentation QA, and Release Gates
2
+
3
+ ## Approval status
4
+
5
+ Status: **Draft - maintained gate template**
6
+
7
+ This document defines reusable QA, documentation-QA, and release-gate templates for Moose Inventory. It maps the local verification gate to the approved requirements baseline and adds human-review checkpoints for release decisions.
8
+
9
+ Approved references:
10
+
11
+ - `GOV-TAILOR-001`: Moose Inventory is approved as Class 4 with target profile Software Library / Package.
12
+ - `GOV-PRODUCT-001`: `docs/product/product-brief.md` is approved as the product-framing baseline.
13
+ - `GOV-REQ-001`: `docs/product/requirements-baseline.md` is approved as the requirements and acceptance criteria baseline.
14
+ - `GOV-UX-001`: `docs/ux/cli-workflow-notes.md` is approved as the CLI UX/workflow baseline.
15
+ - `GOV-ARCH-001`: `docs/architecture/architecture-and-trust-boundaries.md` is approved as the architecture and trust-boundary baseline.
16
+ - `GOV-SEC-001`: `docs/security/security-privacy-process.md` is approved as the security and privacy process baseline.
17
+ - `GOV-RISK-REG-001`: `docs/security/accepted-risk-register.md` is approved as the maintained accepted-risk register baseline.
18
+
19
+ Scope limit: this document is a QA/release evidence template. It does not approve a release, public/compliance claim, RubyGems publishing, accepted risk, new feature scope, or future architecture/security change.
20
+
21
+ ## Gate principles
22
+
23
+ - Evidence is not approval. Passing checks support a release decision; they do not make the decision.
24
+ - Release decisions remain human-owned.
25
+ - Every exception must be either fixed, deferred as explicit backlog work, or accepted through `docs/security/accepted-risk-register.md` when it is security/privacy/release risk.
26
+ - A release candidate should be traceable to requirements, tests, documentation, security scans, package sanity, and rollback/recovery notes.
27
+ - Network-dependent security checks may fail closed. If the failure is environmental rather than a finding, record the failed check, rerun when available, and do not publish until the gate is either passing or explicitly accepted.
28
+
29
+ ## Local gate mapping
30
+
31
+ `./scripts/check.sh` is the default local release-readiness gate. Run with security tools required for release evidence:
32
+
33
+ ```bash
34
+ MOOSE_INVENTORY_REQUIRE_SECURITY_TOOLS=1 ./scripts/check.sh
35
+ ```
36
+
37
+ | Gate step | Evidence produced | Requirement / release criteria supported | Release interpretation |
38
+ | --- | --- | --- | --- |
39
+ | `bundle exec rspec --format progress` | Automated spec result and coverage report | CLI, CFG, DB, INV, DRY, SNAP, DOC, AUD, TAG, ANS, CI, COMPAT, DOCS acceptance criteria | Required passing evidence for supported behavior. Any failure blocks release unless a human records an explicit exception. |
40
+ | `scripts/ci/check_rubocop.sh` | RuboCop result for Ruby source, executable loader, scripts, specs, and gemspec | COMPAT and maintainability expectations; release quality hygiene | Required passing evidence. Style failures indicate unreviewed code-quality drift. |
41
+ | `git diff --check` | Whitespace/conflict-marker check | Documentation/source hygiene and merge-safety expectations | Required passing evidence. Failure blocks release until fixed. |
42
+ | `scripts/ci/check_permissions.sh` | Tracked executable permission allow-list check | PKG and release-integrity expectations | Required passing evidence. Unexpected executables are potential packaging/security drift. |
43
+ | `scripts/ci/check_generated_artifacts.sh` | Generated artifact ignore/tracking guard | QA, PKG, and release-integrity expectations for local reports, package output, temporary files, and audit scratch space | Required passing evidence. Generated paths must stay ignored and untracked unless intentionally promoted. |
44
+ | `scripts/ci/check_security.sh` | OSV batch query, `bundler-audit`, and optional/required `osv-scanner` lockfile/source scan | SEC and PKG dependency/security acceptance criteria | Required passing evidence for release. Critical/high findings block release unless explicitly accepted by a human. |
45
+ | `scripts/ci/check_secrets.sh` | `gitleaks` filesystem scan with redaction | SEC secrets-handling criteria | Required passing evidence for release. Any true secret finding requires cleanup and rotation outside Moose Inventory. |
46
+ | `scripts/ci/package_sanity.sh` | Built gem, metadata inspection, required packaged files, CLI version smoke | PKG release-integrity criteria | Required passing evidence that the packaged artifact contains expected entrypoints and metadata. |
47
+
48
+ ## Documentation QA checklist
49
+
50
+ Use this before release and after material user-facing changes.
51
+
52
+ ```markdown
53
+ ## Documentation QA checklist
54
+
55
+ Release candidate / commit:
56
+ Reviewer:
57
+ Date:
58
+
59
+ Required docs:
60
+ - [ ] `README.md` reflects current supported CLI workflows and examples.
61
+ - [ ] `docs/product/requirements-baseline.md` still matches intended behavior, or proposed changes are recorded for approval.
62
+ - [ ] `docs/ux/cli-workflow-notes.md` still matches command behavior and output conventions.
63
+ - [ ] `docs/architecture/architecture-and-trust-boundaries.md` still matches implementation and release flow.
64
+ - [ ] `docs/security/security-privacy-process.md` still matches security/privacy posture.
65
+ - [ ] `docs/security/accepted-risk-register.md` is reviewed and current.
66
+ - [ ] `docs/release/publishing.md` and `docs/release/release-readiness.md` match the actual release workflow.
67
+
68
+ Content checks:
69
+ - [ ] Examples avoid real infrastructure, real credentials, real hostnames, and private data.
70
+ - [ ] Snapshot/import/export examples warn that inventory data can be sensitive where relevant.
71
+ - [ ] Database credential examples prefer `password_env` over plaintext `password`.
72
+ - [ ] Destructive or high-risk workflows show dry-run/confirmation expectations where relevant.
73
+ - [ ] Release notes distinguish evidence from approval.
74
+ - [ ] Known limitations and non-goals are visible enough for users.
75
+ - [ ] New or changed options include machine-readable output implications where relevant.
76
+
77
+ Evidence:
78
+ - [ ] Documentation diff reviewed.
79
+ - [ ] Link/path references checked by inspection or tooling.
80
+ - [ ] No stale version numbers, release tags, or command output examples remain.
81
+ - [ ] Follow-up documentation gaps added to `BACKLOG.md`.
82
+ ```
83
+
84
+ ## Release readiness checklist
85
+
86
+ Use this for every release candidate before creating a `v*` tag.
87
+
88
+ ```markdown
89
+ ## Release readiness checklist
90
+
91
+ Release version:
92
+ Release candidate commit:
93
+ Reviewer / release owner:
94
+ Date:
95
+
96
+ Source state:
97
+ - [ ] `git checkout master` completed.
98
+ - [ ] `git pull --ff-only origin master` completed.
99
+ - [ ] `git status --short --branch` is clean and on the expected branch.
100
+ - [ ] Version in `lib/moose_inventory/version.rb` matches the intended release.
101
+ - [ ] Version is greater than the latest published RubyGems version.
102
+ - [ ] Changelog/release notes drafted if maintainers want public notes.
103
+
104
+ Requirement and QA evidence:
105
+ - [ ] Material changes map to approved requirements or have approval/backlog records.
106
+ - [ ] `MOOSE_INVENTORY_REQUIRE_SECURITY_TOOLS=1 ./scripts/check.sh` passed.
107
+ - [ ] Documentation QA checklist completed.
108
+ - [ ] Known compatibility impact reviewed.
109
+ - [ ] Generated artifacts, local databases, coverage reports, and temporary files are not committed unless intentional.
110
+
111
+ Security and risk evidence:
112
+ - [ ] Release security gate completed.
113
+ - [ ] Accepted-risk disposition completed.
114
+ - [ ] No unresolved critical/high findings remain unless explicitly accepted.
115
+ - [ ] Secret-scan results reviewed; true positives cleaned and rotated outside Moose Inventory.
116
+ - [ ] Package sanity passed for the gem artifact.
117
+
118
+ Publishing readiness:
119
+ - [ ] GitHub Actions CI is green for the release commit.
120
+ - [ ] RubyGems trusted publishing setup is still expected to use repository `RusDavies/moose-inventory`, workflow `release.yml`, and environment `release`.
121
+ - [ ] Required GitHub `release` environment approvals, if any, are known to the release owner.
122
+ - [ ] Manual RubyGems publishing fallback is not used unless trusted publishing is unavailable and a RubyGems owner explicitly approves.
123
+
124
+ Release decision:
125
+ - [ ] Human approver:
126
+ - [ ] Approval reference / message:
127
+ - [ ] Tag to create:
128
+ - [ ] Release notes location:
129
+ ```
130
+
131
+ ## Release security gate template
132
+
133
+ ```markdown
134
+ ## Release security gate
135
+
136
+ Release version:
137
+ Release candidate commit:
138
+ Reviewer:
139
+ Date:
140
+
141
+ Automated security checks:
142
+ - [ ] OSV batch query passed.
143
+ - [ ] `bundle-audit check --update` passed.
144
+ - [ ] `osv-scanner` lockfile/source scan passed with `MOOSE_INVENTORY_REQUIRE_SECURITY_TOOLS=1`.
145
+ - [ ] `gitleaks detect --no-git --source . --config .gitleaks.toml --redact --no-banner --log-level warn` passed.
146
+ - [ ] Package sanity check passed.
147
+
148
+ Manual review:
149
+ - [ ] Dependency changes reviewed for reachability and release impact.
150
+ - [ ] GitHub Actions workflow changes reviewed for permission, token, and publishing risk.
151
+ - [ ] Gemspec/package metadata reviewed for MFA, executable, file list, and dependency changes.
152
+ - [ ] Config, database, import/export, audit, and release docs reviewed for secret/privacy leakage.
153
+ - [ ] Any new external network behavior is documented and approved.
154
+
155
+ Findings:
156
+ - Critical findings:
157
+ - High findings:
158
+ - Medium findings:
159
+ - Low findings:
160
+
161
+ Disposition:
162
+ - [ ] All critical/high findings fixed, or accepted risk recorded.
163
+ - [ ] Medium/low findings are fixed, deferred to backlog, or accepted as appropriate.
164
+ - [ ] No credentials or private inventory data are present in committed files, logs, docs, examples, or release artifacts.
165
+ ```
166
+
167
+ ## Accepted-risk disposition template
168
+
169
+ Use this before release, even when there are no accepted risks.
170
+
171
+ ```markdown
172
+ ## Accepted-risk disposition
173
+
174
+ Release version:
175
+ Release candidate commit:
176
+ Reviewer:
177
+ Date:
178
+
179
+ Register reviewed:
180
+ - [ ] `docs/security/accepted-risk-register.md` reviewed.
181
+ - [ ] Accepted risks are current and within review date/trigger.
182
+ - [ ] Proposed/monitored risks are not being treated as accepted by accident.
183
+ - [ ] Any release-blocking proposed/monitored risk has a human decision.
184
+
185
+ Accepted risks shipping in this release:
186
+ - Risk ID:
187
+ - Scope:
188
+ - Severity:
189
+ - Why still acceptable for this release:
190
+ - Compensating controls:
191
+ - Approver / approval reference:
192
+
193
+ New risk decisions required:
194
+ - Risk ID or short name:
195
+ - Decision needed:
196
+ - Blocker status:
197
+ - Owner:
198
+
199
+ Outcome:
200
+ - [ ] No accepted risks ship in this release.
201
+ - [ ] Accepted risks ship only within documented scope.
202
+ - [ ] Release is blocked pending risk decision.
203
+ ```
204
+
205
+ ## Package yank, deprecation, and rollback path
206
+
207
+ RubyGems packages cannot be rolled back in place like a service deployment. Recovery is versioned and human-owned.
208
+
209
+ ### If a release is bad but not security-sensitive
210
+
211
+ 1. Stop further release activity.
212
+ 2. Record the affected version, tag, workflow run, and observed issue.
213
+ 3. Decide whether users should keep using the previous version or upgrade to a patch.
214
+ 4. Prepare and verify a patch release on a new version number.
215
+ 5. Publish the patch through trusted publishing.
216
+ 6. Add release notes explaining the fix and impact at an appropriate detail level.
217
+
218
+ ### If a release exposes a security issue or secret
219
+
220
+ 1. Stop release activity and preserve evidence.
221
+ 2. Identify whether credentials, private inventory data, package integrity, or user safety is affected.
222
+ 3. Rotate exposed credentials outside Moose Inventory where applicable.
223
+ 4. Decide with a human maintainer whether to yank, deprecate, patch, or publish an advisory.
224
+ 5. Prepare the smallest safe patch release and run the full release gate.
225
+ 6. Publish via trusted publishing when approved.
226
+ 7. Update `docs/security/accepted-risk-register.md`, security audit notes, or incident notes as appropriate.
227
+
228
+ ### RubyGems yanking/deprecation notes
229
+
230
+ - Yanking removes a version from normal installation resolution but does not erase every copy already downloaded, cached, mirrored, or vendored.
231
+ - Deprecation/advisory communication may be more useful than yanking when users need migration context.
232
+ - Never yank or deprecate a gem version without explicit human maintainer approval.
233
+ - Manual RubyGems credentials, if used in an emergency, must not be committed or pasted into logs.
234
+
235
+ ## Post-release review template
236
+
237
+ Run after the workflow completes and published-version verification is available.
238
+
239
+ ```markdown
240
+ ## Post-release review
241
+
242
+ Release version:
243
+ Release tag:
244
+ Release commit:
245
+ Workflow run:
246
+ Reviewer:
247
+ Date:
248
+
249
+ Publishing outcome:
250
+ - [ ] `release.yml` completed successfully, or failure is explained below.
251
+ - [ ] Published version appears in `gem info moose-inventory --remote --all`.
252
+ - [ ] Fresh install test completed where practical.
253
+ - [ ] `moose-inventory --help` or equivalent smoke check completed from installed gem.
254
+
255
+ Evidence links / references:
256
+ - CI run:
257
+ - Release workflow run:
258
+ - RubyGems version URL:
259
+ - Release notes / tag:
260
+
261
+ Problems observed:
262
+ - Workflow false negatives:
263
+ - RubyGems propagation delays:
264
+ - Install/smoke-test failures:
265
+ - User-visible documentation gaps:
266
+ - Security/risk follow-up:
267
+
268
+ Follow-up actions:
269
+ - [ ] Backlog items added for any release friction.
270
+ - [ ] Accepted-risk register updated if any risk decision changed.
271
+ - [ ] Release docs updated if the process diverged from documentation.
272
+ - [ ] Maintainers notified of release outcome.
273
+ ```
274
+
275
+ ## Current release blockers and follow-ups
276
+
277
+ These templates do not make the current repository release-ready by themselves. Before the next release, maintainers should still review:
278
+
279
+ - confirmed GitHub `release` environment protection rules;
280
+ - any active security-audit findings or dependency advisories;
281
+ - whether public `SECURITY.md` vulnerability intake should be added;
282
+ - whether destructive-command confirmation is required before broadening destructive workflows;
283
+ - whether package provenance beyond RubyGems trusted publishing is needed for the intended audience.
@@ -0,0 +1,126 @@
1
+ # Package provenance hardening evaluation
2
+
3
+ Status: evaluated as future hardening, not a current release requirement.
4
+
5
+ Moose Inventory publishes the `moose-inventory` RubyGem through GitHub Actions and RubyGems trusted publishing. This document records the current package-provenance evaluation so release decisions do not confuse useful future hardening with a present release blocker.
6
+
7
+ ## Current baseline
8
+
9
+ The approved release baseline is:
10
+
11
+ - releases start from reviewed `v*` tags;
12
+ - the GitHub `release` environment requires human review by `RusDavies`;
13
+ - the release workflow verifies that the pushed tag matches `Moose::Inventory::VERSION`;
14
+ - the release workflow runs `MOOSE_INVENTORY_REQUIRE_SECURITY_TOOLS=1 ./scripts/check.sh`;
15
+ - RubyGems trusted publishing/OIDC issues a short-lived publish token to the reviewed workflow;
16
+ - no long-lived RubyGems API token is required in GitHub secrets;
17
+ - `scripts/ci/package_sanity.sh` builds and inspects the gem payload before release.
18
+
19
+ This is adequate for the current project profile: a Ruby CLI/RubyGem maintained by Russ, with no current security-sensitive consumer requirement for separately signed provenance artifacts.
20
+
21
+ ## Options evaluated
22
+
23
+ ### RubyGems trusted publishing/OIDC
24
+
25
+ Decision: keep as the required baseline.
26
+
27
+ Strengths:
28
+
29
+ - avoids long-lived RubyGems publishing secrets in GitHub;
30
+ - binds publishing to the repository, workflow, environment, and tag-triggered release path;
31
+ - fits the current RubyGems-native release process;
32
+ - already verified with release `v2.0` / gem `2.0`.
33
+
34
+ Limitations:
35
+
36
+ - proves the publish path, not a separately downloadable signed software bill of materials or artifact attestation;
37
+ - consumers still rely on RubyGems distribution metadata and the source repository release evidence.
38
+
39
+ ### Checksums for built gems
40
+
41
+ Decision: useful as low-complexity future release evidence, but not currently required.
42
+
43
+ Possible implementation:
44
+
45
+ - build the gem in the release workflow;
46
+ - compute `sha256sum` for the `.gem` artifact;
47
+ - publish the checksum as a GitHub release artifact or release note after the gem publish succeeds.
48
+
49
+ Tradeoffs:
50
+
51
+ - simple and understandable;
52
+ - helps consumers compare a downloaded gem against release evidence;
53
+ - does not by itself prove who built or approved the artifact unless paired with workflow provenance.
54
+
55
+ ### GitHub artifact attestations
56
+
57
+ Decision: promising future hardening, but defer until there is a consumer or policy need.
58
+
59
+ Possible implementation:
60
+
61
+ - grant the release workflow the minimum attestation permission required by GitHub;
62
+ - generate an attestation for the built `.gem` artifact before or during publish;
63
+ - document consumer verification commands.
64
+
65
+ Tradeoffs:
66
+
67
+ - stronger provenance signal than a bare checksum;
68
+ - adds GitHub-specific release machinery and consumer education;
69
+ - needs careful validation with RubyGems release tooling so the attested artifact is exactly the published gem.
70
+
71
+ ### Sigstore / cosign-style detached signatures
72
+
73
+ Decision: not currently recommended.
74
+
75
+ Tradeoffs:
76
+
77
+ - can provide ecosystem-neutral signatures;
78
+ - introduces extra tooling, keyless identity semantics or key-management questions, and support burden;
79
+ - RubyGems consumers do not universally expect or verify these signatures.
80
+
81
+ ### RubyGems gem signing with certificates
82
+
83
+ Decision: not currently recommended.
84
+
85
+ Tradeoffs:
86
+
87
+ - RubyGems has historic support for signed gems;
88
+ - practical adoption and verification are limited;
89
+ - certificate/key management would add risk and maintenance overhead disproportionate to current needs.
90
+
91
+ ### SBOM generation
92
+
93
+ Decision: defer.
94
+
95
+ Tradeoffs:
96
+
97
+ - useful if enterprise consumers request dependency inventory evidence;
98
+ - adds format, generation, storage, and review questions;
99
+ - current dependency-audit controls already query OSV and bundler-audit from `Gemfile.lock` during release gates.
100
+
101
+ ## Recommendation
102
+
103
+ Do not make additional package provenance a release blocker now.
104
+
105
+ Keep RubyGems trusted publishing/OIDC as the release baseline and revisit stronger provenance when one of these triggers occurs:
106
+
107
+ - a consumer requests verifiable artifact provenance, SBOMs, checksums, or signatures;
108
+ - Moose Inventory becomes part of a more security-sensitive deployment path;
109
+ - release policy changes require artifact attestations;
110
+ - the project starts publishing multiple binary/native artifacts rather than a source RubyGem;
111
+ - GitHub/RubyGems provenance tooling becomes simple enough to adopt with low operational burden.
112
+
113
+ If the trigger occurs, the preferred first hardening step is GitHub artifact attestation plus a published SHA-256 checksum for the exact built `.gem`, because that balances verification value against operational complexity. Sigstore/cosign, RubyGems certificate signing, and SBOM publication should remain second-stage options unless a consumer specifically needs them.
114
+
115
+ ## Non-goals
116
+
117
+ This evaluation does not approve:
118
+
119
+ - changing the GitHub release workflow;
120
+ - publishing a new gem release;
121
+ - adding new GitHub permissions;
122
+ - adding or rotating signing keys;
123
+ - changing RubyGems settings;
124
+ - making public compliance or supply-chain-security claims.
125
+
126
+ Those actions require separate approval and verification.
@@ -4,6 +4,8 @@ This project is published to RubyGems as [`moose-inventory`](https://rubygems.or
4
4
 
5
5
  The preferred publishing path is GitHub Actions trusted publishing from reviewed `v*` tags. Manual publishing remains documented as a fallback only.
6
6
 
7
+ Routine release-infrastructure stewardship and AI-agent boundaries are documented in `docs/maintenance/package-maintenance-and-agent-boundaries.md`.
8
+
7
9
  ## Trusted publishing setup
8
10
 
9
11
  The repository side is `.github/workflows/release.yml`.
@@ -16,7 +18,11 @@ RubyGems has a trusted publisher configured for the existing `moose-inventory` g
16
18
  - Environment: `release`
17
19
  - Workflow repository owner/name: blank, because the workflow lives in this repository
18
20
 
19
- The release workflow requires the GitHub environment name `release`. If that environment has protection rules, approve the deployment when releasing.
21
+ The release workflow requires the GitHub environment name `release`. Current environment protection evidence is documented in `docs/release/release-environment-protection.md`.
22
+
23
+ As of 2026-05-29, the GitHub `release` environment has required reviewer protection for `RusDavies`, self-review prevention disabled, admin bypass disabled, and a custom deployment policy named `v*`. Self-review prevention is disabled because OpenClaw/automation pushes use Russ's GitHub account; with `RusDavies` as the only required reviewer, enabling self-review prevention could prevent Russ from approving the deployment. The workflow itself still runs only for pushed `v*` tags and verifies tag/version alignment before publishing. Because GitHub reports the custom deployment policy object as `type: branch`, verify tag-deployment behavior on the next real release and adjust the environment policy if needed.
24
+
25
+ Package provenance hardening beyond RubyGems trusted publishing is evaluated in `docs/release/package-provenance-hardening.md`. Additional checksums, GitHub artifact attestations, signatures, or SBOM publication are future hardening options, not current release blockers.
20
26
 
21
27
  ## Trusted publishing release checklist
22
28
 
@@ -37,10 +43,10 @@ The release workflow requires the GitHub environment name `release`. If that env
37
43
 
38
44
  If the repository version is not higher than the latest RubyGems version, bump `lib/moose_inventory/version.rb` first and commit that change before releasing.
39
45
 
40
- 3. Run the local release gate.
46
+ 3. Run the local release gate with security tools required, and complete the QA/release templates in `docs/qa/qa-documentation-and-release-gates.md`.
41
47
 
42
48
  ```bash
43
- ./scripts/check.sh
49
+ MOOSE_INVENTORY_REQUIRE_SECURITY_TOOLS=1 ./scripts/check.sh
44
50
  ```
45
51
 
46
52
  4. Push the release commit and wait for CI to pass.
@@ -65,6 +71,8 @@ The release workflow requires the GitHub environment name `release`. If that env
65
71
 
66
72
  The workflow verifies that the pushed tag version matches `Moose::Inventory::VERSION`, runs `./scripts/check.sh`, builds the gem through `rubygems/release-gem@v1`, and publishes using RubyGems trusted publishing/OIDC. No RubyGems API key should be stored in GitHub secrets for this workflow.
67
73
 
74
+ Trusted-publishing verification was completed with release tag `v2.0` / gem version `2.0`. The gem published successfully to RubyGems via OIDC, but the initial workflow finished red because the post-publish `rubygems-await` step timed out waiting for the RubyGems full index even though the gem was already available through the API/install path. The workflow now sets `await-release: false` to avoid that false negative; use the direct verification commands below when you want explicit propagation proof after a release.
75
+
68
76
  ## Verify the published version
69
77
 
70
78
  After the workflow succeeds:
@@ -0,0 +1,70 @@
1
+ # GitHub Release Environment Protection Rules
2
+
3
+ ## Status
4
+
5
+ Status: **Configured release-process evidence**
6
+
7
+ This document records the current GitHub `release` environment protection settings used by the Moose Inventory trusted-publishing workflow.
8
+
9
+ Initial confirmation date: 2026-05-29
10
+ Protection configuration date: 2026-05-29
11
+ Self-review adjustment date: 2026-05-29
12
+
13
+ Confirmation/configuration commands:
14
+
15
+ ```bash
16
+ gh api repos/RusDavies/moose-inventory/environments/release --jq '.'
17
+ gh api -X PUT repos/RusDavies/moose-inventory/environments/release --input /tmp/moose-env-release.json
18
+ gh api -X POST repos/RusDavies/moose-inventory/environments/release/deployment-branch-policies -f name='v*'
19
+ gh api repos/RusDavies/moose-inventory/environments/release/deployment-branch-policies --jq '.'
20
+ ```
21
+
22
+ Confirmed repository/environment:
23
+
24
+ - Repository: `RusDavies/moose-inventory`
25
+ - Environment: `release`
26
+ - Environment URL: `https://github.com/RusDavies/moose-inventory/deployments/activity_log?environments_filter=release`
27
+ - Release workflow: `.github/workflows/release.yml`
28
+ - Release trigger: pushed `v*` tags
29
+ - Release job environment: `release`
30
+ - RubyGems trusted publisher environment: `release`
31
+
32
+ ## Configured settings
33
+
34
+ | Setting | Configured value | Release-process interpretation |
35
+ | --- | --- | --- |
36
+ | Required deployment reviewers | `RusDavies` | The `release` environment now requires deployment approval by Russ before the release job can proceed. |
37
+ | Prevent self-review | Disabled (`prevent_self_review: false`) | Disabled because OpenClaw/automation pushes use Russ's GitHub account. With `RusDavies` as the only required reviewer, self-review prevention could block Russ from approving a release deployment triggered through his own account. |
38
+ | Wait timer | `0` / none | No arbitrary delay is configured. Human review is the intended release friction. |
39
+ | Deployment branch/tag policy mode | Custom branch policies enabled (`protected_branches: false`, `custom_branch_policies: true`) | The environment uses an explicit allow-list rather than all branches/tags. |
40
+ | Custom deployment policy | `v*` | Intended to align environment deployment eligibility with the release workflow's `v*` tag trigger. GitHub API reports this policy object with `type: branch`; verify behavior on the next real release tag and adjust if GitHub does not apply it to tag deployments as expected. |
41
+ | Admin bypass | Disabled (`can_admins_bypass: false`) | Admins should not be able to bypass environment protection for this environment through the normal bypass setting. |
42
+
43
+ ## Current trusted-publishing path
44
+
45
+ The current release path relies on these controls:
46
+
47
+ 1. The release workflow only runs on pushed tags matching `v*`.
48
+ 2. The GitHub `release` environment requires review by `RusDavies` before the release job can proceed.
49
+ 3. Self-review prevention is disabled so `RusDavies` can approve deployments triggered by automation authenticated as Russ's GitHub account.
50
+ 4. Admin bypass is disabled for the `release` environment.
51
+ 5. The environment has a custom deployment policy named `v*`.
52
+ 6. The release workflow verifies that the tag version matches `Moose::Inventory::VERSION`.
53
+ 7. The release workflow installs security tools and runs:
54
+
55
+ ```bash
56
+ MOOSE_INVENTORY_REQUIRE_SECURITY_TOOLS=1 ./scripts/check.sh
57
+ ```
58
+
59
+ 8. RubyGems trusted publishing/OIDC is scoped to repository `RusDavies/moose-inventory`, workflow `release.yml`, and environment `release`.
60
+ 9. The package sanity gate verifies the gem payload and executable metadata before publishing.
61
+
62
+ ## Residual verification note
63
+
64
+ GitHub accepted the custom deployment policy name `v*`, but the deployment-branch-policy API response reports the policy object as `type: branch`. The next real release should verify that a pushed `v*` tag can still deploy to the `release` environment after human approval.
65
+
66
+ If GitHub treats the custom policy as branch-only and blocks tag deployments, maintainers should either adjust the environment policy to the supported tag pattern mechanism or document the limitation and rely on the workflow's `v*` tag trigger plus tag/version check as the tag-control layer.
67
+
68
+ ## Change-control note
69
+
70
+ Changing GitHub environment protection settings is repository/release-infrastructure administration. AI agents may document the current state and prepare recommendations, but must not change environment rules without explicit human approval.
@@ -2,6 +2,10 @@
2
2
 
3
3
  This project now has a small release-readiness gate intended to catch the regressions found during the modernization and security-audit passes.
4
4
 
5
+ Reusable QA, documentation-QA, release, security, accepted-risk, rollback, and post-release templates live in `docs/qa/qa-documentation-and-release-gates.md`.
6
+
7
+ Routine package maintenance and AI-agent operation boundaries live in `docs/maintenance/package-maintenance-and-agent-boundaries.md`.
8
+
5
9
  ## Local gate
6
10
 
7
11
  Run:
@@ -13,10 +17,19 @@ Run:
13
17
  The gate currently runs:
14
18
 
15
19
  1. RSpec with coverage via the existing spec helper.
16
- 2. `git diff --check` for whitespace/conflict-marker issues in the working tree.
17
- 3. `scripts/ci/check_permissions.sh` to ensure only intentional tracked repository entrypoints are executable.
18
- 4. `scripts/ci/check_security.sh` to query OSV for locked RubyGems dependency advisories.
19
- 5. `scripts/ci/package_sanity.sh` to build the gem, inspect the packaged payload, and smoke-test the CLI version command.
20
+ 2. `scripts/ci/check_rubocop.sh` for targeted Ruby style/lint checks.
21
+ 3. `git diff --check` for whitespace/conflict-marker issues in the working tree.
22
+ 4. `scripts/ci/check_permissions.sh` to ensure only intentional tracked repository entrypoints are executable.
23
+ 5. `scripts/ci/check_generated_artifacts.sh` to ensure generated/local artifact paths remain ignored and untracked.
24
+ 6. `scripts/ci/check_security.sh` to query OSV, run `bundler-audit`, and run `osv-scanner` when available or required.
25
+ 7. `scripts/ci/check_secrets.sh` to run the dedicated `gitleaks` secret scan when available or required.
26
+ 8. `scripts/ci/package_sanity.sh` to build the gem, inspect the packaged payload, and smoke-test the CLI version command.
27
+
28
+ For release evidence, prefer:
29
+
30
+ ```bash
31
+ MOOSE_INVENTORY_REQUIRE_SECURITY_TOOLS=1 ./scripts/check.sh
32
+ ```
20
33
 
21
34
  ## CI gate
22
35
 
@@ -38,6 +51,12 @@ The release workflow runs when a `v*` tag is pushed. It:
38
51
 
39
52
  RubyGems has a trusted publisher configured for repository `RusDavies/moose-inventory`, workflow `release.yml`, and environment `release`, so the workflow can request a short-lived publish token when a real release tag is pushed.
40
53
 
54
+ Current GitHub `release` environment protection evidence is recorded in `docs/release/release-environment-protection.md`. As of 2026-05-29, the environment requires review by `RusDavies`, has self-review prevention disabled, disables admin bypass, and has a custom deployment policy named `v*`. Self-review prevention is disabled because OpenClaw/automation pushes use Russ's GitHub account, and `RusDavies` is currently the only required reviewer. Because GitHub reports the custom deployment policy object as `type: branch`, verify tag-deployment behavior on the next real release and adjust the environment policy if needed.
55
+
56
+ This path was verified with release `v2.0` / gem `2.0`: RubyGems trusted publishing succeeded and the published gem was installable afterward. The release workflow now disables `rubygems/release-gem`'s post-publish await step (`await-release: false`) because RubyGems full-index propagation lag produced false-negative workflow failures even after successful publishes.
57
+
58
+ Package provenance hardening beyond trusted publishing is evaluated in `docs/release/package-provenance-hardening.md`. The current release-readiness gate does not require additional checksums, GitHub artifact attestations, detached signatures, RubyGems certificate signing, or SBOM publication unless a future consumer or policy requirement explicitly adds that work.
59
+
41
60
  ## Package sanity expectations
42
61
 
43
62
  `package_sanity.sh` validates that the built gem includes at least:
@@ -0,0 +1,84 @@
1
+ # Moose Inventory Accepted-Risk Register
2
+
3
+ ## Approval status
4
+
5
+ Status: **Approved register - no accepted risks currently approved here**
6
+
7
+ Russ / Rusty Frink Desiato approved this register's structure and use as part of the Moose Inventory security/privacy process baseline on 2026-05-29. Approval reference: `GOV-SEC-001`.
8
+
9
+ Russ / Rusty Frink Desiato separately approved this accepted-risk register as the maintained accepted-risk register baseline for Moose Inventory on 2026-05-29. Approval reference: `GOV-RISK-REG-001`.
10
+
11
+ This register records security, privacy, release, and supply-chain risks that are intentionally accepted rather than fixed before a defined milestone. A proposed risk is not accepted until an approver records an explicit approval decision.
12
+
13
+ Approved references:
14
+
15
+ - `GOV-TAILOR-001`: Moose Inventory is approved as Class 4 with target profile Software Library / Package.
16
+ - `GOV-PRODUCT-001`: `docs/product/product-brief.md` is approved as the product-framing baseline.
17
+ - `GOV-REQ-001`: `docs/product/requirements-baseline.md` is approved as the requirements and acceptance criteria baseline.
18
+ - `GOV-UX-001`: `docs/ux/cli-workflow-notes.md` is approved as the CLI UX/workflow baseline.
19
+ - `GOV-ARCH-001`: `docs/architecture/architecture-and-trust-boundaries.md` is approved as the architecture and trust-boundary baseline.
20
+ - `GOV-SEC-001`: this register's structure and use are approved as part of the security/privacy process baseline.
21
+ - `GOV-RISK-REG-001`: this register is approved as the maintained accepted-risk register baseline.
22
+
23
+ Scope limit: this register records accepted-risk decisions only. It does not approve a release, compliance claim, public advisory, RubyGems publishing, future architecture/security changes, or acceptance of any proposed/monitored risk listed below. Approval of the register baseline does not convert proposed or monitored risks into accepted risks.
24
+
25
+ ## Acceptance rules
26
+
27
+ Each accepted risk must include:
28
+
29
+ - risk ID;
30
+ - decision and scope;
31
+ - severity;
32
+ - affected assets/workflows;
33
+ - rationale for acceptance;
34
+ - compensating controls;
35
+ - owner;
36
+ - review date or trigger;
37
+ - approver and approval date;
38
+ - related issue/commit/document evidence where applicable.
39
+
40
+ Evidence is not approval. A finding listed under proposed or monitored risks remains unaccepted until explicitly approved.
41
+
42
+ ## Accepted risks
43
+
44
+ _No accepted risks are currently recorded._
45
+
46
+ ## Proposed or monitored risks
47
+
48
+ | ID | Status | Severity | Risk | Current controls | Required decision / next action |
49
+ | --- | --- | --- | --- | --- | --- |
50
+ | RISK-SEC-001 | Monitored, not accepted as permanent | Medium | GitHub secret scanning is unavailable/disabled in current repository evidence, so GitHub-native secret scanning cannot be relied on as a control. | Local/CI `gitleaks` gate, `MOOSE_INVENTORY_REQUIRE_SECURITY_TOOLS=1 ./scripts/check.sh`, docs warning against committing secrets. | Revisit if GitHub secret scanning becomes available. If releases rely on this limitation long-term, record an explicit accepted-risk decision or enable equivalent control. |
51
+ | RISK-SEC-002 | Evaluated, not accepted as release blocker | Low | Additional signed provenance/artifact attestations beyond RubyGems trusted publishing are not a current requirement. | RubyGems trusted publishing/OIDC, package sanity check, release workflow gate, package provenance hardening evaluation. | Revisit if security-sensitive consumers, release policy, or supply-chain requirements justify checksums, GitHub artifact attestations, signatures, or SBOM publication. |
52
+ | RISK-SEC-003 | Open process gap, not accepted | Medium | Public vulnerability intake is informal without a repo-local `SECURITY.md` or private advisory workflow documented for users. | GitHub issues for non-sensitive reports, maintainer/private coordination where available, security audit docs. | Decide whether to add public `SECURITY.md` as part of security/privacy baseline approval or maintenance runbook work. |
53
+ | RISK-SEC-004 | Open UX gap, not accepted | Medium | Destructive CLI commands do not yet have a consistent explicit confirmation / `--yes` pattern. | Explicit command names, dry-run support, tests, UX implementation backlog. | Complete UX implementation backlog item before expanding destructive behavior. |
54
+ | RISK-SEC-005 | Mitigated release-governance gap, monitor next release | Low | GitHub `release` environment protection rules were absent when first documented on 2026-05-29. They are now configured with required reviewer `RusDavies`, self-review prevention disabled, admin bypass disabled, and a custom `v*` deployment policy. Self-review prevention is disabled because OpenClaw/automation pushes use Russ's GitHub account, and `RusDavies` is currently the only required reviewer. GitHub reports the custom policy object as `type: branch`, so tag-deployment behavior still needs verification on the next real release. | Release workflow only runs on `v*` tags, verifies tag/version alignment, runs full security-required check gate, uses RubyGems trusted publishing/OIDC, and now requires environment review before the release job proceeds. | Verify next real `v*` tag release can deploy after approval. If the custom policy blocks tags, adjust the environment policy or document the GitHub limitation. |
55
+
56
+ ## Accepted-risk template
57
+
58
+ ```markdown
59
+ ### RISK-SEC-XXX: Short risk name
60
+
61
+ - Status: Proposed | Accepted | Retired
62
+ - Severity: Critical | High | Medium | Low
63
+ - Affected assets/workflows:
64
+ - Decision scope:
65
+ - Risk statement:
66
+ - Rationale for acceptance:
67
+ - Compensating controls:
68
+ - Owner:
69
+ - Review trigger/date:
70
+ - Approver:
71
+ - Approval date:
72
+ - Evidence:
73
+ ```
74
+
75
+ ## Review cadence
76
+
77
+ Review this register:
78
+
79
+ - before each material public release;
80
+ - when `scripts/check.sh` or security tooling changes;
81
+ - when a security audit finds a new issue;
82
+ - when a dependency advisory affects the supported dependency set;
83
+ - when release infrastructure, RubyGems trusted publishing, or GitHub environment protection changes;
84
+ - when a proposed risk is accepted, retired, or no longer accurate.