Skip to content

FFI capability and contract coverage

The Rust core defines behavior. The Diplomat bridge in fatoora-ffi exposes that behavior through generated C, C++, C#, Nanobind and JavaScript/TypeScript bindings. The public Python facade handles Python values, exceptions, and lifetimes. CFFI and the former handwritten C ABI have been removed.

The C API covers all bridge operations with ordinary strings, shared statuses, and named-field options. Its owned strings, optional text, independent snapshots, consumption, and allocation failures are checked by c_facade_contract.c and c_facade_allocation.c. Guide examples are compiled and run by scripts/check_c_examples.py; the API submission example runs only its help path during that check.

This table maps exposed capabilities to bridge methods and regression coverage. Exposure does not imply that every platform build has passed. See Diplomat bindings for generation, ownership, and verification status. Generated C names follow fatoora_Type_method; C++ uses fatoora::Type::method.

The C# contracts exercise optional text, strict Unicode conversion, native errors, deterministic disposal, key encodings, invoice signing, hashes against the frozen SDK fixtures, prepared requests, and response snapshots. Separate runtime tests exercise concurrent borrowed-byte access and source disposal. scripts/check_dotnet.py --package-dir dist/dotnet also runs the contracts in a fresh NuGet consumer. The CI matrix covers Linux, Windows, and macOS; local Linux results do not establish the other platform outcomes.

Capability Bridge type and methods Contract coverage
Environment and configuration Config::{new,env} Rust crypto tests; C/C++ contracts reject unknown environments
Signing keys SigningKey::{generate,from_pem,from_der,to_pem,to_der} Rust crypto tests; C++ key DER roundtrip; Python documentation examples
CSR configuration CsrProperties::{new,from_properties_str,parse_csr_config_file,build} Rust crypto tests; C++ construction and environment rejection; Python examples
CSR serialization and extensions Csr::{from_der,to_der,to_pem,to_base64,to_pem_base64,subject_string,extension_values_der} C++ DER roundtrip and detached extension bytes; Rust byte-list bounds checks
Invoice construction InvoiceBuilder::new, setters, add_line_item, build C/C++ exact-decimal and consumption contracts; Python builder and numeric tests
Finalized invoice parsing and XML FinalizedInvoice::{from_xml,from_file,data,totals,hash_base64,xml} C/C++ XML rounding; Python parsing, numeric, and documentation tests
Signed invoice parsing and XML ownership SignedInvoice::{from_xml,from_file,xml,into_xml,to_xml_base64} C++ exact fixture bytes and consumed-state errors; Python ownership tests
Invoice snapshots InvoiceData, Party, Address, VatId, OtherId, InvoiceNote, OriginalInvoiceRef, InvoiceLineItem, InvoiceTotals accessors C++ detached data/party/address/line owners; Python numeric/address tests
Signing and certificates Signer::{from_pem,from_der,certificate_pem,certificate_der,sign} Rust invalid certificate/key tests; Python signing examples
Raw XML signing Signer::sign_xml Exposed through generated bindings and Python facade; signing regressions belong with the signing tests
Raw XML hashing Xml::hash; Python invoice_hash_base64_from_xml_str Exposed through generated bindings and Python facade; hash equivalence regressions belong with XML tests
Local ZATCA validation Xml::validate_zatca; Python validate_zatca_invoice_from_str C owned-report contract; Python stage coverage, rejection, partial errors, and installed-wheel checks
XML validation Xml::validate; Python validate_xml_invoice_from_str Python validation/error tests; core XML validation regressions
Signature and QR metadata SignedInvoice::{qr_code,signature,public_key,invoice_hash,issuer,serial,cert_hash,signed_props_hash,signing_time,zatca_key_signature} Python signing and documentation examples; signed XML fixture contracts
CSID credentials CsidCompliance and CsidProduction: create, env, request_id, binary_security_token, secret Python HTTP/credential tests; optional text preserves absence
Onboarding and renewal ZatcaClient::{create,post_csr_for_ccsid,post_ccsid_for_pcsid,renew_csid} Python API examples and Rust API tests; generated blocking Python aliases release the GIL
Compliance, reporting, clearance ZatcaClient::{check_invoice_compliance,report_simplified_invoice,clear_standard_invoice} Python local-gateway tests preserve HTTP status, body, endpoint, and error classification
Response acceptance and cleared XML ValidationResponse::{http_status,outcome,ensure_accepted,cleared_invoice_xml,cleared_invoice_base64} and status accessors Python accepted/rejected/unknown outcomes and missing/invalid cleared-invoice tests
Validation messages ValidationResponse::validation_results, ValidationResults indexed message accessors, ValidationMessage accessors Python response tests; owned snapshots and bounds errors
Structured errors BindingError::{code,message,details_json} C/C++ error lifetime tests; Python known/unknown codes and validation details; Rust panic containment
Owned optional text and bytes Text::value, Bytes::as_slice, BytesList::{len,is_empty,get} C++ independent byte owners; Python conversion to owned strings and bytes

Changing a capability

  1. Define the core behavior and its regression case.
  2. Extend the relevant bridge module.
  3. Run generate_bindings.py, then its --check mode.
  4. Update the Python facade where the public operation needs conversions or locking.
  5. Exercise the generated ABI and installed Python wheel. Include failure paths, owned-output lifetimes, and consumption where they apply.

Raw XML signing and hashing are now exposed; they are no longer missing binding capabilities. Country, currency, and timestamp values cross the boundary as validated strings. Internal views and serialization helpers remain implementation details; this interface does not promise a separate foreign type for every Rust type. Structured errors cross as numeric classification, message, and JSON details.

Regression entry points

Tests tied to handwritten CFFI declarations or opaque-handle layouts are replaced by generated C/C++ contracts. Public behavior tests remain acceptance criteria for the Python facade. HTTP tests must use a Python server thread to detect calls that incorrectly retain the GIL. Concurrency regressions must also check that close or consumption waits while another operation uses the same owner.

JavaScript / TypeScript coverage

JS uses the same bridge for keys, CSRs, invoice construction, signing, validation, metadata, credentials and response decoding. The async fetch facade supports all six gateway operations through owned prepared requests. Filesystem helpers and native blocking methods are excluded; the host supplies file contents and time.

Runtime tests cover exact decimals, Arabic optional strings, consuming methods, memory growth, all gateway operations and valid/invalid schema inputs. Chromium and isolated npm consumer checks exercise the packaged WASM loader. These local tests do not prove live gateway or CORS acceptance. See the JS/TS reference.