Billing docs improvement + build opt #696

Merged
tech merged 1 commits from docs-693 into main 2026-03-06 15:20:32 +00:00
79 changed files with 597 additions and 503 deletions

View File

@@ -1,2 +1,18 @@
ci/dev/mongo.key* ci/dev/mongo.key*
# VCS / editor files
.git
.vscode
.DS_Store
**/.DS_Store
# Local caches and temporary artifacts
.cache
.gocache
**/.gocache
**/tmp/
**/tmp/**
# Frontend local build artifacts (rebuilt in Docker)
frontend/**/.dart_tool
frontend/**/build

View File

@@ -20,7 +20,7 @@ BACKEND_SERVICES := \
dev-tron-gateway-vault-agent \ dev-tron-gateway-vault-agent \
dev-tron-gateway \ dev-tron-gateway \
dev-aurora-gateway \ dev-aurora-gateway \
dev-tgsettle-gateway \ dev-chsettle-gateway \
dev-notification \ dev-notification \
dev-callbacks-vault-agent \ dev-callbacks-vault-agent \
dev-callbacks \ dev-callbacks \
@@ -61,7 +61,7 @@ help:
@echo " make build-core Build core services (discovery, ledger, fees, documents)" @echo " make build-core Build core services (discovery, ledger, fees, documents)"
@echo " make build-fx Build FX services (oracle, ingestor)" @echo " make build-fx Build FX services (oracle, ingestor)"
@echo " make build-payments Build payment orchestrator" @echo " make build-payments Build payment orchestrator"
@echo " make build-gateways Build gateway services (chain, tron, aurora, tgsettle)" @echo " make build-gateways Build gateway services (chain, tron, aurora, chsettle)"
@echo " make build-api Build API services (notification, callbacks, bff)" @echo " make build-api Build API services (notification, callbacks, bff)"
@echo " make build-frontend Build Flutter web frontend" @echo " make build-frontend Build Flutter web frontend"
@echo "" @echo ""
@@ -247,7 +247,7 @@ services-up:
dev-chain-gateway \ dev-chain-gateway \
dev-tron-gateway \ dev-tron-gateway \
dev-aurora-gateway \ dev-aurora-gateway \
dev-tgsettle-gateway \ dev-chsettle-gateway \
dev-notification \ dev-notification \
dev-callbacks \ dev-callbacks \
dev-bff \ dev-bff \
@@ -292,7 +292,7 @@ list-services:
@echo " - dev-chain-gateway :50070, :9404 (EVM Blockchain Gateway)" @echo " - dev-chain-gateway :50070, :9404 (EVM Blockchain Gateway)"
@echo " - dev-tron-gateway :50071, :9408 (TRON Blockchain Gateway)" @echo " - dev-tron-gateway :50071, :9408 (TRON Blockchain Gateway)"
@echo " - dev-aurora-gateway :50075, :9405, :8084 (Card Payouts Simulator)" @echo " - dev-aurora-gateway :50075, :9405, :8084 (Card Payouts Simulator)"
@echo " - dev-tgsettle-gateway :50080, :9406 (Telegram Settlements)" @echo " - dev-chsettle-gateway :50080, :9406 (Chimera Settlements Simulator)"
@echo " - dev-notification :8081 (Notifications)" @echo " - dev-notification :8081 (Notifications)"
@echo " - dev-callbacks :9420 (Webhook Callbacks)" @echo " - dev-callbacks :9420 (Webhook Callbacks)"
@echo " - dev-bff :8080 (Backend for Frontend)" @echo " - dev-bff :8080 (Backend for Frontend)"
@@ -322,7 +322,7 @@ build-payments:
build-gateways: build-gateways:
@echo "$(GREEN)Building gateway services...$(NC)" @echo "$(GREEN)Building gateway services...$(NC)"
@$(COMPOSE) build dev-chain-gateway dev-tron-gateway dev-aurora-gateway dev-tgsettle-gateway @$(COMPOSE) build dev-chain-gateway dev-tron-gateway dev-aurora-gateway dev-chsettle-gateway
build-api: build-api:
@echo "$(GREEN)Building API services...$(NC)" @echo "$(GREEN)Building API services...$(NC)"

View File

@@ -25,14 +25,15 @@ Financial services platform providing payment orchestration, ledger accounting,
| Gateway Chain | `api/gateway/chain/` | EVM blockchain gateway | | Gateway Chain | `api/gateway/chain/` | EVM blockchain gateway |
| Gateway TRON | `api/gateway/tron/` | TRON blockchain gateway | | Gateway TRON | `api/gateway/tron/` | TRON blockchain gateway |
| Gateway Aurora | `api/gateway/aurora/` | Card payouts simulator | | Gateway Aurora | `api/gateway/aurora/` | Card payouts simulator |
| Gateway ChimeraSettle | `api/gateway/chsettle/` | Dummy settlement simulator (fast/slow/success/fail/stuck) |
| Gateway MNTX | `api/gateway/mntx/` | Card payouts | | Gateway MNTX | `api/gateway/mntx/` | Card payouts |
| Gateway TGSettle | `api/gateway/tgsettle/` | Telegram settlements with MNTX | | Gateway TGSettle (legacy) | `api/gateway/tgsettle/` | Legacy Telegram settlement gateway (not used in dev compose) |
| Notification | `api/notification/` | Notifications | | Notification | `api/notification/` | Notifications |
| BFF | `api/edge/bff/` | Backend for frontend | | BFF | `api/edge/bff/` | Backend for frontend |
| Callbacks | `api/edge/callbacks/` | Webhook callbacks delivery | | Callbacks | `api/edge/callbacks/` | Webhook callbacks delivery |
| Frontend | `frontend/pweb/` | Flutter web UI | | Frontend | `frontend/pweb/` | Flutter web UI |
Gateway note: current dev compose workflows (`make services-up`, `make build-gateways`) use Aurora for card-payout flows (`chain`, `tron`, `aurora`, `tgsettle`). The MNTX gateway codebase is retained separately for Monetix-specific integration. Gateway note: current dev compose workflows (`make services-up`, `make build-gateways`) use (`chain`, `tron`, `aurora`, `chsettle`). ChimeraSettle is the settlement simulator for test flows; it supports deterministic behavior routing via explicit scenario override and amount buckets. TGSettle remains in-repo as legacy code and is not started by default in dev compose.
## Prerequisites ## Prerequisites
@@ -87,7 +88,7 @@ make list-services # Show service names, ports, and descriptions
make build-core # discovery, ledger, fees, documents make build-core # discovery, ledger, fees, documents
make build-fx # oracle, ingestor make build-fx # oracle, ingestor
make build-payments # orchestrator, quotation, methods make build-payments # orchestrator, quotation, methods
make build-gateways # chain, tron, aurora, tgsettle make build-gateways # chain, tron, aurora, chsettle
make build-api # notification, callbacks, bff make build-api # notification, callbacks, bff
make build-frontend # Flutter web UI make build-frontend # Flutter web UI
``` ```

View File

@@ -24,8 +24,6 @@ database:
documents: documents:
issuer: issuer:
legal_name: "Sendico Ltd"
legal_address: "12 Market Street, London, UK"
logo_path: "assets/logo.png" logo_path: "assets/logo.png"
templates: templates:
acceptance_path: "templates/acceptance.tpl" acceptance_path: "templates/acceptance.tpl"

View File

@@ -24,8 +24,6 @@ database:
documents: documents:
issuer: issuer:
legal_name: "Sendico Ltd"
legal_address: "12 Market Street, London, UK"
logo_path: "/app/assets/logo.png" logo_path: "/app/assets/logo.png"
templates: templates:
acceptance_path: "/app/templates/acceptance.tpl" acceptance_path: "/app/templates/acceptance.tpl"

View File

@@ -8,14 +8,14 @@ require (
github.com/aws/aws-sdk-go-v2 v1.41.3 github.com/aws/aws-sdk-go-v2 v1.41.3
github.com/aws/aws-sdk-go-v2/config v1.32.11 github.com/aws/aws-sdk-go-v2/config v1.32.11
github.com/aws/aws-sdk-go-v2/credentials v1.19.11 github.com/aws/aws-sdk-go-v2/credentials v1.19.11
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.3 github.com/aws/aws-sdk-go-v2/service/s3 v1.96.4
github.com/jung-kurt/gofpdf v1.16.2 github.com/jung-kurt/gofpdf v1.16.2
github.com/prometheus/client_golang v1.23.2 github.com/prometheus/client_golang v1.23.2
github.com/shopspring/decimal v1.4.0 github.com/shopspring/decimal v1.4.0
github.com/tech/sendico/pkg v0.1.0 github.com/tech/sendico/pkg v0.1.0
go.mongodb.org/mongo-driver/v2 v2.5.0 go.mongodb.org/mongo-driver/v2 v2.5.0
go.uber.org/zap v1.27.1 go.uber.org/zap v1.27.1
google.golang.org/grpc v1.79.1 google.golang.org/grpc v1.79.2
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )
@@ -25,7 +25,7 @@ require (
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.19 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.19 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.19 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.20 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.11 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.11 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19 // indirect

View File

@@ -20,8 +20,8 @@ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19 h1:AWeJMk33GTBf6J20XJ
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19/go.mod h1:+GWrYoaAsV7/4pNHpwh1kiNLXkKaSoppxQq9lbH8Ejw= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19/go.mod h1:+GWrYoaAsV7/4pNHpwh1kiNLXkKaSoppxQq9lbH8Ejw=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5 h1:clHU5fm//kWS1C2HgtgWxfQbFbx4b6rx+5jzhgX9HrI= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5 h1:clHU5fm//kWS1C2HgtgWxfQbFbx4b6rx+5jzhgX9HrI=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.19 h1:3Y4oma5TiV7tT9wa8zRcdoXwZkGz9Q/wxbEUK7cMuAM= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.20 h1:qi3e/dmpdONhj1RyIZdi6DKKpDXS5Lb8ftr3p7cyHJc=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.19/go.mod h1:V1K+TeJVD5JOk3D9e5tsX2KUdL7BlB+FV6cBhdobN8c= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.20/go.mod h1:V1K+TeJVD5JOk3D9e5tsX2KUdL7BlB+FV6cBhdobN8c=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6 h1:XAq62tBTJP/85lFD5oqOOe7YYgWxY9LvWq8plyDvDVg= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6 h1:XAq62tBTJP/85lFD5oqOOe7YYgWxY9LvWq8plyDvDVg=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.11 h1:BYf7XNsJMzl4mObARUBUib+j2tf0U//JAAtTnYqvqCw= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.11 h1:BYf7XNsJMzl4mObARUBUib+j2tf0U//JAAtTnYqvqCw=
@@ -30,8 +30,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19 h1:X1Tow7su
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19/go.mod h1:/rARO8psX+4sfjUQXp5LLifjUt8DuATZ31WptNJTyQA= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19/go.mod h1:/rARO8psX+4sfjUQXp5LLifjUt8DuATZ31WptNJTyQA=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.19 h1:JnQeStZvPHFHeyky/7LbMlyQjUa+jIBj36OlWm0pzIk= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.19 h1:JnQeStZvPHFHeyky/7LbMlyQjUa+jIBj36OlWm0pzIk=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.19/go.mod h1:HGyasyHvYdFQeJhvDHfH7HXkHh57htcJGKDZ+7z+I24= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.19/go.mod h1:HGyasyHvYdFQeJhvDHfH7HXkHh57htcJGKDZ+7z+I24=
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.3 h1:+d0SsTvxtIJt4tSJ6wr+jrxEMDa6XeupjRv8H7Qitkk= github.com/aws/aws-sdk-go-v2/service/s3 v1.96.4 h1:4ExZyubQ6LQQVuF2Qp9OsfEvsTdAWh5Gfwf6PgIdLdk=
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.3/go.mod h1:ROUNFvFWPwBlOu687WJNQ9cPvd2ccpFrnCiA1YGz50o= github.com/aws/aws-sdk-go-v2/service/s3 v1.96.4/go.mod h1:NF3JcMGOiARAss1ld3WGORCw71+4ExDD2cbbdKS5PpA=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.7 h1:Y2cAXlClHsXkkOvWZFXATr34b0hxxloeQu/pAZz2row= github.com/aws/aws-sdk-go-v2/service/signin v1.0.7 h1:Y2cAXlClHsXkkOvWZFXATr34b0hxxloeQu/pAZz2row=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.7/go.mod h1:idzZ7gmDeqeNrSPkdbtMp9qWMgcBwykA7P7Rzh5DXVU= github.com/aws/aws-sdk-go-v2/service/signin v1.0.7/go.mod h1:idzZ7gmDeqeNrSPkdbtMp9qWMgcBwykA7P7Rzh5DXVU=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.12 h1:iSsvB9EtQ09YrsmIc44Heqlx5ByGErqhPK1ZQLppias= github.com/aws/aws-sdk-go-v2/service/sso v1.30.12 h1:iSsvB9EtQ09YrsmIc44Heqlx5ByGErqhPK1ZQLppias=
@@ -260,8 +260,8 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU=
google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -0,0 +1,116 @@
package content
// Issuer details are intentionally centralized to avoid document text drift.
const (
IssuerLegalName = "SMX Operations Limited"
IssuerLegalAddress = "Room 607, 12/F., Block C, Hong Kong Industrial Centre, 489-491 Castle Peak Road, Lai Chi Kok, Hong Kong"
)
const (
PDFTitleActOfAcceptance = "Act of Acceptance"
DocumentIntegrityHashPrefix = "Document integrity hash: "
)
// AcceptanceTemplateContent contains all static copy used by the acceptance act template.
type AcceptanceTemplateContent struct {
Title string
Subtitle string
MetaDateLabel string
MetaActNumberLabel string
SectionParties string
PartiesIntro string
PartyExecutorLabel string
PartyStatusLabel string
PartyStatusValue string
SectionBasis string
BasisLine1 string
BasisLine2 string
SectionServicesRendered string
ServicesRenderedLine1 string
ServicesRenderedLine2 string
SectionRemuneration string
RemunerationHeaderDesc string
RemunerationHeaderAmount string
RemunerationServicesDesc string
SectionConfirmation string
ConfirmationLine1 string
ConfirmationLine2 string
ConfirmationPaymentLine1 string
ConfirmationPaymentLine2 string
SectionSignatures string
SignatureCustomerLine string
SignatureExecutorLine string
}
var AcceptanceTemplate = AcceptanceTemplateContent{
Title: "ACT OF ACCEPTANCE OF SERVICES",
Subtitle: "under the Public Offer Agreement",
MetaDateLabel: "Date",
MetaActNumberLabel: "Act No",
SectionParties: "PARTIES",
PartiesIntro: "This Act is made between the following Parties.",
PartyExecutorLabel: "Executor",
PartyStatusLabel: "Status",
PartyStatusValue: "Individual",
SectionBasis: "BASIS",
BasisLine1: "This Act is issued pursuant to the Public Offer Agreement",
BasisLine2: "accepted by the Executor by joining the offer.",
SectionServicesRendered: "SERVICES RENDERED",
ServicesRenderedLine1: "The Executor has rendered services to the Customer",
ServicesRenderedLine2: "in accordance with the terms of the Public Offer Agreement.",
SectionRemuneration: "REMUNERATION",
RemunerationHeaderDesc: "Description",
RemunerationHeaderAmount: "Amount",
RemunerationServicesDesc: "Services rendered under the Public Offer Agreement",
SectionConfirmation: "CONFIRMATION",
ConfirmationLine1: "The Customer confirms that the services were rendered properly",
ConfirmationLine2: "and accepted without any claims.",
ConfirmationPaymentLine1: "The remuneration for the services was paid to the Executor",
ConfirmationPaymentLine2: "using the bank card details provided by the Executor.",
SectionSignatures: "SIGNATURES",
SignatureCustomerLine: "Customer ___________________________",
SignatureExecutorLine: "Executor ___________________________",
}
// OperationDocumentContent contains all static copy for operation documents.
type OperationDocumentContent struct {
Title string
Subtitle string
MetaDocumentType string
SectionOperation string
SectionFailure string
RowOrganization string
RowGatewayService string
RowOperationRef string
RowPaymentRef string
RowCode string
RowState string
RowLabel string
RowStartedAtUTC string
RowCompletedAtUTC string
RowAmount string
RowFailureCode string
RowFailureReason string
MissingValuePlaceholder string
}
var OperationDocument = OperationDocumentContent{
Title: "OPERATION BILLING DOCUMENT",
Subtitle: "Gateway operation statement",
MetaDocumentType: "Document Type: Operation",
SectionOperation: "OPERATION DETAILS",
SectionFailure: "FAILURE DETAILS",
RowOrganization: "Organization",
RowGatewayService: "Gateway Service",
RowOperationRef: "Operation Ref",
RowPaymentRef: "Payment Ref",
RowCode: "Code",
RowState: "State",
RowLabel: "Label",
RowStartedAtUTC: "Started At (UTC)",
RowCompletedAtUTC: "Completed At (UTC)",
RowAmount: "Amount",
RowFailureCode: "Failure Code",
RowFailureReason: "Failure Reason",
MissingValuePlaceholder: "n/a",
}

View File

@@ -3,18 +3,24 @@ package documents
import ( import (
"strings" "strings"
"github.com/tech/sendico/billing/documents/internal/content"
"github.com/tech/sendico/billing/documents/internal/docstore" "github.com/tech/sendico/billing/documents/internal/docstore"
"github.com/tech/sendico/billing/documents/renderer" "github.com/tech/sendico/billing/documents/renderer"
) )
// Config holds document service settings loaded from YAML. // Config holds document service settings loaded from YAML.
type Config struct { type Config struct {
Issuer renderer.Issuer `yaml:"issuer"` Issuer IssuerConfig `yaml:"issuer"`
Templates TemplateConfig `yaml:"templates"` Templates TemplateConfig `yaml:"templates"`
Protection ProtectionConfig `yaml:"protection"` Protection ProtectionConfig `yaml:"protection"`
Storage docstore.Config `yaml:"storage"` Storage docstore.Config `yaml:"storage"`
} }
// IssuerConfig defines issuer settings that are environment-specific.
type IssuerConfig struct {
LogoPath string `yaml:"logo_path"`
}
// TemplateConfig defines document template locations. // TemplateConfig defines document template locations.
type TemplateConfig struct { type TemplateConfig struct {
AcceptancePath string `yaml:"acceptance_path"` AcceptancePath string `yaml:"acceptance_path"`
@@ -25,6 +31,14 @@ type ProtectionConfig struct {
OwnerPassword string `yaml:"owner_password"` OwnerPassword string `yaml:"owner_password"`
} }
func (c Config) IssuerDetails() renderer.Issuer {
return renderer.Issuer{
LegalName: content.IssuerLegalName,
LegalAddress: content.IssuerLegalAddress,
LogoPath: c.Issuer.LogoPath,
}
}
func (c Config) AcceptanceTemplatePath() string { func (c Config) AcceptanceTemplatePath() string {
if strings.TrimSpace(c.Templates.AcceptancePath) == "" { if strings.TrimSpace(c.Templates.AcceptancePath) == "" {
return "templates/acceptance.tpl" return "templates/acceptance.tpl"

View File

@@ -7,7 +7,6 @@ import (
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/client_golang/prometheus/promauto"
documentsv1 "github.com/tech/sendico/pkg/proto/billing/documents/v1"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
) )
@@ -17,7 +16,6 @@ var (
requestsTotal *prometheus.CounterVec requestsTotal *prometheus.CounterVec
requestLatency *prometheus.HistogramVec requestLatency *prometheus.HistogramVec
batchSize prometheus.Histogram
documentBytes *prometheus.HistogramVec documentBytes *prometheus.HistogramVec
) )
@@ -44,16 +42,6 @@ func initMetrics() {
[]string{"call", "status", "doc_type"}, []string{"call", "status", "doc_type"},
) )
batchSize = promauto.NewHistogram(
prometheus.HistogramOpts{
Namespace: "billing",
Subsystem: "documents",
Name: "batch_size",
Help: "Number of payment references in batch resolution requests.",
Buckets: []float64{0, 1, 2, 5, 10, 20, 50, 100, 250, 500},
},
)
documentBytes = promauto.NewHistogramVec( documentBytes = promauto.NewHistogramVec(
prometheus.HistogramOpts{ prometheus.HistogramOpts{
Namespace: "billing", Namespace: "billing",
@@ -67,18 +55,14 @@ func initMetrics() {
}) })
} }
func observeRequest(call string, docType documentsv1.DocumentType, statusLabel string, took time.Duration) { func observeRequest(call string, documentKind, statusLabel string, took time.Duration) {
typeLabel := docTypeLabel(docType) kind := docKindLabel(documentKind)
requestsTotal.WithLabelValues(call, statusLabel, typeLabel).Inc() requestsTotal.WithLabelValues(call, statusLabel, kind).Inc()
requestLatency.WithLabelValues(call, statusLabel, typeLabel).Observe(took.Seconds()) requestLatency.WithLabelValues(call, statusLabel, kind).Observe(took.Seconds())
} }
func observeBatchSize(size int) { func observeDocumentBytes(documentKind string, size int) {
batchSize.Observe(float64(size)) documentBytes.WithLabelValues(docKindLabel(documentKind)).Observe(float64(size))
}
func observeDocumentBytes(docType documentsv1.DocumentType, size int) {
documentBytes.WithLabelValues(docTypeLabel(docType)).Observe(float64(size))
} }
func statusFromError(err error) string { func statusFromError(err error) string {
@@ -100,10 +84,10 @@ func statusFromError(err error) string {
return strings.ToLower(code.String()) return strings.ToLower(code.String())
} }
func docTypeLabel(docType documentsv1.DocumentType) string { func docKindLabel(documentKind string) string {
label := docType.String() label := strings.TrimSpace(documentKind)
if label == "" { if label == "" {
return "DOCUMENT_TYPE_UNSPECIFIED" return "operation"
} }
return label return label

View File

@@ -5,11 +5,11 @@ import (
"crypto/sha256" "crypto/sha256"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"path/filepath"
"strings" "strings"
"time" "time"
"github.com/tech/sendico/billing/documents/internal/appversion" "github.com/tech/sendico/billing/documents/internal/appversion"
"github.com/tech/sendico/billing/documents/internal/content"
"github.com/tech/sendico/billing/documents/internal/docstore" "github.com/tech/sendico/billing/documents/internal/docstore"
"github.com/tech/sendico/billing/documents/renderer" "github.com/tech/sendico/billing/documents/renderer"
"github.com/tech/sendico/billing/documents/storage" "github.com/tech/sendico/billing/documents/storage"
@@ -145,94 +145,6 @@ func (s *Service) Shutdown() {
} }
} }
func (s *Service) BatchResolveDocuments(ctx context.Context, req *documentsv1.BatchResolveDocumentsRequest) (resp *documentsv1.BatchResolveDocumentsResponse, err error) {
start := time.Now()
paymentRefs := 0
if req != nil {
paymentRefs = len(req.GetPaymentRefs())
}
logger := s.logger.With(zap.Int("payment_refs", paymentRefs))
defer func() {
statusLabel := statusFromError(err)
observeRequest("batch_resolve", documentsv1.DocumentType_DOCUMENT_TYPE_UNSPECIFIED, statusLabel, time.Since(start))
observeBatchSize(paymentRefs)
itemsCount := 0
if resp != nil {
itemsCount = len(resp.GetItems())
}
fields := []zap.Field{
zap.String("status", statusLabel),
zap.Duration("duration", time.Since(start)),
zap.Int("items", itemsCount),
}
if err != nil {
logger.Warn("BatchResolveDocuments failed", append(fields, zap.Error(err))...)
return
}
logger.Info("BatchResolveDocuments finished", fields...)
}()
_ = ctx
err = status.Error(codes.Unimplemented, "payment-level document flow removed; use GetOperationDocument")
return nil, err
}
func (s *Service) GetDocument(ctx context.Context, req *documentsv1.GetDocumentRequest) (resp *documentsv1.GetDocumentResponse, err error) {
start := time.Now()
docType := documentsv1.DocumentType_DOCUMENT_TYPE_UNSPECIFIED
paymentRef := ""
if req != nil {
docType = req.GetType()
paymentRef = strings.TrimSpace(req.GetPaymentRef())
}
logger := s.logger.With(
zap.String("payment_ref", paymentRef),
zap.String("document_type", docTypeLabel(docType)),
)
defer func() {
statusLabel := statusFromError(err)
observeRequest("get_document", docType, statusLabel, time.Since(start))
if resp != nil {
observeDocumentBytes(docType, len(resp.GetContent()))
}
contentBytes := 0
if resp != nil {
contentBytes = len(resp.GetContent())
}
fields := []zap.Field{
zap.String("status", statusLabel),
zap.Duration("duration", time.Since(start)),
zap.Int("content_bytes", contentBytes),
}
if err != nil {
logger.Warn("GetDocument failed", append(fields, zap.Error(err))...)
return
}
logger.Info("GetDocument finished", fields...)
}()
_ = ctx
err = status.Error(codes.Unimplemented, "payment-level document flow removed; use GetOperationDocument")
return nil, err
}
func (s *Service) GetOperationDocument(_ context.Context, req *documentsv1.GetOperationDocumentRequest) (resp *documentsv1.GetDocumentResponse, err error) { func (s *Service) GetOperationDocument(_ context.Context, req *documentsv1.GetOperationDocumentRequest) (resp *documentsv1.GetDocumentResponse, err error) {
start := time.Now() start := time.Now()
organizationRef := "" organizationRef := ""
@@ -253,11 +165,10 @@ func (s *Service) GetOperationDocument(_ context.Context, req *documentsv1.GetOp
defer func() { defer func() {
statusLabel := statusFromError(err) statusLabel := statusFromError(err)
docType := documentsv1.DocumentType_DOCUMENT_TYPE_UNSPECIFIED observeRequest("get_operation_document", "operation", statusLabel, time.Since(start))
observeRequest("get_operation_document", docType, statusLabel, time.Since(start))
if resp != nil { if resp != nil {
observeDocumentBytes(docType, len(resp.GetContent())) observeDocumentBytes("operation", len(resp.GetContent()))
} }
contentBytes := 0 contentBytes := 0
@@ -342,12 +253,6 @@ func (e serviceError) Error() string {
return string(e) return string(e)
} }
var (
errStorageUnavailable = serviceError("documents: storage not initialised")
errDocStoreUnavailable = serviceError("documents: document store not initialised")
errTemplateUnavailable = serviceError("documents: template renderer not initialised")
)
func (s *Service) generateActPDF(snapshot model.ActSnapshot) ([]byte, string, error) { func (s *Service) generateActPDF(snapshot model.ActSnapshot) ([]byte, string, error) {
blocks, err := s.template.Render(snapshot) blocks, err := s.template.Render(snapshot)
if err != nil { if err != nil {
@@ -363,7 +268,7 @@ func (s *Service) generateOperationPDF(snapshot operationSnapshot) ([]byte, stri
func (s *Service) renderPDFWithIntegrity(blocks []renderer.Block) ([]byte, string, error) { func (s *Service) renderPDFWithIntegrity(blocks []renderer.Block) ([]byte, string, error) {
generated := renderer.Renderer{ generated := renderer.Renderer{
Issuer: s.config.Issuer, Issuer: s.config.IssuerDetails(),
OwnerPassword: s.config.Protection.OwnerPassword, OwnerPassword: s.config.Protection.OwnerPassword,
} }
@@ -427,39 +332,41 @@ func operationSnapshotFromRequest(req *documentsv1.GetOperationDocumentRequest)
} }
func buildOperationBlocks(snapshot operationSnapshot) []renderer.Block { func buildOperationBlocks(snapshot operationSnapshot) []renderer.Block {
documentCopy := content.OperationDocument
rows := [][]string{ rows := [][]string{
{"Organization", snapshot.OrganizationRef}, {documentCopy.RowOrganization, snapshot.OrganizationRef},
{"Gateway Service", snapshot.GatewayService}, {documentCopy.RowGatewayService, snapshot.GatewayService},
{"Operation Ref", snapshot.OperationRef}, {documentCopy.RowOperationRef, snapshot.OperationRef},
{"Payment Ref", safeValue(snapshot.PaymentRef)}, {documentCopy.RowPaymentRef, safeValue(snapshot.PaymentRef)},
{"Code", safeValue(snapshot.OperationCode)}, {documentCopy.RowCode, safeValue(snapshot.OperationCode)},
{"State", safeValue(snapshot.OperationState)}, {documentCopy.RowState, safeValue(snapshot.OperationState)},
{"Label", safeValue(snapshot.OperationLabel)}, {documentCopy.RowLabel, safeValue(snapshot.OperationLabel)},
{"Started At (UTC)", formatSnapshotTime(snapshot.StartedAt)}, {documentCopy.RowStartedAtUTC, formatSnapshotTime(snapshot.StartedAt)},
{"Completed At (UTC)", formatSnapshotTime(snapshot.CompletedAt)}, {documentCopy.RowCompletedAtUTC, formatSnapshotTime(snapshot.CompletedAt)},
} }
if snapshot.Amount != "" || snapshot.Currency != "" { if snapshot.Amount != "" || snapshot.Currency != "" {
rows = append(rows, []string{"Amount", strings.TrimSpace(strings.TrimSpace(snapshot.Amount) + " " + strings.TrimSpace(snapshot.Currency))}) rows = append(rows, []string{documentCopy.RowAmount, strings.TrimSpace(strings.TrimSpace(snapshot.Amount) + " " + strings.TrimSpace(snapshot.Currency))})
} }
blocks := []renderer.Block{ blocks := []renderer.Block{
{ {
Tag: renderer.TagTitle, Tag: renderer.TagTitle,
Lines: []string{"OPERATION BILLING DOCUMENT"}, Lines: []string{documentCopy.Title},
}, },
{ {
Tag: renderer.TagSubtitle, Tag: renderer.TagSubtitle,
Lines: []string{"Gateway operation statement"}, Lines: []string{documentCopy.Subtitle},
}, },
{ {
Tag: renderer.TagMeta, Tag: renderer.TagMeta,
Lines: []string{ Lines: []string{
"Document Type: Operation", documentCopy.MetaDocumentType,
}, },
}, },
{ {
Tag: renderer.TagSection, Tag: renderer.TagSection,
Lines: []string{"OPERATION DETAILS"}, Lines: []string{documentCopy.SectionOperation},
}, },
{ {
Tag: renderer.TagKV, Tag: renderer.TagKV,
@@ -469,12 +376,12 @@ func buildOperationBlocks(snapshot operationSnapshot) []renderer.Block {
if snapshot.FailureCode != "" || snapshot.FailureReason != "" { if snapshot.FailureCode != "" || snapshot.FailureReason != "" {
blocks = append(blocks, blocks = append(blocks,
renderer.Block{Tag: renderer.TagSection, Lines: []string{"FAILURE DETAILS"}}, renderer.Block{Tag: renderer.TagSection, Lines: []string{documentCopy.SectionFailure}},
renderer.Block{ renderer.Block{
Tag: renderer.TagKV, Tag: renderer.TagKV,
Rows: [][]string{ Rows: [][]string{
{"Failure Code", safeValue(snapshot.FailureCode)}, {documentCopy.RowFailureCode, safeValue(snapshot.FailureCode)},
{"Failure Reason", safeValue(snapshot.FailureReason)}, {documentCopy.RowFailureReason, safeValue(snapshot.FailureReason)},
}, },
}, },
) )
@@ -485,7 +392,7 @@ func buildOperationBlocks(snapshot operationSnapshot) []renderer.Block {
func formatSnapshotTime(value time.Time) string { func formatSnapshotTime(value time.Time) string {
if value.IsZero() { if value.IsZero() {
return "n/a" return content.OperationDocument.MissingValuePlaceholder
} }
return value.UTC().Format(time.RFC3339) return value.UTC().Format(time.RFC3339)
@@ -494,7 +401,7 @@ func formatSnapshotTime(value time.Time) string {
func safeValue(value string) string { func safeValue(value string) string {
trimmed := strings.TrimSpace(value) trimmed := strings.TrimSpace(value)
if trimmed == "" { if trimmed == "" {
return "n/a" return content.OperationDocument.MissingValuePlaceholder
} }
return trimmed return trimmed
@@ -535,50 +442,3 @@ func sanitizeFilenameComponent(value string) string {
return strings.Trim(b.String(), "_") return strings.Trim(b.String(), "_")
} }
func toProtoTypes(types []model.DocumentType) []documentsv1.DocumentType {
if len(types) == 0 {
return nil
}
result := make([]documentsv1.DocumentType, 0, len(types))
for _, t := range types {
result = append(result, t.Proto())
}
return result
}
func documentStoragePath(paymentRef string, docType documentsv1.DocumentType) string {
suffix := "document.pdf"
switch docType {
case documentsv1.DocumentType_DOCUMENT_TYPE_ACT:
suffix = "act.pdf"
case documentsv1.DocumentType_DOCUMENT_TYPE_INVOICE:
suffix = "invoice.pdf"
case documentsv1.DocumentType_DOCUMENT_TYPE_RECEIPT:
suffix = "receipt.pdf"
case documentsv1.DocumentType_DOCUMENT_TYPE_UNSPECIFIED:
// default suffix used
}
return filepath.ToSlash(filepath.Join("documents", paymentRef, suffix))
}
func documentFilename(docType documentsv1.DocumentType, paymentRef string) string {
name := "document"
switch docType {
case documentsv1.DocumentType_DOCUMENT_TYPE_ACT:
name = "act"
case documentsv1.DocumentType_DOCUMENT_TYPE_INVOICE:
name = "invoice"
case documentsv1.DocumentType_DOCUMENT_TYPE_RECEIPT:
name = "receipt"
case documentsv1.DocumentType_DOCUMENT_TYPE_UNSPECIFIED:
// default name used
}
return fmt.Sprintf("%s_%s.pdf", name, paymentRef)
}

View File

@@ -7,6 +7,7 @@ import (
"time" "time"
"github.com/shopspring/decimal" "github.com/shopspring/decimal"
"github.com/tech/sendico/billing/documents/internal/content"
"github.com/tech/sendico/billing/documents/renderer" "github.com/tech/sendico/billing/documents/renderer"
"github.com/tech/sendico/billing/documents/storage" "github.com/tech/sendico/billing/documents/storage"
"github.com/tech/sendico/billing/documents/storage/model" "github.com/tech/sendico/billing/documents/storage/model"
@@ -59,10 +60,6 @@ type memDocStore struct {
loadCount int loadCount int
} }
func newMemDocStore() *memDocStore {
return &memDocStore{data: map[string][]byte{}}
}
func (m *memDocStore) Save(_ context.Context, key string, data []byte) error { func (m *memDocStore) Save(_ context.Context, key string, data []byte) error {
m.saveCount++ m.saveCount++
copyData := make([]byte, len(data)) copyData := make([]byte, len(data))
@@ -112,15 +109,7 @@ func TestGenerateActPDF_IdempotentAndHashed(t *testing.T) {
}, },
} }
cfg := Config{
Issuer: renderer.Issuer{
LegalName: "Sendico Ltd",
LegalAddress: "12 Market Street, London, UK",
},
}
svc := NewService(zap.NewNop(), nil, nil, svc := NewService(zap.NewNop(), nil, nil,
WithConfig(cfg),
WithTemplateRenderer(tmpl), WithTemplateRenderer(tmpl),
) )
@@ -164,7 +153,7 @@ func TestGenerateActPDF_IdempotentAndHashed(t *testing.T) {
} }
func extractFooterHash(pdf []byte) string { func extractFooterHash(pdf []byte) string {
prefix := []byte("Document integrity hash: ") prefix := []byte(content.DocumentIntegrityHashPrefix)
idx := bytes.Index(pdf, prefix) idx := bytes.Index(pdf, prefix)
if idx == -1 { if idx == -1 {
@@ -191,11 +180,7 @@ func isHexDigit(b byte) bool {
} }
func TestGetOperationDocument_GeneratesPDF(t *testing.T) { func TestGetOperationDocument_GeneratesPDF(t *testing.T) {
svc := NewService(zap.NewNop(), nil, nil, WithConfig(Config{ svc := NewService(zap.NewNop(), nil, nil)
Issuer: renderer.Issuer{
LegalName: "Sendico Ltd",
},
}))
resp, err := svc.GetOperationDocument(context.Background(), &documentsv1.GetOperationDocumentRequest{ resp, err := svc.GetOperationDocument(context.Background(), &documentsv1.GetOperationDocumentRequest{
OrganizationRef: "org-1", OrganizationRef: "org-1",

View File

@@ -9,6 +9,7 @@ import (
"time" "time"
"github.com/shopspring/decimal" "github.com/shopspring/decimal"
"github.com/tech/sendico/billing/documents/internal/content"
"github.com/tech/sendico/billing/documents/renderer" "github.com/tech/sendico/billing/documents/renderer"
"github.com/tech/sendico/billing/documents/storage/model" "github.com/tech/sendico/billing/documents/storage/model"
) )
@@ -17,6 +18,11 @@ type templateRenderer struct {
tpl *template.Template tpl *template.Template
} }
type acceptanceTemplateData struct {
model.ActSnapshot
Content content.AcceptanceTemplateContent
}
func newTemplateRenderer(path string) (*templateRenderer, error) { func newTemplateRenderer(path string) (*templateRenderer, error) {
data, err := os.ReadFile(path) data, err := os.ReadFile(path)
if err != nil { if err != nil {
@@ -38,7 +44,12 @@ func newTemplateRenderer(path string) (*templateRenderer, error) {
func (r *templateRenderer) Render(snapshot model.ActSnapshot) ([]renderer.Block, error) { func (r *templateRenderer) Render(snapshot model.ActSnapshot) ([]renderer.Block, error) {
var buf bytes.Buffer var buf bytes.Buffer
if err := r.tpl.Execute(&buf, snapshot); err != nil { data := acceptanceTemplateData{
ActSnapshot: snapshot,
Content: content.AcceptanceTemplate,
}
if err := r.tpl.Execute(&buf, data); err != nil {
return nil, fmt.Errorf("execute template: %w", err) return nil, fmt.Errorf("execute template: %w", err)
} }

View File

@@ -7,6 +7,7 @@ import (
"time" "time"
"github.com/shopspring/decimal" "github.com/shopspring/decimal"
"github.com/tech/sendico/billing/documents/internal/content"
"github.com/tech/sendico/billing/documents/renderer" "github.com/tech/sendico/billing/documents/renderer"
"github.com/tech/sendico/billing/documents/storage/model" "github.com/tech/sendico/billing/documents/storage/model"
) )
@@ -42,7 +43,7 @@ func TestTemplateRenderer_Render(t *testing.T) {
t.Fatalf("expected title block") t.Fatalf("expected title block")
} }
if !slices.Contains(title.Lines, "ACT OF ACCEPTANCE OF SERVICES") { if !slices.Contains(title.Lines, content.AcceptanceTemplate.Title) {
t.Fatalf("expected title content not found") t.Fatalf("expected title content not found")
} }
@@ -54,7 +55,7 @@ func TestTemplateRenderer_Render(t *testing.T) {
foundExecutor := false foundExecutor := false
for _, row := range kv.Rows { for _, row := range kv.Rows {
if len(row) >= 2 && row[0] == "Executor" && row[1] == snapshot.ExecutorFullName { if len(row) >= 2 && row[0] == content.AcceptanceTemplate.PartyExecutorLabel && row[1] == snapshot.ExecutorFullName {
foundExecutor = true foundExecutor = true
break break

View File

@@ -6,6 +6,7 @@ import (
"strings" "strings"
"github.com/jung-kurt/gofpdf" "github.com/jung-kurt/gofpdf"
"github.com/tech/sendico/billing/documents/internal/content"
) )
const ( const (
@@ -28,7 +29,7 @@ func (r Renderer) Render(blocks []Block, footerHash string) ([]byte, error) {
pdf.SetAutoPageBreak(true, pageMarginBottom) pdf.SetAutoPageBreak(true, pageMarginBottom)
pdf.SetCompression(false) pdf.SetCompression(false)
pdf.SetAuthor(r.Issuer.LegalName, false) pdf.SetAuthor(r.Issuer.LegalName, false)
pdf.SetTitle("Act of Acceptance", false) pdf.SetTitle(content.PDFTitleActOfAcceptance, false)
owner := strings.TrimSpace(r.OwnerPassword) owner := strings.TrimSpace(r.OwnerPassword)
if owner != "" { if owner != "" {
@@ -39,7 +40,7 @@ func (r Renderer) Render(blocks []Block, footerHash string) ([]byte, error) {
pdf.SetY(-15) pdf.SetY(-15)
pdf.SetFont("Helvetica", "", 8) pdf.SetFont("Helvetica", "", 8)
footer := "Document integrity hash: " + footerHash footer := content.DocumentIntegrityHashPrefix + footerHash
pdf.CellFormat(0, 5, footer, "", 0, "L", false, 0, "") pdf.CellFormat(0, 5, footer, "", 0, "L", false, 0, "")
}) })

View File

@@ -6,6 +6,8 @@ import (
"strings" "strings"
"testing" "testing"
"unicode/utf16" "unicode/utf16"
"github.com/tech/sendico/billing/documents/internal/content"
) )
func TestRenderer_RenderContainsText(t *testing.T) { func TestRenderer_RenderContainsText(t *testing.T) {
@@ -31,7 +33,7 @@ func TestRenderer_RenderContainsText(t *testing.T) {
t.Fatalf("expected PDF bytes") t.Fatalf("expected PDF bytes")
} }
checks := []string{"Sendico Ltd", "Jane Doe", "100 USD", "Document integrity hash"} checks := []string{"Sendico Ltd", "Jane Doe", "100 USD", strings.TrimSpace(strings.TrimSuffix(content.DocumentIntegrityHashPrefix, ": "))}
for _, token := range checks { for _, token := range checks {
if !containsPDFText(pdfBytes, token) { if !containsPDFText(pdfBytes, token) {

View File

@@ -6,14 +6,13 @@ import (
"github.com/shopspring/decimal" "github.com/shopspring/decimal"
"github.com/tech/sendico/pkg/db/storable" "github.com/tech/sendico/pkg/db/storable"
documentsv1 "github.com/tech/sendico/pkg/proto/billing/documents/v1"
) )
const ( const (
DocumentRecordsCollection = "document_records" DocumentRecordsCollection = "document_records"
) )
// DocumentType mirrors the protobuf enum but stores string names for Mongo compatibility. // DocumentType represents document kinds cached in storage.
type DocumentType string type DocumentType string
const ( const (
@@ -23,24 +22,6 @@ const (
DocumentTypeReceipt DocumentType = "DOCUMENT_TYPE_RECEIPT" DocumentTypeReceipt DocumentType = "DOCUMENT_TYPE_RECEIPT"
) )
// DocumentTypeFromProto converts a protobuf enum to the storage representation.
func DocumentTypeFromProto(t documentsv1.DocumentType) DocumentType {
if name, ok := documentsv1.DocumentType_name[int32(t)]; ok {
return DocumentType(name)
}
return DocumentTypeUnspecified
}
// Proto converts the storage representation to a protobuf enum.
func (t DocumentType) Proto() documentsv1.DocumentType {
if value, ok := documentsv1.DocumentType_value[string(t)]; ok {
return documentsv1.DocumentType(value)
}
return documentsv1.DocumentType_DOCUMENT_TYPE_UNSPECIFIED
}
// ActSnapshot captures the immutable data needed to generate an acceptance act. // ActSnapshot captures the immutable data needed to generate an acceptance act.
type ActSnapshot struct { type ActSnapshot struct {
PaymentID string `bson:"paymentId" json:"paymentId"` PaymentID string `bson:"paymentId" json:"paymentId"`

View File

@@ -2,66 +2,66 @@
#title #title
ACT OF ACCEPTANCE OF SERVICES {{ .Content.Title }}
#subtitle #subtitle
under the Public Offer Agreement {{ .Content.Subtitle }}
#meta #meta
Date: {{ date .Date }} {{ .Content.MetaDateLabel }}: {{ date .Date }}
Act No: {{ .PaymentID }} {{ .Content.MetaActNumberLabel }}: {{ .PaymentID }}
#section #section
PARTIES {{ .Content.SectionParties }}
#text #text
This Act is made between the following Parties. {{ .Content.PartiesIntro }}
#kv #kv
Executor | {{ .ExecutorFullName }} {{ .Content.PartyExecutorLabel }} | {{ .ExecutorFullName }}
Status | Individual {{ .Content.PartyStatusLabel }} | {{ .Content.PartyStatusValue }}
#section #section
BASIS {{ .Content.SectionBasis }}
#text #text
This Act is issued pursuant to the Public Offer Agreement {{ .Content.BasisLine1 }}
accepted by the Executor by joining the offer. {{ .Content.BasisLine2 }}
#section #section
SERVICES RENDERED {{ .Content.SectionServicesRendered }}
#text #text
The Executor has rendered services to the Customer {{ .Content.ServicesRenderedLine1 }}
in accordance with the terms of the Public Offer Agreement. {{ .Content.ServicesRenderedLine2 }}
#section #section
REMUNERATION {{ .Content.SectionRemuneration }}
#table #table
Description | Amount {{ .Content.RemunerationHeaderDesc }} | {{ .Content.RemunerationHeaderAmount }}
Services rendered under the Public Offer Agreement | {{ money .Amount .Currency }} {{ .Content.RemunerationServicesDesc }} | {{ money .Amount .Currency }}
#section #section
CONFIRMATION {{ .Content.SectionConfirmation }}
#text #text
The Customer confirms that the services were rendered properly {{ .Content.ConfirmationLine1 }}
and accepted without any claims. {{ .Content.ConfirmationLine2 }}
The remuneration for the services was paid to the Executor {{ .Content.ConfirmationPaymentLine1 }}
using the bank card details provided by the Executor. {{ .Content.ConfirmationPaymentLine2 }}
#section #section
SIGNATURES {{ .Content.SectionSignatures }}
#sign #sign
Customer ___________________________ {{ .Content.SignatureCustomerLine }}
Executor ___________________________ {{ .Content.SignatureExecutorLine }}

View File

@@ -10,7 +10,7 @@ require (
github.com/tech/sendico/fx/oracle v0.0.0 github.com/tech/sendico/fx/oracle v0.0.0
github.com/tech/sendico/pkg v0.1.0 github.com/tech/sendico/pkg v0.1.0
go.uber.org/zap v1.27.1 go.uber.org/zap v1.27.1
google.golang.org/grpc v1.79.1 google.golang.org/grpc v1.79.2
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )

View File

@@ -210,8 +210,8 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU=
google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -44,6 +44,6 @@ require (
golang.org/x/sys v0.41.0 // indirect golang.org/x/sys v0.41.0 // indirect
golang.org/x/text v0.34.0 // indirect golang.org/x/text v0.34.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect
google.golang.org/grpc v1.79.1 // indirect google.golang.org/grpc v1.79.2 // indirect
google.golang.org/protobuf v1.36.11 // indirect google.golang.org/protobuf v1.36.11 // indirect
) )

View File

@@ -210,8 +210,8 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU=
google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -18,7 +18,7 @@ require (
github.com/aws/aws-sdk-go-v2 v1.41.3 github.com/aws/aws-sdk-go-v2 v1.41.3
github.com/aws/aws-sdk-go-v2/config v1.32.11 github.com/aws/aws-sdk-go-v2/config v1.32.11
github.com/aws/aws-sdk-go-v2/credentials v1.19.11 github.com/aws/aws-sdk-go-v2/credentials v1.19.11
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.3 github.com/aws/aws-sdk-go-v2/service/s3 v1.96.4
github.com/go-chi/chi/v5 v5.2.5 github.com/go-chi/chi/v5 v5.2.5
github.com/go-chi/cors v1.2.2 github.com/go-chi/cors v1.2.2
github.com/go-chi/jwtauth/v5 v5.4.0 github.com/go-chi/jwtauth/v5 v5.4.0
@@ -38,7 +38,7 @@ require (
go.mongodb.org/mongo-driver/v2 v2.5.0 go.mongodb.org/mongo-driver/v2 v2.5.0
go.uber.org/zap v1.27.1 go.uber.org/zap v1.27.1
golang.org/x/net v0.51.0 golang.org/x/net v0.51.0
google.golang.org/grpc v1.79.1 google.golang.org/grpc v1.79.2
google.golang.org/protobuf v1.36.11 google.golang.org/protobuf v1.36.11
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
moul.io/chizap v1.0.3 moul.io/chizap v1.0.3
@@ -59,7 +59,7 @@ require (
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.19 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.19 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.19 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.20 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.11 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.11 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19 // indirect

View File

@@ -22,8 +22,8 @@ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19 h1:AWeJMk33GTBf6J20XJ
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19/go.mod h1:+GWrYoaAsV7/4pNHpwh1kiNLXkKaSoppxQq9lbH8Ejw= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19/go.mod h1:+GWrYoaAsV7/4pNHpwh1kiNLXkKaSoppxQq9lbH8Ejw=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5 h1:clHU5fm//kWS1C2HgtgWxfQbFbx4b6rx+5jzhgX9HrI= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5 h1:clHU5fm//kWS1C2HgtgWxfQbFbx4b6rx+5jzhgX9HrI=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.19 h1:3Y4oma5TiV7tT9wa8zRcdoXwZkGz9Q/wxbEUK7cMuAM= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.20 h1:qi3e/dmpdONhj1RyIZdi6DKKpDXS5Lb8ftr3p7cyHJc=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.19/go.mod h1:V1K+TeJVD5JOk3D9e5tsX2KUdL7BlB+FV6cBhdobN8c= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.20/go.mod h1:V1K+TeJVD5JOk3D9e5tsX2KUdL7BlB+FV6cBhdobN8c=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6 h1:XAq62tBTJP/85lFD5oqOOe7YYgWxY9LvWq8plyDvDVg= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6 h1:XAq62tBTJP/85lFD5oqOOe7YYgWxY9LvWq8plyDvDVg=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.11 h1:BYf7XNsJMzl4mObARUBUib+j2tf0U//JAAtTnYqvqCw= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.11 h1:BYf7XNsJMzl4mObARUBUib+j2tf0U//JAAtTnYqvqCw=
@@ -32,8 +32,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19 h1:X1Tow7su
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19/go.mod h1:/rARO8psX+4sfjUQXp5LLifjUt8DuATZ31WptNJTyQA= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19/go.mod h1:/rARO8psX+4sfjUQXp5LLifjUt8DuATZ31WptNJTyQA=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.19 h1:JnQeStZvPHFHeyky/7LbMlyQjUa+jIBj36OlWm0pzIk= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.19 h1:JnQeStZvPHFHeyky/7LbMlyQjUa+jIBj36OlWm0pzIk=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.19/go.mod h1:HGyasyHvYdFQeJhvDHfH7HXkHh57htcJGKDZ+7z+I24= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.19/go.mod h1:HGyasyHvYdFQeJhvDHfH7HXkHh57htcJGKDZ+7z+I24=
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.3 h1:+d0SsTvxtIJt4tSJ6wr+jrxEMDa6XeupjRv8H7Qitkk= github.com/aws/aws-sdk-go-v2/service/s3 v1.96.4 h1:4ExZyubQ6LQQVuF2Qp9OsfEvsTdAWh5Gfwf6PgIdLdk=
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.3/go.mod h1:ROUNFvFWPwBlOu687WJNQ9cPvd2ccpFrnCiA1YGz50o= github.com/aws/aws-sdk-go-v2/service/s3 v1.96.4/go.mod h1:NF3JcMGOiARAss1ld3WGORCw71+4ExDD2cbbdKS5PpA=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.7 h1:Y2cAXlClHsXkkOvWZFXATr34b0hxxloeQu/pAZz2row= github.com/aws/aws-sdk-go-v2/service/signin v1.0.7 h1:Y2cAXlClHsXkkOvWZFXATr34b0hxxloeQu/pAZz2row=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.7/go.mod h1:idzZ7gmDeqeNrSPkdbtMp9qWMgcBwykA7P7Rzh5DXVU= github.com/aws/aws-sdk-go-v2/service/signin v1.0.7/go.mod h1:idzZ7gmDeqeNrSPkdbtMp9qWMgcBwykA7P7Rzh5DXVU=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.12 h1:iSsvB9EtQ09YrsmIc44Heqlx5ByGErqhPK1ZQLppias= github.com/aws/aws-sdk-go-v2/service/sso v1.30.12 h1:iSsvB9EtQ09YrsmIc44Heqlx5ByGErqhPK1ZQLppias=
@@ -403,8 +403,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171 h1:
google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171/go.mod h1:M5krXqk4GhBKvB596udGL3UyjL4I1+cTbK0orROM9ng= google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171/go.mod h1:M5krXqk4GhBKvB596udGL3UyjL4I1+cTbK0orROM9ng=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU=
google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -59,6 +59,6 @@ require (
golang.org/x/text v0.34.0 // indirect golang.org/x/text v0.34.0 // indirect
golang.org/x/time v0.14.0 // indirect golang.org/x/time v0.14.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect
google.golang.org/grpc v1.79.1 // indirect google.golang.org/grpc v1.79.2 // indirect
google.golang.org/protobuf v1.36.11 // indirect google.golang.org/protobuf v1.36.11 // indirect
) )

View File

@@ -245,8 +245,8 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU=
google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -48,6 +48,6 @@ require (
golang.org/x/sys v0.41.0 // indirect golang.org/x/sys v0.41.0 // indirect
golang.org/x/text v0.34.0 // indirect golang.org/x/text v0.34.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect
google.golang.org/grpc v1.79.1 // indirect google.golang.org/grpc v1.79.2 // indirect
google.golang.org/protobuf v1.36.11 // indirect google.golang.org/protobuf v1.36.11 // indirect
) )

View File

@@ -210,8 +210,8 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU=
google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -13,7 +13,7 @@ require (
github.com/tech/sendico/pkg v0.1.0 github.com/tech/sendico/pkg v0.1.0
go.mongodb.org/mongo-driver/v2 v2.5.0 go.mongodb.org/mongo-driver/v2 v2.5.0
go.uber.org/zap v1.27.1 go.uber.org/zap v1.27.1
google.golang.org/grpc v1.79.1 google.golang.org/grpc v1.79.2
google.golang.org/protobuf v1.36.11 google.golang.org/protobuf v1.36.11
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )

View File

@@ -210,8 +210,8 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU=
google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -0,0 +1,101 @@
# ChimeraSettle Gateway (`chsettle`)
ChimeraSettle is a dummy settlement gateway for dev/test flows.
It simulates settlement outcomes deterministically, without real fund movement.
## What It Simulates
- Fast success
- Slow success
- Immediate failure
- Timeout-like failure
- Stuck pending/processing
- Retry-like progression before success
- Deterministic chaos bucket
## How Behavior Is Chosen
Selection order:
1. Explicit scenario override from request metadata:
- `chsettle_scenario`
- `scenario` (alias)
2. Amount bucket routing based on:
- `amount_minor % 1000`
3. Hash fallback using idempotency key (if amount cannot be parsed)
## Scenario Overrides
Accepted override values (aliases supported in code):
- `fast_success`
- `slow_success`
- `fail_immediate`
- `fail_timeout`
- `stuck_pending` (also `stuck`)
- `retry_then_success`
- `webhook_delayed_success`
- `slow_then_fail`
- `partial_progress_stuck`
- `chaos`
## Amount Bucket Map (`%1000`)
| Slot range | Scenario |
|---|---|
| `000-099` | `fast_success` |
| `100-199` | `slow_success` |
| `200-299` | `fail_immediate` |
| `300-399` | `fail_timeout` |
| `400-499` | `stuck_pending` |
| `500-599` | `retry_then_success` |
| `600-699` | `webhook_delayed_success` |
| `700-799` | `slow_then_fail` |
| `800-899` | `partial_progress_stuck` |
| `900-999` | `chaos` (deterministic by idempotency key) |
## Request Usage
### Through Connector `SubmitOperation`
Use operation param:
- `scenario` (optional)
or put it inside `metadata` as:
- `chsettle_scenario`
### Through Gateway `SubmitTransfer`
Set metadata key directly:
- `chsettle_scenario`
## Dev Environment
Compose service:
- `dev-chsettle-gateway`
Ports:
- gRPC: `50080`
- metrics: `9406`
Start only this gateway:
```bash
docker compose -f docker-compose.dev.yml --env-file .env.dev up -d dev-chsettle-gateway
```
## Logging
ChimeraSettle emits:
- `info` logs for scenario decisions and transition milestones
- `warn` logs for recoverable/non-fatal errors
- `error` logs for startup-fatal failures
- detailed `debug` logs for request execution tracing

View File

@@ -11,7 +11,7 @@ require (
github.com/tech/sendico/pkg v0.1.0 github.com/tech/sendico/pkg v0.1.0
go.mongodb.org/mongo-driver/v2 v2.5.0 go.mongodb.org/mongo-driver/v2 v2.5.0
go.uber.org/zap v1.27.1 go.uber.org/zap v1.27.1
google.golang.org/grpc v1.79.1 google.golang.org/grpc v1.79.2
google.golang.org/protobuf v1.36.11 google.golang.org/protobuf v1.36.11
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )

View File

@@ -212,8 +212,8 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU=
google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -51,6 +51,6 @@ require (
golang.org/x/sync v0.19.0 // indirect golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.41.0 // indirect golang.org/x/sys v0.41.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect
google.golang.org/grpc v1.79.1 // indirect google.golang.org/grpc v1.79.2 // indirect
google.golang.org/protobuf v1.36.11 // indirect google.golang.org/protobuf v1.36.11 // indirect
) )

View File

@@ -227,8 +227,8 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU=
google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -11,7 +11,7 @@ require (
github.com/tech/sendico/pkg v0.1.0 github.com/tech/sendico/pkg v0.1.0
go.mongodb.org/mongo-driver/v2 v2.5.0 go.mongodb.org/mongo-driver/v2 v2.5.0
go.uber.org/zap v1.27.1 go.uber.org/zap v1.27.1
google.golang.org/grpc v1.79.1 google.golang.org/grpc v1.79.2
google.golang.org/protobuf v1.36.11 google.golang.org/protobuf v1.36.11
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )

View File

@@ -212,8 +212,8 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU=
google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -25,7 +25,7 @@ require (
github.com/tech/sendico/pkg v0.1.0 github.com/tech/sendico/pkg v0.1.0
go.mongodb.org/mongo-driver/v2 v2.5.0 go.mongodb.org/mongo-driver/v2 v2.5.0
go.uber.org/zap v1.27.1 go.uber.org/zap v1.27.1
google.golang.org/grpc v1.79.1 google.golang.org/grpc v1.79.2
google.golang.org/protobuf v1.36.11 google.golang.org/protobuf v1.36.11
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )

View File

@@ -213,8 +213,8 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU=
google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -19,7 +19,7 @@ require (
go.mongodb.org/mongo-driver/v2 v2.5.0 go.mongodb.org/mongo-driver/v2 v2.5.0
go.uber.org/zap v1.27.1 go.uber.org/zap v1.27.1
golang.org/x/crypto v0.48.0 golang.org/x/crypto v0.48.0
google.golang.org/grpc v1.79.1 google.golang.org/grpc v1.79.2
google.golang.org/protobuf v1.36.11 google.golang.org/protobuf v1.36.11
) )

View File

@@ -344,8 +344,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b h1:
google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:Xa7le7qx2vmqB/SzWUBa7KdMjpdpAHlh5QCSnjessQk= google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:Xa7le7qx2vmqB/SzWUBa7KdMjpdpAHlh5QCSnjessQk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU=
google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -39,6 +39,7 @@ const (
ChainTransfers Type = "chain_transfers" // Represents chain transfers ChainTransfers Type = "chain_transfers" // Represents chain transfers
ChainDeposits Type = "chain_deposits" // Represents chain deposits ChainDeposits Type = "chain_deposits" // Represents chain deposits
Callbacks Type = "callbacks" // Represents webhook callback subscriptions Callbacks Type = "callbacks" // Represents webhook callback subscriptions
ChSettle Type = "chsettle_gateway" // Represents chimera settlement gateway
Notifications Type = "notifications" // Represents notifications sent to users Notifications Type = "notifications" // Represents notifications sent to users
Organizations Type = "organizations" // Represents organizations in the system Organizations Type = "organizations" // Represents organizations in the system
Payments Type = "payments" // Represents payments service Payments Type = "payments" // Represents payments service
@@ -66,7 +67,7 @@ func StringToSType(s string) (Type, error) {
ChainTransfers, ChainDeposits, Callbacks, MntxGateway, PaymentGateway, FXOracle, FeePlans, BillingDocuments, FilterProjects, Invitations, Invoices, Logo, Ledger, ChainTransfers, ChainDeposits, Callbacks, MntxGateway, PaymentGateway, FXOracle, FeePlans, BillingDocuments, FilterProjects, Invitations, Invoices, Logo, Ledger,
LedgerAccounts, LedgerBalances, LedgerEntries, LedgerOutbox, LedgerParties, LedgerPlines, Notifications, LedgerAccounts, LedgerBalances, LedgerEntries, LedgerOutbox, LedgerParties, LedgerPlines, Notifications,
Organizations, Payments, PaymentRoutes, PaymentOrchestrator, PaymentMethods, Permissions, Policies, PolicyAssignements, Organizations, Payments, PaymentRoutes, PaymentOrchestrator, PaymentMethods, Permissions, Policies, PolicyAssignements,
Recipients, RefreshTokens, Roles, Storage, Tenants, Workflows, Discovery: Recipients, RefreshTokens, Roles, Storage, Tenants, Workflows, Discovery, ChSettle:
return Type(s), nil return Type(s), nil
default: default:
return "", merrors.InvalidArgument("invalid service type", s) return "", merrors.InvalidArgument("invalid service type", s)

View File

@@ -5,94 +5,18 @@ package billing.documents.v1;
option go_package = "github.com/tech/sendico/pkg/proto/billing/documents/v1;documentsv1"; option go_package = "github.com/tech/sendico/pkg/proto/billing/documents/v1;documentsv1";
// ---------------------------
// ENUMS
// ---------------------------
// DocumentType defines supported accounting document kinds.
enum DocumentType {
DOCUMENT_TYPE_UNSPECIFIED = 0;
// Invoice issued for the payment
DOCUMENT_TYPE_INVOICE = 1;
// Service acceptance act (common in EU/RU accounting)
DOCUMENT_TYPE_ACT = 2;
// Simple receipt confirmation
DOCUMENT_TYPE_RECEIPT = 3;
}
// --------------------------- // ---------------------------
// SERVICE // SERVICE
// --------------------------- // ---------------------------
// DocumentService provides document metadata for payment lists // DocumentService provides operation-level document generation.
// and lazy document generation on demand.
service DocumentService { service DocumentService {
// BatchResolveDocuments is used by BFF when rendering
// a page of payments. This prevents N+1 calls by resolving
// document metadata for many payments in a single request.
rpc BatchResolveDocuments(BatchResolveDocumentsRequest)
returns (BatchResolveDocumentsResponse);
// GetDocument returns the actual PDF file.
// If the document was not generated before, the service
// generates it lazily, stores it, and returns it.
rpc GetDocument(GetDocumentRequest)
returns (GetDocumentResponse);
// GetOperationDocument returns a generated PDF file for // GetOperationDocument returns a generated PDF file for
// a gateway operation snapshot provided by the caller. // a gateway operation snapshot provided by the caller.
rpc GetOperationDocument(GetOperationDocumentRequest) rpc GetOperationDocument(GetOperationDocumentRequest)
returns (GetDocumentResponse); returns (GetDocumentResponse);
} }
// ---------------------------
// BATCH RESOLVE (for payment tables)
// ---------------------------
// BatchResolveDocumentsRequest contains a list of payment references
// for which document availability should be resolved.
message BatchResolveDocumentsRequest {
repeated string payment_refs = 1;
}
// DocumentMeta describes document availability for a single payment.
message DocumentMeta {
// Payment reference
string payment_ref = 1;
// Document types that are applicable for this payment
// based on business rules and payment snapshot.
repeated DocumentType available_types = 2;
// Document types that were already generated and stored.
// Other available types will be generated lazily when requested.
repeated DocumentType ready_types = 3;
}
// BatchResolveDocumentsResponse returns metadata for all requested payments.
message BatchResolveDocumentsResponse {
repeated DocumentMeta items = 1;
}
// ---------------------------
// GET DOCUMENT (lazy generation)
// ---------------------------
// GetDocumentRequest requests a specific document for a payment.
message GetDocumentRequest {
string payment_ref = 1;
// Type of document to retrieve (invoice, act, receipt, etc.)
DocumentType type = 2;
}
// GetDocumentResponse returns the generated PDF content. // GetDocumentResponse returns the generated PDF content.
message GetDocumentResponse { message GetDocumentResponse {
// Raw PDF bytes // Raw PDF bytes

View File

@@ -16,7 +16,7 @@
- [x] Payments Orchestrator Service - [x] Payments Orchestrator Service
- [x] Chain Gateway Service - [x] Chain Gateway Service
- [x] MNTX Gateway Service - [x] MNTX Gateway Service
- [x] TGSettle Gateway Service - [x] ChimeraSettle Gateway Service
- [x] Notification Service - [x] Notification Service
- [x] BFF (Server) Service - [x] BFF (Server) Service
- [x] Frontend (Flutter Web) - [x] Frontend (Flutter Web)
@@ -36,7 +36,7 @@
- [x] ci/dev/payments-orchestrator.dockerfile - [x] ci/dev/payments-orchestrator.dockerfile
- [x] ci/dev/chain-gateway.dockerfile - [x] ci/dev/chain-gateway.dockerfile
- [x] ci/dev/mntx-gateway.dockerfile - [x] ci/dev/mntx-gateway.dockerfile
- [x] ci/dev/tgsettle-gateway.dockerfile - [x] ci/dev/chsettle-gateway.dockerfile
- [x] ci/dev/notification.dockerfile - [x] ci/dev/notification.dockerfile
- [x] ci/dev/bff.dockerfile - [x] ci/dev/bff.dockerfile
- [x] ci/dev/frontend.dockerfile - [x] ci/dev/frontend.dockerfile
@@ -93,7 +93,7 @@ Service Layer:
├─ dev-payments-orchestrator → [mongo, nats, ledger, billing-fees] ├─ dev-payments-orchestrator → [mongo, nats, ledger, billing-fees]
├─ dev-chain-gateway → [mongo, nats, discovery, vault] ├─ dev-chain-gateway → [mongo, nats, discovery, vault]
├─ dev-mntx-gateway → [nats, discovery, vault] ├─ dev-mntx-gateway → [nats, discovery, vault]
├─ dev-tgsettle-gateway → [mongo, nats, discovery, vault] ├─ dev-chsettle-gateway → [mongo, nats, discovery, vault]
├─ dev-notification → [nats] ├─ dev-notification → [nats]
├─ dev-bff → [mongo, nats, ledger, payments, chain-gateway] ├─ dev-bff → [mongo, nats, ledger, payments, chain-gateway]
└─ dev-frontend → [bff] └─ dev-frontend → [bff]
@@ -120,7 +120,7 @@ Service Layer:
### 4. Gateways ### 4. Gateways
- [ ] Chain gateway connects to Vault for keys - [ ] Chain gateway connects to Vault for keys
- [ ] MNTX gateway is reachable - [ ] MNTX gateway is reachable
- [ ] TGSettle gateway connects to Telegram - [ ] ChimeraSettle gateway is reachable and scenario routing works
### 5. Frontend ### 5. Frontend
- [ ] BFF serves API endpoints - [ ] BFF serves API endpoints
@@ -129,8 +129,8 @@ Service Layer:
## 🐛 Known Considerations ## 🐛 Known Considerations
1. **Vault Secrets**: Services using Vault (chain, mntx, tgsettle) need secrets populated 1. **Vault Secrets**: Services using Vault (chain, mntx, chsettle) need secrets populated
2. **External APIs**: MNTX and TGSettle need API credentials from Vault 2. **External APIs**: MNTX needs API credentials from Vault
3. **Blockchain**: Chain gateway needs blockchain node URLs and private keys 3. **Blockchain**: Chain gateway needs blockchain node URLs and private keys
4. **Build Time**: Frontend build takes ~5-10 minutes (Flutter compile) 4. **Build Time**: Frontend build takes ~5-10 minutes (Flutter compile)
@@ -138,7 +138,7 @@ Service Layer:
- [ ] Populate Vault with blockchain keys for Chain Gateway - [ ] Populate Vault with blockchain keys for Chain Gateway
- [ ] Add MNTX API credentials to Vault - [ ] Add MNTX API credentials to Vault
- [ ] Add TGSettle (Telegram) credentials to Vault - [ ] Validate ChimeraSettle scenario overrides in test flows
- [ ] Seed test data into MongoDB - [ ] Seed test data into MongoDB
- [ ] Configure blockchain RPC endpoints - [ ] Configure blockchain RPC endpoints
- [ ] Test full payment flow end-to-end - [ ] Test full payment flow end-to-end

View File

@@ -11,7 +11,7 @@ Docker Compose + Makefile build system for local development.
**Services:** **Services:**
- Discovery, Ledger, Billing Fees, Billing Documents, FX Oracle, Payments Orchestrator - Discovery, Ledger, Billing Fees, Billing Documents, FX Oracle, Payments Orchestrator
- Chain Gateway, MNTX Gateway, TGSettle Gateway - Chain Gateway, MNTX Gateway, ChimeraSettle Gateway
- FX Ingestor, Notification, BFF (Server), Callbacks, Frontend - FX Ingestor, Notification, BFF (Server), Callbacks, Frontend
## Quick Start ## Quick Start
@@ -59,7 +59,7 @@ make status # Check service status
Examples: Examples:
- Blockchain private keys (Chain Gateway) - Blockchain private keys (Chain Gateway)
- External API keys (MNTX, TGSettle) - External API keys (MNTX)
- Webhook signing secrets (Callbacks) - Webhook signing secrets (Callbacks)
- Production-like secrets - Production-like secrets

View File

@@ -0,0 +1,36 @@
# Development Dockerfile for chsettle-gateway Service with Air hot reload
FROM golang:alpine AS builder
RUN apk add --no-cache bash git build-base protoc protobuf-dev && \
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest && \
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest && \
go install github.com/air-verse/air@latest
WORKDIR /src
COPY api/proto ./api/proto
COPY api/pkg ./api/pkg
COPY api/gateway/common ./api/gateway/common
COPY ci/scripts/proto/generate.sh ./ci/scripts/proto/
RUN bash ci/scripts/proto/generate.sh
# Runtime stage for development with Air
FROM golang:alpine
RUN apk add --no-cache bash git build-base && \
go install github.com/air-verse/air@latest
WORKDIR /src
# Copy generated proto and pkg from builder
COPY --from=builder /src/api/proto ./api/proto
COPY --from=builder /src/api/pkg ./api/pkg
COPY --from=builder /src/api/gateway/common ./api/gateway/common
# Source code will be mounted at runtime
WORKDIR /src/api/gateway/chsettle
EXPOSE 50080 9406
CMD ["air", "-c", ".air.toml", "--", "-config.file", "/app/config.yml", "-debug"]

View File

@@ -13,10 +13,7 @@ ENV GO111MODULE=on
ENV PATH="/go/bin:${PATH}" ENV PATH="/go/bin:${PATH}"
WORKDIR /src WORKDIR /src
COPY . . COPY . .
RUN apk add --no-cache bash git build-base protoc protobuf-dev \ RUN apk add --no-cache git build-base
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@latest \
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest \
&& bash ci/scripts/proto/generate.sh
WORKDIR /src/api/edge/bff WORKDIR /src/api/edge/bff
RUN --mount=type=cache,target=/root/.cache/go-build \ RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/go/pkg/mod \

View File

@@ -13,10 +13,7 @@ ENV GO111MODULE=on
ENV PATH="/go/bin:${PATH}" ENV PATH="/go/bin:${PATH}"
WORKDIR /src WORKDIR /src
COPY . . COPY . .
RUN apk add --no-cache bash git build-base protoc protobuf-dev \ RUN apk add --no-cache git build-base
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@latest \
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest \
&& bash ci/scripts/proto/generate.sh
WORKDIR /src/api/billing/documents WORKDIR /src/api/billing/documents
RUN --mount=type=cache,target=/root/.cache/go-build \ RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/go/pkg/mod \

View File

@@ -13,10 +13,7 @@ ENV GO111MODULE=on
ENV PATH="/go/bin:${PATH}" ENV PATH="/go/bin:${PATH}"
WORKDIR /src WORKDIR /src
COPY . . COPY . .
RUN apk add --no-cache bash git build-base protoc protobuf-dev \ RUN apk add --no-cache git build-base
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@latest \
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest \
&& bash ci/scripts/proto/generate.sh
WORKDIR /src/api/billing/fees WORKDIR /src/api/billing/fees
RUN --mount=type=cache,target=/root/.cache/go-build \ RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/go/pkg/mod \

View File

@@ -13,10 +13,7 @@ ENV GO111MODULE=on
ENV PATH="/go/bin:${PATH}" ENV PATH="/go/bin:${PATH}"
WORKDIR /src WORKDIR /src
COPY . . COPY . .
RUN apk add --no-cache bash git build-base protoc protobuf-dev \ RUN apk add --no-cache git build-base
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@latest \
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest \
&& bash ci/scripts/proto/generate.sh
WORKDIR /src/api/edge/callbacks WORKDIR /src/api/edge/callbacks
RUN --mount=type=cache,target=/root/.cache/go-build \ RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/go/pkg/mod \

View File

@@ -13,10 +13,7 @@ ENV GO111MODULE=on
ENV PATH="/go/bin:${PATH}" ENV PATH="/go/bin:${PATH}"
WORKDIR /src WORKDIR /src
COPY . . COPY . .
RUN apk add --no-cache bash git build-base protoc protobuf-dev \ RUN apk add --no-cache git build-base
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@latest \
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest \
&& bash ci/scripts/proto/generate.sh
WORKDIR /src/api/gateway/chain WORKDIR /src/api/gateway/chain
RUN --mount=type=cache,target=/root/.cache/go-build \ RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/go/pkg/mod \

View File

@@ -13,10 +13,7 @@ ENV GO111MODULE=on
ENV PATH="/go/bin:${PATH}" ENV PATH="/go/bin:${PATH}"
WORKDIR /src WORKDIR /src
COPY . . COPY . .
RUN apk add --no-cache bash git build-base protoc protobuf-dev \ RUN apk add --no-cache git build-base
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@latest \
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest \
&& bash ci/scripts/proto/generate.sh
WORKDIR /src/api/discovery WORKDIR /src/api/discovery
RUN --mount=type=cache,target=/root/.cache/go-build \ RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/go/pkg/mod \

View File

@@ -13,10 +13,7 @@ ENV GO111MODULE=on
ENV PATH="/go/bin:${PATH}" ENV PATH="/go/bin:${PATH}"
WORKDIR /src WORKDIR /src
COPY . . COPY . .
RUN apk add --no-cache bash git build-base protoc protobuf-dev \ RUN apk add --no-cache git build-base
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@latest \
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest \
&& bash ci/scripts/proto/generate.sh
WORKDIR /src/api/fx/ingestor WORKDIR /src/api/fx/ingestor
RUN --mount=type=cache,target=/root/.cache/go-build \ RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/go/pkg/mod \

View File

@@ -13,10 +13,7 @@ ENV GO111MODULE=on
ENV PATH="/go/bin:${PATH}" ENV PATH="/go/bin:${PATH}"
WORKDIR /src WORKDIR /src
COPY . . COPY . .
RUN apk add --no-cache bash git build-base protoc protobuf-dev \ RUN apk add --no-cache git build-base
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@latest \
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest \
&& bash ci/scripts/proto/generate.sh
WORKDIR /src/api/fx/oracle WORKDIR /src/api/fx/oracle
RUN --mount=type=cache,target=/root/.cache/go-build \ RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/go/pkg/mod \

View File

@@ -13,10 +13,7 @@ ENV GO111MODULE=on
ENV PATH="/go/bin:${PATH}" ENV PATH="/go/bin:${PATH}"
WORKDIR /src WORKDIR /src
COPY . . COPY . .
RUN apk add --no-cache bash git build-base protoc protobuf-dev \ RUN apk add --no-cache git build-base
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@latest \
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest \
&& bash ci/scripts/proto/generate.sh
WORKDIR /src/api/ledger WORKDIR /src/api/ledger
RUN --mount=type=cache,target=/root/.cache/go-build \ RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/go/pkg/mod \

View File

@@ -13,10 +13,7 @@ ENV GO111MODULE=on
ENV PATH="/go/bin:${PATH}" ENV PATH="/go/bin:${PATH}"
WORKDIR /src WORKDIR /src
COPY . . COPY . .
RUN apk add --no-cache bash git build-base protoc protobuf-dev \ RUN apk add --no-cache git build-base
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@latest \
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest \
&& bash ci/scripts/proto/generate.sh
WORKDIR /src/api/gateway/mntx WORKDIR /src/api/gateway/mntx
RUN --mount=type=cache,target=/root/.cache/go-build \ RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/go/pkg/mod \

View File

@@ -13,10 +13,7 @@ ENV GO111MODULE=on
ENV PATH="/go/bin:${PATH}" ENV PATH="/go/bin:${PATH}"
WORKDIR /src WORKDIR /src
COPY . . COPY . .
RUN apk add --no-cache bash git build-base protoc protobuf-dev \ RUN apk add --no-cache git build-base
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@latest \
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest \
&& bash ci/scripts/proto/generate.sh
WORKDIR /src/api/notification WORKDIR /src/api/notification
RUN --mount=type=cache,target=/root/.cache/go-build \ RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/go/pkg/mod \

View File

@@ -13,10 +13,7 @@ ENV GO111MODULE=on
ENV PATH="/go/bin:${PATH}" ENV PATH="/go/bin:${PATH}"
WORKDIR /src WORKDIR /src
COPY . . COPY . .
RUN apk add --no-cache bash git build-base protoc protobuf-dev \ RUN apk add --no-cache git build-base
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@latest \
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest \
&& bash ci/scripts/proto/generate.sh
WORKDIR /src/api/payments/methods WORKDIR /src/api/payments/methods
RUN --mount=type=cache,target=/root/.cache/go-build \ RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/go/pkg/mod \

View File

@@ -13,10 +13,7 @@ ENV GO111MODULE=on
ENV PATH="/go/bin:${PATH}" ENV PATH="/go/bin:${PATH}"
WORKDIR /src WORKDIR /src
COPY . . COPY . .
RUN apk add --no-cache bash git build-base protoc protobuf-dev \ RUN apk add --no-cache git build-base
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@latest \
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest \
&& bash ci/scripts/proto/generate.sh
WORKDIR /src/api/payments/orchestrator WORKDIR /src/api/payments/orchestrator
RUN --mount=type=cache,target=/root/.cache/go-build \ RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/go/pkg/mod \

View File

@@ -13,10 +13,7 @@ ENV GO111MODULE=on
ENV PATH="/go/bin:${PATH}" ENV PATH="/go/bin:${PATH}"
WORKDIR /src WORKDIR /src
COPY . . COPY . .
RUN apk add --no-cache bash git build-base protoc protobuf-dev \ RUN apk add --no-cache git build-base
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@latest \
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest \
&& bash ci/scripts/proto/generate.sh
WORKDIR /src/api/payments/quotation WORKDIR /src/api/payments/quotation
RUN --mount=type=cache,target=/root/.cache/go-build \ RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/go/pkg/mod \

View File

@@ -13,10 +13,7 @@ ENV GO111MODULE=on
ENV PATH="/go/bin:${PATH}" ENV PATH="/go/bin:${PATH}"
WORKDIR /src WORKDIR /src
COPY . . COPY . .
RUN apk add --no-cache bash git build-base protoc protobuf-dev \ RUN apk add --no-cache git build-base
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@latest \
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest \
&& bash ci/scripts/proto/generate.sh
WORKDIR /src/api/gateway/tgsettle WORKDIR /src/api/gateway/tgsettle
RUN --mount=type=cache,target=/root/.cache/go-build \ RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/go/pkg/mod \

View File

@@ -13,10 +13,7 @@ ENV GO111MODULE=on
ENV PATH="/go/bin:${PATH}" ENV PATH="/go/bin:${PATH}"
WORKDIR /src WORKDIR /src
COPY . . COPY . .
RUN apk add --no-cache bash git build-base protoc protobuf-dev \ RUN apk add --no-cache git build-base
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@latest \
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest \
&& bash ci/scripts/proto/generate.sh
WORKDIR /src/api/gateway/tron WORKDIR /src/api/gateway/tron
RUN --mount=type=cache,target=/root/.cache/go-build \ RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/go/pkg/mod \

View File

@@ -73,6 +73,9 @@ if [ ! -d "${BUILD_CONTEXT}" ]; then
BUILD_CONTEXT="/workspace" BUILD_CONTEXT="/workspace"
fi fi
KANIKO_CACHE_REPO="${KANIKO_CACHE_REPO:-${REGISTRY_URL}/kaniko-cache}"
KANIKO_CACHE_TTL="${KANIKO_CACHE_TTL:-336h}"
/kaniko/executor \ /kaniko/executor \
--context "${BUILD_CONTEXT}" \ --context "${BUILD_CONTEXT}" \
--dockerfile "${BFF_DOCKERFILE}" \ --dockerfile "${BFF_DOCKERFILE}" \
@@ -82,4 +85,8 @@ fi
--build-arg BUILD_BRANCH="${BUILD_BRANCH}" \ --build-arg BUILD_BRANCH="${BUILD_BRANCH}" \
--build-arg BUILD_DATE="${BUILD_DATE}" \ --build-arg BUILD_DATE="${BUILD_DATE}" \
--build-arg BUILD_USER="${BUILD_USER}" \ --build-arg BUILD_USER="${BUILD_USER}" \
--single-snapshot --cache=true \
--cache-copy-layers \
--cache-run-layers \
--cache-repo "${KANIKO_CACHE_REPO}" \
--cache-ttl "${KANIKO_CACHE_TTL}"

View File

@@ -73,6 +73,9 @@ if [ ! -d "${BUILD_CONTEXT}" ]; then
BUILD_CONTEXT="/workspace" BUILD_CONTEXT="/workspace"
fi fi
KANIKO_CACHE_REPO="${KANIKO_CACHE_REPO:-${REGISTRY_URL}/kaniko-cache}"
KANIKO_CACHE_TTL="${KANIKO_CACHE_TTL:-336h}"
/kaniko/executor \ /kaniko/executor \
--context "${BUILD_CONTEXT}" \ --context "${BUILD_CONTEXT}" \
--dockerfile "${DOCUMENTS_DOCKERFILE}" \ --dockerfile "${DOCUMENTS_DOCKERFILE}" \
@@ -82,4 +85,8 @@ fi
--build-arg BUILD_BRANCH="${BUILD_BRANCH}" \ --build-arg BUILD_BRANCH="${BUILD_BRANCH}" \
--build-arg BUILD_DATE="${BUILD_DATE}" \ --build-arg BUILD_DATE="${BUILD_DATE}" \
--build-arg BUILD_USER="${BUILD_USER}" \ --build-arg BUILD_USER="${BUILD_USER}" \
--single-snapshot --cache=true \
--cache-copy-layers \
--cache-run-layers \
--cache-repo "${KANIKO_CACHE_REPO}" \
--cache-ttl "${KANIKO_CACHE_TTL}"

View File

@@ -73,6 +73,9 @@ if [ ! -d "${BUILD_CONTEXT}" ]; then
BUILD_CONTEXT="/workspace" BUILD_CONTEXT="/workspace"
fi fi
KANIKO_CACHE_REPO="${KANIKO_CACHE_REPO:-${REGISTRY_URL}/kaniko-cache}"
KANIKO_CACHE_TTL="${KANIKO_CACHE_TTL:-336h}"
/kaniko/executor \ /kaniko/executor \
--context "${BUILD_CONTEXT}" \ --context "${BUILD_CONTEXT}" \
--dockerfile "${FEES_DOCKERFILE}" \ --dockerfile "${FEES_DOCKERFILE}" \
@@ -82,4 +85,8 @@ fi
--build-arg BUILD_BRANCH="${BUILD_BRANCH}" \ --build-arg BUILD_BRANCH="${BUILD_BRANCH}" \
--build-arg BUILD_DATE="${BUILD_DATE}" \ --build-arg BUILD_DATE="${BUILD_DATE}" \
--build-arg BUILD_USER="${BUILD_USER}" \ --build-arg BUILD_USER="${BUILD_USER}" \
--single-snapshot --cache=true \
--cache-copy-layers \
--cache-run-layers \
--cache-repo "${KANIKO_CACHE_REPO}" \
--cache-ttl "${KANIKO_CACHE_TTL}"

View File

@@ -73,6 +73,9 @@ if [ ! -d "${BUILD_CONTEXT}" ]; then
BUILD_CONTEXT="/workspace" BUILD_CONTEXT="/workspace"
fi fi
KANIKO_CACHE_REPO="${KANIKO_CACHE_REPO:-${REGISTRY_URL}/kaniko-cache}"
KANIKO_CACHE_TTL="${KANIKO_CACHE_TTL:-336h}"
/kaniko/executor \ /kaniko/executor \
--context "${BUILD_CONTEXT}" \ --context "${BUILD_CONTEXT}" \
--dockerfile "${CALLBACKS_DOCKERFILE}" \ --dockerfile "${CALLBACKS_DOCKERFILE}" \
@@ -82,4 +85,8 @@ fi
--build-arg BUILD_BRANCH="${BUILD_BRANCH}" \ --build-arg BUILD_BRANCH="${BUILD_BRANCH}" \
--build-arg BUILD_DATE="${BUILD_DATE}" \ --build-arg BUILD_DATE="${BUILD_DATE}" \
--build-arg BUILD_USER="${BUILD_USER}" \ --build-arg BUILD_USER="${BUILD_USER}" \
--single-snapshot --cache=true \
--cache-copy-layers \
--cache-run-layers \
--cache-repo "${KANIKO_CACHE_REPO}" \
--cache-ttl "${KANIKO_CACHE_TTL}"

View File

@@ -90,6 +90,9 @@ if [ ! -f "${BUILD_CONTEXT}/${CHAIN_GATEWAY_DOCKERFILE}" ]; then
exit 68 exit 68
fi fi
KANIKO_CACHE_REPO="${KANIKO_CACHE_REPO:-${REGISTRY_URL}/kaniko-cache}"
KANIKO_CACHE_TTL="${KANIKO_CACHE_TTL:-336h}"
/kaniko/executor \ /kaniko/executor \
--context "${BUILD_CONTEXT}" \ --context "${BUILD_CONTEXT}" \
--dockerfile "${CHAIN_GATEWAY_DOCKERFILE}" \ --dockerfile "${CHAIN_GATEWAY_DOCKERFILE}" \
@@ -99,4 +102,8 @@ fi
--build-arg BUILD_BRANCH="${BUILD_BRANCH}" \ --build-arg BUILD_BRANCH="${BUILD_BRANCH}" \
--build-arg BUILD_DATE="${BUILD_DATE}" \ --build-arg BUILD_DATE="${BUILD_DATE}" \
--build-arg BUILD_USER="${BUILD_USER}" \ --build-arg BUILD_USER="${BUILD_USER}" \
--single-snapshot --cache=true \
--cache-copy-layers \
--cache-run-layers \
--cache-repo "${KANIKO_CACHE_REPO}" \
--cache-ttl "${KANIKO_CACHE_TTL}"

View File

@@ -73,6 +73,9 @@ if [ ! -d "${BUILD_CONTEXT}" ]; then
BUILD_CONTEXT="/workspace" BUILD_CONTEXT="/workspace"
fi fi
KANIKO_CACHE_REPO="${KANIKO_CACHE_REPO:-${REGISTRY_URL}/kaniko-cache}"
KANIKO_CACHE_TTL="${KANIKO_CACHE_TTL:-336h}"
/kaniko/executor \ /kaniko/executor \
--context "${BUILD_CONTEXT}" \ --context "${BUILD_CONTEXT}" \
--dockerfile "${DISCOVERY_DOCKERFILE}" \ --dockerfile "${DISCOVERY_DOCKERFILE}" \
@@ -82,4 +85,8 @@ fi
--build-arg BUILD_BRANCH="${BUILD_BRANCH}" \ --build-arg BUILD_BRANCH="${BUILD_BRANCH}" \
--build-arg BUILD_DATE="${BUILD_DATE}" \ --build-arg BUILD_DATE="${BUILD_DATE}" \
--build-arg BUILD_USER="${BUILD_USER}" \ --build-arg BUILD_USER="${BUILD_USER}" \
--single-snapshot --cache=true \
--cache-copy-layers \
--cache-run-layers \
--cache-repo "${KANIKO_CACHE_REPO}" \
--cache-ttl "${KANIKO_CACHE_TTL}"

View File

@@ -73,6 +73,9 @@ if [ ! -d "${BUILD_CONTEXT}" ]; then
BUILD_CONTEXT="/workspace" BUILD_CONTEXT="/workspace"
fi fi
KANIKO_CACHE_REPO="${KANIKO_CACHE_REPO:-${REGISTRY_URL}/kaniko-cache}"
KANIKO_CACHE_TTL="${KANIKO_CACHE_TTL:-336h}"
/kaniko/executor \ /kaniko/executor \
--context "${BUILD_CONTEXT}" \ --context "${BUILD_CONTEXT}" \
--dockerfile "${FRONTEND_DOCKERFILE}" \ --dockerfile "${FRONTEND_DOCKERFILE}" \
@@ -82,4 +85,8 @@ fi
--build-arg BUILD_BRANCH="${BUILD_BRANCH}" \ --build-arg BUILD_BRANCH="${BUILD_BRANCH}" \
--build-arg BUILD_DATE="${BUILD_DATE}" \ --build-arg BUILD_DATE="${BUILD_DATE}" \
--build-arg BUILD_USER="${BUILD_USER}" \ --build-arg BUILD_USER="${BUILD_USER}" \
--single-snapshot --cache=true \
--cache-copy-layers \
--cache-run-layers \
--cache-repo "${KANIKO_CACHE_REPO}" \
--cache-ttl "${KANIKO_CACHE_TTL}"

View File

@@ -73,6 +73,9 @@ if [ ! -d "${BUILD_CONTEXT}" ]; then
BUILD_CONTEXT="/workspace" BUILD_CONTEXT="/workspace"
fi fi
KANIKO_CACHE_REPO="${KANIKO_CACHE_REPO:-${REGISTRY_URL}/kaniko-cache}"
KANIKO_CACHE_TTL="${KANIKO_CACHE_TTL:-336h}"
/kaniko/executor \ /kaniko/executor \
--context "${BUILD_CONTEXT}" \ --context "${BUILD_CONTEXT}" \
--dockerfile "${FX_DOCKERFILE}" \ --dockerfile "${FX_DOCKERFILE}" \
@@ -82,4 +85,8 @@ fi
--build-arg BUILD_BRANCH="${BUILD_BRANCH}" \ --build-arg BUILD_BRANCH="${BUILD_BRANCH}" \
--build-arg BUILD_DATE="${BUILD_DATE}" \ --build-arg BUILD_DATE="${BUILD_DATE}" \
--build-arg BUILD_USER="${BUILD_USER}" \ --build-arg BUILD_USER="${BUILD_USER}" \
--single-snapshot --cache=true \
--cache-copy-layers \
--cache-run-layers \
--cache-repo "${KANIKO_CACHE_REPO}" \
--cache-ttl "${KANIKO_CACHE_TTL}"

View File

@@ -73,6 +73,9 @@ if [ ! -d "${BUILD_CONTEXT}" ]; then
BUILD_CONTEXT="/workspace" BUILD_CONTEXT="/workspace"
fi fi
KANIKO_CACHE_REPO="${KANIKO_CACHE_REPO:-${REGISTRY_URL}/kaniko-cache}"
KANIKO_CACHE_TTL="${KANIKO_CACHE_TTL:-336h}"
/kaniko/executor \ /kaniko/executor \
--context "${BUILD_CONTEXT}" \ --context "${BUILD_CONTEXT}" \
--dockerfile "${LEDGER_DOCKERFILE}" \ --dockerfile "${LEDGER_DOCKERFILE}" \
@@ -82,4 +85,8 @@ fi
--build-arg BUILD_BRANCH="${BUILD_BRANCH}" \ --build-arg BUILD_BRANCH="${BUILD_BRANCH}" \
--build-arg BUILD_DATE="${BUILD_DATE}" \ --build-arg BUILD_DATE="${BUILD_DATE}" \
--build-arg BUILD_USER="${BUILD_USER}" \ --build-arg BUILD_USER="${BUILD_USER}" \
--single-snapshot --cache=true \
--cache-copy-layers \
--cache-run-layers \
--cache-repo "${KANIKO_CACHE_REPO}" \
--cache-ttl "${KANIKO_CACHE_TTL}"

View File

@@ -90,6 +90,9 @@ if [ ! -f "${BUILD_CONTEXT}/${MNTX_GATEWAY_DOCKERFILE}" ]; then
exit 68 exit 68
fi fi
KANIKO_CACHE_REPO="${KANIKO_CACHE_REPO:-${REGISTRY_URL}/kaniko-cache}"
KANIKO_CACHE_TTL="${KANIKO_CACHE_TTL:-336h}"
/kaniko/executor \ /kaniko/executor \
--context "${BUILD_CONTEXT}" \ --context "${BUILD_CONTEXT}" \
--dockerfile "${MNTX_GATEWAY_DOCKERFILE}" \ --dockerfile "${MNTX_GATEWAY_DOCKERFILE}" \
@@ -99,4 +102,8 @@ fi
--build-arg BUILD_BRANCH="${BUILD_BRANCH}" \ --build-arg BUILD_BRANCH="${BUILD_BRANCH}" \
--build-arg BUILD_DATE="${BUILD_DATE}" \ --build-arg BUILD_DATE="${BUILD_DATE}" \
--build-arg BUILD_USER="${BUILD_USER}" \ --build-arg BUILD_USER="${BUILD_USER}" \
--single-snapshot --cache=true \
--cache-copy-layers \
--cache-run-layers \
--cache-repo "${KANIKO_CACHE_REPO}" \
--cache-ttl "${KANIKO_CACHE_TTL}"

View File

@@ -73,6 +73,9 @@ if [ ! -d "${BUILD_CONTEXT}" ]; then
BUILD_CONTEXT="/workspace" BUILD_CONTEXT="/workspace"
fi fi
KANIKO_CACHE_REPO="${KANIKO_CACHE_REPO:-${REGISTRY_URL}/kaniko-cache}"
KANIKO_CACHE_TTL="${KANIKO_CACHE_TTL:-336h}"
/kaniko/executor \ /kaniko/executor \
--context "${BUILD_CONTEXT}" \ --context "${BUILD_CONTEXT}" \
--dockerfile "${NOTIFICATION_DOCKERFILE}" \ --dockerfile "${NOTIFICATION_DOCKERFILE}" \
@@ -82,4 +85,8 @@ fi
--build-arg BUILD_BRANCH="${BUILD_BRANCH}" \ --build-arg BUILD_BRANCH="${BUILD_BRANCH}" \
--build-arg BUILD_DATE="${BUILD_DATE}" \ --build-arg BUILD_DATE="${BUILD_DATE}" \
--build-arg BUILD_USER="${BUILD_USER}" \ --build-arg BUILD_USER="${BUILD_USER}" \
--single-snapshot --cache=true \
--cache-copy-layers \
--cache-run-layers \
--cache-repo "${KANIKO_CACHE_REPO}" \
--cache-ttl "${KANIKO_CACHE_TTL}"

View File

@@ -73,6 +73,9 @@ if [ ! -d "${BUILD_CONTEXT}" ]; then
BUILD_CONTEXT="/workspace" BUILD_CONTEXT="/workspace"
fi fi
KANIKO_CACHE_REPO="${KANIKO_CACHE_REPO:-${REGISTRY_URL}/kaniko-cache}"
KANIKO_CACHE_TTL="${KANIKO_CACHE_TTL:-336h}"
/kaniko/executor \ /kaniko/executor \
--context "${BUILD_CONTEXT}" \ --context "${BUILD_CONTEXT}" \
--dockerfile "${PAYMENTS_METHODS_DOCKERFILE}" \ --dockerfile "${PAYMENTS_METHODS_DOCKERFILE}" \
@@ -82,4 +85,8 @@ fi
--build-arg BUILD_BRANCH="${BUILD_BRANCH}" \ --build-arg BUILD_BRANCH="${BUILD_BRANCH}" \
--build-arg BUILD_DATE="${BUILD_DATE}" \ --build-arg BUILD_DATE="${BUILD_DATE}" \
--build-arg BUILD_USER="${BUILD_USER}" \ --build-arg BUILD_USER="${BUILD_USER}" \
--single-snapshot --cache=true \
--cache-copy-layers \
--cache-run-layers \
--cache-repo "${KANIKO_CACHE_REPO}" \
--cache-ttl "${KANIKO_CACHE_TTL}"

View File

@@ -73,6 +73,9 @@ if [ ! -d "${BUILD_CONTEXT}" ]; then
BUILD_CONTEXT="/workspace" BUILD_CONTEXT="/workspace"
fi fi
KANIKO_CACHE_REPO="${KANIKO_CACHE_REPO:-${REGISTRY_URL}/kaniko-cache}"
KANIKO_CACHE_TTL="${KANIKO_CACHE_TTL:-336h}"
/kaniko/executor \ /kaniko/executor \
--context "${BUILD_CONTEXT}" \ --context "${BUILD_CONTEXT}" \
--dockerfile "${PAYMENTS_DOCKERFILE}" \ --dockerfile "${PAYMENTS_DOCKERFILE}" \
@@ -82,4 +85,8 @@ fi
--build-arg BUILD_BRANCH="${BUILD_BRANCH}" \ --build-arg BUILD_BRANCH="${BUILD_BRANCH}" \
--build-arg BUILD_DATE="${BUILD_DATE}" \ --build-arg BUILD_DATE="${BUILD_DATE}" \
--build-arg BUILD_USER="${BUILD_USER}" \ --build-arg BUILD_USER="${BUILD_USER}" \
--single-snapshot --cache=true \
--cache-copy-layers \
--cache-run-layers \
--cache-repo "${KANIKO_CACHE_REPO}" \
--cache-ttl "${KANIKO_CACHE_TTL}"

View File

@@ -73,6 +73,9 @@ if [ ! -d "${BUILD_CONTEXT}" ]; then
BUILD_CONTEXT="/workspace" BUILD_CONTEXT="/workspace"
fi fi
KANIKO_CACHE_REPO="${KANIKO_CACHE_REPO:-${REGISTRY_URL}/kaniko-cache}"
KANIKO_CACHE_TTL="${KANIKO_CACHE_TTL:-336h}"
/kaniko/executor \ /kaniko/executor \
--context "${BUILD_CONTEXT}" \ --context "${BUILD_CONTEXT}" \
--dockerfile "${PAYMENTS_QUOTATION_DOCKERFILE}" \ --dockerfile "${PAYMENTS_QUOTATION_DOCKERFILE}" \
@@ -82,4 +85,8 @@ fi
--build-arg BUILD_BRANCH="${BUILD_BRANCH}" \ --build-arg BUILD_BRANCH="${BUILD_BRANCH}" \
--build-arg BUILD_DATE="${BUILD_DATE}" \ --build-arg BUILD_DATE="${BUILD_DATE}" \
--build-arg BUILD_USER="${BUILD_USER}" \ --build-arg BUILD_USER="${BUILD_USER}" \
--single-snapshot --cache=true \
--cache-copy-layers \
--cache-run-layers \
--cache-repo "${KANIKO_CACHE_REPO}" \
--cache-ttl "${KANIKO_CACHE_TTL}"

View File

@@ -90,6 +90,9 @@ if [ ! -f "${BUILD_CONTEXT}/${TGSETTLE_GATEWAY_DOCKERFILE}" ]; then
exit 68 exit 68
fi fi
KANIKO_CACHE_REPO="${KANIKO_CACHE_REPO:-${REGISTRY_URL}/kaniko-cache}"
KANIKO_CACHE_TTL="${KANIKO_CACHE_TTL:-336h}"
/kaniko/executor \ /kaniko/executor \
--context "${BUILD_CONTEXT}" \ --context "${BUILD_CONTEXT}" \
--dockerfile "${TGSETTLE_GATEWAY_DOCKERFILE}" \ --dockerfile "${TGSETTLE_GATEWAY_DOCKERFILE}" \
@@ -99,4 +102,8 @@ fi
--build-arg BUILD_BRANCH="${BUILD_BRANCH}" \ --build-arg BUILD_BRANCH="${BUILD_BRANCH}" \
--build-arg BUILD_DATE="${BUILD_DATE}" \ --build-arg BUILD_DATE="${BUILD_DATE}" \
--build-arg BUILD_USER="${BUILD_USER}" \ --build-arg BUILD_USER="${BUILD_USER}" \
--single-snapshot --cache=true \
--cache-copy-layers \
--cache-run-layers \
--cache-repo "${KANIKO_CACHE_REPO}" \
--cache-ttl "${KANIKO_CACHE_TTL}"

View File

@@ -90,6 +90,9 @@ if [ ! -f "${BUILD_CONTEXT}/${TRON_GATEWAY_DOCKERFILE}" ]; then
exit 68 exit 68
fi fi
KANIKO_CACHE_REPO="${KANIKO_CACHE_REPO:-${REGISTRY_URL}/kaniko-cache}"
KANIKO_CACHE_TTL="${KANIKO_CACHE_TTL:-336h}"
/kaniko/executor \ /kaniko/executor \
--context "${BUILD_CONTEXT}" \ --context "${BUILD_CONTEXT}" \
--dockerfile "${TRON_GATEWAY_DOCKERFILE}" \ --dockerfile "${TRON_GATEWAY_DOCKERFILE}" \
@@ -99,4 +102,8 @@ fi
--build-arg BUILD_BRANCH="${BUILD_BRANCH}" \ --build-arg BUILD_BRANCH="${BUILD_BRANCH}" \
--build-arg BUILD_DATE="${BUILD_DATE}" \ --build-arg BUILD_DATE="${BUILD_DATE}" \
--build-arg BUILD_USER="${BUILD_USER}" \ --build-arg BUILD_USER="${BUILD_USER}" \
--single-snapshot --cache=true \
--cache-copy-layers \
--cache-run-layers \
--cache-repo "${KANIKO_CACHE_REPO}" \
--cache-ttl "${KANIKO_CACHE_TTL}"

View File

@@ -779,15 +779,15 @@ services:
VAULT_ADDR: ${VAULT_ADDR} VAULT_ADDR: ${VAULT_ADDR}
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# TGSettle Gateway Service (Telegram settlements) # ChimeraSettle Gateway Service (simulated settlements)
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
dev-tgsettle-gateway: dev-chsettle-gateway:
<<: *common-env <<: *common-env
build: build:
context: . context: .
dockerfile: ci/dev/tgsettle-gateway.dockerfile dockerfile: ci/dev/chsettle-gateway.dockerfile
image: sendico-dev/tgsettle-gateway:latest image: sendico-dev/chsettle-gateway:latest
container_name: dev-tgsettle-gateway container_name: dev-chsettle-gateway
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
dev-mongo-init: { condition: service_completed_successfully } dev-mongo-init: { condition: service_completed_successfully }
@@ -795,29 +795,29 @@ services:
dev-discovery: { condition: service_started } dev-discovery: { condition: service_started }
dev-vault: { condition: service_healthy } dev-vault: { condition: service_healthy }
volumes: volumes:
- ./api/gateway/tgsettle:/src/api/gateway/tgsettle - ./api/gateway/chsettle:/src/api/gateway/chsettle
- ./api/gateway/common:/src/api/gateway/common - ./api/gateway/common:/src/api/gateway/common
- ./api/gateway/tgsettle/config.dev.yml:/app/config.yml:ro - ./api/gateway/chsettle/config.dev.yml:/app/config.yml:ro
ports: ports:
- "50080:50080" - "50080:50080"
- "9406:9406" - "9406:9406"
networks: networks:
- sendico-dev - sendico-dev
environment: environment:
TGSETTLE_GATEWAY_MONGO_HOST: dev-mongo-1 CHSETTLE_GATEWAY_MONGO_HOST: dev-mongo-1
TGSETTLE_GATEWAY_MONGO_PORT: 27017 CHSETTLE_GATEWAY_MONGO_PORT: 27017
TGSETTLE_GATEWAY_MONGO_DATABASE: tgsettle_gateway CHSETTLE_GATEWAY_MONGO_DATABASE: chsettle_gateway
TGSETTLE_GATEWAY_MONGO_USER: ${MONGO_USER} CHSETTLE_GATEWAY_MONGO_USER: ${MONGO_USER}
TGSETTLE_GATEWAY_MONGO_PASSWORD: ${MONGO_PASSWORD} CHSETTLE_GATEWAY_MONGO_PASSWORD: ${MONGO_PASSWORD}
TGSETTLE_GATEWAY_MONGO_AUTH_SOURCE: admin CHSETTLE_GATEWAY_MONGO_AUTH_SOURCE: admin
TGSETTLE_GATEWAY_MONGO_REPLICA_SET: dev-rs CHSETTLE_GATEWAY_MONGO_REPLICA_SET: dev-rs
NATS_HOST: dev-nats NATS_HOST: dev-nats
NATS_PORT: 4222 NATS_PORT: 4222
NATS_USER: ${NATS_USER} NATS_USER: ${NATS_USER}
NATS_PASSWORD: ${NATS_PASSWORD} NATS_PASSWORD: ${NATS_PASSWORD}
NATS_URL: nats://${NATS_USER}:${NATS_PASSWORD}@dev-nats:4222 NATS_URL: nats://${NATS_USER}:${NATS_PASSWORD}@dev-nats:4222
TGSETTLE_GATEWAY_GRPC_PORT: 50080 CHSETTLE_GATEWAY_GRPC_PORT: 50080
TGSETTLE_GATEWAY_METRICS_PORT: 9406 CHSETTLE_GATEWAY_METRICS_PORT: 9406
VAULT_ADDR: ${VAULT_ADDR} VAULT_ADDR: ${VAULT_ADDR}
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------