### Install GOBL CLI Source: https://github.com/invopop/gobl/blob/main/README.md Install the GOBL command-line interface tool using the Go install command. This tool is part of the gobl.dev project which includes the CLI, HTTP API, MCP server, and WebAssembly build. ```sh go install github.com/invopop/gobl.dev/cmd/gobl@latest ``` -------------------------------- ### Install GOBL Go Package Source: https://github.com/invopop/gobl/blob/main/README.md Run this command to install the GOBL Go package for use in your Go applications. ```go go get github.com/invopop/gobl ``` -------------------------------- ### GOBL Net Public Key Structure Source: https://github.com/invopop/gobl/blob/main/net/README.md Example of a public key response from the per-kid endpoint, including optional GOBL Net validity windows. ```json { "kty": "EC", "crv": "P-256", "kid": "…", "x": "…", "y": "…", "valid_from": "2026-01-01T00:00:00.000Z", "valid_until": "2027-01-01T00:00:00.000Z" } ``` -------------------------------- ### VS Code Settings for GolangCI-Lint Source: https://github.com/invopop/gobl/blob/main/CONTRIBUTING.md Configure VS Code to use golangci-lint for linting and formatting. Ensure golangci-lint is installed and accessible in your PATH. ```json "go.lintTool": "golangci-lint", "go.lintFlags": [ "--path-mode=abs", "--fast-only" ], "go.formatTool": "custom", "go.alternateTools": { "customFormatter": "golangci-lint" }, "go.formatFlags": [ "fmt", "--stdin" ] ``` -------------------------------- ### GOBL Net Bulk JWKS Endpoint Response Source: https://github.com/invopop/gobl/blob/main/net/README.md Example of the JSON Web Key Set response from the /.well-known/jwks.json endpoint, with keys ordered newest first. ```json { "keys": [ { "kty": "EC", "kid": "", "valid_from": "…", … }, { "kty": "EC", "kid": "", "valid_until": "…", … } ] } ``` -------------------------------- ### GET /.well-known/gobl/keys/ Source: https://github.com/invopop/gobl/blob/main/net/README.md Retrieves a single RFC 7517 JSON Web Key for a given key ID (kid). The response includes the key and optionally GOBL Net's valid_from/valid_until extension members. An unknown kid results in a 404 Not Found response. ```APIDOC ## GET /.well-known/gobl/keys/ ### Description Retrieves a single RFC 7517 JSON Web Key for a given key ID (kid). The response includes the key and optionally GOBL Net's valid_from/valid_until extension members. An unknown kid results in a 404 Not Found response. ### Method GET ### Endpoint `/.well-known/gobl/keys/` ### Parameters #### Path Parameters - **kid** (string) - Required - The key ID of the JSON Web Key to retrieve. ### Response #### Success Response (200) - **application/json** - The RFC 7517 JSON Web Key, potentially with GOBL Net extension members. #### Response Example { "example": "{\"kty\": \"EC\", \"crv\": \"P-256\", \"x\": \"...\", \"y\": \"...\", \"kid\": \"...\", \"valid_from\": \"...\", \"valid_until\": \"...\"}" } #### Error Response (404 Not Found) - Unknown kid. ``` -------------------------------- ### Import Rules and Is Packages Source: https://github.com/invopop/gobl/blob/main/rules/README.md Import the rules package and the is sub-package for validation tests. ```go import ( "github.com/invopop/gobl/rules" "github.com/invopop/gobl/rules/is" ) ``` -------------------------------- ### Testing Specific Regimes or Addons Source: https://github.com/invopop/gobl/blob/main/CONTRIBUTING.md Execute tests for a particular tax regime or addon by specifying its path in the command. ```bash go test ./regimes//... ``` ```bash go test ./addons///... ``` -------------------------------- ### Registering a New Addon Definition Source: https://github.com/invopop/gobl/blob/main/CONTRIBUTING.md Addons self-register by calling `tax.RegisterAddonDef(newAddon())` within their `init()` functions. This is the standard way to integrate new addons into the GOBL system. ```go tax.RegisterAddonDef(newAddon()) ``` -------------------------------- ### Importing an External Addon Source: https://github.com/invopop/gobl/blob/main/addons/README.md To use an external addon, import its module. This ensures the addon is loaded at runtime for validation and calculation. ```go import _ "github.com/invopop/gobl.fr.ctc/addon" ``` -------------------------------- ### Run GOBL Code Generation Source: https://github.com/invopop/gobl/blob/main/README.md Execute the 'go generate' command to automatically create JSON schemas, definitions, and Go code output. This should be run after any changes to GOBL's code. ```bash go generate . ``` -------------------------------- ### Map Payment Instructions to TFormaPlatnosci Source: https://github.com/invopop/gobl/blob/main/addons/pl/favat/README.md Maps GOBL payment instruction keys to the Polish FA_VAT TFormaPlatnosci codes. Use 'cash' for 'Gotówka'. ```json { "$schema": "https://gobl.org/draft-0/bill/invoice", // [...] "payment": { "instructions": { "key": "cash" } } } ``` -------------------------------- ### Register Rules with Global Registry Source: https://github.com/invopop/gobl/blob/main/rules/README.md Register rule sets with the global GOBL registry in a package's `init()` function. This allows `rules.Validate(obj)` to automatically apply these rules. ```go func init() { schema.Register(schema.GOBL.Add("mypkg"), MyStruct{}) rules.Register( "mypkg", rules.GOBL.Add("MYPKG"), myStructRules(), anotherStructRules(), ) } ``` -------------------------------- ### GOBL Well-Known Paths and URLs Source: https://github.com/invopop/gobl/blob/main/net/README.md Defines constants for well-known GOBL paths and illustrates how to construct canonical URIs and URLs for various services like key discovery and identity lookup. Emphasizes the use of HTTPS. ```Go package main import ( "fmt" "net/address" ) func main() { addr, _ := address.ParseAddress("example.com") // Canonical URI (iss / aud value) fmt.Printf("gobl:%s\n", addr.URI()) // Key discovery URLs fmt.Printf("https://%s%s\n", addr.String(), address.KeysPath) fmt.Printf("https://%s%s\n", addr.String(), address.KeyPath("kid123")) // Identity and inbox URLs fmt.Printf("https://%s%s\n", addr.String(), address.WhoPath) fmt.Printf("https://%s%s\n", addr.String(), address.InboxPath) // JWKS URL fmt.Printf("https://%s%s\n", addr.String(), address.JWKSPath) } ``` -------------------------------- ### Common Mage Build Targets Source: https://github.com/invopop/gobl/blob/main/CONTRIBUTING.md Run these commands using the Mage build tool to perform common development tasks like code generation, linting, testing, and building. ```bash mage generate # Regenerate JSON schemas, definitions, and Go code ``` ```bash mage lint # Run golangci-lint ``` ```bash mage fix # Run golangci-lint with auto-fix ``` ```bash mage test # Run all tests ``` ```bash mage testrace # Run all tests with the race detector ``` ```bash mage build # Build the CLI binary ``` ```bash mage install # Install the CLI binary ``` ```bash mage check # Full pipeline: lint + generate + test + verify no uncommitted changes ``` -------------------------------- ### Registering a New Regime Definition Source: https://github.com/invopop/gobl/blob/main/CONTRIBUTING.md Regimes self-register by calling `tax.RegisterRegimeDef(New())` within their `init()` functions. This pattern ensures that new regimes are automatically discovered and available for use. ```go tax.RegisterRegimeDef(New()) ``` -------------------------------- ### GOBL Net Address Parsing and Normalization Source: https://github.com/invopop/gobl/blob/main/net/README.md Demonstrates accepted and rejected inputs for GOBL Net Address parsing, including whitespace trimming, trailing dot removal, IDNA normalization, and DNS label validation. Rejects inputs with schemes, ports, or paths. ```Go package main import ( "fmt" "net/address" ) func main() { // Accepted (after normalization) addresses := []string{ "billing.invopop.com", "sub.domain.example.org", "Billing.Invopop.COM", "billing.invopop.com.", " billing.invopop.com ", "München.DE", "xn--mnchen-3ya.de", } fmt.Println("Accepted:") for _, addr := range addresses { parsed, err := address.ParseAddress(addr) if err != nil { fmt.Printf("\t%s -> Error: %v\n", addr, err) } else { fmt.Printf("\t%s -> %s\n", addr, parsed.String()) } } // Rejected rejected := []string{ "", // ErrAddressEmpty "localhost", // ErrAddressInvalid (single label) "http://example.com", // ErrAddressInvalid (scheme) "example.com/path", // ErrAddressInvalid (path) "example.com:8080", // ErrAddressInvalid (port) "not valid!.com", // ErrAddressInvalid (illegal characters) "-bad.com", // ErrAddressInvalid (invalid IDN label) } fmt.Println("\nRejected:") for _, addr := range rejected { _, err := address.ParseAddress(addr) if err != nil { fmt.Printf("\t%s -> Error: %v\n", addr, err) } else { fmt.Printf("\t%s -> Parsed (unexpectedly)\n", addr) } } } ``` -------------------------------- ### Customizing JSON Schema Output (Full Override) Source: https://github.com/invopop/gobl/blob/main/CONTRIBUTING.md Implement the `JSONSchema()` method to provide a complete custom JSON Schema for a type. This allows for fine-grained control over the schema definition. ```go func (t *MyType) JSONSchema() *jsonschema.Schema { // return custom schema } ``` -------------------------------- ### Validate with Contextual Information Source: https://github.com/invopop/gobl/blob/main/rules/README.md The `Set.Validate` method accepts optional context values to inject information for context-aware validation guards. ```go faults := validator.Validate(obj, func(rc *rules.Context) { rc.Set("country", "ES") }) ``` -------------------------------- ### Apply Margin Scheme Extension Source: https://github.com/invopop/gobl/blob/main/addons/pl/favat/README.md Sets the 'pl-favat-margin-scheme' extension for invoices subject to the margin scheme. Use '2' for travel agencies. ```json { "$schema": "https://gobl.org/draft-0/bill/invoice", "tax": { "ext": { "pl-favat-margin-scheme": "2" }, }, // ... } ``` -------------------------------- ### Signing an Envelope with Scope Source: https://github.com/invopop/gobl/blob/main/net/README.md Sign an envelope using a specific key and include issuer, audience, and verified scope options. This is useful for asserting a verified identity during the signing process. ```go env.Sign(authorityKey, head.WithIssuer(authorityAddr.URI()), head.WithAudience(subjectAddr.URI()), head.WithScope(head.ScopeVerified)) ``` -------------------------------- ### Client.VerifyEnvelope Source: https://github.com/invopop/gobl/blob/main/net/README.md Verifies an envelope and returns the verified issuer address. This process involves checking the signature, fetching the issuer's public key, and validating various fields like `iss`, `aud`, `iat`, `valid_from`, and `valid_until`. ```APIDOC ## Client.VerifyEnvelope ### Description Verifies an envelope and returns the verified issuer address. The process includes checking the signature, fetching the issuer's public key, and validating fields like `iss`, `aud`, `iat`, `valid_from`, and `valid_until`. ### Method `Client.VerifyEnvelope(ctx, env, expectedAud)` ### Parameters #### Path Parameters None #### Query Parameters - **expectedAud** (string) - Optional - The expected audience for the envelope. #### Request Body - **ctx** (context.Context) - The context for the operation. - **env** (Envelope) - The envelope to verify. ### Request Example None explicitly provided. ### Response #### Success Response - **verified issuer address** (string) - The address of the verified issuer. #### Response Example None explicitly provided. ### Error Handling - `ErrVerifyFailed`: If the envelope is not signed or if any verification step fails. ``` -------------------------------- ### Apply Exemption Extension and Note Source: https://github.com/invopop/gobl/blob/main/addons/pl/favat/README.md Sets the 'pl-favat-exemption' extension and adds a corresponding note for exempt invoices. Use 'A' for exemptions under Polish law. ```json { "$schema": "https://gobl.org/draft-0/bill/invoice", "tax": { "ext": { "pl-favat-exemption": "A" }, }, "notes": [ { "key": "legal", "code": "A", // must match the code in tax.ext "src": "pl-favat-exemption", "text": "Art. 25a ust. 1 pkt 9 ustawy o VAT" // text describing the legal basis } ] // ... } ``` -------------------------------- ### Define a Partial GOBL Invoice Document Source: https://github.com/invopop/gobl/blob/main/README.md This Go code defines a minimal GOBL Invoice Document, including series, code, issue date, supplier, customer, and line items. Note that sums and calculations are not yet included. ```go inv := &bill.Invoice{ Series: "F23", Code: "00010", IssueDate: cal.MakeDate(2023, time.May, 11), Supplier: &org.Party{ TaxID: &tax.Identity{ Country: l10n.US, }, Name: "Provider One Inc.", Alias: "Provider One", Emails: []*org.Email{ { Address: "billing@provideone.com", }, }, Addresses: []*org.Address{ { Number: "16", Street: "Jessie Street", Locality: "San Francisco", Region: "CA", Code: "94105", Country: l10n.US, }, }, }, Customer: &org.Party{ Name: "Sample Customer", Emails: []*org.Email{ { Address: "email@sample.com", }, }, }, Lines: []*bill.Line{ { Quantity: num.MakeAmount(20, 0), Item: &org.Item{ Name: "A stylish mug", Price: num.MakeAmount(2000, 2), Unit: org.UnitHour, }, Taxes: []*tax.Combo{ { Category: common.TaxCategoryST, Percent: num.NewPercentage(85, 3), }, }, }, }, } ``` -------------------------------- ### Conditional Rule Subsets Source: https://github.com/invopop/gobl/blob/main/rules/README.md Use `rules.When` to conditionally evaluate a subset of rules based on a condition test. The condition receives the full parent struct. ```go rules.When(conditionTest, rules.Field("code", rules.Assert("01", "code is required", is.Present)), ) ``` -------------------------------- ### Normalizer / Validator Dispatch Pattern Source: https://github.com/invopop/gobl/blob/main/CONTRIBUTING.md This `switch` statement pattern is used in both regimes and addons to dispatch normalization and validation logic to the appropriate handler based on the document type. It ensures type-safe processing. ```go switch obj := doc.(type) { // ... handler logic ... } ``` -------------------------------- ### Create Standalone Namespace Validator Sets Source: https://github.com/invopop/gobl/blob/main/rules/README.md Use `rules.NewSet` to create a validator set with a custom namespace, independent of the global GOBL registry. This is useful for validating request bodies or external data. ```go const MyApp rules.Code = "MYAPP" personSet := rules.For(new(Person), rules.Assert("01", "name required", is.Present), ) emailSet := rules.For(new(Email), rules.Field("addr", rules.Assert("01", "email required", is.Present), ), ) validator := rules.NewSet(MyApp, personSet, emailSet) // Codes: MYAPP-PERSON-01, MYAPP-EMAIL-01 ``` -------------------------------- ### Per-Element Assertions on a Slice Field Source: https://github.com/invopop/gobl/blob/main/rules/README.md Use `rules.Each` within a `rules.Field` to apply assertions to every element of a slice. Faults will include indexed paths like `lines[0].code`. ```go rules.Field("lines", rules.Assert("01", "no duplicate line codes", is.Func("no duplicates", hasNoDuplicateLineCodes), ), rules.Each( rules.Field("code", rules.Assert("02", "line code is required", is.Present), ), ), ) ``` -------------------------------- ### Global Registry Validation Source: https://github.com/invopop/gobl/blob/main/rules/README.md Validate an object against rules registered globally using rules.Validate. Assert on the returned rules.Faults for errors. ```go import "github.com/invopop/gobl/rules" // Global registry validation: err := rules.Validate(obj) assert.NoError(t, err) faults := rules.Validate(obj) require.NotNil(t, faults) assert.True(t, faults.HasPath("field")) assert.True(t, faults.HasCode("GOBL-PKG-STRUCT-01")) assert.Equal(t, "assertion description", faults.First().Message()) ``` -------------------------------- ### Define a Rule Set for a Struct Source: https://github.com/invopop/gobl/blob/main/rules/README.md Use `rules.For` to create a rule set for a specific struct type. The prototype value is used for type inference and validating field names during initialization. ```go func myRules() *rules.Set { return rules.For(new(MyStruct), // ... Defs ) } ``` -------------------------------- ### Customizing JSON Schema Output (Augmentation) Source: https://github.com/invopop/gobl/blob/main/CONTRIBUTING.md Use `JSONSchemaExtend()` to augment the auto-generated JSON Schema. This is useful for adding specific details like enum values without redefining the entire schema. ```go func (t *MyType) JSONSchemaExtend(s *jsonschema.Schema) { // augment schema s } ``` -------------------------------- ### Object-Level Assertions with is.Expr and is.Func Source: https://github.com/invopop/gobl/blob/main/rules/README.md Use is.Expr for simple cross-field comparisons and is.Func for more complex logic or named, testable functions. Object-level functions may receive either *T or T as input. ```go rules.Assert("10", "digest must be nil when MIME type is not provided", is.Expr(`MIME != "" || Digest == nil`), ) func digestHasMIME(val any) bool { obj, ok := val.(*MyStruct) if !ok || obj == nil { return false } return obj.MIME != "" || obj.Digest == nil } rules.Assert("10", "digest must be nil when MIME type is not provided", is.Func("no digest without MIME", digestHasMIME), ) ``` -------------------------------- ### Standalone Set Validation Source: https://github.com/invopop/gobl/blob/main/rules/README.md Validate an object using a standalone rules.Set with set.Validate. Check the returned rules.Faults for validation errors. ```go faults := mySet.Validate(obj) require.NotNil(t, faults) assert.True(t, faults.HasCode("MYAPP-STRUCT-01")) ``` -------------------------------- ### Define a Single Validation Assertion Source: https://github.com/invopop/gobl/blob/main/rules/README.md Use `rules.Assert` to define a single validation check. All provided tests must pass; the first failure short-circuits and emits a fault. Assertion codes are automatically prefixed. ```go rules.Assert("01", "description", test1, test2, ...) ``` -------------------------------- ### Insert Invoice into GOBL Envelope Source: https://github.com/invopop/gobl/blob/main/README.md This Go code demonstrates how to insert a previously defined Invoice into a GOBL Envelope. The envelope ensures the integrity of the payload by preventing modifications. ```go // Prepare an "Envelope" env := gobl.NewEnvelope() if err := env.Insert(inv); err != nil { panic(err) } ``` -------------------------------- ### Error String Format Source: https://github.com/invopop/gobl/blob/main/rules/README.md The error string format for rules.Faults includes the fully-qualified code, the field path, and the assertion description. ```text [GOBL-PKG-STRUCT-01] field: assertion description ``` -------------------------------- ### GOBL Address Topic Derivation Source: https://github.com/invopop/gobl/blob/main/net/README.md Shows how to derive the 'topic' form of a GOBL Net Address by reversing its labels and joining them with dots. This form is intended for notification fan-out implementations. ```Go package main import ( "fmt" "net/address" ) func main() { addr, _ := address.ParseAddress("billing.invopop.com") fmt.Println(addr.Topic()) } ``` -------------------------------- ### POST /.well-known/gobl/who Source: https://github.com/invopop/gobl/blob/main/net/README.md Facilitates authenticated party exchange. The caller sends a signed envelope containing their party information. The server verifies the signature, checks audience and issuer allow-lists, and responds with its own signed party envelope. ```APIDOC ## POST /.well-known/gobl/who ### Description Facilitates authenticated party exchange. The caller sends a signed envelope containing their party information. The server verifies the signature, checks audience and issuer allow-lists, and responds with its own signed party envelope. ### Method POST ### Endpoint `/.well-known/gobl/who` ### Parameters #### Request Body - **envelope** (object) - Required - A signed GOBL envelope containing the caller's `org.Party` information. ### Request Example { "example": "{\"iss\": \"gobl:caller\", \"aud\": \"gobl:self\", \"doc\": {\"type\": \"object\", \"value\": { ... \"Party\" data ... }}}" } ### Response #### Success Response (200 OK) - **application/json** - The server's signed party envelope. #### Response Example { "example": "{\"iss\": \"gobl:self\", \"aud\": \"gobl:caller\", \"doc\": {\"type\": \"object\", \"value\": { ... server \"Party\" data ... }}}" } #### Error Responses - **400 Bad Request**: Body did not decode as an envelope. - **401 Unauthorized**: Signature/issuer/audience verification failed. - **403 Forbidden**: Caller (`iss`) not on the domain's allow-list. ``` -------------------------------- ### Conditional Assertion for Present Fields Source: https://github.com/invopop/gobl/blob/main/rules/README.md Use `AssertIfPresent` when a validation should only be applied if the field is not nil or empty. This is useful for optional fields. ```go rules.Field("code", rules.AssertIfPresent("01", "code format invalid", is.Func("valid", isValidCode), ), ) ``` -------------------------------- ### POST /.well-known/gobl/inbox Source: https://github.com/invopop/gobl/blob/main/net/README.md Accepts a signed GOBL Envelope. The signer's identity is verified against their published key, and the envelope's audience must match the inbox's address. An allow-list can be applied to the signer. ```APIDOC ## POST /.well-known/gobl/inbox ### Description Accepts a signed GOBL Envelope. The signer (`iss`) is verified against its published key. The signed `aud` MUST be present and MUST equal this inbox's Address. Envelopes signed without an audience, or bound to a different audience, MUST be rejected. The allow-list (if present) is applied to `iss`. ### Method POST ### Endpoint `/.well-known/gobl/inbox` ### Request Body - **Envelope** (GOBL Envelope) - Required - The signed GOBL Envelope to be submitted. ### Status Codes - **202 Accepted**: Envelope parsed, validated, signature verified, persisted. - **400 Bad Request**: Body could not be read or did not decode as JSON. - **401 Unauthorized**: Envelope signature did not verify, or `aud` missing / not equal to this inbox. - **403 Forbidden**: Caller (`iss`) not on the domain's allow-list. - **422 Unprocessable Entity**: Envelope failed structural validation. - **500 Internal Server Error**: Persistence failed. ### Response #### Success Response (202 Accepted) - The response body is empty. ### Considerations - The request body size is capped at 1 MiB. - The protocol does not mandate where or how an accepted envelope is persisted. ``` -------------------------------- ### Conditional Validation with is.Func Source: https://github.com/invopop/gobl/blob/main/rules/README.md Apply rules conditionally based on a function's return value. The function receives the object and should return true if the condition is met. ```go func envelopeNotSigned(val any) bool { e, ok := val.(*Envelope) return ok && len(e.Signatures) == 0 } rules.When(is.Func("not signed", envelopeNotSigned), rules.Field("stamps", rules.Assert("12", "stamps not allowed before signing", is.Length(0, 0)), ), ) ``` -------------------------------- ### Canonicalize JSON Data in Go Source: https://github.com/invopop/gobl/blob/main/c14n/README.md Use this function to canonicalize JSON data from an io.Reader. Ensure proper error handling for the canonicalization process. ```go package main import ( "fmt" "strings" "github.com/invopop/gobl/c14n" ) func main() { d := `{ "foo":"bar", "c": 123.4, "a": 56, "b": 0.0, "y":null}` r := strings.NewReader(d) res, err := c14n.CanonicalJSON(r) if err != nil { panic(err.Error()) } fmt.Printf("Result: %v\n", string(res)) // Output: {"a":56,"b":0.0E0,"c":1.234E2,"foo":"bar"} } ``` -------------------------------- ### Group Object-Level Assertions Source: https://github.com/invopop/gobl/blob/main/rules/README.md Use `rules.Object` to group assertions that apply to the object as a whole, rather than specific fields. This is useful for cross-field constraints and organizational clarity. ```go rules.Object( rules.Assert("10", "cross-field constraint", is.Expr(`FieldA != "" || FieldB == nil`)), ) ``` -------------------------------- ### Assert Allowed Category Values Source: https://github.com/invopop/gobl/blob/main/rules/README.md Asserts that a category field's value is one of the allowed options. `is.In` normalizes named types, matching both string and custom named types. ```go rules.Field("category", rules.Assert("02", "category is not valid", is.In("a", "b", "c")), ) ``` -------------------------------- ### Custom Validation Function Source: https://github.com/invopop/gobl/blob/main/rules/README.md Defines and uses a custom validation function for a field's checksum. Prefer private named functions for better testability and readability. ```go func myCodeChecksumValid(code string) bool { return isValidChecksum(code) } rules.Field("code", rules.Assert("03", "code checksum mismatch", is.StringFunc("checksum", myCodeChecksumValid), ), ) ``` -------------------------------- ### Rules for Named Value Types Source: https://github.com/invopop/gobl/blob/main/rules/README.md Define rules for named non-struct types using rules.For. Inside is.Expr, the value is exposed as 'this'. ```go func myCodeRules() *rules.Set { return rules.For(MyCode(""), rules.Assert("01", "code must not be empty", is.Present), rules.Assert("02", "code must be alphanumeric", is.Alphanumeric), ) } rules.Assert("02", "code must not exceed 10 characters", is.Expr(`len(this) <= 10`), ) ``` -------------------------------- ### Assert Required Email Address Source: https://github.com/invopop/gobl/blob/main/rules/README.md Asserts that an email address is present and valid. This pattern splits presence and format checks to distinguish between a missing value and a malformed one. ```go rules.Field("addr", rules.Assert("01", "email address is required", is.Present), rules.Assert("02", "email address must be valid", is.EmailFormat), ) ``` -------------------------------- ### GOBL Net Signed Payload Structure Source: https://github.com/invopop/gobl/blob/main/net/README.md The structure of the payload signed by each GOBL Net signature, including document identifiers, issuer, audience, and signing time. ```json { "uuid": "…", "dig": "…", "iss": "gobl:billing.invopop.com", "aud": "…", "iat": 1678886400 } ``` -------------------------------- ### Scope Assertions to a Field Source: https://github.com/invopop/gobl/blob/main/rules/README.md Use `rules.Field` to apply assertions to a specific field within a struct. The field name must match its JSON tag and is validated at initialization. ```go rules.Field("name", rules.Assert("01", "name is required", is.Present), ) ``` -------------------------------- ### Envelope.Sign Source: https://github.com/invopop/gobl/blob/main/net/README.md Signs the document identity along with the signer's issuer and optional audience. Options can be used to specify issuer, audience, and scope. ```APIDOC ## Envelope.Sign ### Description Signs the document identity plus the signer's `iss` and optional `aud`. The `iss` and `aud` can be set using `head.WithIssuer` and `head.WithAudience` options. Both may be omitted for a plain, non-GOBL-Net signature. ### Method `Envelope.Sign(key, opts...) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```go env.Sign(authorityKey, head.WithIssuer(authorityAddr.URI()), head.WithAudience(subjectAddr.URI()), head.WithScope(head.ScopeVerified)) ``` ### Response #### Success Response Returns a signed envelope. #### Response Example None explicitly provided. ### Error Handling Errors are not explicitly detailed in this section. ``` -------------------------------- ### Nested Field Validation in GOBL Source: https://github.com/invopop/gobl/blob/main/rules/README.md Define rules for nested structures by nesting rules.Field calls. This allows constraining child fields from the parent's perspective. ```go func invoiceRules() *rules.Set { return rules.For(new(Invoice), rules.When(is.InContext(tax.RegimeIn("XX")), rules.Field("supplier", rules.Assert("01", "supplier is required", is.Present), rules.Field("tax_id", rules.Assert("02", "supplier tax ID is required", is.Present), rules.Field("code", rules.Assert("03", "supplier tax ID must have a code", is.Present), ), ), ), ), ) } ``` -------------------------------- ### Tag Reverse Charge Invoices Source: https://github.com/invopop/gobl/blob/main/addons/pl/favat/README.md Applies the 'reverse-charge' tag to indicate a reverse charge invoice, corresponding to the pl-favat-reverse-charge extension. ```json { "$schema": "https://gobl.org/draft-0/bill/invoice", "$tags": ["reverse-charge"] // ... } ``` -------------------------------- ### Tag Self-Billed Invoices Source: https://github.com/invopop/gobl/blob/main/addons/pl/favat/README.md Applies the 'self-billed' tag to indicate a self-billing invoice, which corresponds to the pl-favat-self-billing extension. ```json { "$schema": "https://gobl.org/draft-0/bill/invoice", "$tags": ["self-billed"] // ... } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.