Skip to main content

coffeehouse-common

Shared Python package for Coffee House ecosystem FastAPI apps:

  • coffeehouse_common.csrf — CSRFMiddleware subclass (form body + header + safe body replay)
  • coffeehouse_common.security_middleware — SecurityHeadersMiddleware (raw ASGI)
  • coffeehouse_common.logging_config — RequestIdMiddleware (raw ASGI), RequestIdFilter, configure_logging, get_request_id
  • coffeehouse_common.observability — init_sentry(app_slug) Sentry SDK bootstrap; reads SENTRY_DSN from env (no-op when unset), tags events with app_slug, drops 4xx HTTP/CSRF noise, keeps 5xx

v0.3.0+ implements security headers and request ID middleware as raw ASGI (not BaseHTTPMiddleware) so streaming responses are not fully buffered. v0.3.1 sets X-Frame-Options: SAMEORIGIN (same-origin iframes allowed; third-party framing blocked). Logs include a per-request correlation id when configure_logging() + RequestIdMiddleware are used.

Install

From GitHub (pinned tag):

pip install "coffeehouse-common @ git+https://github.com/rubencfh/coffeehouse-common.git@v0.9.0"

Local editable install:

pip install -e ../coffeehouse-common

Development

Set up the repo for local development + testing:

git clone https://github.com/rubencfh/coffeehouse-common.git
cd coffeehouse-common
pip install -e ".[testing]"
pip install -r requirements-dev.txt
pre-commit install

Run the full test suite (with coverage, fails under 70%):

pytest

Run the pre-commit hooks against all files (format, lint, secret scan, syntax check):

pre-commit run --all-files

Individual checks:

ruff format --check .          # formatting
ruff check .                   # linting
mypy coffeehouse_common        # type-checking (lenient baseline)
bandit -c pyproject.toml -r coffeehouse_common coffeehouse_testing  # SAST
pip-audit -r requirements-dev.txt                                    # SCA

CI runs the same checks on every push / PR via .github/workflows/ci.yml. See coffeehouse-ecosystem/docs/pipeline.md for the broader pipeline.

Shared test fixtures

The coffeehouse_testing subpackage ships with this repo and provides shared pytest fixtures that consumer apps import in their own tests/conftest.py:

from coffeehouse_testing.jwt_factory import jwt_factory
from coffeehouse_testing.client import authed_client
from coffeehouse_testing.db import postgres_container, clean_db  # noqa: F401
from coffeehouse_testing.auth_stub import make_auth_stub, build_roles_manifest

All heavy dependencies (PyJWT, testcontainers, starlette) are loaded lazily — import the modules you need in tests and the import errors only fire if the underlying package is not installed.

Usage

from coffeehouse_common.csrf import CSRFMiddleware
from coffeehouse_common.logging_config import RequestIdMiddleware, configure_logging
from coffeehouse_common.observability import init_sentry
from coffeehouse_common.security_middleware import SecurityHeadersMiddleware

configure_logging()  # once at startup; attaches RequestIdFilter for %(request_id)s
init_sentry(app_slug="auth")  # no-op if SENTRY_DSN is unset

init_sentry reads SENTRY_DSN, RAILWAY_ENVIRONMENT_NAME (or ENVIRONMENT), and RAILWAY_GIT_COMMIT_SHA from the environment. Errors-only sample rate by default (traces_sample_rate=0.0). 401/403/404/405 responses, 4xx HTTPExceptions, and CSRFErrors are dropped client-side so they don't burn the Sentry quota. 5xx HTTPExceptions and any other exception class are kept. Pass extra_ignored_status_codes= / extra_ignored_exceptions= to extend the filter per app.

Explicit dependency: itsdangerous (CSRF token signing).

Report-table sorting

coffeehouse_common.report_sort (promoted from Grind after Stoply became the second adopter) pairs with coffeehouse-ui's sortable_th macro: parse_sort(request, allowed=..., default_sort=...) validates ?sort=/?dir= against a per-report allowlist; sort_data(rows, sort, dir) sorts a materialized list[dict] in place (Nones last in both directions, case-insensitive strings). Both are re-exported from the package root.

Redirects by route name

coffeehouse_common.redirects (promoted from Cupping) builds every Post/Redirect/Get target from the app's own route table instead of a string:

# app/redirects.py -- one Redirector per app
from typing import Any

from coffeehouse_common.redirects import Redirector


def _app() -> Any:
    from app.server import app  # lazy: server imports the route modules

    return app


redirects = Redirector(_app)

# in a route
return redirects.to("view_thing", fallback="list_things", thing_id=7, success="saved")

to() answers 303 with flash codes in the query string (error=, success=, warning=; a value that is not a code is dropped). The Location comes from Starlette's url_path_for, so it can only be one of the app's own paths. A route name the table does not serve, or a path parameter that is not an int or a string of URL-unreserved characters, falls back to the named fallback route, and to root (/) if that cannot be built either -- with a warning that names parameter keys and types, never values. url_for() is the href-building half and raises instead of falling back. Redirector(..., int_param_suffix="_id") additionally requires every *_id parameter to be an int. Unlike coffeehouse_common.flash (a sentence in a session cookie), this needs no middleware.

See CONVENTIONS.md in the coffeehouse-ecosystem repo for middleware order and CSRF patterns.

First-time publish (maintainers)

  1. Create an empty repo on GitHub: rubencfh/coffeehouse-common
  2. From this directory:
git remote add origin https://github.com/rubencfh/coffeehouse-common.git
git push -u origin master
git push origin v0.9.0

Until the repo and tag exist, app Docker builds that pip install from GitHub will fail. For local dev, use editable install (above).

Metadata

Release files for coffeehouse-common 0.19.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for coffeehouse-common 0.19.0
File Size Uploaded
coffeehouse_common-0.19.0.tar.gz 66.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for coffeehouse-common 0.19.0
File Interpreter ABI Platform
coffeehouse_common-0.19.0-py3-none-any.whl Python 3 none any Details

Total release size: 117.2 kB

Release files / coffeehouse_common-0.19.0.tar.gz

Download URL coffeehouse_common-0.19.0.tar.gz
Size 66.1 kB
Tags Source
SHA-256 checksum
How to use checksums
c45f1638edbe4282339d5ad2e338dc0f4affddb71dc8e28cc9084a9df15f7663
BLAKE2b-256 checksum
How to use checksums
0839dace8cdf9f5565ef56d64cc84eef9d55f3529805a63a7ba45401007f8104
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release files / coffeehouse_common-0.19.0-py3-none-any.whl

Download URL coffeehouse_common-0.19.0-py3-none-any.whl
Size 51.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9bfaaf71021edb183cce14b8e6ecafd50bf9e36be0d15d92c0775aed9ba03a12
BLAKE2b-256 checksum
How to use checksums
4130a7f128ec6201b0db6ce90fa0104d9d50586c033adced6c9a4f64e114012e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release history Release notifications | RSS feed

0.21.0

2 release files

This release

0.19.0 This release

2 release files

0.17.0

2 release files

0.16.0

2 release files

0.15.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page