Skip to content

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 05 Sep 20:31
· 101 commits to main since this release
3bbc5d2

Version 0.2.1 was prepared but never tagged or published; its contents are
included here.

Added

  • Certificate schema lethe.cert/3. lethe.cert/1 and lethe.cert/2
    certificates still validate and verify.
    • key_id — which key epoch signed the certificate, derived from the public
      key (ed25519: + truncated SHA-256). Recomputed and checked at
      verification, so a certificate cannot name a key other than its signer.
      New reason code KEY_ID_MISMATCH.
    • audit_head — the audit-chain position the deletion run started from, so
      the certificate and the tamper-evident log reference each other.
    • reverifiable — whether the issuer retained what a later re-query needs.
    • timestamp — reserved, currently always null: a slot for external
      corroboration of issued_at (e.g. RFC 3161) so adding one later needs no
      schema v4.
  • reconcile() / lethe reconcile — compares what a store actually holds
    for a subject against what the provenance ledger knows, exposing records that
    bypassed the wrapper. --tag-untracked tags findings for deletion. New
    optional connector capability scan(), implemented for pgvector.
  • reverify() / lethe reverify — re-checks absence after valid_until,
    enabled by the new Lethe(retain_verification_ids=True).
  • External anchoring — lethe anchor timestamps the audit chain head with
    an RFC 3161 authority, and records the raw token as a chain entry. Anchoring
    the head rather than each certificate covers every recorded event, keeps the
    authority out of the deletion path (a TSA outage never blocks a data-subject
    request), and costs one call per interval. Closes backdating: an entry cannot
    be inserted before an anchored head, and a timestamp dated in the past cannot
    be obtained. Optional dependency: pip install 'lethe-delete[anchor]'.
    See docs/anchoring.md.
  • docs/anchoring.md — choosing an authority (including eIDAS qualified
    timestamps), what anchoring does and does not prove, and how to verify a
    stored token with openssl ts.
  • docs/threat-model.md — who must be trusted for a certificate to mean
    anything, and what holds against a third party versus a dishonest operator.
  • docs/key-rotation.md — rotation, verifying older certificates, and the
    key-compromise case.
  • SECURITY.md — private vulnerability reporting and scope.
  • CI — GitHub Actions on Python 3.11 and 3.12 against a real Postgres
    service, including a guard that fails the build if any test is skipped.
  • CodeQL — static analysis on pushes, pull requests, and weekly, using the
    security-extended query suite. The weekly run matters as much as the diff
    runs: new queries find issue classes in code that has not changed.
  • Release workflow — pushing a v* tag publishes the GitHub Release, with
    notes taken from this file. It refuses to publish if the tag disagrees with
    lethe/version.py, or if the changelog section is missing or still marked
    unreleased, so a tag and its release cannot describe different things.

Changed

  • The certificate claim now discloses self-issuance inside the signed
    payload: issued_at is the issuer's own clock, and the signature proves only
    that the key holder produced it. The limitation travels with the artifact.
  • The claim's re-verify advice is scoped to reverifiable, rather than
    advising an action the default configuration makes impossible.

Fixed

  • mcp 2.x broke the MCP server. The mcp extra declared mcp>=1.9,
    which resolves to 2.x where FastMCP was renamed to MCPServer, so
    lethe.mcp raised ModuleNotFoundError on import. Pinned to mcp>=1.9,<2;
    migrating to the 2.x API is separate work.
  • The package version had drifted from the test suite (test_version still
    asserted 0.1.0 after the 0.2.0 release). pyproject now derives the
    version from lethe/version.py, so the two cannot diverge.
  • Two DB tests raised KeyError instead of skipping when
    LETHE_TEST_DATABASE_URL was unset.
  • Test isolation: the new retention table is now dropped between tests.