Data handling#
Pain001 is a library and a set of commands that run on your own infrastructure. There is no hosted Pain001 service, no account and no telemetry. This page says exactly when the software opens a network connection, so a reviewer can check each statement against the code.
What Pain001 does not do#
No hosted service. The project runs no server that receives your payment files. Generating, validating and checking files happen in your process.
No telemetry. Nothing reports usage, errors or file contents to the project. The only tracing support is the opt-in OpenTelemetry integration described below, which sends spans only to an endpoint you configure.
No schema downloads. XSD validation uses the schemas bundled in the package. The
lxmlparser runs with entity resolution, DTD loading and network access switched off (pain001/xml/validate_via_xsd.py).
When Pain001 opens a network connection#
Each case needs an optional extra, an explicit command or explicit configuration. None is on by default.
Case |
What connects, and to where |
Needs |
|---|---|---|
|
An SFTP connection to the host you name, after its host key is checked and before any credential is sent ( |
the |
|
The same SFTP session, to fetch replies from the host you name (ADR 0013) |
the |
|
Listens for HTTP requests (it does not connect out). Without |
the |
REST job store or rate limiter on Redis |
Connects to the Redis URL you set in |
the |
OpenTelemetry tracing |
Exports spans over OTLP/HTTP to the endpoint in the standard |
the |
The MCP server (pain001 mcp) talks to its client over standard input
and output; it opens no network port and makes no outbound connection
(pain001/mcp/server.py).
MCP and REST never fetch or send files over SFTP: download is a
command-line and library feature only (ADR 0013).
Data at rest#
Pain001 writes only what you ask for: generated XML, reports, and files
downloadsaves to the directory you name.pain001 downloadkeeps a local SQLite ledger (file mode 0600) of the remote paths it fetched and where it saved them. The ledger holds no file contents and no credentials.The REST API keeps job state in memory by default, or on disk or in Redis when you configure it to.
Reading a
.gpgor.ascfile (thegpgextra) decrypts it in memory, then writes the plaintext to a temporary file created with mode 0600, in/dev/shmon Linux when it is writable and in the system temporary directory otherwise, so the inner loader can read it. The file is unlinked as soon as that read ends (with--streaming, when the last chunk has been read), including on error; it is not overwritten first. WithPAIN001_GPG_KEYFILEand noPAIN001_GPG_HOMEDIR, the key is imported into a throwaway keyring directory under/tmpthat is removed afterwards (pain001/plugins/builtins_gpg.py).Structured logs redact IBAN, BIC and name fields by default (
pain001/logging_schema/redaction.py). In the library and CLI, schema and XSD validation errors carry the rule and the field path, not the value; scheme-rule findings quote the rejected code, currency or amount, and the structural BIC check quotes the BIC it rejects.Row errors in REST responses mask IBAN, BIC, account and name values (first and last four characters, or
[REDACTED]for names), with the same rules as the log redactor (pain001/api/_redact.py).
How to check this yourself#
# Network clients appear only in the opt-in transport, API and tracing code
grep -rlE 'import (socket|paramiko|redis)|from (paramiko|redis)|urlopen|httpx|aiohttp|OTLPSpanExporter' pain001/
The expected result is files under pain001/transport/, pain001/api/
and pain001/observability/ only.