GOBL (Go Business Language)

repository·main·Indexed 43 days ago

https://github.com/invopop/gobl

A core library and schema system for building, validating, and signing electronic business documents like invoices globally. It features a standardized JSON schema, precise tax calculations, a plugin system for local regulatory requirements via addons, and a deterministic JSON canonicalization (c14n) process for digital signatures. The ecosystem includes the dsig package for JWS/JWK signatures and GOBL Net, a decentralized discovery and delivery protocol for signed documents.

Tokens
15K
Snippets
40
Records
67
Agent score
53%

What's inside GOBL

  1. Overview of Currency Reference Data in GOBL

    main
    The currency package in GOBL provides comprehensive support for global currencies. It includes reference data for most world currencies and provides methods to format and manipulate them. The source data is inspired by the Ruby money gem and is maintained within the repository's /data/currency directory.
  2. Overview of GoBL Digital Signatures

    main

    The dsig package provides functionality for handling GoBL document digests and signatures. It uses the JOSE (Javascript Object Signing and Encryption) standards, specifically JWS (JSON Web Signatures - RFC7515) and JWK (JSON Web Keys - RFC7517).

    GoBL uses the go-jose library under the hood but provides wrappers with sensible defaults optimized for GoBL document use cases. This ensures that signatures can be mathematically verified using a public key to confirm the identity of the private key owner.

  3. What is GOBL Net?

    main

    GOBL Net is a decentralized discovery and delivery protocol for signed GOBL documents. It uses Fully Qualified Domain Names (FQDNs) to identify participants and relies on HTTPS to bind addresses to three well-known resources:

    • /.well-known/gobl/keys/<kid>: Publishes a single verification key (RFC 7517 JWK).
    • /.well-known/gobl/who: Publishes a signed org.Party identity.
    • /.well-known/gobl/inbox: Accepts signed GOBL envelopes.

    Verification is achieved by obtaining the issuer's key from their domain and relying on Web PKI to authenticate the HTTPS response. Registration authorities can add a trust layer by countersigning party envelopes.

  4. Security considerations for GOBL Net

    main

    When implementing or using GOBL Net, keep the following security principles in mind:

    • Web PKI: Control of an address and its TLS certificate controls its published keys. Applications must compare verified issuers with expected identities or apply authority policy.
    • Key Removal: Use FlushKeyCache and short TTLs to mitigate the risk of accepting revoked keys still in the cache.
    • Endorsement Freshness: Authority and verifier exp claims bound their lifetimes. Identity caches must also have bounded lifetimes.
    • Resource Limits: Clients limit response bodies to 1 MiB and verification to 32 signatures per envelope. Servers should implement similar limits.
    • Privacy: Request tokens identify callers but do not make party data public. Limit audit-log retention to protect requester metadata.
    • Routing Fields: Unsigned from and to values are only hints. Always use signed claims for security decisions.
  5. How GOBL Net addresses and discovery work

    main

    A GOBL Net address is an FQDN without a scheme, port, path, query, or fragment (e.g., supplier.example.com).

    Address Parsing

    ParseAddress performs the following:

    1. Trims surrounding whitespace and one trailing dot.
    2. Converts internationalized names to lowercase ASCII A-labels using the IDNA2008 lookup profile.
    3. Validates DNS label syntax.
    4. Requires at least two labels.

    URI Formats

    • Canonical Form: supplier.example.com (used in signed iss, aud, and verifier claims).
    • gobl: URI: gobl:supplier.example.com (used in org.Party endpoints and optional envelope routing fields).

    Resource Mapping

    For an address supplier.example.com, the following resources are expected:

    • https://supplier.example.com/.well-known/gobl/keys/<kid>
    • https://supplier.example.com/.well-known/gobl/who
    • https://supplier.example.com/.well-known/gobl/inbox
    • https://supplier.example.com/.well-known/jwks.json (optional for generic tooling)
  6. How to perform conditional validation with When

    main

    Use rules.When to apply a subset of rules only when a specific condition is met. Conditions are evaluated based on the object's state, as rules do not have access to context.Context.

    To ensure faults land on the correct field when a requirement is conditional, combine is.Not with rules.When.

    // Apply rules for 'stamps' only if the envelope is not signed
    rules.When(is.Func("not signed", envelopeNotSigned),
        rules.Field("stamps",
            rules.Assert("12", "stamps not allowed before signing", is.Length(0, 0)),
        ),
    )
  7. How GOBL addons work

    main

    Addons are used to add normalization, validation rules, and specific scenarios to a GOBL document to adapt it to a particular format or regulatory regime.

    To use an addon, a document must list the addon's versioned key (e.g., mx-cfdi-v4) under the $addons field in its JSON representation.

    There are two types of addons:

    1. In-core addons: These are part of the main github.com/invopop/gobl package and are automatically available when you import the core library.
    2. External addons: These live in their own Go modules (e.g., github.com/invopop/gobl.fr.ctc). These allow for country-specific rules to be opted into only when needed, keeping the core library lightweight.
  8. How envelopes work in GOBL

    main

    In GOBL, an Envelope is a wrapper used to hold business document data (like an Invoice). The envelope provides functionality to guarantee that the underlying payload has not been modified. Instead of working directly on the document, you insert your document into an envelope to manage its lifecycle and integrity.

    // Prepare an "Envelope"
    env := gobl.NewEnvelope()
    if err := env.Insert(inv); err != nil {
    	panic(err)
    }
  9. Understand the typical delivery flow

    main

    A standard delivery in GOBL Net follows these steps:

    1. Discovery: The sender obtains the receiver's address out of band.
    2. Inquiry (Optional): The sender may call /who to retrieve the receiver's invoicing details.
    3. Signing: The sender signs the envelope with iss=sender and aud=receiver.
    4. Submission: The sender posts the envelope to the receiver's inbox using a request token.
    5. Verification: The receiver verifies the token and calls VerifyDelivery.
    6. Endorsement (Optional): The receiver may call VerifySender on the returned issuer.
    7. Confirmation: A 202 status code confirms durable receipt.

    Note: Only step 6 requires authority endorsement, and that requirement applies to the sender. Any response document is treated as a new delivery and is subject to the same rules.

  10. Use GOBL Addons for regulatory compliance

    main

    Addons adapt GOBL documents to specific formats or regulatory regimes. They add extensions, normalization, and validation rules identified by a versioned key under the $addons field in the JSON (e.g., es-facturae-v3).

    While many addons are bundled in the core library, some must be imported separately as Go modules:

    • gobl.br.nfe (Brazil NF-e, br-nfe-v4)
    • gobl.br.nfse (Brazil NFS-e, br-nfse-v1)
    • gobl.fr.ctc (France CTC flows)
    • gobl.mx.cfdi (Mexican SAT CFDI, mx-cfdi-v4)
    • gobl.pt.saft (Portugal SAF-T, pt-saft-v1)
    • gobl.sa.zatca (Saudi Arabia ZATCA, sa-zatca-v1)

    For a complete set of addons including these external ones, use the gobl.dev project.

  11. How GOBL Net keys and signatures work

    main

    Key Discovery

    Each signing key must be available as a single RFC 7517 JWK at /.well-known/gobl/keys/<kid>. Signatures identify keys using the kid claim; they do not use a jku header.

    Published dsig.PublicKey objects may include valid_from and valid_until bounds. If a signature contains an iat (issued at) claim, verification will fail if the signing time falls outside these bounds.

    Envelope Signature Claims

    The signed payload contains the document uuid and digest, plus these protocol claims:

    • iss: Signer's canonical GOBL Net address.
    • aud: Address to which the signature is bound (required for ordinary inbox deliveries).
    • iat: Signing time (RFC 7519 NumericDate).
    • exp: Optional expiry (used primarily for endorsements).
    • verifier: Optional verifier named by a registration authority.

    Note: Envelope header from and to fields are unsigned routing hints and MUST NOT be used for verification.

  12. Prioritize existing tests over custom functions

    main

    When defining validation rules in GOBL, follow this order of preference to ensure maintainability and reuse:

    1. rules/is: Use generic tests for standard types (strings, ints, slices, etc.).
    2. Domain packages: Check if the package defining your type (e.g., num, tax, org) already exports a test for it.
    3. Custom function: Only use is.Func or is.StringFunc if neither of the above expresses the required rule.

    Best Practice: If you write a custom rule that is generally useful for a GOBL type, add that test to the type's own package rather than keeping it private to your specific addon or implementation.