safe-migrate 0.4.3

Analyze PostgreSQL migrations for schema and locking risks
Documentation
# Contributing to safe-migrate

Thanks for contributing. safe-migrate is a Rust PostgreSQL migration analyzer
with typed AST extraction, stateful schema simulation, and safety rules.

## Start here

- [Documentation index]docs/README.md
- [Architecture and invariants]docs/internal/ARCHITECTURE.md
- [AST development]docs/internal/AST_DEVELOPMENT.md
- [CLI and report contract]docs/CONTRACT.md

## Project structure

```text
src/analysis/   facts, resolution, mutations, dependency graph, state, transactions
src/ast/        extraction from the pinned Squawk typed AST
src/db/         versioned database cache
src/engine/     configuration, orchestration, and rule dispatch
src/model/      modeled PostgreSQL objects
src/report/     human, JSON, and interactive reporting
src/rules/      safety rule implementations
tests/          integration, state-machine, rule, CLI, and regression tests
live_tests/     end-to-end SQL fixtures and frozen database cache
docs/           product contracts and maintainer documentation
```

Prefer this stable directory-level map over a copied inventory of every source
file or rule. Use `rg --files src tests live_tests` when you need the current
layout.

## Development commands

Use locked dependencies:

```bash
cargo build --locked
cargo test --locked
cargo fmt -- --check
cargo clippy --all-targets --locked -- -D warnings
```

Focused examples:

```bash
cargo test rule_evaluation
cargo test architectural_gap
cargo test expression_parsing
```

End-to-end fixtures:

```bash
cd live_tests
./run.sh
./run.sh -d rule_25_schema-drift
```

The fixture runner invokes the compiled binary. Most rule directories lint each
file independently; chain-conflict fixtures use `lint-chain`.

## Adding or changing a rule

1. Implement one safety concept under `src/rules/`.
2. Register the rule in the engine's canonical rule list.
3. Add configuration only when the rule needs a user-controlled policy.
4. Add focused regression tests.
5. Add or update end-to-end fixtures.
6. Update the canonical user-facing rule documentation.
7. Add a `CHANGELOG.md` entry for user-visible behavior.

Rules must:

- handle `MutationResult::Skipped` deliberately;
- distinguish conflicts from applied mutations;
- infer operation and object kinds from the mutation;
- avoid mutating analysis state;
- explain the mechanism and a safer next step;
- document PostgreSQL-version assumptions;
- avoid using row count for lock behavior unless table size actually changes
  the rule's conclusion.

## Extending AST extraction

Do not use an old AST reference or guess accessors from memory. Follow the
[source-first AST workflow](docs/internal/AST_DEVELOPMENT.md):

1. confirm the exact Squawk versions in `Cargo.toml` and `Cargo.lock`;
2. inspect the resolved dependency source and grammar;
3. add an exact fact assertion in `src/ast/visitor_tests.rs`;
4. implement extraction in `src/ast/visitor.rs` or expression conversion in
   `src/analysis/expr_visitor.rs`;
5. test resolver, state, and rule effects when behavior crosses layers;
6. represent unsupported parser behavior explicitly.

A Squawk version upgrade is an AST migration. Update all three pinned Squawk
crates together and validate the full extraction surface through compilation and
tests.

## State-machine changes

When adding modeled state:

1. define the state or overlay in the appropriate model module;
2. add explicit mutations and resolution;
3. preserve baseline-versus-local identity;
4. add transaction undo state for every mutable component;
5. test apply, skip, conflict, rollback, rename, drop, and recreate behavior;
6. update dependency edges and generation metadata where applicable.

See [Architecture and invariants](docs/internal/ARCHITECTURE.md).

## CLI and report changes

User-visible output is an interface. Changes to JSON fields, confidence meaning,
verdicts, exit statuses, output channels, or ordering must:

1. follow [the CLI and report contract]docs/CONTRACT.md;
2. include integration or golden tests;
3. preserve machine-only JSON standard output;
4. update `CHANGELOG.md`;
5. include a migration note when scripts may break.

## Testing expectations

Add regression coverage with every behavior change:

- AST changes: assert exact extracted facts.
- Resolver/state changes: assert the resulting state and undo behavior.
- Rule changes: assert rule ID, tier, object, reason, and relevant recipe.
- Reporter changes: assert structured output and deterministic ordering.
- CLI changes: assert standard output, standard error, and exit status.
- Database metadata changes: use existing cache and live-test helpers.

`safe_*.sql` fixtures are expected not to emit the target rule. Numbered
fixtures are expected to emit the target rule. A fixture count is not a
correctness claim by itself; prefer precise assertions in Rust tests for
object, tier, reason, and source behavior.

## Database synchronization

`safe-migrate sync`, and `lint` or `lint-chain` only when configured with
`auto_sync = true`, read `DATABASE_URL`. Do not commit credentials, connection
strings, or private database dumps. Use a least-privilege PostgreSQL role and
treat cache changes as reviewable schema-state changes.

The frozen cache under `live_tests/` belongs to the test corpus. Update it only
when a fixture requires a changed baseline, and explain the assumption in the
pull request.

## Code style

- Format with `rustfmt`.
- Treat Clippy warnings as errors.
- Use idiomatic Rust naming and four-space indentation.
- Keep one rule concept per file or focused module.
- Document non-obvious undo-log and dependency-graph behavior inline.

## Reporting bugs

Include:

- minimal SQL;
- expected and actual output;
- safe-migrate version;
- PostgreSQL version or assumed version;
- whether a cache was used;
- relevant configuration.

Classify the likely layer:

- AST extraction: add an exact visitor regression and inspect the pinned Squawk
  source.
- Resolution/state: test mutations, overlays, dependencies, and rollback.
- Rule: test false-positive/false-negative behavior and severity.
- CLI/report: test output channels, JSON, and exit status.

## Questions

Open an issue at <https://github.com/dsecurity49/safe-migrate> with a minimal
reproduction and the affected layer.