ccppccpp home

Profiles

Backend Python

Python services, APIs and workers with checked types, explicit failures, safe boundaries, consistent data, owned async work and evidenced completion. Rule IDs ENV/TYP/ARC/PY/API/DB/IO/TST/OPS; NEED TO blocks on demonstrated violations.

Set this profile

ccpp cpo profile set backend-python

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 2

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

  • api09-sensitive-logging

    API-09 · Logs and prints should not receive secrets, credentials or whole request payloads

  • ops02-hardcoded-credentials

    OPS-02 · The user confirms credential-named values written as literals, or secret environment reads with a literal fallback

Authentication & authorization 2

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

  • api06-csrf-protection

    API-06 · The user confirms disabling CSRF protection for cookie-authenticated requests (csrf_exempt, middleware removed, insecure CSRF settings)

  • py06-assert-for-checks

    PY-06 · Validation and authorization never rely on assert (removed under python -O)

Untrusted input 8

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

  • api01-unvalidated-payload

    API-01 · Request payload fields should go through a validator before domain use, not be read raw

  • api04-serialized-fields

    API-04 · Serializers and forms list the fields they expose instead of "__all__"

  • api05-mass-assignment

    API-05 · The user confirms mapping a raw request payload onto persistent objects (unrestricted ** expansion, __dict__ update, setattr loop)

  • api07-quoted-placeholders

    API-07 · Bound-value placeholders are never quoted inside SQL text ('%s')

  • api07-sql-interpolation

    API-07 · The user confirms SQL built by interpolating values or identifiers into the query text

  • api08-dangerous-sinks

    API-08 · eval/exec, shell=True, os.system, pickle and unsafe YAML loading need a demonstrated trusted input

  • api08-untrusted-to-sink

    API-08 · Request data never reaches eval/exec, a shell, or an unsafe deserializer

  • typ06-cast-untrusted-input

    TYP-06 · A cast or annotation on untrusted input is not validation; parse it at runtime

Network & TLS 2

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

  • api10-request-controlled-target

    API-10 · The user confirms outbound URLs, file paths or upload names taken from the request without a visible guard

  • io08-tls-verification

    IO-08 · TLS certificate verification stays on in production code (configure trust roots instead)

Weakened checks 3

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

  • env06-weakened-checks

    ENV-06 · The user authorizes tooling changes that add ignores or exclusions, lower strictness or thresholds, narrow test selection or drop a check

  • tst08-reduced-test-coverage

    TST-08 · The user confirms new skips and expected failures, and removed test functions

  • typ04-suppressions

    TYP-04 · Type and lint suppressions name the diagnostic and justify the exception; no blanket suppression

Type safety 2

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

  • typ01-public-annotations

    TYP-01 · Public production functions should annotate their parameters and return type (None included)

  • typ03-new-any

    TYP-03 · Any and opaque containers should stay at external boundaries and be narrowed before domain use

Error handling 3

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

  • py03-hidden-failure

    PY-03 · An exception handler propagates unexpected failure or implements an explicit recovery, never a silent success

  • py04-broad-except

    PY-04 · Broad exception catches should be boundary handlers that keep diagnostics and failure semantics

  • py05-exception-cause

    PY-05 · An exception translated in a handler keeps the original as its cause (raise … from err)

Async & concurrency 4

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

  • io01-blocking-in-async

    IO-01 · Async functions do not call blocking sleep, HTTP, subprocess or socket APIs on the event-loop thread

  • io02-unawaited-coroutines

    IO-02 · A coroutine created by a statement is awaited or handed to a managed task facility

  • io03-unowned-tasks

    IO-03 · Background tasks have an owner that keeps a reference, observes failure and cancels them on shutdown

  • io04-swallowed-cancellation

    IO-04 · Async code re-raises CancelledError unless it owns the cancelled task

Performance & resource bounds 6

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

  • db06-queries-in-loops

    DB-06 · Loops should not issue one ORM query per item where batch loading preserves semantics

  • io05-missing-timeouts

    IO-05 · Outbound calls keep a finite effective timeout (requests and urlopen have none by default; timeout=None disables it)

  • io06-clients-in-loops

    IO-06 · HTTP, database and cloud clients are created once and reused, not inside loops

  • io07-unclosed-resources

    IO-07 · Files, sockets and streamed responses are closed on every path (context manager) or explicitly handed over

  • io09-unbounded-retries

    IO-09 · Retries are bounded (stop condition, backoff); a loop does not retry a failing operation forever

  • ops05-unbounded-caches

    OPS-05 · In-process caches are bounded and owned (no unbounded @cache, no lru_cache on methods)

Architecture & boundaries 2

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

  • arc01-framework-free-domain

    ARC-01 · Modules the project declared framework-independent import no framework, persistence or transport package at runtime

  • arc08-import-time-effects

    ARC-08 · Importing a module should not reach the network, write data or start tasks and processes

Language idioms 4

The conventions of the language that keep code predictable for its readers.

  • py01-mutable-defaults

    PY-01 · Parameters never default to a shared mutable object (list, dict, set, deque…)

  • py07-finally-control-flow

    PY-07 · No return, break or continue inside finally (it silently discards the pending exception or return)

  • py09-wildcard-imports

    PY-09 · Imports name what they use (no wildcard import outside package re-exports)

  • py10-naive-datetimes

    PY-10 · Instants are timezone-aware (no utcnow, utcfromtimestamp or argument-less now)

HTTP & APIs 1

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

  • ops04-error-details-exposed

    OPS-04 · Error responses expose a stable safe error, not the raw exception or a traceback

Databases & queries 5

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

  • db01-writes-outside-transaction

    DB-01 · Several ORM writes in one function run inside one transaction (Django autocommit commits each separately)

  • db02-side-effect-before-commit

    DB-02 · Side effects that depend on a write (mail, tasks, events, HTTP) are scheduled after commit

  • db03-db-error-inside-atomic

    DB-03 · A database error is not caught and swallowed inside the transaction it broke (use an inner savepoint)

  • db04-uniqueness-precheck

    DB-04 · Uniqueness under concurrency is a database constraint; an exists() pre-check before create races

  • db05-lost-update

    DB-05 · Read-modify-write of a persisted counter or balance should be atomic (F() expression, lock or version check)

Schema migrations 5

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

  • db07-model-without-migration

    DB-07 · A persisted model change ends the turn with its migration (Django apps with migrations/, Alembic projects)

  • db08-edit-applied-migration

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

  • db08-live-models-in-migration

    DB-08 · Migrations use historical models (apps.get_model, op.get_bind), not the application's live models

  • db09-risky-migration-operations

    DB-09 · Destructive, locking or non-null migration operations need a rollout plan (locks, batches, old/new code compatibility)

  • db10-irreversible-migration

    DB-10 · Data migrations declare their reverse, or state that they are irreversible and how to recover

Versions & deprecated APIs 1

Code matches the installed version, without removed, renamed or deprecated APIs.

  • env05-python-version

    ENV-05 · New syntax and stdlib APIs stay within the oldest Python version the project declares (requires-python)

Configuration 1

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

  • ops01-environment-outside-config

    OPS-01 · Configuration is read from the environment and validated at one boundary, not across the code

Logging & observability 1

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

  • ops03-debug-leftovers

    OPS-03 · Production modules carry no debugger traps or diagnostic prints (CLIs and entry points may print)

Dependencies & toolchain 3

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

  • env03-undeclared-imports

    ENV-03 · A newly imported third-party package should be declared in the project's dependency manifest

  • env04-lock-not-updated

    ENV-04 · Changed dependency declarations end the turn with their lock or compiled constraints updated

  • ops07-import-fallbacks

    OPS-07 · An ImportError fallback is tied to a supported version or a declared optional dependency, not invented compatibility

Tests 3

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

  • tst03-tautological-assertions

    TST-03 · Test assertions compare behavior with an independent expectation, not a value with itself or a constant

  • tst05-network-in-unit-tests

    TST-05 · Unit and contract tests do not reach external hosts; live suites are declared separately

  • tst07-sleeps-in-tests

    TST-07 · Tests synchronize on events or control the clock instead of sleeping

Completion evidence 5

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

  • py02-placeholder-implementation

    PY-02 · Production functions implement reachable behavior instead of pass, Ellipsis or a stub-marked constant

  • tst10-completion-claims

    TST-10 · A final message claiming passing checks needs a successful check after Claude's last edit

  • tst10-evidence-ledger

    TST-10 · Records, per session, Claude's edits and the checks (pytest, type checker, linter) that succeeded after them

  • turn-baseline

    Records the work tree when a prompt starts, the baseline of the end-of-turn checks (TYP-02, DB-07, ENV-04)

  • typ02-new-type-errors

    TYP-02 · Claude does not end a turn with type-checker errors it introduced (unresolved imports, syntax, Optional access, unused coroutines included)