Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 3 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,10 @@ jobs:
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7

- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
# make codeguard-ci: CI intentionally runs the stable Marketplace action instead of the in-repo binary.
- uses: devr-tools/codeguard@v1.1.1
with:
go-version-file: go.mod
cache: true

- name: Run repository self-scan
run: make codeguard-ci
config: .codeguard/codeguard.yaml

build:
name: build
Expand Down
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ codeguard version

```yaml
- name: Devr Codeguard
uses: devr-tools/codeguard@v0.8.1
uses: devr-tools/codeguard@v1.1.1
```

Or run in Docker:
Expand Down Expand Up @@ -103,6 +103,23 @@ Text output includes ANSI color and emoji markers by default. Set `NO_COLOR=1` i

If you want a JSON starting point instead, use [examples/codeguard.json](examples/codeguard.json).

## Production Use

For production rollout, start in a narrow mode and expand deliberately:

1. Run `codeguard doctor` and `codeguard validate` in CI first so config and toolchain issues fail early.
2. Start with `codeguard scan -mode diff` on pull requests so only changed lines and diff-aware checks gate merges.
3. Create a baseline for legacy findings with `codeguard baseline` before turning on full-repo enforcement.
4. Enable stricter families such as `design`, `security`, `contracts`, `performance`, and `supply_chain` incrementally per repository.
5. Use `codeguard rules` and `codeguard explain <rule-id>` to document what a failure means before asking teams to act on it.

When a scan fails:

- `fail` findings should block merge or release until fixed, waived, or baselined intentionally.
- `warn` findings are non-blocking by default and are best used to drive cleanup, ownership, or gradual policy hardening.
- section names such as `Design Patterns`, `Security`, or `Code Quality` tell you what kind of action is expected.
- rule IDs are stable handles for waivers, baselines, dashboards, and agent workflows.

## SDK

Import the SDK from `github.com/devr-tools/codeguard/pkg/codeguard`.
Expand Down Expand Up @@ -130,6 +147,7 @@ func main() {
## Docs

- [Getting started](docs/getting-started.md)
- [Production rollout](docs/production.md)
- [Features](docs/features.md)
- [Security & OWASP](docs/security.md)
- [AI-generated code quality](docs/ai-quality.md)
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# CodeGuard Docs

- [Getting started](getting-started.md)
- [Production rollout](production.md)
- [Features](features.md)
- [AI-generated code quality](ai-quality.md)
- [Agent-native features](agent-native.md)
Expand Down
34 changes: 29 additions & 5 deletions docs/checks.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,26 @@

This file documents the current check categories in `codeguard` and the config keys that control them.

## How to interpret results

When `codeguard` reports a finding, read it in this order:

1. Section: tells you the policy family, such as `Security`, `Design Patterns`, or `Code Quality`.
2. Level: `fail` is intended to block; `warn` is intended to surface risk without blocking by default.
3. Rule ID: the stable identifier for waivers, baselines, dashboards, and `codeguard explain`.
4. Message: the repository-specific explanation for the concrete file and location.

Useful commands:

```bash
codeguard rules
codeguard explain design.layer-boundary
codeguard explain quality.ai.semantic-runtime
```

Use `codeguard rules` to discover what exists and `codeguard explain <rule-id>` to
understand why a specific finding failed and what remediation path it expects.

## Top-level shape

```json
Expand Down Expand Up @@ -231,7 +251,7 @@ Current inference behavior:
| Family | Go | C++ | Python | TypeScript | Rust | Java | C# | Ruby |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Quality | `gofmt`, parseability, maintainability thresholds | maintainability thresholds across sources, headers, templates, and modules; optional `clang-format` and sanitized `clang++` validation | maintainability thresholds | maintainability thresholds, `@ts-ignore`, `@ts-nocheck`, `@ts-expect-error`, `explicit any`, double assertions, non-null assertions, `debugger` statements | maintainability thresholds | maintainability thresholds | maintainability thresholds | maintainability thresholds |
| Design | boundary rules, generic package names, type/interface/file-size heuristics | include/module cycles, graph impact, generic filenames, qualified method counts | public-imports-private, public-imports-cli, generic module names | generic module names, max methods per class, max members per interface/object type | module cycles and graph impact | import cycles and graph impact | - | - |
| Design | package boundary rules, generic package names, declarations per file, methods per type, interface size, graph reachability/stability/impact | include and named-module cycles, reachability, stability, graph impact, generic filenames, declarations per file, method counts, contract surface checks, boundary-policy enforcement | public/private and entrypoint coupling, import cycles, generic module names, methods per type, protocol size | generic module names, max methods per class, max members per interface/object type, graph resolution through `tsconfig` paths, package `imports`, and workspace package exports | module cycles, graph impact, generic module names, methods per type, trait size | import cycles and graph impact | - | - |
| Security | insecure TLS, shell execution review, optional `govulncheck` | insecure TLS, shell execution review, unsafe C string APIs, taint flow, SSRF | insecure TLS, shell execution review, dynamic code | insecure TLS, shell execution review, dynamic code, string timer execution, wildcard `postMessage`, Node `vm` execution, unsafe HTML sinks | insecure TLS, shell execution review | insecure TLS, shell execution review | insecure TLS, shell execution review | insecure TLS, shell execution review, dynamic code |
| Commands | language command mappings via config | language command mappings via config | language command mappings via config | language command mappings via config | language command mappings via config | language command mappings via config | language command mappings via config | language command mappings via config |

Expand Down Expand Up @@ -830,13 +850,17 @@ Current behavior:
- fails on configured layer, domain, data-ownership, capability, public-surface, and production/test boundary violations
- can require every module to belong to a configured layer and domain
- warns on configured unreachable modules and stability-direction inversions
- Go targets keep the existing package, import-boundary, declaration-count, type-size, and interface-size heuristics
- Python targets fail on public-to-private imports, direct or transitive entrypoint coupling, and internal import cycles, and warn on overly generic module names
- TypeScript targets warn on overly generic module names, oversized classes, and oversized interfaces or object types using compiler-parsed AST analysis when the semantic runtime is available
- C++ targets build a target-local include/named-module graph for cycles, god modules, and diff impact; they also warn on generic filenames and excessive qualified out-of-line methods for one type
- Go targets keep package and import-boundary checks and warn on declarations per file, methods per type, and oversized interfaces
- Python targets fail on public-to-private imports, direct or transitive entrypoint coupling, and internal import cycles, and warn on overly generic module names, oversized classes, and oversized protocols
- TypeScript targets warn on overly generic module names, oversized classes, and oversized interfaces or object types, while the graph resolver follows relative imports, `tsconfig` aliases and extends chains, package `imports`, and workspace package exports
- Rust targets build a module graph for cycles and impact and warn on generic module names, oversized impls, and oversized traits
- C++ targets build a target-local include/named-module graph for cycles, god modules, reachability, stability, diff impact, and boundary policy enforcement; they also warn on generic filenames, declarations per file, excessive methods on one type, and oversized contract surfaces
- can run language-specific design commands based on `targets[].language`
- language command failures surface as `design.command-check`

For a production rollout sequence and guidance on when to use baselines, waivers,
or diff scans, see [Production rollout](production.md).

Language command example:

```json
Expand Down
7 changes: 6 additions & 1 deletion docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,13 @@ This page lists the current `codeguard` feature surface and the main config entr
- `design`
- layering and boundary rules
- import cycle and god-module detection
- reachability and stability policy warnings over language graphs
- high-impact-change analysis and dependency graph artifacts
- C++ target-local include and named-module graphs, generic filename checks, and qualified method-count limits
- Go package-boundary checks plus declarations-per-file, methods-per-type, and interface-size heuristics
- Python public/private and entrypoint coupling checks, import-cycle detection, generic module names, class-size heuristics, and protocol-size heuristics
- TypeScript generic-module, class-size, and interface-size heuristics plus graph resolution through relative imports, `tsconfig` paths, package `imports`, and workspace package exports
- Rust module graphs plus generic-module, methods-per-type, and trait-size heuristics
- C++ target-local include and named-module graphs for cycles, reachability, stability, change impact, and boundary policy enforcement, plus generic filename, declarations-per-file, method-count, and contract-surface heuristics
- `security`
- hardcoded secrets and private keys
- Go, Python, TypeScript, and JavaScript taint-style flow checks
Expand Down
23 changes: 22 additions & 1 deletion docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Or in GitHub Actions from GitHub Marketplace:

```yaml
- name: Devr Codeguard
uses: devr-tools/codeguard@v0.2.0
uses: devr-tools/codeguard@v1.1.1
```

For SDK consumers:
Expand All @@ -44,6 +44,26 @@ codeguard baseline -config codeguard.yaml -output codeguard-baseline.json

If you prefer a JSON example, start from [examples/codeguard.json](/Users/alex/Documents/GitHub/codeguard/examples/codeguard.json:1).

## First production setup

Use this sequence for a real repository:

1. `codeguard init`
2. `codeguard validate -config codeguard.yaml`
3. `codeguard doctor -config codeguard.yaml`
4. `codeguard scan -mode diff -config codeguard.yaml`
5. `codeguard baseline -config codeguard.yaml -output codeguard-baseline.json` if the repo has pre-existing debt

After that, add a full scan in scheduled CI and tighten check families
incrementally. The detailed rollout guidance lives in [Production rollout](production.md).

## Understanding results

- `fail` findings are intended to block until fixed, waived, or baselined.
- `warn` findings are advisory by default and are best used for gradual cleanup.
- `codeguard rules` lists every rule with section, level, execution model, and language coverage.
- `codeguard explain <rule-id>` explains what a specific failed check means and how to fix it.

## SDK import path

The public SDK import path is:
Expand Down Expand Up @@ -86,5 +106,6 @@ func main() {
- `doctor` checks for config, Git, govulncheck, targets, and cache setup
- `text`, `json`, `sarif`, and `github` report formats
- Diff-mode filtering down to changed lines when Git history is available
- Production rollout tools such as baselines, waivers, diff scans, and rule metadata discovery

Language-specific engines can be added later without changing the repo shape.
4 changes: 2 additions & 2 deletions docs/integrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ This repository also ships the GitHub Marketplace action `Devr Codeguard` from `

```yaml
- name: Devr Codeguard
uses: devr-tools/codeguard@v0.2.0
uses: devr-tools/codeguard@v1.1.1
with:
config: codeguard.yaml
profile: strict
Expand All @@ -36,7 +36,7 @@ For pull request workflows, the action can also publish a sticky fix-oriented co

```yaml
- name: Devr Codeguard
uses: devr-tools/codeguard@v0.2.0
uses: devr-tools/codeguard@v1.1.1
with:
config: codeguard.yaml
mode: diff
Expand Down
172 changes: 172 additions & 0 deletions docs/production.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# Production Rollout

This guide is for teams using `codeguard` as a real merge gate, scheduled audit,
or agent-facing policy service.

## Goals

In production, `codeguard` should do three things well:

- block genuinely risky changes with low ambiguity
- keep historical debt from drowning out new regressions
- make findings understandable enough that humans and agents can act on them

## Recommended rollout order

1. Validate the environment.

Run:

```bash
codeguard validate -config codeguard.yaml
codeguard doctor -config codeguard.yaml
```

This catches broken config, missing binaries, target-path issues, and optional
command integrations before they fail inside CI.

2. Start with pull-request diff scans.

Run `codeguard scan -mode diff` in CI first. This keeps the initial gate tight
around changed code instead of failing the whole repository for historical debt.

3. Capture legacy findings in a baseline.

If the repository already has known issues, write a baseline and check it in:

```bash
codeguard baseline -config codeguard.yaml -output codeguard-baseline.json
```

Then reference it from config so new regressions still fail while existing debt
stays visible but suppressed.

4. Add full-repository scans.

Keep diff scans as the merge gate, then add a scheduled or pre-release full scan
to catch cross-repo issues that are not visible from a small diff.

5. Tighten by family, not all at once.

A practical order is:

- `security`
- `quality`
- `ci`
- `design`
- `contracts`
- `performance`
- `supply_chain`

That ordering usually gives the fastest signal-to-noise improvement.

## How to read a failed scan

Every finding has four pieces that matter operationally:

- section: the owning area, such as `Security`, `Design Patterns`, or `Code Quality`
- rule ID: the stable identifier, such as `design.layer-boundary`
- level: `fail` or `warn`
- message: the repository-specific explanation with path and location

Use them this way:

- `fail` means the finding is intended to block merge or release unless it is fixed,
waived, or suppressed through an explicit baseline.
- `warn` means the scan is surfacing risk or cleanup work without blocking by default.
- the rule ID is what you use in waivers, dashboards, automation, and `codeguard explain`.
- the message is optimized for the concrete instance, not the whole policy; read the
rule explanation when you need broader context.

Helpful commands:

```bash
codeguard rules
codeguard explain design.layer-boundary
codeguard explain security.hardcoded-credential
```

`codeguard rules` is best for catalog discovery. `codeguard explain` is best when a
team or agent needs the meaning of one specific failure.

## Choosing what should block

Use blocking failures for:

- credential leaks
- contract breaks
- architecture violations with clear ownership boundaries
- unsafe prompt or MCP config patterns
- CI policy requirements

Use warnings for:

- maintainability drift
- cleanup-oriented design heuristics
- stability and reachability nudges
- performance smells that still need human review

If a rule is too noisy, do not normalize ignoring it. Either tune the config,
baseline the current debt, or disable that rule family intentionally.

## Baselines, waivers, and policy discipline

Use each mechanism for a different purpose:

- baseline: repository already has known findings; suppress them so only new
regressions gate progress
- waiver: a specific known exception with a reason and optional expiry
- config change: the rule truly does not fit the repository's architecture or risk model

Good production hygiene:

- keep waivers narrow by rule and path
- add reasons that another engineer can evaluate later
- expire temporary waivers
- review baselines periodically so they do not become permanent blind spots

## Suggested CI pattern

For most teams:

- pull requests: `codeguard scan -mode diff`
- nightly or scheduled: `codeguard scan`
- release branches: `codeguard scan` plus contracts and supply-chain enforcement

Prefer SARIF or GitHub output when you want code-host annotations, and JSON when
another system or agent will consume the report programmatically.

## Human and agent workflows

For humans:

- treat the section as the routing signal
- treat the rule ID as the policy anchor
- treat the message as the local debugging hint

For agents:

- fetch rule metadata through `codeguard explain <rule-id>` or the MCP `explain` tool
- preserve the rule ID in summaries and fix proposals
- avoid collapsing `warn` and `fail` into one severity bucket
- use file path and line as the patch target, but use the rule explanation to avoid
fixing the symptom while preserving the policy violation

## Design policy in production

Design checks are most effective when introduced in layers:

1. Start with graph warnings such as cycles, reachability, and stability.
2. Add public-surface and production/test isolation policies.
3. Add layer, domain, capability, and data-ownership boundaries once the
repository's intended architecture is explicit.

This is especially important in mixed-language repositories where Go, TypeScript,
Python, Rust, and C++ may have different maturity levels in their local module layout.

## References

- [Getting started](getting-started.md)
- [Checks reference](checks.md)
- [Features](features.md)
- [Integrations](integrations.md)
2 changes: 1 addition & 1 deletion internal/codeguard/checks/design/design.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func targetLanguageFindings(ctx context.Context, env support.Context, target cor
graph := buildPythonImportGraph(env, target)
return pythonTargetFindings(env, target, graph), moduleGraphFromPython(graph)
case "rust", "rs":
return nil, buildRustImportGraph(env, target)
return rustTargetFindings(env, target), buildRustImportGraph(env, target)
case "java":
return nil, buildJavaImportGraph(env, target)
case "c++", "cpp", "cxx", "cc":
Expand Down
Loading
Loading