baltimore-patapsco (Python)
Reusable Django runtime primitives for Baltimore civic applications.
INSTALLED_APPS += ["baltimore.patapsco"]
REST_FRAMEWORK = {
"EXCEPTION_HANDLER": "baltimore.patapsco.api.exception_handler",
}
urlpatterns = [path("", include("baltimore.patapsco.urls"))]
Place RequestContextMiddleware early in MIDDLEWARE — after
SecurityMiddleware (and WhiteNoise when present), before session, auth, and
anything that can short-circuit a response — so every later middleware, view,
and log line sees the bound request ID. The reference app shows the canonical
order:
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"whitenoise.middleware.WhiteNoiseMiddleware",
"baltimore.patapsco.observability.RequestContextMiddleware",
# sessions, common, csrf, auth, messages, clickjacking...
]
Stable health and readiness views
Applications that mount or extend the operational views directly use the public facade:
from baltimore.patapsco.api import HealthView, ReadinessView
HealthView is process-only liveness. ReadinessView runs the established
database check and returns its public-safe 200 or 503 status document. Both use
no authentication classes and AllowAny, and both remain ordinary DRF
APIView classes with as_view().
An application may subclass either class, override get(), and call
super().get(request) before composing app-owned public-safe checks. The parent
response status, request ID, and database result remain the starting contract;
the application owns an explicit serializer and OpenAPI annotation for any
extended payload.
The previous baltimore.patapsco.api.views imports resolve to the same class
objects for compatibility. DiagnosticsView remains available only from that
module and through the packaged URL configuration; it is intentionally absent
from baltimore.patapsco.api.__all__ because its staff/public policy is a
separate operational surface. The settings-free package root exports neither
view class.
api_error_response() and the DRF exception handler force every 5xx response to
the public internal_error code, generic message, and no details. Application
callers cannot opt a server failure out of that safety boundary. An unexpected
exception also rolls back every active database transaction managed by Django's
ATOMIC_REQUESTS, so a failed request cannot commit partial writes. Applications
retain ownership of explicitly managed transactions.
Use build_logging_config() for the shared JSON/pretty log shape. Modules are
incrementally adoptable; installing the package does not enable auth, email, or
Sentry by itself. Structured log context is copied and recursively redacted,
including credentials nested in mappings and sequences. Credential keys are
matched across case and separator conventions, including clientAPIKey and
X-API-Key; repeated safe context is preserved and cycles are cut safely.
Sentry privacy defaults
Install the observability extra and call the shared initializer only when a DSN
is configured:
from baltimore.patapsco.observability import configure_sentry
configure_sentry(
environment="production",
release="my-app@1.2.3",
traces_sample_rate=0.1,
)
configure_sentry() is deny-by-default: it disables automatic PII, request-body
capture, and stack-frame local variables. Its event pipeline also removes request
cookies and query strings, strips query/fragment data from request URLs, and
recursively redacts the shared credential-key fragments, Sentry's credential/session
denylist, and common civic contact and precise-location fields. This protection
also applies to transaction events. Safe operational fields such as request IDs,
routes, and HTTP methods remain available.
traces_sampler optionally accepts a callable with the SDK sampling-context
dictionary and a return rate from zero to one. It decides whether a trace is
recorded at creation, before event processing; it takes precedence over
traces_sample_rate and the parent decision. Apps own route exclusions and
whether to honor context["parent_sampled"]. Omitting the callback preserves
SDK defaults. Callback exceptions retain SDK behavior and can propagate, so app
samplers must handle their expected failure cases. Initialization failures still
return False without exposing configuration in logs.
Pass dsn="" to explicitly disable reporting even when SENTRY_DSN exists;
omitting the argument or passing None permits that environment fallback.
For domain enrichment, register a public SDK global event processor once, after
successful initialization. It runs before the shared scrubber and final privacy
hooks for errors and transactions. Retain stronger app policies there; do not
import private Patapsco filters or replace the client's privacy options.
Redaction is key-based. Applications must not attach sensitive values under misleading keys or place resident data in exception messages. Product-specific fields still require a privacy review before being added to Sentry context.
Configuration surface
Everything the library reads from the environment or Django settings:
| Name | Kind | Default | Meaning |
|---|---|---|---|
APP_ENV |
env var | local |
Environment label in diagnostics and Sentry events; overridden by PATAPSCO_ENVIRONMENT when set |
APP_RELEASE |
env var | — | Release identifier in diagnostics and Sentry events; overridden by PATAPSCO_RELEASE when set |
APP_LOG_FORMAT |
env var | json |
json or pretty output from build_logging_config() |
APP_LOG_LEVEL |
env var | INFO |
Root log level from build_logging_config() |
SENTRY_DSN |
env var | — | Enables configure_sentry(); absent means Sentry stays off |
PATAPSCO_SERVICE_NAME |
Django setting | project name | Service label in the diagnostics payload |
PATAPSCO_ENVIRONMENT |
Django setting | APP_ENV env var |
Overrides the diagnostics environment field via Django settings instead of the process environment (a real override_settings test seam) |
PATAPSCO_RELEASE |
Django setting | APP_RELEASE env var |
Overrides the diagnostics release field via Django settings instead of the process environment (a real override_settings test seam) |
PATAPSCO_DIAGNOSTICS_PUBLIC |
Django setting | False |
Security-relevant: flips /api/diagnostics from IsAdminUser to AllowAny. Leave False unless the deployment deliberately publishes runtime metadata |
Release files for baltimore-patapsco 0.15.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| baltimore_patapsco-0.15.3.tar.gz | 368.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| baltimore_patapsco-0.15.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 811.1 kB
Release files / baltimore_patapsco-0.15.3.tar.gz
| Download URL | baltimore_patapsco-0.15.3.tar.gz |
|---|---|
| Size | 368.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2db03cd9e1ef584a908c7b29a842e168adb0821cd16de3316091c180e368ffa0
|
|
BLAKE2b-256 checksum How to use checksums |
c4056e08adf15c3e0a8caf66114a2529097e74ad7a7fe6613b102a4e7e476dc1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / baltimore_patapsco-0.15.3-py3-none-any.whl
| Download URL | baltimore_patapsco-0.15.3-py3-none-any.whl |
|---|---|
| Size | 443.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fef7d481354f887e04ccbb587ac24daabb3f09f21a4820e31a7113c8abc32141
|
|
BLAKE2b-256 checksum How to use checksums |
bfea08ee182f04210df35aecc79e1b77b86ec159634b050c7a8e4da8315d42c8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|