ccppccpp home

Profiles

Backend Rust

Rust services, APIs and workers (Tokio, axum, tower, SQLx) with declared boundaries, explicit failures, owned async work, bounded resources, safe inputs and evidenced completion. Rule IDs ARC/TYP/ERR/ASY/API/DB/OPS/QLT; NEED TO blocks on demonstrated violations.

Set this profile

ccpp cpo profile set backend-rust

Inside Claude Code, prefix the command with ! to run it in the session. Downloading a profile needs a Builder or Team plan; listing them does not.

Policies

63 policies, grouped by what they guard.

Secrets & private data 4

Credentials, keys and personal data stay out of files, logs, commands and the conversation.

  • rs-ops05-sensitive-logging

    OPS-05 · Secrets and credentials do not reach logs, spans or Debug output (no logged secrets, no derived Debug on secret fields, instrument skips them)

  • rs-ops10-hardcoded-credentials

    OPS-10 · The user confirms credential-named values written as literals or used as fallbacks for secret environment reads

  • rs-typ07-derived-config-defaults

    TYP-07 · Settings types holding credentials or connection strings do not derive Default (an empty secret is not a configuration)

  • rs-typ07-fabricated-defaults

    TYP-07 · Default implementations do not fabricate credentials, connection strings or identities

Authentication & authorization 2

Who may do what, from roles, privileges and permissions to CSRF, CORS and verified tokens.

  • rs-api04-unverified-tokens

    API-04 · Tokens are verified before they authenticate (no disabled signature or expiry validation, no insecure decode)

  • rs-api05-routes-after-auth-layer

    API-05 · Routes added after an authentication layer in an axum Router chain are intentionally unprotected

Untrusted input 2

Requests, downloads and tool output are validated before they reach SQL, a shell, eval or a deserializer.

  • rs-api07-client-controlled-fields

    API-07 · Request payload types do not let clients set server-owned fields (roles, ownership, tenant, verification state)

  • rs-db01-sql-formatting

    DB-01/DB-02 · The user confirms SQL text built with format!, concatenation or QueryBuilder::push of non-literal values

Network & TLS 1

Outbound data, verified certificates, destinations taken from requests and services exposed to others.

  • rs-ops09-tls-verification

    OPS-09 · Outbound TLS keeps certificate and hostname verification (no danger_accept_invalid_*, no custom no-op verifier)

Weakened checks 3

Suppressions, disabled lint or CI steps and relaxed strictness need a reason or the user's approval.

  • rs-qlt06-blanket-suppressions

    QLT-06 · No blanket or crate-wide lint suppression (allow(warnings), clippy::all, unsafe_code, inner

  • rs-qlt06-unexplained-allows

    QLT-06/QLT-08 · Item-level lint suppressions name their reason (#[expect(lint, reason = "…")]), dead code included

  • rs-qlt10-weakened-checks

    QLT-10 · The user authorizes lint, test or CI configuration changes that allow lints, skip checks or ignore failures

Type safety 5

No escapes from the type checker (any, unchecked casts, non-null assertions) and explicit contracts.

  • rs-qlt06-unsafe-without-safety

    QLT-06 · unsafe blocks, unsafe impls and unsafe fns state their safety obligation (// SAFETY:,

  • rs-typ02-optional-required

    TYP-02 · A function that needs a value takes it, instead of an Option it silently ignores when None

  • rs-typ03-boolean-modes

    TYP-03 · Functions do not take several boolean flags that encode modes; use an enum or a configuration type

  • rs-typ05-borrowed-owned-containers

    TYP-05 · Read-only parameters borrow slices, str or Path, not &Vec, &String, &PathBuf or &Box

  • rs-typ06-cloning-getters

    TYP-06 · Getters return a borrow instead of cloning an owned field on every call

Error handling 8

Failures are propagated or handled, never swallowed or turned into fake success.

  • rs-err01-panics-in-handlers

    ERR-01 · Request handlers return failures instead of panicking (unwrap, expect, panic!) on request-derived values

  • rs-err01-unwrap-on-input

    ERR-01 · Parsing, decoding and conversions of external data outside startup return errors instead of unwrap/expect

  • rs-err02-discarded-ok

    ERR-02 · A fallible result is not erased with a bare `.ok();` statement

  • rs-err02-discarded-results-typed

    ERR-02 · A Result or future bound to `let _` is a justified discard (type from rust-analyzer)

  • rs-err03-failure-as-success

    ERR-03 · A catch-all Err arm does not report success with an empty, default or true value

  • rs-err03-silent-fallbacks

    ERR-03 · Errors replaced by a default value (unwrap_or_else(|_| …), .ok().unwrap_or…, Err(_) => default) are a specified fallback

  • rs-err04-error-text-branching

    ERR-04 · Callers branch on typed error variants, not on the text of an error's Display

  • rs-err06-fallible-middleware

    ERR-06 · Fallible tower middleware (timeout, load_shed, buffer) is paired with an error handler that turns its errors into responses

Async & concurrency 6

Owned tasks, awaited promises, preserved cancellation and no blocking on event loops.

  • rs-asy01-blocking-in-async

    ASY-01 · Async code does not call blocking sleep, file, socket, process or block_on APIs on executor workers

  • rs-asy03-guard-across-await

    ASY-03 · A synchronous lock guard (std or parking_lot) is released before the next .await in the same scope

  • rs-asy04-async-mutex-without-await

    ASY-04 · An async mutex guard that never spans an .await should be a short synchronous critical section

  • rs-asy07-detached-tasks

    ASY-07 · A spawned task has a lifecycle owner that observes its result and stops it on shutdown (no dropped JoinHandle)

  • rs-asy08-cancellation-safety

    ASY-08 · select! branches and timeouts do not cancel operations that are not cancellation-safe (partial reads/writes, commits, executes)

  • rs-asy09-blocking-timeouts

    ASY-09 · A timeout or select! around spawn_blocking accounts for the blocking work that keeps running

Performance & resource bounds 7

Timeouts, bounded retries and fan-out, reused clients, closed resources, no N+1 queries.

  • rs-asy05-unbounded-queues

    ASY-05 · The user confirms unbounded channels, which need a demonstrated finite producer and an overload policy

  • rs-asy06-unbounded-fan-out

    ASY-06 · Tasks and futures created per item of a loop or iterator have an admission limit (semaphore, buffer_unordered, JoinSet cap)

  • rs-asy11-unbounded-retries

    ASY-11 · Retry loops have a bound (attempts or elapsed budget), a delay, and stop on terminal errors

  • rs-db05-pools-per-request

    DB-05 · Pools and HTTP/database clients are built at startup and shared, not per request or per loop iteration

  • rs-db06-unbounded-fetch-all

    DB-06 · fetch_all over a SELECT has a result bound (LIMIT, a key filter, pagination)

  • rs-db09-queries-in-loops

    DB-09 · Request-driven loops do not issue one database query per item (N+1); batch or join instead

  • rs-ops03-client-timeouts

    OPS-03 · Outbound HTTP clients have a deadline (reqwest/ureq builders with timeout, no bare Client::new or reqwest::get)

Architecture & boundaries 2

Declared layers and dependency directions, no import cycles, small modules, explicit dependencies.

  • rs-arc01-dependency-map

    ARC-01 · use paths and Cargo dependencies respect the project's declared dependency map (off until dependencyRules is set)

  • rs-arc02-io-in-domain

    ARC-02 · Designated domain components do not reach transport, persistence, filesystem or environment APIs (off until domainPaths is set)

HTTP & APIs 3

Request and response contracts, schemas, status codes, error bodies and published API surfaces.

  • rs-api03-body-limits

    API-03 · The user confirms removing or bypassing request body limits (DefaultBodyLimit::disable, to_bytes with usize::MAX, unlimited payload configs)

  • rs-asy10-graceful-shutdown

    ASY-10 · A server stops admission and drains in-flight work on shutdown (axum/hyper serve with graceful shutdown)

  • rs-err05-error-details-exposed

    ERR-05 · Internal failures map to stable public errors; 500 responses do not carry the error's text or Debug output

Databases & queries 3

Schemas, queries, transactions and the ORM used as intended.

  • rs-db03-writes-outside-transaction

    DB-03 · Several writes in one operation run in one transaction and report success after commit

  • rs-db04-uncommitted-transactions

    DB-04 · A transaction that is begun is committed (or deliberately rolled back or handed on), never silently dropped on success

  • rs-db07-remote-io-in-transaction

    DB-07 · Outbound network calls do not run while a transaction holds a pooled connection

Schema migrations 2

Migrations come from the tool, applied history stays immutable and risky changes are rolled out safely.

  • rs-db08-edit-applied-migration

    DB-08 · The user confirms editing a migration that already existed before this session (applied history)

  • rs-db08-schema-without-migration

    DB-08 · A change to persisted Rust models (Diesel table!, SeaORM entities, FromRow/Queryable structs) ends the turn with a new migration

Configuration 3

Settings read once at a boundary, validated, with units and without unsafe defaults.

  • rs-ops01-config-fallbacks

    OPS-01 · Environment reads do not fall back to a default for required settings (unwrap_or, unwrap_or_default, unwrap_or_else)

  • rs-ops01-environment-outside-config

    OPS-01 · Configuration is read from the environment and validated once into typed settings, not across the code

  • rs-ops02-unitless-durations

    OPS-02 · Time settings in configuration types carry a unit (Duration, or an explicit _ms/_secs suffix)

Logging & observability 2

Structured logs, bounded metric labels, no debug prints left in production code.

  • rs-ops04-unstructured-logs

    OPS-04 · Production code logs through tracing with structured fields, not println!/eprintln! or values interpolated into the message

  • rs-ops06-unbounded-metric-labels

    OPS-06 · Metric labels have a bounded value set (no user/request IDs, raw paths or error text as labels)

Dependencies & toolchain 1

Packages change through the package manager, lockfiles stay consistent and the project's tools are used.

  • rs-arc08-dependency-changes

    ARC-08 · New Cargo dependencies and features name their capability, enable only needed features and pin git sources

Tests 4

Tests assert behavior, stay deterministic and are not removed or skipped silently.

  • rs-qlt01-test-assertions

    QLT-01 · Tests check an outcome (assert, expected error, unwrap of the result under test), not just run code

  • rs-qlt03-test-timing

    QLT-03 · Tests control time and synchronization instead of sleeping on the real clock

  • rs-qlt10-reduced-tests

    QLT-10 · The user confirms new

  • rs-qlt10-snapshot-updates

    QLT-10 · The user confirms changes to existing approved snapshots (insta .snap files)

Completion evidence 5

A turn ends with its checks run and passing; claims of success need proof after the last edit.

  • rs-qlt05-placeholders

    QLT-05 · Production code ships no todo!(), unimplemented!() or dbg!() placeholders

  • rs-qlt07-completion-claims

    QLT-07 · A final message claiming a passing build, lint or tests needs a successful cargo run after Claude's last edit

  • rs-qlt07-evidence-ledger

    QLT-07 · Records, per session, Claude's edits and the cargo build, lint or test runs that succeeded after them

  • rs-qlt07-new-compile-errors

    QLT-07 · Claude does not end a turn with compiler errors it introduced in Rust sources or their dependents (rust-analyzer)

  • rs-turn-baseline

    Records the work tree when a prompt starts, the baseline of the end-of-turn checks (QLT-07, DB-08)