API Audit (Core + FFI)¶
This page captures the current public surface, the target shape, and a checklist to resolve while finalizing the API. Notes reflect the current codebase (older parity docs may be stale).
Current Surface (Updated)¶
- Core modules:
config,csr,invoice,invoice::sign,invoice::xml,invoice::validation,api(seefatoora-core/src/lib.rs). - Core public API uses crate-owned types only; external types no longer appear in public signatures (HTTP errors and signing time are strings).
- CSR + signing keys are wrapped in crate-owned types (
SigningKey,Csr) with string/bytes constructors and serializers. - Invoice timestamp/currency/country codes are validated string wrappers (
InvoiceTimestamp,CurrencyCode,CountryCode). - FFI exports cover config, CSR, signing keys, invoice builder/sign/parse/accessors, validation, and ZATCA API (
fatoora-ffi/src/lib.rs). - FFI string handling is strict UTF-8 (no lossy conversion or trimming); interior-NUL returns an error or NULL.
- FFI enums use explicit
repr(i32)discriminants for ABI stability. - FFI async calls share a single Tokio runtime (no per-call runtime creation).
- Core defines a unified
ErrorKind/Error; FFI uses the same kind values (1:1 mapping). - Generated C header is in sync with Rust exports and includes validation accessors, totals/party getters, and invoice type getters.
Target Shape (Guiding Principles)¶
- Public API exposes only crate-owned types; external crates stay internal.
- Inputs at the boundary are string/bytes with validation inside the crate.
- FFI is handle-based with
FfiResult<T>for fallible operations; constructors that cannot fail (e.g., config) return raw handles; no panics cross the boundary. - Constructors are minimal; setters carry optional/extended fields.
Final API Checklist¶
- [x] Core public API exposes only crate-owned types (no external crate types in signatures).
- [x] Core uses string/bytes inputs for CSR/signing and also provides
_filehelpers. - [x] Country code, currency code, and timestamp are string wrappers with validation at construction.
- [x] Remove custom XSD inputs entirely;
Configalways uses bundled schemas. - [x]
InvoiceBuilderhas a small required set; optional fields are set via setters. - [x]
InvoiceTypeandInvoiceFlagsare consistent across core and FFI. - [x]
SignedInvoiceandFinalizedInvoiceexpose identical read-only accessors for core invoice data. - [ ] All fallible functions return a single top-level error or a small set of module errors.
- [x] FFI uses
FfiResult<T>for fallible functions; no panics cross the boundary. - [x] FFI exports include all accessors (totals, parties, validation response) and headers match Rust.
- [x] FFI constructors avoid long parameter lists; prefer config handles and setters.
- [x] FFI provides both string/bytes and
_filehelpers for CSR and invoice parsing. - [x] FFI handle types are
#[repr(C)]opaque structs; enums arerepr(i32)with explicit discriminants. - [x] Remove filesystem helpers where not essential (no file-based helpers outside CSR + invoice XML parse).
- [x] Remove custom XSD handling entirely (no
with_xsd_path). - [x] CLI
validateuses bundled XSD only (no--xsd-pathflag). - [ ] Evaluate whether
Configstill adds value beyondEnvironment(keep only if extensibility is needed).
Proposed Signature List (Core)¶
This list is intentionally minimal and string/bytes-only at the public boundary. Names reflect current API.
config¶
pub enum EnvironmentType { NonProduction, Simulation, Production }
pub struct Config { ... }
impl Config {
pub fn new(env: EnvironmentType) -> Self;
pub fn env(&self) -> EnvironmentType;
}
csr¶
pub struct CsrProperties { ... }
impl CsrProperties {
pub fn new(...fields...) -> Result<Self, Error>;
pub fn from_properties_str(s: &str) -> Result<Self, Error>;
pub fn parse_csr_config(properties: &str) -> Result<Self, Error>;
pub fn parse_csr_config_file(path: &Path) -> Result<Self, Error>;
}
pub struct SigningKey { ... }
impl SigningKey {
pub fn generate() -> Self;
pub fn from_der(bytes: &[u8]) -> Result<Self, Error>;
pub fn from_pem(pem: &str) -> Result<Self, Error>;
pub fn to_der(&self) -> Result<Vec<u8>, Error>;
pub fn to_pem(&self) -> Result<String, Error>;
}
pub struct Csr { ... }
impl Csr {
pub fn to_der(&self) -> Result<Vec<u8>, Error>;
pub fn to_pem(&self) -> Result<String, Error>;
pub fn to_base64(&self) -> Result<String, Error>;
pub fn to_pem_base64(&self) -> Result<String, Error>;
}
impl CsrProperties {
pub fn build(&self, key: &SigningKey, env: EnvironmentType) -> Result<Csr, Error>;
}
invoice model¶
pub struct CountryCode(String);
pub struct CurrencyCode(String);
pub struct InvoiceTimestamp(String); // ZATCA ISO UTC: YYYY-MM-DDTHH:MM:SSZ
pub struct Address { ... }
pub struct VatId(String);
pub struct OtherId { ... }
pub struct InvoiceNote { ... }
pub struct Party { ... }
pub type Seller = Party;
pub type Buyer = Party;
pub enum InvoiceSubType { Standard, Simplified }
pub enum InvoiceType {
Tax(InvoiceSubType),
Prepayment(InvoiceSubType),
CreditNote(InvoiceSubType, OriginalInvoiceRef, String),
DebitNote(InvoiceSubType, OriginalInvoiceRef, String),
}
pub struct OriginalInvoiceRef { ... }
bitflags! { pub struct InvoiceFlags: u8 { ... } }
pub struct LineItem { ... }
pub struct InvoiceTotalsData { ... }
pub struct FinalizedInvoice { ... }
pub struct SignedInvoice { ... }
invoice builder¶
pub struct InvoiceBuilder { ... }
impl InvoiceBuilder {
pub fn new(invoice_type: InvoiceType) -> Self;
pub fn set_id(&mut self, id: impl Into<String>) -> &mut Self;
pub fn set_uuid(&mut self, uuid: impl Into<String>) -> &mut Self;
pub fn set_issue_datetime(&mut self, issue_datetime: impl Into<String>) -> &mut Self;
pub fn set_currency(&mut self, currency: impl Into<String>) -> &mut Self;
pub fn set_previous_invoice_hash(&mut self, hash: impl Into<String>) -> &mut Self;
pub fn set_invoice_counter(&mut self, counter: u64) -> &mut Self;
pub fn set_seller(&mut self, seller: Seller) -> &mut Self;
pub fn set_payment_means_code(&mut self, code: impl Into<String>) -> &mut Self;
pub fn set_vat_category(&mut self, vat_category: VatCategory) -> &mut Self;
pub fn set_buyer(&mut self, buyer: Buyer) -> &mut Self;
pub fn set_note(&mut self, note: InvoiceNote) -> &mut Self;
pub fn set_allowance(&mut self, reason: String, amount: f64) -> &mut Self;
pub fn add_line_item(&mut self, item: LineItem) -> &mut Self;
pub fn set_flags(&mut self, flags: InvoiceFlags) -> &mut Self;
pub fn build(self) -> Result<FinalizedInvoice, Error>;
}
invoice signing + XML¶
pub struct InvoiceSigner { ... }
impl InvoiceSigner {
pub fn from_pem(cert_pem: &str, key_pem: &str) -> Result<Self, Error>;
pub fn from_der(cert_der: &[u8], key_der: &[u8]) -> Result<Self, Error>;
pub fn sign(&self, invoice: FinalizedInvoice) -> Result<SignedInvoice, Error>;
pub fn sign_xml(&self, xml: &str) -> Result<SignedInvoice, Error>;
}
pub fn invoice_hash_base64_from_xml(xml: &str) -> Result<String, Error>;
pub fn parse_finalized_invoice_xml(xml: &str) -> Result<FinalizedInvoice, Error>;
pub fn parse_finalized_invoice_xml_file(path: impl AsRef<Path>) -> Result<FinalizedInvoice, Error>;
pub fn parse_signed_invoice_xml(xml: &str) -> Result<SignedInvoice, Error>;
pub fn parse_signed_invoice_xml_file(path: impl AsRef<Path>) -> Result<SignedInvoice, Error>;
pub fn validate_xml_invoice(xml: &str, config: &Config) -> Result<(), Error>;
api client¶
pub enum CsidScope { Compliance, Production }
pub struct CsidCredentials { ... }
pub struct ZatcaClient { ... }
impl ZatcaClient {
pub fn new(config: Config) -> Result<Self, Error>;
pub async fn check_invoice_compliance(
&self,
invoice: &SignedInvoice,
creds: &CsidCredentials,
) -> Result<ValidationResponse, Error>;
pub async fn report_simplified_invoice(
&self,
invoice: &SignedInvoice,
creds: &CsidCredentials,
clearance_status: bool,
accept_language: Option<&str>,
) -> Result<ValidationResponse, Error>;
pub async fn clear_standard_invoice(
&self,
invoice: &SignedInvoice,
creds: &CsidCredentials,
clearance_status: bool,
accept_language: Option<&str>,
) -> Result<ValidationResponse, Error>;
pub async fn post_csr_for_ccsid(&self, csr: &Csr, otp: &str) -> Result<CsidCredentials, Error>;
pub async fn post_ccsid_for_pcsid(&self, creds: &CsidCredentials) -> Result<CsidCredentials, Error>;
pub async fn renew_csid(&self, creds: &CsidCredentials, csr: &Csr, otp: &str, accept_language: Option<&str>)
-> Result<CsidCredentials, Error>;
}
Proposed Signature List (FFI)¶
Names are illustrative; exact naming follows fatoora_ prefix rules. This list reflects the current layout.
FFI types¶
/* Opaque handles */
typedef struct FfiConfig FfiConfig;
typedef struct FfiInvoiceBuilder FfiInvoiceBuilder;
typedef struct FfiFinalizedInvoice FfiFinalizedInvoice;
typedef struct FfiSignedInvoice FfiSignedInvoice;
typedef struct FfiSigner FfiSigner;
typedef struct FfiCsrProperties FfiCsrProperties;
typedef struct FfiCsr FfiCsr;
typedef struct FfiSigningKey FfiSigningKey;
typedef struct FfiZatcaClient FfiZatcaClient;
typedef struct FfiCsidCompliance FfiCsidCompliance;
typedef struct FfiCsidProduction FfiCsidProduction;
typedef struct FfiAddress FfiAddress;
typedef struct FfiParty FfiParty;
typedef struct FfiVatId FfiVatId;
typedef struct FfiOtherId FfiOtherId;
typedef struct FfiInvoiceNote FfiInvoiceNote;
typedef struct FfiOriginalInvoiceRef FfiOriginalInvoiceRef;
typedef struct FfiValidationResponse FfiValidationResponse;
typedef struct FfiValidationResults FfiValidationResults;
typedef struct FfiValidationMessage FfiValidationMessage;
/* Value types */
typedef struct FfiString FfiString;
typedef struct FfiBytes FfiBytes;
typedef struct FfiBytesList FfiBytesList;
/* Enums */
typedef enum FfiEnvironment FfiEnvironment;
typedef enum FfiInvoiceTypeKind FfiInvoiceTypeKind;
typedef enum FfiInvoiceSubType FfiInvoiceSubType;
typedef enum FfiInvoiceFlag FfiInvoiceFlag;
typedef enum FfiVatCategory FfiVatCategory;
typedef enum FfiErrorKind FfiErrorKind;
/* Result wrappers (generated per type) */
typedef struct FfiResult_FfiString FfiResult_FfiString;
/* ...other FfiResult_* specializations... */
config¶
FfiConfig* fatoora_config_new(FfiEnvironment env);
void fatoora_config_free(FfiConfig*);
csr + key¶
FfiResult_FfiCsrProperties fatoora_csr_properties_from_str(const char* s);
FfiResult_FfiCsrProperties fatoora_csr_properties_parse(const char* properties);
FfiResult_FfiCsrProperties fatoora_csr_properties_parse_file(const char* path);
FfiResult_FfiSigningKey fatoora_signing_key_from_pem(const char* pem);
FfiResult_FfiSigningKey fatoora_signing_key_from_der(const uint8_t* der, size_t len);
FfiResult_FfiSigningKey fatoora_signing_key_generate(void);
FfiResult_FfiString fatoora_signing_key_to_pem(FfiSigningKey* key);
FfiResult_FfiCsr fatoora_csr_build(FfiCsrProperties* props, FfiSigningKey* key, FfiEnvironment env);
FfiResult_FfiString fatoora_csr_to_base64(FfiCsr* csr);
FfiResult_FfiString fatoora_csr_to_pem_base64(FfiCsr* csr);
void fatoora_csr_free(FfiCsr*);
void fatoora_signing_key_free(FfiSigningKey*);
invoice builder¶
FfiResult_FfiInvoiceBuilder fatoora_invoice_builder_new(
FfiInvoiceTypeKind kind,
FfiInvoiceSubType sub_type,
const char* original_invoice_id,
const char* original_invoice_uuid,
const char* original_invoice_issue_date,
const char* original_invoice_reason
);
FfiResult_bool fatoora_invoice_builder_set_id(FfiInvoiceBuilder*, const char* id);
FfiResult_bool fatoora_invoice_builder_set_uuid(FfiInvoiceBuilder*, const char* uuid);
FfiResult_bool fatoora_invoice_builder_set_issue_datetime(FfiInvoiceBuilder*, const char* issue_timestamp);
FfiResult_bool fatoora_invoice_builder_set_currency(FfiInvoiceBuilder*, const char* currency_code);
FfiResult_bool fatoora_invoice_builder_set_previous_hash(FfiInvoiceBuilder*, const char* hash);
FfiResult_bool fatoora_invoice_builder_set_invoice_counter(FfiInvoiceBuilder*, uint64_t counter);
FfiResult_bool fatoora_invoice_builder_set_payment_means_code(FfiInvoiceBuilder*, const char* code);
FfiResult_bool fatoora_invoice_builder_set_vat_category(FfiInvoiceBuilder*, FfiVatCategory vat_category);
FfiResult_bool fatoora_invoice_builder_set_seller(FfiInvoiceBuilder*, ...);
FfiResult_bool fatoora_invoice_builder_set_buyer(FfiInvoiceBuilder*, ...);
FfiResult_bool fatoora_invoice_builder_set_note(FfiInvoiceBuilder*, const char* language, const char* text);
FfiResult_bool fatoora_invoice_builder_set_allowance(FfiInvoiceBuilder*, const char* reason, double amount);
FfiResult_bool fatoora_invoice_builder_add_line_item(
FfiInvoiceBuilder*,
const char* description,
double quantity,
const char* unit_code,
double unit_price,
double vat_rate,
FfiVatCategory vat_category
);
FfiResult_bool fatoora_invoice_builder_set_flags(FfiInvoiceBuilder*, uint8_t flags);
FfiResult_FfiFinalizedInvoice fatoora_invoice_builder_build(FfiInvoiceBuilder*);
void fatoora_invoice_builder_free(FfiInvoiceBuilder*);
invoice accessors¶
/* FinalizedInvoice core data accessors */
FfiResult_FfiString fatoora_invoice_id(FfiFinalizedInvoice*);
FfiResult_FfiString fatoora_invoice_uuid(FfiFinalizedInvoice*);
FfiResult_FfiString fatoora_invoice_issue_datetime(FfiFinalizedInvoice*);
FfiResult_FfiString fatoora_invoice_currency(FfiFinalizedInvoice*);
FfiResult_FfiString fatoora_invoice_previous_hash(FfiFinalizedInvoice*);
FfiResult_u64 fatoora_invoice_counter(FfiFinalizedInvoice*);
FfiResult_FfiString fatoora_invoice_payment_means_code(FfiFinalizedInvoice*);
FfiResult_FfiVatCategory fatoora_invoice_vat_category(FfiFinalizedInvoice*);
FfiResult_FfiString fatoora_invoice_allowance_reason(FfiFinalizedInvoice*);
FfiResult_f64 fatoora_invoice_level_charge(FfiFinalizedInvoice*);
FfiResult_f64 fatoora_invoice_level_discount(FfiFinalizedInvoice*);
FfiResult_u8 fatoora_invoice_flags(FfiFinalizedInvoice*);
FfiResult_FfiInvoiceTypeKind fatoora_invoice_type_kind(FfiFinalizedInvoice*);
FfiResult_FfiInvoiceSubType fatoora_invoice_sub_type(FfiFinalizedInvoice*);
FfiResult_FfiOriginalInvoiceRef fatoora_invoice_original_ref(FfiFinalizedInvoice*);
FfiResult_FfiString fatoora_invoice_original_reason(FfiFinalizedInvoice*);
FfiResult_FfiParty fatoora_invoice_seller(FfiFinalizedInvoice*);
FfiResult_FfiParty fatoora_invoice_buyer(FfiFinalizedInvoice*);
FfiResult_FfiInvoiceNote fatoora_invoice_note(FfiFinalizedInvoice*);
/* Line items + totals are mirrored for signed/finalized */
FfiResult_u64 fatoora_invoice_line_item_count(FfiFinalizedInvoice*);
FfiResult_FfiString fatoora_invoice_line_item_description(FfiFinalizedInvoice*, uint64_t index);
FfiResult_FfiString fatoora_invoice_line_item_unit_code(FfiFinalizedInvoice*, uint64_t index);
FfiResult_f64 fatoora_invoice_line_item_quantity(FfiFinalizedInvoice*, uint64_t index);
FfiResult_f64 fatoora_invoice_line_item_unit_price(FfiFinalizedInvoice*, uint64_t index);
FfiResult_f64 fatoora_invoice_line_item_total_amount(FfiFinalizedInvoice*, uint64_t index);
FfiResult_f64 fatoora_invoice_line_item_vat_rate(FfiFinalizedInvoice*, uint64_t index);
FfiResult_f64 fatoora_invoice_line_item_vat_amount(FfiFinalizedInvoice*, uint64_t index);
FfiResult_u8 fatoora_invoice_line_item_vat_category(FfiFinalizedInvoice*, uint64_t index);
FfiResult_f64 fatoora_invoice_totals_tax_inclusive(FfiFinalizedInvoice*);
FfiResult_f64 fatoora_invoice_totals_tax_amount(FfiFinalizedInvoice*);
FfiResult_f64 fatoora_invoice_totals_line_extension(FfiFinalizedInvoice*);
FfiResult_f64 fatoora_invoice_totals_allowance_total(FfiFinalizedInvoice*);
FfiResult_f64 fatoora_invoice_totals_charge_total(FfiFinalizedInvoice*);
FfiResult_f64 fatoora_invoice_totals_taxable_amount(FfiFinalizedInvoice*);
FfiResult_FfiString fatoora_invoice_to_xml(FfiFinalizedInvoice*);
FfiResult_FfiString fatoora_invoice_hash_base64(FfiFinalizedInvoice*);
void fatoora_invoice_free(FfiFinalizedInvoice*);
/* SignedInvoice core data accessors (mirrors FinalizedInvoice) */
FfiResult_FfiString fatoora_signed_invoice_id(FfiSignedInvoice*);
FfiResult_FfiString fatoora_signed_invoice_issue_datetime(FfiSignedInvoice*);
FfiResult_FfiString fatoora_signed_invoice_currency(FfiSignedInvoice*);
FfiResult_FfiString fatoora_signed_invoice_previous_hash(FfiSignedInvoice*);
FfiResult_u64 fatoora_signed_invoice_counter(FfiSignedInvoice*);
FfiResult_FfiString fatoora_signed_invoice_payment_means_code(FfiSignedInvoice*);
FfiResult_FfiVatCategory fatoora_signed_invoice_vat_category(FfiSignedInvoice*);
FfiResult_FfiString fatoora_signed_invoice_allowance_reason(FfiSignedInvoice*);
FfiResult_f64 fatoora_signed_invoice_level_charge(FfiSignedInvoice*);
FfiResult_f64 fatoora_signed_invoice_level_discount(FfiSignedInvoice*);
FfiResult_u8 fatoora_signed_invoice_flags(FfiSignedInvoice*);
FfiResult_FfiInvoiceTypeKind fatoora_signed_invoice_type_kind(FfiSignedInvoice*);
FfiResult_FfiInvoiceSubType fatoora_signed_invoice_sub_type(FfiSignedInvoice*);
FfiResult_FfiOriginalInvoiceRef fatoora_signed_invoice_original_ref(FfiSignedInvoice*);
FfiResult_FfiString fatoora_signed_invoice_original_reason(FfiSignedInvoice*);
FfiResult_FfiParty fatoora_signed_invoice_seller(FfiSignedInvoice*);
FfiResult_FfiParty fatoora_signed_invoice_buyer(FfiSignedInvoice*);
FfiResult_FfiInvoiceNote fatoora_signed_invoice_note(FfiSignedInvoice*);
FfiResult_u64 fatoora_signed_invoice_line_item_count(FfiSignedInvoice*);
FfiResult_FfiString fatoora_signed_invoice_line_item_description(FfiSignedInvoice*, uint64_t index);
FfiResult_FfiString fatoora_signed_invoice_line_item_unit_code(FfiSignedInvoice*, uint64_t index);
FfiResult_f64 fatoora_signed_invoice_line_item_quantity(FfiSignedInvoice*, uint64_t index);
FfiResult_f64 fatoora_signed_invoice_line_item_unit_price(FfiSignedInvoice*, uint64_t index);
FfiResult_f64 fatoora_signed_invoice_line_item_total_amount(FfiSignedInvoice*, uint64_t index);
FfiResult_f64 fatoora_signed_invoice_line_item_vat_rate(FfiSignedInvoice*, uint64_t index);
FfiResult_f64 fatoora_signed_invoice_line_item_vat_amount(FfiSignedInvoice*, uint64_t index);
FfiResult_u8 fatoora_signed_invoice_line_item_vat_category(FfiSignedInvoice*, uint64_t index);
FfiResult_f64 fatoora_signed_invoice_totals_tax_inclusive(FfiSignedInvoice*);
FfiResult_f64 fatoora_signed_invoice_totals_tax_amount(FfiSignedInvoice*);
FfiResult_f64 fatoora_signed_invoice_totals_line_extension(FfiSignedInvoice*);
FfiResult_f64 fatoora_signed_invoice_totals_allowance_total(FfiSignedInvoice*);
FfiResult_f64 fatoora_signed_invoice_totals_charge_total(FfiSignedInvoice*);
FfiResult_f64 fatoora_signed_invoice_totals_taxable_amount(FfiSignedInvoice*);
/* Signed-only accessors */
FfiResult_FfiString fatoora_signed_invoice_xml(FfiSignedInvoice*);
FfiResult_FfiString fatoora_signed_invoice_xml_base64(FfiSignedInvoice*);
FfiResult_FfiString fatoora_signed_invoice_qr(FfiSignedInvoice*);
FfiResult_FfiString fatoora_signed_invoice_uuid(FfiSignedInvoice*);
FfiResult_FfiString fatoora_signed_invoice_hash(FfiSignedInvoice*);
FfiResult_FfiString fatoora_signed_invoice_signature(FfiSignedInvoice*);
FfiResult_FfiString fatoora_signed_invoice_public_key(FfiSignedInvoice*);
FfiResult_FfiString fatoora_signed_invoice_cert_hash(FfiSignedInvoice*);
FfiResult_FfiString fatoora_signed_invoice_signed_props_hash(FfiSignedInvoice*);
FfiResult_FfiString fatoora_signed_invoice_signing_time(FfiSignedInvoice*);
void fatoora_signed_invoice_free(FfiSignedInvoice*);
signing + XML parse¶
FfiResult_FfiSigner fatoora_signer_from_pem(const char* cert_pem, const char* key_pem);
FfiResult_FfiSigner fatoora_signer_from_der(const uint8_t* cert_der, size_t cert_len, const uint8_t* key_der, size_t key_len);
FfiResult_FfiSignedInvoice fatoora_invoice_sign(FfiFinalizedInvoice*, FfiSigner*);
FfiResult_FfiSignedInvoice fatoora_invoice_sign_xml(FfiSigner*, const char* xml);
FfiResult_FfiSignedInvoice fatoora_parse_signed_invoice_xml(const char* xml);
FfiResult_FfiSignedInvoice fatoora_parse_signed_invoice_xml_file(const char* path);
FfiResult_FfiFinalizedInvoice fatoora_parse_finalized_invoice_xml(const char* xml);
FfiResult_FfiFinalizedInvoice fatoora_parse_finalized_invoice_xml_file(const char* path);
validation¶
FfiResult_bool fatoora_validate_xml_str(FfiConfig*, const char* xml);
api client¶
FfiResult_FfiZatcaClient fatoora_zatca_client_new(FfiConfig*);
/* CSID handles (request_id is a UTF-8 string; empty string is the sentinel) */
FfiResult_FfiCsidCompliance fatoora_csid_compliance_new(
FfiEnvironment env,
const char* request_id,
const char* token,
const char* secret
);
FfiResult_FfiCsidProduction fatoora_csid_production_new(
FfiEnvironment env,
const char* request_id,
const char* token,
const char* secret
);
FfiResult_FfiValidationResponse fatoora_zatca_check_compliance(
FfiZatcaClient*,
FfiSignedInvoice*,
FfiCsidCompliance*
);
FfiResult_FfiValidationResponse fatoora_zatca_report_simplified_invoice(
FfiZatcaClient*,
FfiSignedInvoice*,
FfiCsidProduction*,
bool clearance_status,
const char* accept_language
);
FfiResult_FfiValidationResponse fatoora_zatca_clear_standard_invoice(
FfiZatcaClient*,
FfiSignedInvoice*,
FfiCsidProduction*,
bool clearance_status,
const char* accept_language
);
FfiResult_FfiCsidCompliance fatoora_zatca_post_csr_for_ccsid(FfiZatcaClient*, FfiCsr*, const char* otp);
FfiResult_FfiCsidProduction fatoora_zatca_post_ccsid_for_pcsid(FfiZatcaClient*, FfiCsidCompliance*);
FfiResult_FfiCsidProduction fatoora_zatca_renew_csid(
FfiZatcaClient*,
FfiCsidProduction*,
FfiCsr*,
const char* otp,
const char* accept_language
);
void fatoora_zatca_client_free(FfiZatcaClient*);
void fatoora_csid_compliance_free(FfiCsidCompliance*);
void fatoora_csid_production_free(FfiCsidProduction*);
Issues / Inconsistencies / Improvements (Current)¶
Resolved¶
- External types exposed in core public API are removed or wrapped.
- FFI header is in sync with Rust exports (totals, parties, validation response fields, invoice type getters).
- FFI invoice type getters return
FfiInvoiceTypeKind/FfiInvoiceSubTypeand are exported in headers. - Validation response accessors are present in headers.
Remaining / Follow-ups¶
- Decide if
Configremains a public type or ifEnvironmentTypealone is enough. - Review and simplify error taxonomy for a smaller top-level error surface.
- Keep docs/examples aligned with current accessors (especially new invoice accessors for signed/finalized).