Skip to content

Releases: stacking-hq/ksef2

v1.1.0

Choose a tag to compare

@artpods56 artpods56 released this 26 Oct 22:30
9cab185

Added

  • Add ksef2.certificate_stores with sync and async signing-certificate store
    protocols, SigningCertificate records and in-memory adapters, plus
    KSeFCertificateStore* errors. Additive and optional; existing XAdES, profile and
    encryption-certificate store APIs are unchanged.
  • Add authentication.with_stored_certificate() on sync and async clients to
    authenticate with a certificate loaded from a signing-certificate store.
    Reject wrong-environment, Offline and mismatched records before contacting
    KSeF. Document storing issued certificates and writing custom store adapters.
  • Add FilesystemSigningCertificateStore and AsyncFilesystemSigningCertificateStore:
    one password-encrypted record per certificate, atomic publication, owner-only
    files on POSIX, and metadata listing without unlocking keys.

Fixed

  • Correct the certificate enrollment guide: enroll(csr=...) takes a Base64-encoded
    DER CSR, not PEM text.
  • Resolve XSLT code descriptions offline with bundled official country, tax-office,
    tax-office ex-WUS, tax-office-head, and currency lists when
    enable_code_lookups=True. Keep network access and writes blocked, and include
    unresolved URIs in KSeFInvoiceRenderingError messages and details (#324).
  • Preserve the Base64 certificate text returned by auth.certificates.retrieve()
    instead of decoding DER bytes as UTF-8 (#323). Generate all OpenAPI byte fields
    as strings so certificates, hashes, and encrypted data retain their wire values.
  • Include offending field paths and validation messages in
    KSeFResponseValidationError.details for individual and list responses, and
    preserve the original Pydantic validation error.

v1.0.0

Choose a tag to compare

@artpods56 artpods56 released this 26 Oct 00:35
b4afb26

Fixed

  • Fix English and Polish documentation examples for limits, authentication,
    token activation, imports, async entry points, certificate file paths, and
    sample identifiers. Document client and session concurrency boundaries.

  • Add safe filename/path hints for PEM, PKCS#12, and XML content inputs. Existing
    PEM string paths retain their 1.x deprecation behavior.

  • Report synchronous close() misuse on async clients and sessions with
    KSeFArgumentError and guidance to use await ...aclose() or async with.

  • Enable full jitter for retry backoff through RetryConfig.jitter, including
    HTTP retries during polling. jitter=False keeps deterministic backoff;
    Retry-After values and their existing ceiling remain unchanged.

  • Wrap invalid non-builder public model and request-conversion inputs in the
    SDK validation-error hierarchy, preserving the Pydantic cause and naming the
    public parameter. Validate KSeF invoice-number filters at construction,
    including both current and legacy formats.

  • Reject invalid PESEL checksums and PESEL/NIP formats in permission grants, mismatched
    identifier types, empty permission lists, empty revoke IDs, and empty KSeF
    token credentials before HTTP requests. Person and entity grants accept
    snake_case strings or permission enums; PascalCase permissions suggest the
    corresponding snake_case value.

  • Completed exports with zero invoices return immediately from deprecated polling
    helpers. Both export().wait() and export().download(path) return empty
    metadata and invoice lists for these packages without opening an archive.

  • In-memory export downloads verify encrypted and plaintext sizes and SHA-256
    hashes using the same checks as downloads to disk.

  • Require an explicit FA(3) partial-payment status before building payment entries,
    correct both builder guides, and report invalid builder fields as
    KSeFValidationError with the original validation error as the cause. Builder
    amount, quantity, price, and exchange-rate hints now accept floats and numeric
    strings, matching runtime decimal conversion.

  • Restore deprecated ksef2.clients.* submodule imports throughout 1.x.

ksef2 1.0.0 is being prepared as the first stable release. It targets KSeF
OpenAPI 2.8.1 and starts the 1.x compatibility contract. Collective-identifier
invoice queries change because KSeF replaced the endpoint. Old SDK import paths
and method names remain functional throughout 1.x (#171). Read
Breaking changes and Deprecated before upgrading.

Highlights

  • ExportJob.download(Path) decrypts export parts to disk with per-part size and
    hash verification, and ExportedInvoices.from_path() reads ZIP and TarGz
    archives without loading the whole archive into memory (#305). Both accept
    any os.PathLike and reject str/bytes with KSeFArgumentError.

  • Offline validation rejects invoice metadata ranges longer than 100 days, documents
    metadata page-size bounds, checks invoice sizes before sending or batch
    encryption, computes batch part counts before encryption, validates signing
    certificates and transport configuration, and defaults FA(3) XML serialization
    to compact output (#299). PDF exports reject malformed roots and KSeF numbers,
    and the token example stops before a placeholder can be sent.

  • Public input handling follows one rule: bytes and str are content, while
    Path is a file. Batch preparation catches strings that name existing files,
    FA(3) parsing accepts XML text with declarations, and PEM helpers warn when
    legacy string paths are used (#297, #304).

  • The documented import paths (ksef2, ksef2.clients, ksef2.models,
    ksef2.fa3, ksef2.xades, ksef2.logging, ksef2.profiles,
    ksef2.renderers, ksef2.raw,
    ksef2.raw.mappers, and the new ksef2.testdata) are the compatibility
    contract for the whole 1.x line. The rule is simple: a module path with no
    underscore is public, and anything with an underscore is private and may change
    in any release. See the
    public API contract
    and the 1.0.0 release notes.

  • model_dump() and model_dump_json() redact secrets by default and are not a
    persistence format. Use to_dict() / to_json() / from_dict() on resume
    states and to_sensitive_dict() to persist.

  • The invoice and admin workflows have their final 1.x shape: operations that
    start asynchronous KSeF work return a handle with .wait(), every collection
    returns one Pager, and access tokens refresh automatically (#162, #163, #165).
    See the 1.0.0 release notes
    for a before/after.

  • KSeF errors come from one pipeline with one message format, carry ksef_code,
    trace_id and details, and say what to do next in hint (#167).

  • Public Pydantic model validation and invoice-builder validation raise SDK
    exceptions; HTTP 403 raises KSeFPermissionDeniedError, separate from
    KSeFAuthError; terminal operation failures share KSeFOperationFailedError
    (#296).

  • Deprecations are visible to type checkers and IDEs (PEP 702 @deprecated) and
    remain functional through the 1.x line. Removal is a 2.0 decision (#171).

  • Polling helpers continue through retryable server, rate-limit and transport
    errors until their timeout. Invoice sends and refresh-token requests retry
    only after an explicit 429; ambiguous transport failures are not retried.
    Connect failures are reported as non-ambiguous and lost invoice responses
    include a recovery hint (#300).

Fixed

  • FA(3) builder (#293, #304). Emit summary amounts for VAT buckets with
    rows even when rounding or correction arithmetic produces zero, validate
    foreign-currency VAT exchange rates, and document rounding, corrections, and
    large-invoice performance. #304 parser string handling remains in #297; the
    missing corrected-invoice error remains in #296.

Breaking changes

  • Explicit client environments and URL alignment (#294, #295). Client,
    AsyncClient, and InvoicePDFExporter now require an environment. Pass an
    Environment or a case-insensitive name such as "test". A supplied
    http_client with no base_url inherits the selected environment URL; a
    conflicting URL raises KSeFArgumentError during construction. This prevents
    environment guards and network routing from disagreeing.

  • Collective-identifier invoice queries (#128). KSeF API 2.8.1 replaced
    GET /collective-identifiers/{collectiveIdentifierNumber}/invoices with
    POST /collective-identifiers/invoices, which takes up to 10 identifiers in
    the body. The old call is removed, not deprecated. Migration is mechanical:

    # before (0.22.x)
    page = auth.collective_identifiers.list_invoices(collective_identifier_number=cid)
    everything = auth.collective_identifiers.list_all_invoices(
        collective_identifier_number=cid
    )
    
    # after (1.0.0)
    for invoice in auth.collective_identifiers.list_invoices(
        collective_identifier_numbers=[cid]
    ):
        ...

    list_invoices now returns a Pager (iterate items, .pages(), .first_page())
    and no longer takes continuation_token; list_all_invoices remains as a
    deprecated alias that still returns pages (#163). The high-level client
    validates 1 to 10 identifiers before sending. The raw
    endpoint takes a request body instead of a path parameter:

    from ksef2.raw import spec
    
    # before (0.22.x)
    auth.raw.collective_identifiers.list_invoices(cid)
    
    # after (1.0.0)
    auth.raw.collective_identifiers.list_invoices(
        spec.CollectiveIdentifierInvoicesQueryRequest(collectiveIdentifierNumbers=[cid])
    )

Deprecated

  • Keep the former ksef2.core, domain, infra and services imports,
    including submodules, as deprecated aliases throughout 1.x (#171). The first
    import loads the canonical package tree and warns once per package family.

  • Keep deprecated call names, including invoice send/wait/UPO, metadata search,
    download and export aliases, through 1.x. Removal is a 2.0 decision and may
    happen no earlier than 2.0.0, replacing the former 1.10.0 removal schedule.

  • Add English and Polish migration examples for legacy imports and workflows.

  • Former implementation imports (#153, #171). Implementations moved to
    private _-prefixed paths. The old paths remain as deprecated aliases
    throughout 1.x, warning with the public replacement. #171 supplies those aliases
    and the migration examples. Use documented public modules rather than the private paths
    in the table below for new code.

    Old import Private implementation
    ksef2.core ksef2._core
    ksef2.domain ksef2._domain
    ksef2.infra ksef2._infra
    ksef2.endpoints ksef2._endpoints
    ksef2.services ksef2._services
    ksef2.clients.<module> (base, auth, online, async_*, ...) ksef2._clients.<module> (ksef2.clients stays the public facade with the same __all__)
    ksef2.config ksef2._config (names stay exported from ksef2)
    ksef2._logging ksef2.logging (configure_logging)
    ksef2.raw.facade, ksef2.raw.async_facade ksef2.raw._facade, ksef2.raw._async_facade (names stay exported from ksef2.raw)

    If you imported something from an old path, import it from the public module
    instead (see Added for names newly exported from ksef2.models).

Old SDK imports and method names remain functional through 1.x. Replaced
methods keep their old behavior and return type and carry deprecation warnings.
Removal is a 2.0 decision (#171), including APIs deprecated in 0.19.0. See the
deprecated APIs table
on the public API page for every alias and its replacement....

Read more

v0.22.2

Choose a tag to compare

@artpods56 artpods56 released this 25 Sep 16:12
0e3f703
v0.22.2

v0.22.1

Choose a tag to compare

@artpods56 artpods56 released this 25 Sep 14:51
d0c0669

Fix

  • Preserve invoice rejection details and extensions in KSeFInvoiceRejectedError for sync and async clients (#118).

v0.22.0

Choose a tag to compare

@artpods56 artpods56 released this 25 Sep 00:32
805cf15

Feat

  • refactor(release): make tags the release gate and drop commitizen (#121)
  • refactor: derive version from installed package metadata (#120)
  • bump: version 0.20.0 → 0.21.0 (#116)
  • build: update update-spec.yml (#117)
  • chore(release): publish reviewed release PRs through validated tags (#115)

v0.20.0

Choose a tag to compare

@artpods56 artpods56 released this 20 Sep 17:50
91d5567

What's Changed

  • chore: update OpenAPI spec to KSeF API 2.7.1 and regenerate models by @github-actions[bot] in #108
  • chore: update OpenAPI spec to KSeF API 2.8.0 and regenerate models by @github-actions[bot] in #109
  • chore(release): prepare v0.20.0 by @artpods56 in #110

Full Changelog: v0.19.0...v0.20.0

v0.19.0

Choose a tag to compare

@artpods56 artpods56 released this 20 Sep 17:46

What's Changed

  • bump: version 0.18.0 → 0.18.1 by @artpods56 in #77
  • [codex] expose low-level api and harden release gate by @artpods56 in #78
  • chore: update OpenAPI spec to KSeF API 2.6.1 and regenerate models by @github-actions[bot] in #79
  • chore: update OpenAPI spec to KSeF API 2.6.1 and regenerate models by @github-actions[bot] in #83
  • chore: update OpenAPI spec to KSeF API 2.6.1 and regenerate models by @github-actions[bot] in #85
  • chore: update OpenAPI spec to KSeF API 2.6.1 and regenerate models by @github-actions[bot] in #86
  • chore: update OpenAPI spec to KSeF API 2.6.1 and regenerate models by @github-actions[bot] in #87
  • Prepare the 1.0.0 release by @artpods56 in #84
  • docs: document 1.0 release sign-off by @artpods56 in #101
  • chore: update OpenAPI spec to KSeF API 2.7.0 and regenerate models by @github-actions[bot] in #102
  • chore: update OpenAPI spec to KSeF API 2.7.1 and regenerate models by @github-actions[bot] in #106
  • chore: update OpenAPI spec to KSeF API 2.7.1 and regenerate models by @github-actions[bot] in #107

Full Changelog: v0.18.1...v0.19.0

v0.18.1

Choose a tag to compare

@artpods56 artpods56 released this 22 Jun 10:31
0782f6c

v0.18.1

Patch release to republish package metadata with the corrected KSeF OpenAPI target version.

Docs

  • Sync README OpenAPI target version with KSeF API 2.6.1.
  • Publish PyPI long description from the corrected README on current main.

v0.17.1

Choose a tag to compare

@artpods56 artpods56 released this 16 Jun 11:43
658ee2b

v0.17.1 (2026-06-16)

Docs

  • document public SDK exception contracts and API docstrings

v0.17.0

Choose a tag to compare

@artpods56 artpods56 released this 04 Jun 19:22
1ef179c

v0.17.0 (2026-06-04)

Feat

  • fa3: support gross unit price lines