bootprint 0.2.0

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 (71) hide show
  1. checksums.yaml +7 -0
  2. data/.bootprint.yml.example +37 -0
  3. data/ARCHITECTURE.md +46 -0
  4. data/CHANGELOG.md +26 -0
  5. data/CODE_OF_CONDUCT.md +7 -0
  6. data/CONTRIBUTING.md +28 -0
  7. data/LICENSE +21 -0
  8. data/README.md +422 -0
  9. data/RELEASE.md +78 -0
  10. data/ROADMAP.md +15 -0
  11. data/SECURITY.md +47 -0
  12. data/assets/branding/README.md +24 -0
  13. data/assets/branding/bootprint-logo-128.png +0 -0
  14. data/assets/branding/bootprint-logo-512.png +0 -0
  15. data/assets/branding/bootprint-logo-64.png +0 -0
  16. data/assets/branding/bootprint-logo.png +0 -0
  17. data/docs/capturing.md +9 -0
  18. data/docs/ci.md +21 -0
  19. data/docs/comparing.md +22 -0
  20. data/docs/custom-rules.md +7 -0
  21. data/docs/docker.md +7 -0
  22. data/docs/findings.md +7 -0
  23. data/docs/installation.md +7 -0
  24. data/docs/maintainer-setup.md +54 -0
  25. data/docs/plugins.md +7 -0
  26. data/docs/policy.md +9 -0
  27. data/docs/privacy.md +7 -0
  28. data/docs/quick-start.md +9 -0
  29. data/docs/rails.md +13 -0
  30. data/docs/snapshot-schema.md +9 -0
  31. data/docs/troubleshooting.md +8 -0
  32. data/exe/bootprint +6 -0
  33. data/lib/bootprint/analysis.rb +13 -0
  34. data/lib/bootprint/cli.rb +458 -0
  35. data/lib/bootprint/collectors/environment.rb +21 -0
  36. data/lib/bootprint/collectors/filesystem.rb +40 -0
  37. data/lib/bootprint/collectors/gems.rb +96 -0
  38. data/lib/bootprint/collectors/libraries.rb +75 -0
  39. data/lib/bootprint/collectors/operating_system.rb +50 -0
  40. data/lib/bootprint/collectors/rails.rb +97 -0
  41. data/lib/bootprint/collectors/runtime.rb +34 -0
  42. data/lib/bootprint/collectors/toolchain.rb +23 -0
  43. data/lib/bootprint/configuration.rb +38 -0
  44. data/lib/bootprint/diagnosis.rb +95 -0
  45. data/lib/bootprint/diff.rb +47 -0
  46. data/lib/bootprint/docker.rb +149 -0
  47. data/lib/bootprint/doctor.rb +13 -0
  48. data/lib/bootprint/errors.rb +9 -0
  49. data/lib/bootprint/formatters/human.rb +55 -0
  50. data/lib/bootprint/formatters/json.rb +12 -0
  51. data/lib/bootprint/formatters/markdown.rb +27 -0
  52. data/lib/bootprint/formatters/sarif.rb +54 -0
  53. data/lib/bootprint/formatters.rb +22 -0
  54. data/lib/bootprint/initializer_profiler.rb +93 -0
  55. data/lib/bootprint/plugins.rb +90 -0
  56. data/lib/bootprint/policy.rb +191 -0
  57. data/lib/bootprint/rails_state.rb +17 -0
  58. data/lib/bootprint/railtie.rb +36 -0
  59. data/lib/bootprint/rules/builtin.rb +383 -0
  60. data/lib/bootprint/rules/finding.rb +40 -0
  61. data/lib/bootprint/rules/registry.rb +20 -0
  62. data/lib/bootprint/rules/rule.rb +153 -0
  63. data/lib/bootprint/rules.rb +58 -0
  64. data/lib/bootprint/sanitizer.rb +105 -0
  65. data/lib/bootprint/schema.rb +111 -0
  66. data/lib/bootprint/security/auditor.rb +63 -0
  67. data/lib/bootprint/snapshot.rb +122 -0
  68. data/lib/bootprint/version.rb +5 -0
  69. data/lib/bootprint.rb +38 -0
  70. data/lib/tasks/bootprint.rake +18 -0
  71. metadata +120 -0
data/ROADMAP.md ADDED
@@ -0,0 +1,15 @@
1
+ # Roadmap
2
+
3
+ ## 0.2 — Environment Intelligence Engine
4
+
5
+ Schema v2, structured diagnosis, policy, Rails profiling, Docker inspection, CI reports, plugins, and privacy auditing.
6
+
7
+ ## Next
8
+
9
+ - Validate rule behavior across more real JRuby and TruffleRuby applications.
10
+ - Add opt-in offline advisory metadata bundles for unavailable/yanked gems.
11
+ - Improve libc and native-client precision without adding capture-time network access.
12
+ - Publish companion plugins for PostgreSQL, Redis, Sidekiq, and Nokogiri.
13
+ - Stabilize schema migration guarantees before 1.0.
14
+
15
+ Bootprint will remain a CLI/library—not a hosted dashboard, deployment platform, observability agent, or secret manager.
data/SECURITY.md ADDED
@@ -0,0 +1,47 @@
1
+ # Security Policy
2
+
3
+ ## Supported versions
4
+
5
+ | Version | Security fixes |
6
+ |---|---|
7
+ | 0.2.x | Supported |
8
+ | 0.1.x | Upgrade to 0.2.x |
9
+
10
+ Until 1.0, security fixes are released on the latest minor line. Older snapshots remain readable when the documented in-memory migration path supports them.
11
+
12
+ ## Data model
13
+
14
+ Bootprint never reads or stores environment-variable values. It records only selected names with boolean presence. It avoids dumping Rails credentials, database configuration values, authorization headers, command output, complete application files, or arbitrary process memory. Known application-root and home-directory prefixes are replaced with `<APP_ROOT>` and `<HOME>`.
15
+
16
+ Recursive sanitization detects secret-like field names, credential-bearing URLs, private keys, JWT-like strings, authorization fields, and high-entropy token-like values. Digest and checksum fields are safely distinguished from secrets. Strict privacy mode additionally anonymizes hostname-like strings.
17
+
18
+ Snapshots can still reveal operational metadata, including:
19
+
20
+ - gem and native-library versions
21
+ - platform and operating-system details
22
+ - selected environment-variable names
23
+ - Rails adapter and load-path information
24
+
25
+ Treat `bootprint.lock` as ordinary internal project metadata and review it before making it public. Use `ignored_environment_names` for a name that should never appear:
26
+
27
+ ```ruby
28
+ Bootprint.configure do |config|
29
+ config.ignored_environment_names << "INTERNAL_CUSTOMER_CODENAME"
30
+ end
31
+ ```
32
+
33
+ ## Trust boundaries
34
+
35
+ - Snapshot files are parsed strictly as JSON and never evaluated.
36
+ - Policy files use safe YAML loading with aliases and arbitrary classes disabled.
37
+ - Rule plugins are executable Ruby code. Install and register them only from trusted gems.
38
+ - Bootprint does not upload snapshots, enable telemetry, open ports, or execute Docker commands.
39
+ - Capability detection examines executable file presence on `PATH`; it does not run those executables.
40
+
41
+ Docker commands are the explicit exception to the last point: they invoke only Docker, verify that the requested image exists locally, and create a fixed-script `--rm --read-only --network none` temporary container. Bootprint never inspects unrelated running containers.
42
+
43
+ Run `bootprint security audit bootprint.lock` before sharing a snapshot outside your organization.
44
+
45
+ ## Reporting vulnerabilities
46
+
47
+ Please use [GitHub private vulnerability reporting](https://github.com/theworker02/bootprint/security/advisories/new) or email `security@magnexis.com`. Do not open a public issue or include real credentials or production snapshots. Include the affected Bootprint version, operating system, Ruby engine, sanitized reproduction, and expected impact. Expect acknowledgement within seven days.
@@ -0,0 +1,24 @@
1
+ # Bootprint brand assets
2
+
3
+ The Bootprint mark combines a fingerprint with a letter `B`. The interrupted blue path represents an environment difference being isolated from a reproducible runtime fingerprint.
4
+
5
+ ## Files
6
+
7
+ | File | Intended use |
8
+ |---|---|
9
+ | `bootprint-logo.png` | 1024 px transparent master for documentation and release artwork |
10
+ | `bootprint-logo-512.png` | README, repository, and package artwork |
11
+ | `bootprint-logo-128.png` | Example packages and compact documentation headers |
12
+ | `bootprint-logo-64.png` | Small UI and documentation placements |
13
+
14
+ ## Palette
15
+
16
+ | Role | Color |
17
+ |---|---|
18
+ | Ruby/runtime signal | `#CC342D` |
19
+ | Diagnostic/drift signal | `#3977F6` |
20
+ | Structure | `#171A21` |
21
+
22
+ Keep the mark's aspect ratio, preserve clear space around it, and use the transparent PNG on a plain light or dark surface. Do not recolor individual paths, add effects, or place the mark over visually noisy imagery.
23
+
24
+ These assets are distributed with Bootprint under the repository license.
Binary file
data/docs/capturing.md ADDED
@@ -0,0 +1,9 @@
1
+ # Capturing environments
2
+
3
+ `bootprint capture` writes `bootprint.lock`; `bootprint capture local` writes `.bootprint/local.json`. Use `--output`, `--env NAME`, `--required-env NAME`, and `--privacy strict` to control the capture.
4
+
5
+ The snapshot includes runtime, dependency, native-library, configuration, filesystem, and OS facts. Values of environment variables are never read into the snapshot. `--all-env` records all names and should be used deliberately because names reveal infrastructure vocabulary.
6
+
7
+ Capture performs no network requests and modifies no application files. It may create only the requested output file. Docker capture is a separate, explicit command.
8
+
9
+ Strict privacy removes application/home path prefixes and anonymizes hostname-like strings. Run `bootprint security audit PATH` before external sharing.
data/docs/ci.md ADDED
@@ -0,0 +1,21 @@
1
+ # CI integration
2
+
3
+ Use the same committed `bootprint.lock` in generic POSIX CI, GitLab CI, CircleCI, or GitHub Actions:
4
+
5
+ ```yaml
6
+ name: Bootprint
7
+ on: [pull_request, push]
8
+ jobs:
9
+ environment-check:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: ruby/setup-ruby@v1
14
+ with:
15
+ bundler-cache: true
16
+ - run: bundle exec bootprint ci verify --against bootprint.lock
17
+ ```
18
+
19
+ GitHub Actions receives workflow annotations and Markdown appended to `GITHUB_STEP_SUMMARY`. SARIF output is compatible with GitHub code scanning when uploaded by the workflow. Bootprint does not upload reports itself.
20
+
21
+ GitLab, CircleCI, and generic CI receive stable console output and exit codes. CI provider detection uses standard environment-variable presence, not secret values.
data/docs/comparing.md ADDED
@@ -0,0 +1,22 @@
1
+ # Comparing environments and understanding findings
2
+
3
+ Use `bootprint diff SOURCE TARGET` for a complete raw comparison. Use `bootprint diagnose SOURCE TARGET` for compatibility intelligence.
4
+
5
+ Findings have four severities:
6
+
7
+ - `info`: useful context with negligible direct risk
8
+ - `warning`: likely drift that deserves review
9
+ - `error`: behavior or installation is likely to fail
10
+ - `critical`: boot, security, or binary compatibility is at immediate risk
11
+
12
+ Each finding contains a stable rule ID, category, cause, impact, evidence, remediation, optional commands/files, references, and suppression status. `--minimum-severity` controls presentation; policy `fail_on` controls exit code.
13
+
14
+ ## macOS Rails to Linux container
15
+
16
+ ```console
17
+ bootprint capture macos-development
18
+ bootprint docker capture registry.example/myapp:latest --output .bootprint/linux-production.json
19
+ bootprint diagnose macos-development linux-production --only runtime,dependencies,native,configuration
20
+ ```
21
+
22
+ A native `nokogiri` Darwin variant produces a critical platform finding with `bundle lock --add-platform x86_64-linux`. A local-only `REDIS_URL` produces an error without revealing its value. Case sensitivity appears as a warning.
@@ -0,0 +1,7 @@
1
+ # Writing custom rules
2
+
3
+ Define rules after requiring `bootprint`. Rules receive source and target schema-v2 `environment` objects; a third argument receives the active policy.
4
+
5
+ Detection returns `false`/`nil` for no finding, `true` for a finding without custom evidence, or a hash containing evidence. Explanation returns `summary`, `cause`, `impact`, `evidence`, and optional `source_location`. Remediation is always structured and preview-only.
6
+
7
+ Rule IDs are global and later definitions replace earlier rules with the same ID, allowing an application to intentionally customize built-ins. Prefer namespaced IDs for third-party packages. Test rules against fixture snapshots without requiring Rails.
data/docs/docker.md ADDED
@@ -0,0 +1,7 @@
1
+ # Docker support
2
+
3
+ `bootprint docker capture IMAGE` and `bootprint docker diagnose IMAGE --against SNAPSHOT` inspect an image already present locally. Bootprint never pulls an absent image.
4
+
5
+ The temporary container uses `--rm`, `--read-only`, `--network none`, and a fixed Ruby inspection script. No port is required. The container reports Ruby/gem/platform data, native libraries, installed dpkg/apk package names when available, working-directory permissions, and image entrypoint/command metadata.
6
+
7
+ The image must contain a working `ruby` executable. Docker errors are returned as exit code 4 with sanitized stderr. Bootprint never lists or inspects unrelated running containers.
data/docs/findings.md ADDED
@@ -0,0 +1,7 @@
1
+ # Understanding findings
2
+
3
+ Human reports prioritize critical findings, then errors, warnings, and information. JSON and SARIF preserve the same order and stable IDs.
4
+
5
+ Evidence contains captured metadata only. Remediation commands use placeholders such as `<target-platform>` when Bootprint cannot safely infer an exact command. Commands are preview text and are never passed to a shell.
6
+
7
+ Suppressed findings remain in machine-readable output with `suppressed: true` and a reason. They do not block CI. Prefer narrow rule suppression over raising the global minimum severity.
@@ -0,0 +1,7 @@
1
+ # Installation
2
+
3
+ Bootprint supports MRI Ruby 3.1+ and is designed to degrade safely on JRuby. Install globally with `gem install bootprint`, or add `gem "bootprint", require: false` to development and test groups and run `bundle install`.
4
+
5
+ The core gem has no runtime dependencies. Docker support requires a local Docker CLI and running daemon. Rails inspection requires Rails to load Bootprint during application boot.
6
+
7
+ Verify the installation with `bootprint version` and `bootprint doctor`.
@@ -0,0 +1,54 @@
1
+ # GitHub and RubyGems maintainer setup
2
+
3
+ This checklist covers settings that cannot be represented completely by committed files. Apply it after creating `theworker02/bootprint` and before publishing the first gem.
4
+
5
+ ## Repository profile
6
+
7
+ - Description: `Diagnose why Ruby environments work locally but fail in CI, Docker, staging, or production.`
8
+ - Website: `https://rubygems.org/gems/bootprint`
9
+ - Topics: `ruby`, `rails`, `bundler`, `rubygems`, `docker`, `ci`, `diagnostics`, `reproducibility`, `developer-tools`
10
+ - Default branch: `main`
11
+ - Social preview: `assets/branding/bootprint-logo-512.png`
12
+ - Enable Issues and Discussions; disable the wiki unless maintainers intend to support it.
13
+
14
+ ## Ruleset for `main`
15
+
16
+ - Require pull requests and at least one approving review.
17
+ - Dismiss stale approvals when new commits are pushed.
18
+ - Require conversation resolution.
19
+ - Require the four focused CI compatibility checks.
20
+ - Require branches to be up to date before merging.
21
+ - Block force pushes and branch deletion.
22
+ - Restrict bypass permission to release maintainers.
23
+ - Add a tag ruleset protecting `v*` from deletion or update.
24
+
25
+ CodeQL runs weekly or on explicit maintainer request rather than adding another check to every pull request.
26
+
27
+ ## Actions and security
28
+
29
+ - Allow GitHub-authored actions plus `ruby/setup-ruby` and `rubygems/release-gem`.
30
+ - Keep the default workflow token read-only; grant write permissions only inside the release job.
31
+ - Enable the dependency graph, Dependabot alerts, Dependabot security updates, secret scanning, and push protection.
32
+ - Review and merge Dependabot updates rather than enabling unattended auto-merge.
33
+ - Enable private vulnerability reporting and repository security advisories.
34
+ - Retain Actions logs long enough to investigate releases, without treating logs as a secret store.
35
+
36
+ ## Release environment
37
+
38
+ Create an environment named `release`:
39
+
40
+ - Require approval from a release maintainer.
41
+ - Allow deployment only from tags matching `v*`.
42
+ - Do not add `RUBYGEMS_API_KEY`; trusted publishing uses OIDC.
43
+ - Do not expose unrelated organization secrets to the workflow.
44
+
45
+ Then create the RubyGems trusted publisher described in [RELEASE.md](../RELEASE.md). The repository owner, repository name, workflow filename, and environment must match exactly.
46
+
47
+ ## First-publication checklist
48
+
49
+ - Confirm `gem search --remote --exact bootprint` still returns no existing gem.
50
+ - Confirm the repository URLs and `hello@magnexis.com`, `security@magnexis.com`, and `conduct@magnexis.com` mailboxes are controlled and monitored.
51
+ - Confirm the name and copyright holder in `LICENSE` are intentional.
52
+ - Run `bundle exec rake release_check` from a clean checkout.
53
+ - Review the packaged file list and installed CLI behavior.
54
+ - Push `main`, wait for every required check, then create the signed `v0.2.0` tag.
data/docs/plugins.md ADDED
@@ -0,0 +1,7 @@
1
+ # Creating plugins
2
+
3
+ Plugin gems should use names such as `bootprint-sidekiq` or `bootprint-redis`, call `Bootprint::Plugin.api_version "1"`, and register a stable plugin name.
4
+
5
+ Collectors return JSON-safe data and must not return secrets. Bootprint applies recursive sanitization regardless. Rules modules respond to `.install` or `.register` and use the ordinary rule DSL.
6
+
7
+ One plugin exception becomes a warning stored in `capture.warnings`; other collectors continue. Strict policy converts plugin failures into capture failures. Plugins are executable Ruby code and must be installed only from trusted sources.
data/docs/policy.md ADDED
@@ -0,0 +1,9 @@
1
+ # Policy configuration
2
+
3
+ `.bootprint.yml` uses policy schema version 1. Validate it with `bootprint policy validate` and explain effective controls with `bootprint policy explain`.
4
+
5
+ `mode: permissive` reports information and blocks errors/critical findings by default. `mode: strict` reports warnings and blocks warnings/errors/critical findings. Explicit `minimum_severity` and `fail_on` override these defaults.
6
+
7
+ Rules accept `enabled: false` and `severity`. `ignore` suppresses known rule IDs. `allow.environment_variables` declares optional names. `expected_platforms` drives lockfile-platform checks. `redaction.patterns` extends built-in secret-name patterns, while `redaction.safe_list` narrowly exempts known non-secret field names. Plugin failures block only in strict mode or when `plugins.strict: true`.
8
+
9
+ YAML is safe-loaded with aliases and arbitrary Ruby classes disabled. Syntax and semantic errors include absolute file paths and line numbers when identifiable.
data/docs/privacy.md ADDED
@@ -0,0 +1,7 @@
1
+ # Privacy and redaction
2
+
3
+ Bootprint uses data minimization first: it does not collect environment-variable values, Rails credentials, full URLs, cookies, sessions, request data, or arbitrary files.
4
+
5
+ Recursive defense-in-depth redaction handles secret field names, authorization fields, private-key markers, JWT-like strings, high-entropy token-like strings, database/URL credentials, application roots, and user-home paths. Checksum fields are explicitly safe-listed. Strict privacy anonymizes hostname-like values.
6
+
7
+ Project redaction patterns add organization-specific secret vocabulary. A narrow `redaction.safe_list` can exempt a known non-secret field name; values still pass value-based sanitization. Use `bootprint security audit` to inspect a stored snapshot.
@@ -0,0 +1,9 @@
1
+ # Five-minute quick start
2
+
3
+ 1. Run `bundle exec bootprint capture local` on the working environment.
4
+ 2. Run `bundle exec bootprint capture production` in the failing environment, or copy the local capture into CI and run `bootprint diagnose --against bootprint.lock` there.
5
+ 3. Run `bundle exec bootprint diagnose local production`.
6
+ 4. Review each finding's evidence and suggested command. Bootprint never executes remediation.
7
+ 5. Copy `.bootprint.yml.example` to `.bootprint.yml`, declare intentional differences, and use `bootprint ci verify`.
8
+
9
+ Named captures resolve from `.bootprint/NAME.json`, so `local` and `production` can be used instead of full paths.
data/docs/rails.md ADDED
@@ -0,0 +1,13 @@
1
+ # Rails integration
2
+
3
+ Load Bootprint during Rails boot to register `bootprint:capture` and `bootprint:doctor` tasks. Set `BOOTPRINT_INSPECT=1` to observe configuration initializer order without full profiling.
4
+
5
+ ```console
6
+ BOOTPRINT_INSPECT=1 bin/rails bootprint:capture
7
+ BOOTPRINT_OUTPUT=.bootprint/staging.json bin/rails bootprint:capture
8
+ bin/rails bootprint:doctor
9
+ ```
10
+
11
+ Set `BOOTPRINT_PROFILE_BOOT=1` for initializer duration, start/completion order, exception metadata, newly loaded constant names, and heuristic network-call observation. The heuristic is intentionally conservative and can report false positives; it does not intercept or block calls.
12
+
13
+ Bootprint captures adapter names and boolean/presence metadata. It never serializes credentials, database passwords, URLs, cookies, sessions, message contents, or application user data.
@@ -0,0 +1,9 @@
1
+ # Snapshot schema v2
2
+
3
+ Every snapshot contains `schema_version`, `generated_at`, `bootprint_version`, `environment`, and optional `capture`/`extensions` metadata. `environment` contains `name`, `runtime`, `dependencies`, `native_libraries`, `configuration`, `filesystem`, and `operating_system` objects.
4
+
5
+ Keys are recursively sorted. Scalar arrays are sorted; ordered object arrays such as Rails initializers retain capture order. `generated_at`, Bootprint version, capture duration, warnings, and environment labels do not participate in raw environment equality.
6
+
7
+ Schema v1 is migrated in memory. Unknown v1 top-level fields move to `extensions`. Future schemas fail with an instruction to upgrade. `snapshot migrate` always writes a new file unless an explicit output path is selected; it does not overwrite the source by default.
8
+
9
+ Diagnosis JSON uses its own report schema version 1 so snapshot and report evolution remain independent.
@@ -0,0 +1,8 @@
1
+ # Troubleshooting
2
+
3
+ - **Docker unavailable:** verify `docker version` succeeds and that the requested image exists locally. Bootprint does not pull it.
4
+ - **Initializer list empty:** load Bootprint before Rails initializes and set `BOOTPRINT_INSPECT=1` or `BOOTPRINT_PROFILE_BOOT=1`.
5
+ - **Missing environment-variable finding absent:** declare the name with `--required-env`, application configuration, or policy context. Bootprint cannot infer an absent arbitrary name.
6
+ - **Unexpected lockfile platform error:** declare actual deployment targets under `expected_platforms` and run `bundle lock --add-platform` deliberately.
7
+ - **Policy error:** run `bootprint policy validate`; the error includes the policy path and best-known line.
8
+ - **Internal details needed:** set `BOOTPRINT_DEBUG=1` for a stack trace. Review output before sharing because diagnostics may contain local metadata.
data/exe/bootprint ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bootprint/cli"
5
+
6
+ exit Bootprint::CLI.start
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Backward-compatible facade for the 0.1 API.
4
+ module Bootprint
5
+ class Analysis
6
+ def initialize(source, target, allowed_paths: [])
7
+ policy_data = allowed_paths.empty? ? {} : { "allow" => { "paths" => allowed_paths } }
8
+ @diagnosis = Diagnosis.new(source, target, policy: Policy.new(nil, policy_data))
9
+ end
10
+
11
+ def results = @diagnosis.run.findings
12
+ end
13
+ end