moose-inventory 1.0.9 → 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 (176) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +15 -1
  3. data/.github/workflows/release.yml +60 -0
  4. data/.gitignore +2 -1
  5. data/.gitleaks.toml +9 -0
  6. data/.rubocop.yml +49 -0
  7. data/BACKLOG.md +752 -24
  8. data/Gemfile +2 -0
  9. data/Gemfile.lock +36 -1
  10. data/README.md +340 -44
  11. data/Rakefile +2 -0
  12. data/bin/moose-inventory +2 -1
  13. data/docs/architecture/architecture-and-trust-boundaries.md +444 -0
  14. data/docs/compatibility/cli-output-compatibility.md +76 -0
  15. data/docs/governance/approval-register.md +37 -0
  16. data/docs/maintenance/database-backup-restore-guidance.md +162 -0
  17. data/docs/maintenance/package-maintenance-and-agent-boundaries.md +260 -0
  18. data/docs/process/conformance-gap-analysis-2026-05-28.md +192 -0
  19. data/docs/product/product-brief.md +161 -0
  20. data/docs/product/requirements-baseline.md +477 -0
  21. data/docs/qa/qa-documentation-and-release-gates.md +283 -0
  22. data/docs/release/package-provenance-hardening.md +126 -0
  23. data/docs/release/publishing.md +54 -50
  24. data/docs/release/release-environment-protection.md +70 -0
  25. data/docs/release/release-readiness.md +37 -4
  26. data/docs/security/accepted-risk-register.md +84 -0
  27. data/docs/security/security-privacy-process.md +287 -0
  28. data/docs/security-audit-2026-05-26-rerun.md +75 -0
  29. data/docs/security-audit-2026-05-26.md +63 -0
  30. data/docs/ux/cli-workflow-notes.md +287 -0
  31. data/examples/ansible/ansible.cfg +3 -0
  32. data/examples/ansible/inventory/moose_inventory.yml +5 -0
  33. data/examples/ansible/inventory_plugins/moose_inventory.py +100 -0
  34. data/examples/ci/README.md +16 -0
  35. data/examples/ci/github-actions/inventory-review.yml +38 -0
  36. data/examples/ci/inventory/example-snapshot.yml +19 -0
  37. data/examples/ci/scripts/validate-inventory-snapshot.sh +30 -0
  38. data/lib/moose_inventory/cli/application.rb +133 -5
  39. data/lib/moose_inventory/cli/association_rendering.rb +74 -0
  40. data/lib/moose_inventory/cli/association_rendering_support.rb +89 -0
  41. data/lib/moose_inventory/cli/audit.rb +62 -0
  42. data/lib/moose_inventory/cli/audit_recording.rb +40 -0
  43. data/lib/moose_inventory/cli/child_relation_rendering.rb +110 -0
  44. data/lib/moose_inventory/cli/console.rb +135 -0
  45. data/lib/moose_inventory/cli/db.rb +64 -0
  46. data/lib/moose_inventory/cli/factory.rb +28 -0
  47. data/lib/moose_inventory/cli/formatter.rb +8 -12
  48. data/lib/moose_inventory/cli/group.rb +7 -1
  49. data/lib/moose_inventory/cli/group_add.rb +91 -73
  50. data/lib/moose_inventory/cli/group_addchild.rb +41 -66
  51. data/lib/moose_inventory/cli/group_addhost.rb +33 -71
  52. data/lib/moose_inventory/cli/group_addvar.rb +27 -47
  53. data/lib/moose_inventory/cli/group_get.rb +8 -42
  54. data/lib/moose_inventory/cli/group_list.rb +7 -40
  55. data/lib/moose_inventory/cli/group_listvars.rb +9 -55
  56. data/lib/moose_inventory/cli/group_rm.rb +105 -73
  57. data/lib/moose_inventory/cli/group_rmchild.rb +47 -57
  58. data/lib/moose_inventory/cli/group_rmhost.rb +34 -61
  59. data/lib/moose_inventory/cli/group_rmvar.rb +30 -41
  60. data/lib/moose_inventory/cli/group_tags.rb +33 -0
  61. data/lib/moose_inventory/cli/helpers.rb +143 -0
  62. data/lib/moose_inventory/cli/host.rb +8 -2
  63. data/lib/moose_inventory/cli/host_add.rb +91 -66
  64. data/lib/moose_inventory/cli/host_addgroup.rb +39 -66
  65. data/lib/moose_inventory/cli/host_addvar.rb +28 -52
  66. data/lib/moose_inventory/cli/host_get.rb +9 -37
  67. data/lib/moose_inventory/cli/host_list.rb +24 -21
  68. data/lib/moose_inventory/cli/host_listvars.rb +9 -62
  69. data/lib/moose_inventory/cli/host_rm.rb +60 -42
  70. data/lib/moose_inventory/cli/host_rmgroup.rb +39 -55
  71. data/lib/moose_inventory/cli/host_rmvar.rb +31 -45
  72. data/lib/moose_inventory/cli/host_tags.rb +33 -0
  73. data/lib/moose_inventory/cli/listvars_support.rb +55 -0
  74. data/lib/moose_inventory/cli/plan_rendering.rb +50 -0
  75. data/lib/moose_inventory/cli/relation_transaction_support.rb +51 -0
  76. data/lib/moose_inventory/cli/tag_support.rb +97 -0
  77. data/lib/moose_inventory/cli/variable_rendering.rb +67 -0
  78. data/lib/moose_inventory/config/config.rb +185 -108
  79. data/lib/moose_inventory/db/db.rb +188 -193
  80. data/lib/moose_inventory/db/exceptions.rb +6 -3
  81. data/lib/moose_inventory/db/models.rb +16 -0
  82. data/lib/moose_inventory/db/schema_migrations.rb +248 -0
  83. data/lib/moose_inventory/inventory_context.rb +116 -0
  84. data/lib/moose_inventory/operations/add_associations.rb +131 -0
  85. data/lib/moose_inventory/operations/add_groups.rb +123 -0
  86. data/lib/moose_inventory/operations/add_hosts.rb +123 -0
  87. data/lib/moose_inventory/operations/add_variables.rb +77 -0
  88. data/lib/moose_inventory/operations/entity_variable_operation_support.rb +46 -0
  89. data/lib/moose_inventory/operations/group_child_relations.rb +125 -0
  90. data/lib/moose_inventory/operations/group_cleanup.rb +70 -0
  91. data/lib/moose_inventory/operations/import_inventory_snapshot.rb +41 -0
  92. data/lib/moose_inventory/operations/inventory_doctor.rb +172 -0
  93. data/lib/moose_inventory/operations/inventory_snapshot.rb +60 -0
  94. data/lib/moose_inventory/operations/inventory_snapshot_applier.rb +112 -0
  95. data/lib/moose_inventory/operations/inventory_snapshot_preview.rb +174 -0
  96. data/lib/moose_inventory/operations/inventory_snapshot_validator.rb +134 -0
  97. data/lib/moose_inventory/operations/operation_event_support.rb +27 -0
  98. data/lib/moose_inventory/operations/query_inventory/base_query.rb +24 -0
  99. data/lib/moose_inventory/operations/query_inventory/group_queries.rb +86 -0
  100. data/lib/moose_inventory/operations/query_inventory/host_queries.rb +106 -0
  101. data/lib/moose_inventory/operations/query_inventory.rb +47 -0
  102. data/lib/moose_inventory/operations/remove_associations.rb +113 -0
  103. data/lib/moose_inventory/operations/remove_groups.rb +79 -0
  104. data/lib/moose_inventory/operations/remove_hosts.rb +68 -0
  105. data/lib/moose_inventory/operations/remove_variables.rb +67 -0
  106. data/lib/moose_inventory/runtime_options.rb +31 -0
  107. data/lib/moose_inventory/version.rb +3 -1
  108. data/lib/moose_inventory.rb +10 -7
  109. data/moose-inventory.gemspec +22 -35
  110. data/scripts/check.sh +3 -0
  111. data/scripts/ci/check_generated_artifacts.sh +41 -0
  112. data/scripts/ci/check_permissions.sh +5 -0
  113. data/scripts/ci/check_rubocop.sh +33 -0
  114. data/scripts/ci/check_secrets.sh +26 -0
  115. data/scripts/ci/check_security.sh +18 -0
  116. data/scripts/ci/install_security_tools.sh +47 -0
  117. data/scripts/files.rb +5 -4
  118. data/scripts/install_dependencies.sh +2 -0
  119. data/spec/examples/ci_examples_spec.rb +37 -0
  120. data/spec/lib/moose_inventory/ansible_plugin_examples_spec.rb +29 -0
  121. data/spec/lib/moose_inventory/cli/application_doctor_spec.rb +50 -0
  122. data/spec/lib/moose_inventory/cli/application_import_export_spec.rb +100 -0
  123. data/spec/lib/moose_inventory/cli/application_spec.rb +25 -15
  124. data/spec/lib/moose_inventory/cli/audit_spec.rb +56 -0
  125. data/spec/lib/moose_inventory/cli/cli_spec.rb +15 -19
  126. data/spec/lib/moose_inventory/cli/console_spec.rb +98 -0
  127. data/spec/lib/moose_inventory/cli/factory_spec.rb +27 -0
  128. data/spec/lib/moose_inventory/cli/formatter_spec.rb +95 -3
  129. data/spec/lib/moose_inventory/cli/group_add_spec.rb +140 -116
  130. data/spec/lib/moose_inventory/cli/group_addchild_spec.rb +89 -35
  131. data/spec/lib/moose_inventory/cli/group_addhost_spec.rb +81 -84
  132. data/spec/lib/moose_inventory/cli/group_addvar_spec.rb +65 -68
  133. data/spec/lib/moose_inventory/cli/group_get_spec.rb +17 -33
  134. data/spec/lib/moose_inventory/cli/group_list_spec.rb +16 -38
  135. data/spec/lib/moose_inventory/cli/group_listvar_spec.rb +33 -40
  136. data/spec/lib/moose_inventory/cli/group_rm_spec.rb +165 -85
  137. data/spec/lib/moose_inventory/cli/group_rmchild_spec.rb +100 -30
  138. data/spec/lib/moose_inventory/cli/group_rmhost_spec.rb +76 -78
  139. data/spec/lib/moose_inventory/cli/group_rmvar_spec.rb +57 -63
  140. data/spec/lib/moose_inventory/cli/group_spec.rb +2 -0
  141. data/spec/lib/moose_inventory/cli/helpers_spec.rb +146 -0
  142. data/spec/lib/moose_inventory/cli/host_add_spec.rb +170 -116
  143. data/spec/lib/moose_inventory/cli/host_addgroup_spec.rb +100 -83
  144. data/spec/lib/moose_inventory/cli/host_addvar_spec.rb +92 -74
  145. data/spec/lib/moose_inventory/cli/host_get_spec.rb +14 -33
  146. data/spec/lib/moose_inventory/cli/host_list_spec.rb +41 -33
  147. data/spec/lib/moose_inventory/cli/host_listvar_spec.rb +45 -53
  148. data/spec/lib/moose_inventory/cli/host_rm_spec.rb +66 -48
  149. data/spec/lib/moose_inventory/cli/host_rmgroup_spec.rb +73 -83
  150. data/spec/lib/moose_inventory/cli/host_rmvar_spec.rb +56 -63
  151. data/spec/lib/moose_inventory/cli/host_spec.rb +2 -0
  152. data/spec/lib/moose_inventory/cli/tags_spec.rb +81 -0
  153. data/spec/lib/moose_inventory/config/config_spec.rb +41 -3
  154. data/spec/lib/moose_inventory/db/db_spec.rb +551 -29
  155. data/spec/lib/moose_inventory/db/exceptions_spec.rb +18 -0
  156. data/spec/lib/moose_inventory/db/models_spec.rb +7 -3
  157. data/spec/lib/moose_inventory/db_lifecycle_spec.rb +73 -0
  158. data/spec/lib/moose_inventory/inventory_context_spec.rb +10 -0
  159. data/spec/lib/moose_inventory/operations/add_associations_spec.rb +111 -0
  160. data/spec/lib/moose_inventory/operations/add_groups_spec.rb +80 -0
  161. data/spec/lib/moose_inventory/operations/add_hosts_spec.rb +82 -0
  162. data/spec/lib/moose_inventory/operations/add_variables_spec.rb +103 -0
  163. data/spec/lib/moose_inventory/operations/group_child_relations_spec.rb +122 -0
  164. data/spec/lib/moose_inventory/operations/import_inventory_snapshot_spec.rb +226 -0
  165. data/spec/lib/moose_inventory/operations/inventory_doctor_spec.rb +77 -0
  166. data/spec/lib/moose_inventory/operations/inventory_snapshot_spec.rb +50 -0
  167. data/spec/lib/moose_inventory/operations/operation_event_support_spec.rb +78 -0
  168. data/spec/lib/moose_inventory/operations/query_inventory_spec.rb +146 -0
  169. data/spec/lib/moose_inventory/operations/remove_associations_spec.rb +113 -0
  170. data/spec/lib/moose_inventory/operations/remove_groups_spec.rb +78 -0
  171. data/spec/lib/moose_inventory/operations/remove_hosts_spec.rb +55 -0
  172. data/spec/lib/moose_inventory/operations/remove_variables_spec.rb +83 -0
  173. data/spec/shared/shared_config_setup.rb +4 -3
  174. data/spec/spec_helper.rb +50 -40
  175. data/spec/support/cli_harness.rb +33 -0
  176. metadata +163 -35
@@ -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
 
@@ -24,6 +37,26 @@ GitHub Actions workflow: `.github/workflows/ci.yml`.
24
37
 
25
38
  It installs native headers needed by the DB gems, runs the same `./scripts/check.sh` gate used locally, and tests the maintained Ruby version range through the GitHub Actions matrix.
26
39
 
40
+ ## Trusted publishing gate
41
+
42
+ GitHub Actions workflow: `.github/workflows/release.yml`.
43
+
44
+ The release workflow runs when a `v*` tag is pushed. It:
45
+
46
+ 1. Checks out the repository using `actions/checkout@v5`.
47
+ 2. Installs Ruby and native database build dependencies.
48
+ 3. Fails if the tag version does not match `Moose::Inventory::VERSION`.
49
+ 4. Runs the full local `./scripts/check.sh` gate.
50
+ 5. Publishes the gem with `rubygems/release-gem@v1` using RubyGems trusted publishing/OIDC.
51
+
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.
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
+
27
60
  ## Package sanity expectations
28
61
 
29
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.
@@ -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.
@@ -0,0 +1,75 @@
1
+ # Security Audit Rerun — 2026-05-26
2
+
3
+ Repository: `RusDavies/moose-inventory`
4
+ Local path: `/home/skippy/.openclaw/workspace/projects/moose-inventory`
5
+ Audited commit at start: `a07b5c89214a3cee66170217c5b38e9ad2ae093a`
6
+ Audit branch: `security-audit-2026-05-26-rerun`
7
+ Evidence store: `.openclaw-security-audit/audit.sqlite`, audit run `2`
8
+
9
+ ## Executive summary
10
+
11
+ The rerun found no exploitable application vulnerabilities in the Ruby CLI/config/database code reviewed, and all deterministic dependency, advisory, package, and secret-scanning gates passed.
12
+
13
+ One release-supply-chain hardening gap was identified and fixed during the audit: the release workflow ran `./scripts/check.sh` without installing or requiring the dedicated security tools, so a tag-based release could publish even if `gitleaks`, `osv-scanner`, or `bundler-audit` coverage was absent from that release job. CI already enforced those tools; release now does too.
14
+
15
+ ## Scope
16
+
17
+ Reviewed security-relevant surfaces and changes since the prior audit:
18
+
19
+ - GitHub Actions CI and release workflows.
20
+ - Security-tool installation and enforcement scripts.
21
+ - Ruby CLI entrypoints and Thor command surfaces.
22
+ - YAML configuration loading.
23
+ - SQLite/MySQL/PostgreSQL connection setup and password handling.
24
+ - Recursive group deletion behavior touched by recent issue work.
25
+ - Gem packaging/release path.
26
+
27
+ ## Deterministic results
28
+
29
+ - Full local required-tool gate: passed.
30
+ - RSpec: 268 examples, 0 failures.
31
+ - Coverage: 96.52% line coverage.
32
+ - Custom OSV dependency check: 45 dependencies queried, 0 vulnerable.
33
+ - `bundler-audit`: no vulnerabilities found.
34
+ - `osv-scanner`: no issues found in `Gemfile.lock`.
35
+ - `gitleaks`: dedicated secret scan passed.
36
+ - Package sanity: built and inspected `tmp/pkg/moose-inventory.gem` successfully.
37
+ - Semgrep Ruby registry scan: 62 tracked Ruby files scanned with 44 Ruby rules, 0 findings.
38
+ - GitHub Dependabot open alerts: 0.
39
+ - GitHub code scanning alerts: unavailable / no analysis found (`404`).
40
+ - GitHub secret scanning alerts: unavailable because secret scanning is disabled for this repository.
41
+ - Workflow YAML parse check: `ci.yml` and `release.yml` parsed successfully with Ruby Psych.
42
+ - Current GitHub CI before audit branch: latest `master` CI run succeeded for Ruby 3.2, 3.3, and 3.4.
43
+
44
+ ## Finding fixed during audit
45
+
46
+ ### SEC-RERUN-2026-05-26-01 — Release workflow did not require dedicated security tools
47
+
48
+ - Priority before fix: P2 medium, release supply-chain hardening.
49
+ - Exposure: tag-triggered release workflow.
50
+ - Affected file: `.github/workflows/release.yml`.
51
+ - Evidence: CI installed `gitleaks`/`osv-scanner` and set `MOOSE_INVENTORY_REQUIRE_SECURITY_TOOLS=1`, but the release workflow only ran `./scripts/check.sh`. In local mode, `scripts/ci/check_security.sh` and `scripts/ci/check_secrets.sh` intentionally skip missing optional security tools unless `MOOSE_INVENTORY_REQUIRE_SECURITY_TOOLS=1` is set.
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
+ - 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
+ - Verification: full local required-tool gate passed after the workflow change.
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
+
57
+ ## Reviewed areas with no actionable finding
58
+
59
+ - YAML config loading uses `YAML.safe_load_file` with aliases disabled and no permitted classes/symbols.
60
+ - SQLite database path handling creates parent directories with `FileUtils.mkdir_p`; this is local config-driven CLI behavior, not a remotely reachable path traversal surface.
61
+ - MySQL/PostgreSQL password handling supports `password_env`; plaintext `password` remains for compatibility but README guidance discourages committing it.
62
+ - CLI input reaches Sequel model operations rather than shell execution; no shell/eval sink was identified in application code.
63
+ - Recent recursive group deletion is explicit opt-in and keeps host fallback behavior covered by regression tests.
64
+ - GitHub Actions release job uses OIDC/trusted publishing and does not store a RubyGems API key in the workflow.
65
+
66
+ ## Limitations
67
+
68
+ - This was a local/source and CI/release workflow audit, not an active test against live external databases or RubyGems publishing.
69
+ - GitHub code scanning is not configured, so there were no CodeQL/code-scanning results to review.
70
+ - GitHub secret scanning is disabled for the repository; local `gitleaks` coverage was used instead.
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
+
73
+ ## Conclusion
74
+
75
+ No open exploitable vulnerabilities remain from this rerun. The only identified security gap was release-pipeline parity with CI security tooling, and it was fixed in this audit branch.
@@ -0,0 +1,63 @@
1
+ # Security audit — 2026-05-26
2
+
3
+ Scope: local static/security review of the `moose-inventory` Ruby CLI/gem at commit `8c3eaada5d70ef599961b8ca8b78e12ea4ce83c9` on branch `security-audit-2026-05-26`.
4
+
5
+ ## Executive summary
6
+
7
+ No actionable security vulnerabilities were identified in this pass.
8
+
9
+ The meaningful attack surface remains local CLI execution, configuration-file loading, database access through Sequel, package/release automation, and developer tooling. There is no HTTP server, RPC endpoint, webhook handler, queue consumer, file upload parser, shell-command execution path, or plugin system in this repository.
10
+
11
+ The areas remediated in the prior 2026-05-21 audit remain in good shape: YAML config loading uses `YAML.safe_load_file`, DB credentials can be supplied through environment variables, OSV reports no known vulnerable locked RubyGems dependencies, CI/package sanity gates are present, and GitHub Dependabot has no open alerts.
12
+
13
+ ## Surfaces reviewed
14
+
15
+ - CLI entrypoint: `bin/moose-inventory`
16
+ - Global option parsing and config loading: `lib/moose_inventory/config/config.rb`
17
+ - DB connection/schema/transaction code: `lib/moose_inventory/db/db.rb`
18
+ - Sequel models and associations: `lib/moose_inventory/db/models.rb`
19
+ - CLI command handlers under `lib/moose_inventory/cli/`
20
+ - Formatter/output serialization: `lib/moose_inventory/cli/formatter.rb`
21
+ - Packaging and release metadata: `moose-inventory.gemspec`, `Gemfile`, `Gemfile.lock`, `.github/workflows/ci.yml`, `.github/workflows/release.yml`
22
+ - Helper scripts under `scripts/`
23
+ - Test config/spec fixtures under `spec/`
24
+
25
+ ## Findings
26
+
27
+ No P0/P1/P2/P3 actionable findings were identified.
28
+
29
+ ## Notable negative findings
30
+
31
+ - Config deserialization uses `YAML.safe_load_file` with aliases disabled and no permitted classes/symbols.
32
+ - No runtime shell execution sinks were identified.
33
+ - Database access uses Sequel model/dataset/hash APIs for user-controlled names, groups, hosts, and variables; no raw SQL interpolation was identified in reviewed runtime paths.
34
+ - MySQL/PostgreSQL passwords can be supplied via `password_env`, and README guidance prefers environment-backed passwords over plaintext config values.
35
+ - No committed secrets were identified outside expected example/test placeholders.
36
+ - GitHub Actions release publishing uses RubyGems trusted publishing/OIDC rather than a stored RubyGems API key.
37
+ - Dependency advisory gate queried OSV for 41 locked RubyGems dependency records and reported zero known vulnerabilities.
38
+ - GitHub Dependabot open-alert query returned zero open alerts.
39
+
40
+ ## Tooling evidence
41
+
42
+ - Audit evidence store initialized at `.openclaw-security-audit/audit.sqlite` with `audit_run_id=1`.
43
+ - Inventory: 187 files; Ruby manifests detected: `Gemfile`, `Gemfile.lock`, plus generated package-sanity manifests under `tmp/package-sanity`.
44
+ - Symbol extractor scanned 156 files but did not extract Ruby symbols/surfaces with the current lightweight extractor.
45
+ - Semgrep auto-config failed because metrics are disabled; reran explicit Ruby registry rules instead.
46
+ - Semgrep: `semgrep --config p/ruby --json --metrics=off --exclude .openclaw-security-audit --exclude spec/reports --exclude tmp .` scanned 62 tracked Ruby files with 44 rules and returned 0 findings.
47
+ - Dependency advisory gate: `./scripts/ci/check_security.sh` queried 41 RubyGems dependencies and returned 0 vulnerable dependencies.
48
+ - Full local gate: `./scripts/check.sh` passed with 268 examples, 0 failures, 96.52% line coverage, OSV 0 vulnerabilities, and package sanity passed.
49
+ - GitHub Dependabot: `gh api 'repos/RusDavies/moose-inventory/dependabot/alerts?state=open' --jq 'length'` returned `0`.
50
+ - GitHub code-scanning alerts could not be queried because no code-scanning analysis exists for this repository; GitHub returned `404 no analysis found`.
51
+
52
+ ## Tooling limitations
53
+
54
+ - `osv-scanner`, `bundler-audit`/`bundle-audit`, `gitleaks`, `trufflehog`, `brakeman`, `flog`, and `reek` were not installed in this environment.
55
+ - `bundle exec rubocop` could not run because RuboCop is not part of the bundle. This is not a security gate failure, but it limits style/static-quality coverage.
56
+ - Secret scanning was limited to tracked-file grep patterns because dedicated secret scanners were unavailable.
57
+ - The audit did not perform active exploitation against external systems or live database servers.
58
+
59
+ ## Residual risks / recommendations
60
+
61
+ - Consider adding a dedicated secret scanner such as `gitleaks` or `trufflehog` to local/CI security tooling if this project will accept outside contributions.
62
+ - Consider adding `bundler-audit` or `osv-scanner` as an optional developer tool if broader advisory coverage is desired beyond the existing custom OSV gate.
63
+ - Keep generated coverage and package-sanity artifacts excluded from security scans; they are noisy and not part of the runtime gem surface.