High-trust OpenPGP keyserver APIs that embrace the HPKS v2 specification while preserving legacy HKP compatibility, powered by the Tigrbl application engine.
- 🔄 Dual-protocol support – serves both legacy
/pks/lookupflows and HPKS v2 JSON/binary routes with consistent persistence. - 🧩 Merge-aware storage – idempotent upserts normalize fingerprints, union metadata, and track revocation state without losing history.
- 📦 Single source of truth – admin CRUD and public HPKS endpoints share the same
openpgp_keystable and Tigrbl handlers. - 🛡️ Spec-aligned responses – machine-readable index output, binary bundle delivery, and required CORS headers baked in.
- ⚙️ Composable operations –
@op_ctxpowered helpers expose reusable alias handlers for/pksworkflows.
uv add tigrbl_api_hpkspip install tigrbl_api_hpksimport asyncio
from httpx import ASGITransport, AsyncClient
from tigrbl_api_hpks import app
async def bootstrap():
await app.initialize() # create in-memory tables
# Submit an ASCII-armored key bundle via the legacy endpoint
armored_blob = """-----BEGIN PGP PUBLIC KEY BLOCK-----\n...\n-----END PGP PUBLIC KEY BLOCK-----"""
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://testserver") as client:
resp = await client.post(
"/pks/add",
data={"keytext": armored_blob},
headers={"Content-Type": "application/x-www-form-urlencoded"},
)
resp.raise_for_status()
# Lookup via HPKS v2 JSON index
lookup = await client.get("/pks/v2/index/example.com")
print(lookup.json())
asyncio.run(bootstrap())Run the package test suite in isolation:
uv run --package tigrbl_api_hpks --directory pkgs/community/tigrbl_api_hpks pytestThis project is licensed under the terms of the Apache 2.0 license.