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,287 @@
1
+ # Moose Inventory Security and Privacy Process
2
+
3
+ ## Approval status
4
+
5
+ Status: **Approved**
6
+
7
+ Russ / Rusty Frink Desiato approved this document as the Moose Inventory security and privacy process baseline on 2026-05-29. Approval reference: `GOV-SEC-001`.
8
+
9
+ This document captures the maintained security and privacy process baseline for Moose Inventory. It is prepared from the approved product, requirements, CLI UX, and architecture baselines, plus current security-audit evidence and verification scripts.
10
+
11
+ Approved references:
12
+
13
+ - `GOV-TAILOR-001`: Moose Inventory is approved as Class 4 with target profile Software Library / Package.
14
+ - `GOV-PRODUCT-001`: `docs/product/product-brief.md` is approved as the product-framing baseline.
15
+ - `GOV-REQ-001`: `docs/product/requirements-baseline.md` is approved as the requirements and acceptance criteria baseline.
16
+ - `GOV-UX-001`: `docs/ux/cli-workflow-notes.md` is approved as the CLI UX/workflow baseline.
17
+ - `GOV-ARCH-001`: `docs/architecture/architecture-and-trust-boundaries.md` is approved as the architecture and trust-boundary baseline.
18
+ - `GOV-SEC-001`: this document is approved as the security and privacy process baseline.
19
+
20
+ Scope limit: this document covers security and privacy process expectations for a Ruby CLI/RubyGem package. It is not release approval, accepted-risk approval, public/compliance-claim approval, RubyGems publishing approval, or approval to operate Moose Inventory as a hosted service. Approval of this baseline does not approve any proposed or monitored risk in the accepted-risk register.
21
+
22
+ ## Security posture summary
23
+
24
+ Moose Inventory is a local/automation-run CLI and RubyGem. It is not a hosted service and does not provide authentication, multi-user authorization, network listeners, or a managed SaaS control plane.
25
+
26
+ The main security responsibilities are:
27
+
28
+ - avoid leaking inventory, environment, and credential data;
29
+ - avoid unsafe mutation of inventory state;
30
+ - preserve package and release integrity;
31
+ - keep dependencies and CI/release tooling scanned;
32
+ - give maintainers a clear vulnerability intake and patch process;
33
+ - record accepted risks explicitly instead of smuggling them through vibes, the least trustworthy transport layer.
34
+
35
+ ## Assets and data classification
36
+
37
+ | Asset / data | Classification | Location / flow | Handling expectation |
38
+ | --- | --- | --- | --- |
39
+ | Inventory host and group names | Internal / environment-sensitive | User database, CLI output, snapshot exports, Ansible integration | Treat as potentially sensitive infrastructure metadata. Avoid publishing real inventories in examples, issues, logs, or screenshots. |
40
+ | Host/group variables | Internal to confidential depending on user content | User database, CLI output, snapshot exports, Ansible integration | Values may contain endpoints, usernames, tokens, or operational details. Users should not store secrets as inventory variables unless their environment explicitly protects them. |
41
+ | Database configuration | Confidential when credentials are present | YAML config files and selected environment sections | Prefer `password_env`; discourage committed plaintext passwords. Doctor should flag plaintext DB password configuration. |
42
+ | Environment variables containing DB passwords | Secret | User shell, CI environment, process environment | Do not log. Do not print in diagnostics. Rotate outside Moose Inventory if exposed. |
43
+ | SQLite database file | Internal to confidential | User-selected local filesystem path | User controls filesystem permissions, backups, and deletion. Backup copies inherit sensitivity of source data. |
44
+ | MySQL/MariaDB/PostgreSQL database state | Internal to confidential | User-managed database server | User controls database users, network access, server backup, restore, and encryption posture. |
45
+ | Audit/change records | Internal / environment-sensitive | User database audit tables and CLI audit output | Preserve append-only intent. Treat as operational history; avoid leaking in public bug reports. |
46
+ | Snapshot import/export files | Internal to confidential | Files passed to `import`/`export`, CI artifacts | Treat as inventory data. Review before sharing. Avoid storing secrets in exported snapshots. |
47
+ | CI/release artifacts and built gem | Public once released | GitHub Actions, RubyGems, local `tmp/pkg` | Verify package sanity and release workflow integrity before publishing. |
48
+ | Security-audit and release evidence | Internal to public depending on repo visibility | `docs/`, CI logs, release records | Avoid secrets. Make limitations explicit. Evidence is not approval by itself. |
49
+
50
+ ## Data flows
51
+
52
+ ### Local CLI mutation flow
53
+
54
+ ```text
55
+ Human / automation caller
56
+ |
57
+ v
58
+ moose-inventory CLI arguments/options
59
+ |
60
+ v
61
+ config discovery + selected environment
62
+ |
63
+ v
64
+ operation object validation
65
+ |
66
+ v
67
+ transactional database write
68
+ |
69
+ v
70
+ CLI output + audit/change record where applicable
71
+ ```
72
+
73
+ Security expectations:
74
+
75
+ - Validate arguments before mutation where practical.
76
+ - Keep dry-run non-mutating.
77
+ - Use transactions for write operations where practical.
78
+ - Do not print configured database passwords or environment-variable values.
79
+ - Keep destructive or high-risk changes explicit and reviewable.
80
+
81
+ ### Snapshot import/export flow
82
+
83
+ ```text
84
+ inventory.yml / inventory.json
85
+ |
86
+ v
87
+ parser + snapshot validator
88
+ |
89
+ v
90
+ transactional import apply OR validation failure
91
+ |
92
+ v
93
+ exported snapshot / CLI report / audit evidence
94
+ ```
95
+
96
+ Security expectations:
97
+
98
+ - Validate before write.
99
+ - Treat snapshot files as potentially confidential.
100
+ - Do not make import a destructive sync unless separately designed, documented, tested, and approved.
101
+ - Future preview/diff behavior should remain non-mutating.
102
+
103
+ ### Release and dependency flow
104
+
105
+ ```text
106
+ source + Gemfile.lock + workflows
107
+ |
108
+ v
109
+ scripts/check.sh
110
+ |
111
+ +--> RSpec / coverage
112
+ +--> RuboCop
113
+ +--> git diff --check
114
+ +--> permissions check
115
+ +--> OSV / bundler-audit
116
+ +--> gitleaks
117
+ +--> package sanity
118
+ |
119
+ v
120
+ reviewed tag + GitHub release workflow
121
+ |
122
+ v
123
+ RubyGems trusted publishing / OIDC
124
+ ```
125
+
126
+ Security expectations:
127
+
128
+ - Release jobs must require the same security-tool coverage expected by CI.
129
+ - A passing check is evidence, not release approval.
130
+ - Trusted publishing is the current package provenance baseline.
131
+ - Additional signed provenance or artifact attestations are future hardening, not a current blocker unless separately approved.
132
+
133
+ ## Threat and abuse-case model
134
+
135
+ | ID | Threat / abuse case | Impact | Current controls | Follow-up posture |
136
+ | --- | --- | --- | --- | --- |
137
+ | T-001 | User commits plaintext DB passwords in config | Credential disclosure | README guidance, `password_env`, doctor finding for plaintext password config, local `gitleaks` gate | Keep plaintext password support for compatibility; prefer `password_env`; track secret-scanning limits in risk register. |
138
+ | T-002 | Inventory snapshots or audit output are shared publicly | Infrastructure metadata disclosure | Documentation guidance, export is explicit, audit output is user-invoked | Treat snapshots/audit as sensitive; future docs should repeat sharing guidance near examples. |
139
+ | T-003 | Wrong config/environment is selected | Accidental mutation of wrong inventory DB | Explicit `--config`, `--env`, config validation, dry-run support | Future destructive confirmation should show environment/config context. |
140
+ | T-004 | Destructive commands remove intended inventory state without enough friction | Operational disruption | Explicit command names, dry-run coverage, backlog item for destructive confirmation | Implement confirmation/`--yes` behavior before expanding destructive workflows. |
141
+ | T-005 | Malformed import file causes partial or inconsistent writes | Data corruption | Snapshot validation before apply, transactional import | Keep import validation coverage with schema changes. |
142
+ | T-006 | Duplicate/conflicting DB records bypass application logic | Corrupt inventory behavior | Schema uniqueness/index migrations, duplicate cleanup/refusal | Keep migration tests and future-schema refusal. |
143
+ | T-007 | CLI input reaches shell execution | Command injection | Application uses Ruby/Sequel operations, not shell execution for inventory mutations | Security reviews should re-check new integrations for shell invocation. |
144
+ | T-008 | Dependency vulnerability ships in a release | User environment compromise | OSV query, `osv-scanner`, `bundler-audit`, release parity enforcement | Patch according to vulnerability policy below; accept residual risk only through risk register. |
145
+ | T-009 | Secret scanner is unavailable in GitHub repository settings | Missed committed secrets | Local/CI `gitleaks` gate | Track as accepted/monitored residual risk until GitHub secret scanning is available/enabled. |
146
+ | T-010 | Release workflow publishes unreviewed or tampered package | Supply-chain compromise | GitHub Actions release workflow, trusted publishing/OIDC, package sanity, tag/version checks | Document confirmed release environment protections after maintainers verify settings. |
147
+ | T-011 | Database server backups/restores are assumed to be handled by Moose Inventory | Data loss or false assurance | Architecture says server-backed DB operations remain user-managed; `docs/maintenance/database-backup-restore-guidance.md` documents native-tool backup/restore boundaries for SQLite, MySQL/MariaDB, and PostgreSQL | Keep backup/restore guidance current when database lifecycle commands change. |
148
+ | T-012 | AI-assisted maintenance performs external or irreversible actions without approval | Governance/security failure | Workspace process and approval register | Repo-local AI-agent boundaries remain a separate process item. |
149
+
150
+ ## Authentication and authorization model
151
+
152
+ Moose Inventory does not authenticate users itself. It relies on the caller's local operating-system account, shell environment, filesystem permissions, and configured database credentials.
153
+
154
+ Authorization boundaries:
155
+
156
+ - CLI execution authority is inherited from the local user or automation account running the command.
157
+ - SQLite access is controlled by filesystem permissions.
158
+ - MySQL/MariaDB/PostgreSQL access is controlled by the configured database account and server policy.
159
+ - GitHub/RubyGems release authority is controlled outside the gem by repository, workflow, environment, and trusted-publishing configuration.
160
+
161
+ Security expectations:
162
+
163
+ - Use least-privilege database accounts where practical.
164
+ - Avoid sharing config files that contain credentials.
165
+ - Keep release and package-publishing authority human-owned and separately approved.
166
+ - Do not imply Moose Inventory provides RBAC or tenant isolation.
167
+
168
+ ## Secrets handling model
169
+
170
+ Preferred posture:
171
+
172
+ - Use `password_env` for DB passwords.
173
+ - Store secrets in the caller's environment, shell secret manager, CI secret store, or database/platform secret mechanism.
174
+ - Keep plaintext `password` only as a compatibility option.
175
+
176
+ Rules:
177
+
178
+ - Do not print DB passwords in normal output, errors, doctor reports, or audit records.
179
+ - Do not add examples that contain real secrets, tokens, host inventories, or live infrastructure details.
180
+ - Do not commit `.env`, real config files, live inventory exports, database files, or secret-containing logs.
181
+ - If a secret is committed, rotate it outside Moose Inventory and record the incident/cleanup evidence.
182
+
183
+ ## Logging and audit expectations
184
+
185
+ Moose Inventory has an append-only audit/change-history feature for inventory mutations. That audit log is product evidence and operational history, not a rollback system and not a tamper-proof security ledger.
186
+
187
+ Expectations:
188
+
189
+ - Mutating commands should record meaningful audit/change evidence where supported.
190
+ - Dry-runs should not mutate inventory state or audit history.
191
+ - Audit output may contain host/group names and variable names; treat it as environment-sensitive.
192
+ - Audit records should not include database passwords or environment-variable secret values.
193
+ - Any future richer audit export should document confidentiality and retention expectations.
194
+
195
+ ## Privacy posture
196
+
197
+ Moose Inventory does not intentionally collect personal data, telemetry, analytics, or hosted-service user behavior.
198
+
199
+ Privacy expectations:
200
+
201
+ - No built-in telemetry without separate product approval.
202
+ - No external network calls during normal inventory operations except database connections explicitly configured by the user.
203
+ - Dependency/security checks in maintainer workflows may contact external advisory services such as OSV and Ruby advisory sources; this is release/maintenance evidence, not runtime telemetry.
204
+ - User inventories may include personal data if users put it there. Treat exported snapshots, audit records, and DB backups according to the sensitivity of user-provided content.
205
+
206
+ ## Vulnerability intake and security patch policy
207
+
208
+ ### Intake channels
209
+
210
+ Current maintained intake channels:
211
+
212
+ - GitHub issues for non-sensitive bugs and security-hardening requests.
213
+ - Direct maintainer contact or private coordination for sensitive vulnerability details when available.
214
+ - Security audit findings recorded under `docs/security-audit-*.md`.
215
+
216
+ Future improvement:
217
+
218
+ - Add a `SECURITY.md` file if maintainers want a public vulnerability-reporting policy on GitHub.
219
+
220
+ ### Triage severity
221
+
222
+ Use the highest applicable severity:
223
+
224
+ - Critical: credible package compromise, credential disclosure in release tooling, arbitrary code execution reachable through normal CLI use, or destructive data corruption with no workaround.
225
+ - High: dependency vulnerability reachable in supported use, unsafe secret exposure, release workflow bypass, or destructive mutation bug likely to affect real inventory.
226
+ - Medium: validation bypass, denial-of-service condition, confusing security-sensitive UX, or hardening gap with plausible user impact.
227
+ - Low: documentation clarity, defense-in-depth, non-reachable dependency advisory, or scanner/process improvement.
228
+
229
+ ### Patch targets
230
+
231
+ Targets are guidance, not an SLA promise:
232
+
233
+ - Critical: stop release activity, prepare fix or mitigation immediately, and require human approval before publishing.
234
+ - High: prioritize before feature work and target the next patch release.
235
+ - Medium: add to backlog with owner/evidence and fix in an upcoming maintenance slice.
236
+ - Low: handle opportunistically or with related docs/process work.
237
+
238
+ ### Release and disclosure
239
+
240
+ - Do not publish a release that knowingly ships an unresolved critical/high security issue unless a human approver records accepted risk.
241
+ - Release notes should describe security fixes at an appropriate level without handing attackers a nicely gift-wrapped exploit manual.
242
+ - If a published gem is compromised or materially unsafe, a human maintainer must decide whether to yank, deprecate, patch, or publish an advisory.
243
+
244
+ ## Security acceptance criteria
245
+
246
+ Security-ready for a release candidate means:
247
+
248
+ - `MOOSE_INVENTORY_REQUIRE_SECURITY_TOOLS=1 ./scripts/check.sh` passes or exceptions are explicitly recorded.
249
+ - No known unresolved critical/high findings remain unless accepted through the risk register.
250
+ - Dependency/advisory scans are current enough for the release decision.
251
+ - Secret scan passes or any finding is triaged, cleaned, and rotated where needed.
252
+ - Package sanity passes for the gem artifact.
253
+ - Release docs and checklist identify any accepted risks, limitations, and non-goals.
254
+ - Approval records distinguish evidence from human approval.
255
+
256
+ ## Accepted-risk register relationship
257
+
258
+ Accepted risks live in `docs/security/accepted-risk-register.md`.
259
+
260
+ Rules:
261
+
262
+ - A risk entry may be proposed by an agent or maintainer, but acceptance requires explicit human approval.
263
+ - Each accepted risk must include scope, reason, compensating controls, owner, review trigger/date, and approval reference.
264
+ - Empty or pending risk tables are useful evidence; they do not mean all risk is approved.
265
+
266
+ ## Current known limitations and compensating controls
267
+
268
+ | Limitation | Current posture | Compensating control / next action |
269
+ | --- | --- | --- |
270
+ | GitHub secret scanning is unavailable/disabled for this repository in current evidence | Not accepted as a permanent claim; tracked as residual posture | Local/CI `gitleaks` gate remains required. Revisit if GitHub secret scanning becomes available. |
271
+ | MySQL/MariaDB/PostgreSQL backups/restores are user-managed | Architecture scope boundary | Expanded guidance lives in `docs/maintenance/database-backup-restore-guidance.md`; update it when database lifecycle commands change. |
272
+ | Public vulnerability intake is informal | Draft process only | Consider adding `SECURITY.md` or GitHub private vulnerability reporting if maintainers want public intake clarity. |
273
+ | Destructive CLI confirmation is not fully implemented | UX follow-up backlog | Implement explicit confirmation / `--yes` behavior before expanding destructive workflows. |
274
+ | Additional package provenance is not required beyond trusted publishing | Architecture decision | Evaluate signed provenance/artifact attestations as future hardening if justified. |
275
+
276
+ ## Review cadence
277
+
278
+ Review this document when any of the following changes:
279
+
280
+ - supported database adapters or schema migration behavior;
281
+ - import/export or audit data handling;
282
+ - release workflow, trusted publishing, or security scanning tools;
283
+ - vulnerability intake expectations;
284
+ - public security/compliance claims;
285
+ - a security incident, secret exposure, or accepted-risk decision.
286
+
287
+ At minimum, revisit before each material public release.
@@ -52,7 +52,7 @@ Reviewed security-relevant surfaces and changes since the prior audit:
52
52
  - Impact: a release tag created from an unexpected commit or during a tooling/path issue could publish without the same dedicated SCA/secret-scan enforcement as CI.
53
53
  - Fix applied: release workflow now sets up Go with cache disabled, installs the pinned security CLIs via `scripts/ci/install_security_tools.sh`, runs native dependency installation with a 5-minute timeout, and runs `./scripts/check.sh` with `MOOSE_INVENTORY_REQUIRE_SECURITY_TOOLS=1`.
54
54
  - Verification: full local required-tool gate passed after the workflow change.
55
- - Residual risk: release workflow can only be fully proven on the next real release tag because already-published `v1.0.9` must not be retagged.
55
+ - Residual risk after later verification: trusted publishing was proven on release tag `v2.0`, but the workflow still has a false-negative path where post-publish waiting can fail if the RubyGems full index lags even after a successful publish.
56
56
 
57
57
  ## Reviewed areas with no actionable finding
58
58
 
@@ -68,7 +68,7 @@ Reviewed security-relevant surfaces and changes since the prior audit:
68
68
  - This was a local/source and CI/release workflow audit, not an active test against live external databases or RubyGems publishing.
69
69
  - GitHub code scanning is not configured, so there were no CodeQL/code-scanning results to review.
70
70
  - GitHub secret scanning is disabled for the repository; local `gitleaks` coverage was used instead.
71
- - The release trusted-publishing path still needs verification on the next real version tag.
71
+ - The release trusted-publishing path was later verified on `v2.0`; the remaining limitation is that workflow success/failure still depends on RubyGems full-index propagation timing.
72
72
 
73
73
  ## Conclusion
74
74
 
@@ -0,0 +1,287 @@
1
+ # Moose Inventory CLI UX and Workflow Notes
2
+
3
+ ## Approval status
4
+
5
+ Status: **Approved CLI UX/workflow baseline**
6
+
7
+ Approval reference: `GOV-UX-001` in `docs/governance/approval-register.md` approves this document as the CLI UX/workflow baseline for Moose Inventory.
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
+
15
+ Scope limit: this approval covers command-line workflows and interaction conventions only. It is not architecture approval, security/privacy design approval, release approval, accepted-risk approval, public/compliance-claim approval, RubyGems publishing approval, or implementation approval for the UX follow-up backlog items.
16
+
17
+ ## UX posture
18
+
19
+ Moose Inventory is a command-line tool and RubyGem, so its UX baseline is not wireframes or visual mockups. The appropriate UX artifact is a workflow and interaction convention baseline for CLI users, automation users, reviewers, and maintainers.
20
+
21
+ Primary UX priorities:
22
+
23
+ 1. Make inventory-changing actions explicit, reviewable, and hard to mistake for read-only actions.
24
+ 2. Preserve existing command names, output shape, and wording where users or tests may depend on them.
25
+ 3. Keep machine-readable output parseable and stable enough for automation.
26
+ 4. Give clear, actionable error messages before any write occurs when inputs/options are invalid.
27
+ 5. Keep safety controls visible: transactions, dry-run, plan output, validation, doctor checks, and audit history.
28
+
29
+ ## User personas and interaction modes
30
+
31
+ ### CLI operator
32
+
33
+ A human operator uses `moose-inventory` directly to inspect and change inventory state.
34
+
35
+ UX needs:
36
+
37
+ - discoverable help
38
+ - predictable command families
39
+ - readable progress output
40
+ - clear success/failure states
41
+ - safe review before mutation
42
+
43
+ ### Automation/review consumer
44
+
45
+ A script, CI job, or reviewer consumes machine-readable output from list/get/doctor/export/dry-run plan commands.
46
+
47
+ UX needs:
48
+
49
+ - parseable YAML/JSON/pjson
50
+ - non-zero status for failed checks/findings where documented
51
+ - stable keys and event structure
52
+ - no secret leakage in examples/output
53
+
54
+ ### Maintainer/release reviewer
55
+
56
+ A maintainer checks behavior, documentation, release evidence, and compatibility.
57
+
58
+ UX needs:
59
+
60
+ - regression tests for output contracts
61
+ - README examples matching supported behavior
62
+ - clear approval boundaries for breaking changes
63
+ - process evidence distinguishing checks from approval
64
+
65
+ ## Core workflows
66
+
67
+ ### 1. Discover commands
68
+
69
+ Workflow:
70
+
71
+ 1. User runs top-level or nested help.
72
+ 2. CLI displays available commands/options.
73
+ 3. User chooses a command family such as `host`, `group`, `db`, `audit`, `doctor`, `import`, or `export`.
74
+
75
+ UX expectations:
76
+
77
+ - Help must be available at top-level and command-family levels.
78
+ - Help examples should be accurate enough to copy/adapt.
79
+ - New command families should follow existing README/help style.
80
+
81
+ ### 2. Select configuration and environment
82
+
83
+ Workflow:
84
+
85
+ 1. User relies on config discovery or passes `--config <FILE>`.
86
+ 2. User relies on `general.defaultenv` or passes `--env <SECTION>`.
87
+ 3. CLI initializes the configured database context.
88
+
89
+ UX expectations:
90
+
91
+ - Missing config, missing environment, and invalid DB config errors should fail before mutation.
92
+ - Error messages should name the missing/invalid element when practical.
93
+ - Docs should steer users toward `password_env` rather than plaintext `password`.
94
+
95
+ ### 3. Inspect inventory
96
+
97
+ Workflow:
98
+
99
+ 1. User runs list/get commands for hosts/groups/variables/tags.
100
+ 2. User optionally passes `--format yaml|json|pjson`.
101
+ 3. CLI returns current state without mutation.
102
+
103
+ UX expectations:
104
+
105
+ - Read-only commands should not create, repair, or migrate data implicitly unless explicitly documented.
106
+ - Machine-readable formats should remain parseable and consistent.
107
+ - Empty results should be explicit rather than misleading.
108
+
109
+ ### 4. Mutate inventory safely
110
+
111
+ Workflow:
112
+
113
+ 1. User chooses a mutating command: add/remove hosts/groups, variables, tags, associations, or child relationships.
114
+ 2. User optionally previews with `--dry-run` or `--dry-run --plan-format`.
115
+ 3. CLI validates inputs/options before writes.
116
+ 4. Destructive removal commands require `--yes` before writing unless the user selected `--dry-run`.
117
+ 5. CLI applies changes transactionally when not dry-run.
118
+ 5. CLI reports progress, warnings, success/failure, and audit evidence where applicable.
119
+
120
+ UX expectations:
121
+
122
+ - Mutating commands must be visually distinguishable from read-only workflows through command naming, progress output, and documentation.
123
+ - Invalid option combinations, such as `--plan-format` without `--dry-run`, fail before mutation.
124
+ - Removal commands should fail closed without `--yes`, while still allowing dry-run preview without confirmation.
125
+ - Dry-run output must not imply changes were applied.
126
+ - Real mutation output should preserve existing output contracts unless a breaking change is approved.
127
+
128
+ ### 5. Review planned changes
129
+
130
+ Workflow:
131
+
132
+ 1. User runs a mutating command with `--dry-run`.
133
+ 2. CLI renders planned progress and ends with `Dry run complete. No changes applied.`
134
+ 3. User optionally requests `--plan-format yaml|json|pjson` for automation review.
135
+
136
+ UX expectations:
137
+
138
+ - Dry-run should use the same conceptual progress path as a real mutation.
139
+ - Dry-run should not write inventory, audit records, schema state, or automatic cleanup associations.
140
+ - Plan output should include ordered event types and payloads suitable for review tools.
141
+ - Human-readable dry-run output should remain easy to compare with real command output.
142
+
143
+ ### 6. Validate health
144
+
145
+ Workflow:
146
+
147
+ 1. User runs `moose-inventory doctor`.
148
+ 2. CLI performs read-only checks.
149
+ 3. CLI reports no issues or lists findings with severity/check identifiers.
150
+ 4. CLI exits non-zero when findings are present.
151
+
152
+ UX expectations:
153
+
154
+ - Findings should be actionable and identify affected subject when practical.
155
+ - Machine-readable doctor output should be suitable for CI gates.
156
+ - Doctor should not silently fix inventory; repairs should remain explicit user actions.
157
+
158
+ ### 7. Import/export snapshots
159
+
160
+ Workflow:
161
+
162
+ 1. User exports inventory for review, backup, migration, or automation.
163
+ 2. User previews a YAML/JSON snapshot with `import FILE --preview` or `--preview --preview-format yaml|json|pjson` when reviewing a proposed change.
164
+ 3. User imports a YAML/JSON snapshot.
165
+ 4. CLI validates before writing and applies additive/update-oriented changes only.
166
+
167
+ UX expectations:
168
+
169
+ - Export should be read-only.
170
+ - Import preview should be read-only and distinct from command-level dry-run planning.
171
+ - Preview output should show creates, variable updates, association additions, unchanged items, ignored existing records, and destructive-change count.
172
+ - Import validation failures should avoid partial writes.
173
+ - Additive import semantics must be documented clearly.
174
+ - Destructive sync/restore semantics must not be introduced without separate requirements, UX, recovery, and approval records.
175
+
176
+ ### 8. Review audit history
177
+
178
+ Workflow:
179
+
180
+ 1. User runs `audit list` with optional format/limit.
181
+ 2. CLI returns append-only evidence for successful mutating commands.
182
+
183
+ UX expectations:
184
+
185
+ - Audit output should help explain what changed, when, by whom/tooling, and against what target.
186
+ - Audit output is accountability/debug evidence, not rollback by itself.
187
+ - Dry-runs should not appear as mutation audit records.
188
+
189
+ ## Destructive and high-risk operations
190
+
191
+ High-risk CLI areas include:
192
+
193
+ - host/group removal
194
+ - recursive group deletion
195
+ - child-group cleanup with orphan deletion
196
+ - variable removal
197
+ - snapshot import into populated databases
198
+ - schema migration
199
+ - backup/restore-adjacent workflows
200
+ - future destructive snapshot sync/restore features, if ever approved
201
+
202
+ UX requirements for high-risk operations:
203
+
204
+ 1. The command name/options must make destructive intent visible.
205
+ 2. Documentation must describe mutation scope and notable cleanup behavior.
206
+ 3. `--dry-run` should be available for documented mutating workflows where supported.
207
+ 4. Invalid inputs/options must fail before writes.
208
+ 5. Real writes should be transactional where practical.
209
+ 6. Future destructive restore/sync behavior requires a separate UX design and approval record.
210
+
211
+ ## Error states and messaging
212
+
213
+ Expected error behavior:
214
+
215
+ - fail early before mutation when arguments/options/config are invalid
216
+ - name the invalid option/value where practical
217
+ - distinguish usage errors from database/runtime failures
218
+ - preserve existing exact error strings where tests or downstream users rely on them
219
+ - avoid exposing secrets in errors
220
+
221
+ Known UX improvement area:
222
+
223
+ - Read-only console parsing now uses shell-style quoting and command-specific validation for the current browsing commands. Future console changes should preserve the read-only boundary unless mutation flows add confirmation, dry-run, and audit behavior.
224
+
225
+ ## Accessibility and readability expectations
226
+
227
+ For a CLI, accessibility/readability means:
228
+
229
+ - plain text that works in ordinary terminals
230
+ - no required color-only signal
231
+ - stable indentation for progress output
232
+ - concise severity/check IDs for doctor findings
233
+ - machine-readable alternatives for automation and assistive tooling
234
+ - examples that can be copied without hidden state or secrets
235
+ - readable failure messages rather than stack traces for ordinary user errors
236
+
237
+ ## Machine-readable output conventions
238
+
239
+ Machine-readable output is automation-facing UX and is governed by `CLI-OUTPUT-v1` in `docs/compatibility/cli-output-compatibility.md`.
240
+
241
+ Expectations:
242
+
243
+ - JSON/YAML/pjson structures should remain parseable.
244
+ - Event/check keys should not be renamed casually.
245
+ - New fields should prefer additive compatibility.
246
+ - Breaking output changes require approval and migration/release notes.
247
+ - Pretty JSON is for humans reviewing structured data; normal JSON/YAML are for scripts and CI.
248
+
249
+ ## Compatibility conventions
250
+
251
+ Human-readable output is also a versioned compatibility surface under `CLI-OUTPUT-v1` when tests, docs, or scripts rely on exact wording.
252
+
253
+ Expectations:
254
+
255
+ - Preserve existing wording/newline behavior during refactors unless an intentional change is approved.
256
+ - Tests should cover known legacy output contracts, especially around warnings and cleanup behavior.
257
+ - README examples should not promise output that the CLI no longer emits.
258
+ - Breaking human-readable output changes need backlog/approval evidence and release notes just like machine-readable breaking changes.
259
+
260
+ ## UX acceptance checklist
261
+
262
+ A new or changed CLI workflow is UX-ready when:
263
+
264
+ - The command path and option names are consistent with existing command families.
265
+ - Read vs write behavior is obvious from command naming and docs.
266
+ - Invalid inputs/options fail before mutation.
267
+ - Mutating behavior is transactional where practical.
268
+ - Dry-run/plan behavior exists where required by the requirements baseline.
269
+ - Human-readable output is clear and compatible unless an approved breaking change exists.
270
+ - Machine-readable output is parseable and compatibility-reviewed.
271
+ - README/help examples are updated where user-facing behavior changed.
272
+ - Tests cover success, failure, and safety boundaries.
273
+ - Any unresolved UX risk is recorded as a backlog item or accepted risk.
274
+
275
+ ## UX decisions recorded from review
276
+
277
+ These decisions were provided by Russ during review on 2026-05-28. They are captured here as product/UX direction for future implementation, but this draft UX baseline still requires explicit approval through `GOV-UX-001` before it becomes approved UX evidence.
278
+
279
+ 1. Destructive commands should eventually require explicit confirmation unless `--yes` or an equivalent non-interactive acknowledgement is provided.
280
+ 2. Human-readable output compatibility is formally versioned through `CLI-OUTPUT-v1`, alongside machine-readable output compatibility.
281
+ 3. Read-only console support for quoted names and richer validation through `Shellwords.split` should be prioritized before adding more CLI features.
282
+ 4. Audit history should remain evidence only; future rollback/change-set UX should not be introduced through audit history.
283
+ 5. Snapshot import should eventually offer a formal preview/diff mode distinct from command-level dry-run planning, but this is future work and does not block the current UX baseline.
284
+
285
+ ## Open UX questions
286
+
287
+ No open UX questions remain in this draft. Future questions should be added here only when they are not already represented as a decision, backlog item, or accepted scope limit.
@@ -0,0 +1,3 @@
1
+ [defaults]
2
+ inventory = inventory/moose_inventory.yml
3
+ inventory_plugins = inventory_plugins
@@ -0,0 +1,5 @@
1
+ ---
2
+ plugin: moose_inventory
3
+ executable: moose-inventory
4
+ config: ./example.conf
5
+ env: dev