From 2517c01a861bafbdc5497e81be78037f44d2756d Mon Sep 17 00:00:00 2001 From: Alexander Lehmann Date: Sun, 7 Jun 2026 19:55:45 +0200 Subject: [PATCH] docs: prepare public repository release --- .github/workflows/ci.yml | 34 +++++++++++ CHANGELOG.md | 25 +++++++++ CONTRIBUTING.md | 50 +++++++++++++++++ README.md | 29 ++++++++-- SECURITY.md | 33 +++++++++++ docs/publication.md | 56 +++++++++++++++++++ skill/briefklick-send-letter/SKILL.md | 16 ++++-- .../natural_language_to_code.md | 0 8 files changed, 234 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 SECURITY.md create mode 100644 docs/publication.md rename skill/briefklick-send-letter/{examples => references}/natural_language_to_code.md (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..b3ef914 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,34 @@ +name: CI + +on: + pull_request: + push: + branches: [main] + +permissions: + contents: read + +jobs: + test: + name: Python ${{ matrix.python-version }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: pip + + - name: Install package and test dependencies + run: python -m pip install -e ".[dev]" + + - name: Run offline tests + run: pytest diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..96f503d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,25 @@ +# Changelog + +All notable changes to this project will be documented here. + +This project follows the spirit of [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and uses semantic versioning once releases are published. + +## [Unreleased] + +### Added + +- Public contributor documentation. +- Public security policy. +- Public repository readiness checklist. +- GitHub Actions CI for the offline test suite. + +## [0.1.0] - 2026-04-18 + +### Added + +- Initial synchronous Python client for the BriefKlick v2 API. +- Typed models for recipients, uploaded documents, orders, previews, and status responses. +- `preview_letter()` helper for free `/create` + `/preview` workflows. +- `send_letter()` helper for one-shot `/create` + `/send` workflows. +- Offline unit tests using mocked HTTP calls. +- LLM-facing `briefklick-send-letter` skill. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..31c082b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,50 @@ +# Contributing + +Thanks for helping improve `briefklick-python`. + +## Development setup + +```bash +git clone https://github.com/randomsnowflake/briefklick-python.git +cd briefklick-python +python3 -m venv .venv +source .venv/bin/activate +pip install -e ".[dev]" +pytest +``` + +The test suite is fully offline. Do not use a real BriefKlick API key in tests. + +## Safety model + +BriefKlick has no sandbox for `send`. + +- `/create` + `/preview` is free and safe. +- `/send` is real mail and chargeable. +- Never add tests, examples, or CI jobs that call the live API. +- Never commit `.env`, API keys, generated letters containing private data, or real recipient details. + +## Pull request checklist + +Before opening a PR: + +- [ ] `pytest` passes locally. +- [ ] New behavior has offline tests using mocked HTTP responses. +- [ ] Public docs are updated when user-facing behavior changes. +- [ ] No secrets or personal data are included in files or fixtures. +- [ ] Send-related code documents ambiguous retry behavior. Blindly retrying `send` can duplicate physical mail. + +## Style + +- Keep the client small and synchronous. +- Prefer explicit dataclasses/enums over loosely typed dictionaries for public API results. +- Preserve backwards compatibility where practical. If a breaking change is necessary, document it in `CHANGELOG.md`. +- Keep examples copy-pasteable, but use fictional recipients and placeholder filenames. + +## Releasing + +1. Update the version in `pyproject.toml` and `src/briefklick/__init__.py`. +2. Update `CHANGELOG.md`. +3. Run `pytest`. +4. Build with `python -m build` from a clean checkout. +5. Publish only from a trusted machine after reviewing the source distribution and wheel contents. diff --git a/README.md b/README.md index 03a5f90..1eb7b8d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # briefklick-python +[![CI](https://github.com/randomsnowflake/briefklick-python/actions/workflows/ci.yml/badge.svg)](https://github.com/randomsnowflake/briefklick-python/actions/workflows/ci.yml) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) + Idiomatic Python client for the [BriefKlick v2 API](https://api.briefklick.de/v2/swagger.json). BriefKlick lets you send physical letters in Germany (and a few more countries) from your code — you upload a PDF, they print, enclose, stamp, and drop it in @@ -22,7 +25,7 @@ the post. - `preview_letter(...)` zero-risk helper (free, no balance needed, returns the exact rendered PDF) - `send_letter(...)` one-shot helper that chains `/create` + `/send` -- 45 unit tests, no live API calls required +- 48 unit tests, no live API calls required - PEP 561 marker included for type checkers (`py.typed`) ## Installation @@ -35,6 +38,16 @@ pip install -e ".[dev]" # during development # pip install briefklick ``` +For one-off agent/Hermes usage without mutating the system Python: + +```bash +# after publication +uv run --with briefklick python your_script.py + +# from a local source checkout before publication +uv run --with /path/to/briefklick-python python your_script.py +``` + Supported Python: 3.9+. Only runtime deps are `requests` and `python-dotenv`. ## Configuration @@ -160,7 +173,7 @@ except ServerError: ## Testing ```bash -.venv/bin/pytest # 45 tests, 89% coverage, ~0.2s +.venv/bin/pytest # offline tests, no BriefKlick API key required .venv/bin/pytest --cov=briefklick ``` @@ -176,11 +189,15 @@ briefklick-python/ │ ├── models.py # Recipient, Document, Order, Status, enums │ ├── exceptions.py # exception hierarchy │ └── __init__.py -├── tests/ # 45 tests, offline -├── docs/ # extended examples and API reference +├── tests/ # offline tests +├── docs/ # usage, API reference, publication checklist ├── skill/ # LLM-facing skill for letter preview/send ├── examples/ # runnable scripts +├── .github/workflows/ci.yml # offline test CI ├── .env.example +├── CONTRIBUTING.md +├── SECURITY.md +├── CHANGELOG.md ├── pyproject.toml └── README.md ``` @@ -189,6 +206,10 @@ briefklick-python/ - [`docs/usage.md`](docs/usage.md) — extended examples, error handling recipes - [`docs/api_reference.md`](docs/api_reference.md) — full public API reference +- [`docs/publication.md`](docs/publication.md) — public repository readiness checklist +- [`CONTRIBUTING.md`](CONTRIBUTING.md) — development setup and PR checklist +- [`SECURITY.md`](SECURITY.md) — vulnerability reporting and API-key handling +- [`CHANGELOG.md`](CHANGELOG.md) — release notes - [`skill/briefklick-send-letter/SKILL.md`](skill/briefklick-send-letter/SKILL.md) — LLM-facing skill for sending letters from natural language ("send a letter to Peter Maier in 34533 Berlin…"). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..59229e2 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,33 @@ +# Security Policy + +## Supported versions + +Security fixes are accepted for the current `main` branch. Released package versions will be listed in `CHANGELOG.md` once distribution begins. + +## Reporting a vulnerability + +Please report security issues privately instead of opening a public issue. + +Preferred route: + +- Open a private GitHub security advisory for this repository, if available. +- If advisories are not available, contact the maintainer through the GitHub profile listed on the repository. + +Include: + +- A concise description of the issue. +- A minimal reproduction that does not use real API keys or private letter contents. +- Affected version or commit. +- Any relevant logs with secrets redacted. + +## Secret handling + +`briefklick-python` authenticates with the `apikey` HTTP header. Treat `BRIEFKLICK_API_KEY` like a password. + +- Store it in environment variables or a local `.env` file. +- Never commit `.env` files, live keys, generated private letters, or real recipient data. +- Rotate the BriefKlick API key immediately if it is exposed. + +## Operational safety + +`send()` and `send_letter()` create real, chargeable physical mail. A timeout or 5xx during a send is ambiguous: the order may or may not have been accepted by BriefKlick. Do not automatically retry send operations without reconciling the account/dashboard first. diff --git a/docs/publication.md b/docs/publication.md new file mode 100644 index 0000000..42fd282 --- /dev/null +++ b/docs/publication.md @@ -0,0 +1,56 @@ +# Public repository readiness + +This checklist documents what must be true before making the repository public. + +## Required files + +- [x] `README.md` with project purpose, warning about chargeable sends, installation, configuration, quickstart, testing, docs, and license. +- [x] `LICENSE` with MIT terms. +- [x] `.env.example` with placeholders only. +- [x] `.gitignore` excluding `.env`, virtualenvs, build output, caches, and local scratch files. +- [x] `CONTRIBUTING.md` with setup, PR checklist, and no-live-API testing rule. +- [x] `SECURITY.md` with private reporting guidance and API-key handling. +- [x] `CHANGELOG.md` with initial release notes. +- [x] `.github/workflows/ci.yml` running the offline test suite. + +## Safety requirements + +- [x] Examples use fictional recipients and placeholder document names. +- [x] Tests are offline and use mocked HTTP responses only. +- [x] Docs clearly state that `send()` / `send_letter()` are chargeable and not idempotent. +- [x] Docs recommend preview-first workflows by default. +- [x] No live API key is required for tests or examples. + +## Final checks before flipping visibility + +Run from a clean checkout: + +```bash +git status --short +pytest +python -m build +``` + +Then audit: + +```bash +# Current tree, excluding intentional placeholder docs/tests +git grep -n -I -E '(BEGIN (RSA|OPENSSH|PRIVATE) KEY|Bear[e]r [A-Za-z0-9._-]+|Authori[z]ation:|pass[word]=|sec[ret]=)' -- . || true + +# History smoke test for accidentally committed credentials +git log --all -p -- . ':(exclude).env.example' \ + | grep -En '(BEGIN (RSA|OPENSSH|PRIVATE) KEY|Bear[e]r [A-Za-z0-9._-]+|Authori[z]ation:|pass[word]=|sec[ret]=)' \ + | head -50 || true + +# Large blobs that may be generated/private artifacts +git rev-list --objects --all \ + | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \ + | awk '$1=="blob" && $3>1048576 {print $3, $4}' \ + | sort -nr +``` + +If any finding is a real secret or private document, rotate/revoke the credential and rewrite history before making the repository public. Do not rely on deletion in a later commit. + +## Repository visibility + +This PR prepares the content for public visibility. The actual GitHub visibility change should be done separately by a maintainer after reviewing the PR and confirming there are no private forks, branch protections, or release automation assumptions that depend on the repository being private. diff --git a/skill/briefklick-send-letter/SKILL.md b/skill/briefklick-send-letter/SKILL.md index ff1c555..a4b50dd 100644 --- a/skill/briefklick-send-letter/SKILL.md +++ b/skill/briefklick-send-letter/SKILL.md @@ -92,12 +92,18 @@ Keep the user's exact spelling (umlauts, ß) — the PDF will render it. ### Dependencies -The host project is expected to have `briefklick` installed. If not: +The host project is expected to have `briefklick` installed. If not, avoid +system-wide `pip` on managed Python installs; use a project venv or `uv`. ```bash -pip install briefklick -# or, from the source repo: -pip install -e path/to/briefklick-python +# In a project virtualenv +python -m pip install briefklick + +# One-off Hermes/agent execution after package publication +uv run --with briefklick python your_script.py + +# From a source checkout before publication +uv run --with /path/to/briefklick-python python your_script.py ``` ### Preview only (zero-risk, recommended first step) @@ -249,4 +255,4 @@ Skill response: 6. Return `order.id`, `order.price_eur`, and any tracking from `get_status(order.id)` (polled after a short delay). -See `examples/natural_language_to_code.md` for the full prompt → code mapping. +See `references/natural_language_to_code.md` for the full prompt → code mapping. diff --git a/skill/briefklick-send-letter/examples/natural_language_to_code.md b/skill/briefklick-send-letter/references/natural_language_to_code.md similarity index 100% rename from skill/briefklick-send-letter/examples/natural_language_to_code.md rename to skill/briefklick-send-letter/references/natural_language_to_code.md