# Pma Rust

> Production-grade Rust implementation and acceptance baseline for PMA-managed Rust services and CLIs. Use with /pma when creating, upgrading, or validating acceptance of Rust workspaces, Axum/Tokio services, CLI binaries, CI pipelines, release packaging, lint policy, dependencies, testing, observability, security, or supply-chain controls. Use pma-cr for code-review workflow.

- Skill: `zzci/pma-rust` (Agent Skill, multi-file: 7 files)
- Install (CLI): `npx skillmds add zzci/pma-rust`
- Raw SKILL.md: https://api.skillmd.com/api/skills/zzci/pma-rust/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: zzci (https://skillmd.com/u/zzci)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/zzci/pma-rust

---


# Rust Project Implementation & Acceptance Guide

Use this skill together with `/pma`. `/pma` controls workflow, approval, and task tracking; this guide defines the **product-grade acceptance baseline** for every PMA-Rust project.

Every claim in the reference packs is **anchored to file:line evidence** from the standard-bearer projects below. If a recommendation is missing evidence, it is marked as such.

## Hard Locks (non-negotiable)

These rules apply to **every** PMA-Rust project. They cannot be overridden by project-level `CLAUDE.md`, only by an explicit, time-boxed exception in `docs/decisions/` with a sunset date.

| # | Rule | Enforcement |
|---|---|---|
| 1 | **Pure Rust ecosystem first.** No new dependency may pull in OpenSSL, native-tls, libgit2-sys, or any other C-FFI binding when a pure-Rust alternative exists. The one pre-sanctioned C/asm core is rustls's default `aws-lc-rs` crypto provider (no mature pure-Rust crypto exists; `ring` is equally non-pure). See `baseline.md` Lock 1/2. | `cargo deny bans` + dependency review |
| 2 | **rustls only** for TLS, **`aws-lc-rs` crypto provider** (the rustls 0.23 default). `tokio-rustls` / `rustls-pemfile` / `rustls-platform-verifier` are the canonical stack; install the provider in `main()`. | `bans.deny = [openssl, openssl-sys, native-tls, native-tls-sys]` |
| 3 | **`#![forbid(unsafe_code)]`** at every crate root (lib.rs / main.rs). Only data-crate or FFI-crate may relax to `deny`, with `// SAFETY:` comments on every `unsafe` block. | clippy + workspace lints |
| 4 | **Deny warnings is workspace-manifest policy.** Set `[workspace.lints.rust] warnings = { level = "deny", priority = -2 }` (the rustc `warnings` lint-group; covers all current and future warn-by-default lints). Members inherit via `[lints] workspace = true`. CI runs `cargo clippy` with no `-- -D warnings` suffix — policy lives in `Cargo.toml`, versioned with code, inherited everywhere. | `[workspace.lints.rust]` |
| 5 | **MSRV declared** in `[workspace.package].rust-version`. CI verifies via `cargo hack check --rust-version` or `cargo msrv verify`. | CI gate |
| 6 | **No `unwrap` / `expect` / `panic!` in runtime paths.** Allowed only in `#[cfg(test)]`, `xtask/`, `build.rs`. Enforced via clippy `unwrap_used = "deny"` / `panic = "deny"` in runtime crates. | workspace lints |
| 7 | **edition 2024.** New crates and refactors must adopt edition 2024 unless an upstream dependency blocks. | `[workspace.package].edition` |
| 8 | **Quality gates green** before merge: fmt + clippy + nextest + doctest + cargo-deny + cargo-shear + typos + MSRV check (`cargo hack check --rust-version` or `cargo msrv verify`, per Lock 5). Clippy invoked plainly — deny policy is in `[workspace.lints]`, not on the CLI. See `references/delivery.md`. | CI gate |

Loosening any hard lock requires an explicit, dated decision record (Why? What's the sunset?). PMA `/pma` enforces this by refusing implementation approval when these gates are not configured.

**Locks are defaults, not handcuffs.** `references/baseline.md` "Known Trade-offs (When the Locks Backfire)" lists the real-world scenarios where each lock harms the project (FIPS compliance, ML/HPC C bindings, CLI stdout, glibc NSS, etc.) and the discharge mechanism (`docs/decisions/<adr>.md` with sunset). Read that section before applying a lock dogmatically — and before relaxing one.

## Standard-Bearer Anchors

Every recommendation in the reference packs is grounded in 10 clone-verified standard-bearer projects (cargo, rust-analyzer, reth, vector, tokio, axum, linkerd2-proxy, uv, ruff, quickwit). The evidence anchors for every lock — what each project is mirrored for, plus exact file:line citations — live in `references/evidence.md`.

## Loading Order

Always load `references/baseline.md` first. Then load the pack(s) relevant to the task:

1. `references/baseline.md` — hard locks, tech stack, naming, code quality (always required)
2. `references/toolchain-and-workspace.md` — workspace layout, edition 2024, `[workspace.lints]` vs build-flag pattern, toolchain pinning, dev-loop tools
3. `references/runtime-and-data.md` — Axum 0.8 + tower + tokio runtime, error handling with `IntoResponse`, SQLx/SeaORM/Diesel selection, layered config, graceful shutdown
4. `references/delivery.md` — security, secrets, OTLP observability, testing layers, supply-chain (`cargo-deny`/`cargo-shear`/`typos`), release automation, CI
5. `references/evidence.md` — anchored citations (load when verifying or extending the skill)

## Quick Routing

| If the task touches… | Load |
|---|---|
| New workspace, lints, toolchain, dev tooling | `toolchain-and-workspace.md` |
| Axum/tower handlers, DB access, config, shutdown | `runtime-and-data.md` |
| Tests, CI, observability, release, secrets, supply chain | `delivery.md` |
| "Why is this rule here?" / "What proves X is best practice?" | `evidence.md` |
| Anything else (always) | `baseline.md` |

## Acceptance Checklist (PMA gate)

Before `/pma` accepts a Rust crate or service for production:

- [ ] Workspace declares `edition = "2024"` and `rust-version`
- [ ] Every crate has `#![forbid(unsafe_code)]` (or documented exception)
- [ ] CI runs: fmt + clippy with workspace deny-warnings policy + nextest + `--doc` test + cargo-deny + cargo-shear (or machete) + typos + MSRV check (`cargo hack check --rust-version` or `cargo msrv verify`)
- [ ] No transitive `openssl` / `native-tls` (verified by `cargo deny bans`)
- [ ] All TLS uses rustls; the `aws-lc-rs` provider installed early in `main` (canonical snippet: `references/baseline.md` Lock 2)
- [ ] Tracing initialized with JSON formatter in prod; OTLP optional
- [ ] `/livez` (liveness) + `/readyz` (readiness) endpoints exist for services
- [ ] Graceful shutdown wired via `axum::serve(...).with_graceful_shutdown(...)` + `CancellationToken` (or equivalent)
- [ ] Secrets wrapped in `secrecy::Secret<T>`; never `Debug`-formatted
- [ ] Config layered: defaults → file → env → CLI; validated post-merge
- [ ] Errors typed per crate (`thiserror` 2.x); `anyhow`/`eyre` only in bin entry points
- [ ] Release pipeline reproducible: tag → CI → signed binaries (cargo-dist or custom)
- [ ] Distributable binaries built against `*-unknown-linux-musl` with `+crt-static` (verified via `ldd` saying "not a dynamic executable") **when** the project ships portable CLI binaries
- [ ] `[profile.dist]` defined with size-tuned options (`lto=fat`, `codegen-units=1`, `panic=abort`, `strip=symbols`) when shipping CLI binaries
- [ ] Container base image chosen **with intent and documented in `docs/decisions/`**: pick by ops needs (minimal runtime, debug-friendly, glibc-bound, corporate base, multi-arch). No fixed size target — the right size is whatever the chosen base + binary needs
- [ ] **Core dumps suppressed at all reachable layers** — in-process `rlimit::setrlimit(Resource::CORE, 0, 0)` early in `main` (always), plus systemd `LimitCORE=0` / container `--ulimit core=0:0` / K8s read-only rootfs / kernel `kernel.core_pattern = \|/bin/false` per environment
- [ ] **Panic hook installed** in `main` to emit a structured `tracing::error!` with backtrace before the runtime aborts; production logs replace post-mortem cores

If any item fails, the project is **not production-ready**.

