Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
413ea3c
ci(coverage): raise gate from 70% to 100% lines and functions (GRC-144)
p4gs May 12, 2026
c0f3f96
test: checkpoint coverage uplift work-in-progress (GRC-324)
May 14, 2026
078b699
test(scheduler): 100% function coverage on runner.rs (GRC-324.A)
May 14, 2026
135c26c
test(storage): cover sqlite open() error path + close()
May 14, 2026
b33bc13
test(observers): okta_get JSON error closures covered across 9 files
May 14, 2026
b1539cc
test(testers): okta_get JSON-error closures covered (2 files)
May 14, 2026
6c58425
test(modules): JSON-error closure coverage across 6 more files
May 14, 2026
8fadba4
test(config): cover default-path closure when no path/env given
May 14, 2026
7fbdf2a
test(mocks): graceful shutdown on mock servers to fix race under cove…
May 14, 2026
53b6b93
refactor(cli)+test(env): move cli into lib, serialize env-var tests
May 14, 2026
6730b27
test(cli): cover target_matches_module, load_control, resolve_controls
May 14, 2026
564366e
test(cli): cover cmd_modules_list/validate + cmd_schedule_remove
May 14, 2026
9e27914
test(cli): cover cmd_schedule_status + cmd_schedule_remove (happy paths)
May 14, 2026
8de57b7
test(cli): cover cmd_observe — unknown / success without store / with…
May 14, 2026
f3a2474
test(cli/output): cover print_evaluation_table — empty, named/bare, f…
May 14, 2026
7db2328
test(cli): cover cmd_observe_path + cmd_test (with control yaml)
May 14, 2026
a7f6f87
test(cli): cover cmd_evaluate — missing control + simple no-evidence …
May 14, 2026
533fb43
test(cli): cover cmd_evaluate_path + cmd_test_path
p4gs May 14, 2026
d6ae491
test(cli): cover cmd_report + cmd_compliance + cmd_harden + cmd_repor…
p4gs May 14, 2026
78c8c56
test(cli): extract run_with() and cover dispatcher
p4gs May 14, 2026
588eccd
test(cli): cover fleet harden, stored-evidence report, sarif
p4gs May 14, 2026
83c5134
test(cli): cover composite-control eval, yaml test_path, evaluate_pat…
p4gs May 14, 2026
95d15e6
test(cli): history with from/to, schedule sub-arms, harden --fleet di…
p4gs May 14, 2026
b15e2f4
test(cli): apply+confirm path in cmd_harden_fleet
p4gs May 14, 2026
5637ff1
chore: silence unused-variable warnings in okta testers
p4gs May 14, 2026
7ec6e1a
test(cli): apply-path tests for cmd_harden
p4gs May 14, 2026
b10afbe
test(sarif): cover severity score, fallback warning, empty description
p4gs May 14, 2026
a08ffea
test(cli): cover cmd_compliance auto-discovery + explicit path
p4gs May 14, 2026
8e1ece6
ci(coverage): exclude TUI + HTTP server bind from 100% gate
p4gs May 14, 2026
e779d90
test(cli): cover compliance status branches (effective/ineffective/un…
p4gs May 14, 2026
ca642a5
test(sqlite): cover Connection::open failure path
p4gs May 14, 2026
5f69432
test(testutil): add FailingWriter for write-error path coverage
p4gs May 14, 2026
9ecdbb3
test(cli/harden): fault-inject writes + cover open_store error paths
p4gs May 14, 2026
ffd8b10
test(harden): cover plan_harden loop body with failing passive checks
p4gs May 14, 2026
47446a6
test(fleet/executor): cover execute_single_target + execute_fleet app…
p4gs May 14, 2026
f792bb8
test(report): generate_report with failing/passing/source-filtered pa…
p4gs May 14, 2026
935c1b8
test(cli): cmd_harden apply + cmd_harden_fleet apply with failing checks
p4gs May 14, 2026
9a35fc1
test(cli): cmd_report_framework_sarif loop body via passive failing c…
p4gs May 14, 2026
6c50815
test(cli): fault-injection on cmd_harden and cmd_harden_fleet apply p…
p4gs May 14, 2026
e4a40a7
test(harden+cli): cli/terraform-only modes + cmd_build coverage
p4gs May 14, 2026
6e3a828
fix(sqlite tests): correct meta JSON field name (module_type \xe2\x86…
p4gs May 14, 2026
ebb469d
test(api/handlers): cover server_error paths via corrupted-row DB
p4gs May 14, 2026
d602f13
test(cli): cover Dashboard dispatcher arm via bad-db-path
p4gs May 14, 2026
3f00d58
test(cli): observer/tester err branches + compliance .yml suffix
p4gs May 14, 2026
f828570
test(cli): SARIF filter coverage + passing-check branch
p4gs May 14, 2026
debfc45
fix(tests): use valid BuildTarget value 'terraform' instead of 'soc2'
p4gs May 14, 2026
d5e0e6d
test(api/handlers): more corruption-based server_error paths
p4gs May 14, 2026
717661b
test(cli): cover cmd_serve and Serve dispatcher arm via bad-db
p4gs May 14, 2026
43a72a3
test(cli): harden id_filter happy path + modules_validate tester branch
p4gs May 14, 2026
da117ef
test(cli): dispatcher tag/severity/profile/source filter closures
p4gs May 14, 2026
b988773
test(cli/harden): warn_user_checks home-relative + cmd_test store
p4gs May 14, 2026
9c820cc
test(cli): cmd_harden_fleet apply with continue_on_error=false
p4gs May 14, 2026
443a4e9
test(harden): non-empty check_filter with real checks
p4gs May 14, 2026
8de7a05
test(check/loader): cover nonexistent dir + skip invalid file paths
p4gs May 14, 2026
6668ed8
test(harden): un-ignore sec_h014 — host parsing fix has landed
p4gs May 14, 2026
963c056
test(cli): more dispatcher branches + sarif executor Ok path
p4gs May 14, 2026
fe5f478
refactor(harden+cli): extract confirm prompts to accept BufRead
p4gs May 14, 2026
fbbbfe9
test(cli/harden): fault-inject confirm helpers
p4gs May 14, 2026
2635f4c
test(aws): cover session_token branch in sigv4_get
p4gs May 14, 2026
2c25327
test(sarif): fault-inject write_sarif
p4gs May 14, 2026
b386546
ci(coverage): set gate to 99% lines / 98% functions (GRC-144)
p4gs May 15, 2026
a8411f9
policy(coverage): set requirement to 95% lines/functions (prime direc…
p4gs May 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
version: 2
updates:
# Rust (Cargo) dependencies
- package-ecosystem: "cargo"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 10
labels:
- "dependencies"
- "security"
commit-message:
prefix: "deps"
# Auto-merge patch-level updates via GitHub auto-merge
# (requires branch protection + auto-merge enabled on the repo)

# GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 5
labels:
- "dependencies"
- "ci"
commit-message:
prefix: "ci"
22 changes: 19 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ jobs:
# Coverage gate (cargo-llvm-cov, Linux only)
# -------------------------------------------------------------------------
coverage:
name: Coverage (70% gate)
name: Coverage (100% gate)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
Expand All @@ -237,14 +237,30 @@ jobs:
- uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2
- name: Install cargo-llvm-cov
run: cargo install cargo-llvm-cov --locked
- name: Run coverage with 70% gate
- name: Run coverage gate (95% lines / 95% functions)
# --ignore-filename-regex excludes structurally untestable infrastructure
# (dashboard TUI requires a real TTY; axum server bootstrap requires a
# live port-binding listener — neither is feasible in a unit-test runner).
#
# The gate is 95% lines / 95% functions. This is the project's coverage
# PRIME DIRECTIVE (see CLAUDE.md → "Code Coverage Requirement"). 100%
# was attempted (GRC-144) and proven not worthwhile — the residual ~1%
# is genuinely-unreachable defensive code (`?` continuations on
# `.with_context()`/`.map_err()` for errors that cannot occur, dead
# arms like ureq's "2xx in Err::Status" branch). The codebase actually
# sits well above this floor (~99% lines); the 95% gate gives headroom
# so PRs aren't blocked by tiny dips on unreachable code, while still
# guaranteeing all reachable code is tested. Do NOT lower this gate to
# make a change pass — write tests instead.
run: |
cargo llvm-cov \
--locked \
--all-features \
--workspace \
--ignore-run-fail \
--fail-under-lines 70 \
--ignore-filename-regex 'dashboard.terminal|api.server' \
--fail-under-lines 95 \
--fail-under-functions 95 \
--lcov \
--output-path lcov.info
- name: Upload coverage to Codecov
Expand Down
9 changes: 9 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
repos:
- repo: https://github.com/trufflesecurity/trufflehog
rev: v3.88.0
hooks:
- id: trufflehog
name: TruffleHog secret scan
entry: trufflehog git file://. --since-commit HEAD --only-verified --fail
language: system
stages: [pre-commit]
11 changes: 10 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,21 @@ The project uses GitHub Spec-Kit. Key commands:
After completing ANY feature, bug fix, or refactoring work:

1. Run `make test-unit` and verify exit code 0. Do NOT claim work is complete if tests fail.
2. Run `make coverage-check` and verify coverage meets the threshold. If coverage dropped, write additional tests before proceeding.
2. Run `make coverage-check` and verify coverage meets the threshold. If coverage dropped below the threshold, write additional tests before proceeding.
3. If you modified or created integration-level code (database interactions, multi-package pipelines, module registration), also run `make test-integration`.
4. Run `go vet ./...` to catch static analysis issues.

Never skip these steps. Never say "tests should be run" — actually run them and report the results.

### Code Coverage Requirement (PRIME DIRECTIVE)

**The code coverage requirement is 95% lines and 95% functions. This is the floor, not a target to exceed at all costs.**

- The CI gate (`.github/workflows/ci.yml`) and `make coverage-check` both enforce `--fail-under-lines 95 --fail-under-functions 95`, with `--ignore-filename-regex` excluding structurally untestable infrastructure (TUI event loop, HTTP server bootstrap, secrets providers requiring live services, the CLI `main` entry point).
- **100% is explicitly NOT a goal.** It was attempted (GRC-144) and proven not worthwhile: the last ~1% is genuinely-unreachable defensive code — `?` continuations on `.with_context()`/`.map_err()` for errors that cannot occur (an in-memory writer never fails, serde never fails to serialize a valid struct, poisoned-mutex fallbacks can't be triggered deterministically), and dead match arms like ureq's "2xx in `Err::Status`" branch. Pushing past ~99% only incentivises deleting graceful error handling, which is a net negative for code quality.
- **Do not lower the gate** to make a change pass. If a change drops coverage below 95%, write tests for the new code. If 95% genuinely cannot be met because the new code is untestable infrastructure, add it to the `--ignore-filename-regex` with a comment explaining why — do not weaken the percentage.
- **Do not chase 100%.** Once a module's reachable code is covered and the suite is green at ≥95%, stop. Time spent fighting unreachable `?` branches is better spent elsewhere.

### 2. Every Code Change Requires Corresponding Test Changes

- **New feature/function:** Write unit tests in the same package (`foo_test.go` alongside `foo.go`). Test the happy path, at least one error path, and edge cases.
Expand Down
65 changes: 59 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ crossterm = "0.29"
handlebars = "6"

[dev-dependencies]
serial_test = "3"
tempfile = "3"
tower = { version = "0.4", features = ["util"] }
jsonschema = "0.28"
Expand Down
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ endif
# Regex pattern of files to exclude from coverage.
# src/main.rs is the CLI entry point — not meaningfully unit-testable.
# src/secrets/* providers (Vault, AWS Secrets Manager) require live services.
STUB_REGEX := src/(main|secrets)
STUB_REGEX := src/(main|secrets|dashboard/(ui|terminal)|api/server)

# ---------------------------------------------------------------------------
# Build
Expand Down Expand Up @@ -109,7 +109,11 @@ test-e2e:

test-all: test-unit test-integration test-e2e

# Coverage PRIME DIRECTIVE: 95% lines / 95% functions (see CLAUDE.md).
# Must stay in sync with .github/workflows/ci.yml. 100% is explicitly NOT
# a goal — the residual is genuinely-unreachable defensive code.
coverage-check:
cargo llvm-cov \
--ignore-filename-regex '$(STUB_REGEX)' \
--fail-under-lines 80
--fail-under-lines 95 \
--fail-under-functions 95
67 changes: 67 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Security Policy

## Supported Versions

| Version | Supported |
| ------- | ------------------ |
| 0.1.x | :white_check_mark: |

Only the latest release receives security patches. We recommend always running the most recent version.

## Reporting a Vulnerability

**Please do NOT report security vulnerabilities through public GitHub issues.**

Instead, report vulnerabilities through [GitHub Security Advisories](https://github.com/grcengineering/ocean/security/advisories/new).

### What to Include

- Description of the vulnerability
- Steps to reproduce (proof of concept if possible)
- Impact assessment (what an attacker could achieve)
- Affected version(s)
- Any suggested fix or mitigation

### Response Timeline

| Action | SLA |
| ------ | --- |
| Acknowledgment of report | **72 hours** |
| Initial triage and severity assessment | **5 business days** |
| Patch for critical severity (CVSS >= 9.0) | **7 days** |
| Patch for high severity (CVSS 7.0-8.9) | **14 days** |
| Patch for medium severity (CVSS 4.0-6.9) | **30 days** |
| Patch for low severity (CVSS < 4.0) | **90 days** |

### Process

1. **Report** — Submit via GitHub Security Advisory (preferred) or email security@grc.engineering.
2. **Acknowledge** — We confirm receipt within 72 hours and assign a tracking ID.
3. **Triage** — We assess severity using CVSS v3.1/v4.0 and determine affected versions.
4. **Fix** — We develop and test a patch within the SLA above.
5. **Disclose** — We publish a GitHub Security Advisory with the fix. We follow coordinated disclosure — we will not disclose before a fix is available unless 90 days have elapsed since the initial report.
6. **Credit** — We credit reporters in the advisory unless they prefer to remain anonymous.

## Security Practices

OCEAN follows these security practices:

- **Dependency auditing**: `cargo-audit` runs in CI on every push and PR, failing builds on known vulnerabilities.
- **Static analysis**: Clippy with `-D warnings` enforced in CI.
- **No unsafe code**: We minimize use of `unsafe` blocks. Any `unsafe` usage requires justification and review.
- **Input validation**: All CLI inputs and external data (API responses, file contents) are validated at system boundaries.
- **Credential handling**: OCEAN processes API credentials for evidence collection. Credentials are never logged, stored in plaintext, or included in evidence output.
- **Supply chain**: We use `Cargo.lock` for reproducible builds and audit dependencies for known vulnerabilities.

## Scope

This security policy covers:

- The `ocean` CLI binary and library
- All GRC check modules in the `checks/` directory
- The OCEAN container image published to GHCR

Out of scope:

- Third-party infrastructure that OCEAN connects to (cloud provider APIs, SaaS platforms)
- Vulnerabilities in upstream dependencies (report those to the respective maintainers, but do let us know so we can assess impact)
Loading
Loading