compliance

package
v1.6.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 29, 2026 License: AGPL-3.0 Imports: 9 Imported by: 0

Documentation

Overview

Package compliance orchestrates the KYB lifecycle described in elliptic-compliance-integration.md §13: a counterparty submits an address, KYB approval triggers screening via pkg/compliance.Screener, and the verdict is applied to pkg/repository.CounterpartyRepository's three tables.

This is core-owned end to end — unlike pkg/services/mgpoller, which splits its interfaces because MoneyGram's flow touches credit-owned loans, nothing here reaches outside core, so there is no adapter indirection to a credit-side implementation.

Scope for this pass (Phase 2 of the source design doc): persistence and the lifecycle service. It does not submit the vault contract's allow_depositor transaction — see RecordScreening's doc comment on why that stays a separate, not-yet-built worker.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidAddress is a submitted address that isn't a well-formed
	// Stellar Ed25519 public key — rejected before any Elliptic call.
	ErrInvalidAddress = errors.New("address is not a valid stellar public key")

	// ErrCounterpartyMissing means an address's counterparty association
	// could not be loaded — should not happen given the foreign key, but
	// screening needs the counterparty's elliptic_customer_reference, so
	// this is checked explicitly rather than trusting a nil pointer.
	ErrCounterpartyMissing = errors.New("address has no associated counterparty")
)

Functions

This section is empty.

Types

type Deps

type Deps struct {
	Repo              repository.CounterpartyRepository
	Screener          pkgcompliance.Screener
	ScreeningValidity time.Duration
	Logger            *slog.Logger
}

Deps are Service's collaborators; all required except Logger and ScreeningValidity.

type OnchainSigner

type OnchainSigner interface {
	AllowDepositor(ctx context.Context, address string) error
	DisallowDepositor(ctx context.Context, address string) error
}

OnchainSigner is the two vault-contract calls the writer needs — narrow enough that soroban.Service satisfies it directly, and tests can fake it without a real signing key. See soroban.Service.WithComplianceRole's doc comment on why these calls need the compliance role key, not the admin key the rest of this backend already holds.

type OnchainWriter

type OnchainWriter struct {
	// contains filtered or unexported fields
}

OnchainWriter is the separate worker the source design doc §14 calls for: "the admin writes intent to counterparty_addresses and a separate worker performs the on-chain write and reconciles onchain_state — which keeps signing keys out of the web process." It runs in the credit backend (which already holds the treasury/admin keys), not cmd/admin.

func NewOnchainWriter

func NewOnchainWriter(deps OnchainWriterDeps) *OnchainWriter

NewOnchainWriter builds the worker.

func (*OnchainWriter) Start

func (w *OnchainWriter) Start(ctx context.Context)

Start runs the write loop until ctx is cancelled — the same tick-immediately-then-on-interval shape as every other ticker in this codebase (pkg/services/mpesapoller, pkg/services/vaultwatch).

type OnchainWriterDeps

type OnchainWriterDeps struct {
	Repo     repository.CounterpartyRepository
	Signer   OnchainSigner
	Interval time.Duration
	Logger   *slog.Logger
}

OnchainWriterDeps are OnchainWriter's collaborators; all required except Logger.

type RescreenSweep

type RescreenSweep struct {
	// contains filtered or unexported fields
}

RescreenSweep is the source design doc §6's "our own sweep": neither of Elliptic's own rescreening mechanisms (three rescreens over a window, or retries on a failed call) amount to standing monitoring, so an allowlist that gates money needs its own scheduled walk of every address whose screening has gone stale.

Unlike a batch-endpoint sweep, this reuses Service.ScreenAndRecord one address at a time — Phase 1 deliberately didn't build the POST /v2/wallet batch endpoint (out of scope, see pkg/compliance/elliptic doc.go), and at this volume the sync endpoint in a loop costs nothing extra worth a second client code path for.

func NewRescreenSweep

func NewRescreenSweep(deps RescreenSweepDeps) *RescreenSweep

NewRescreenSweep builds the sweep.

func (*RescreenSweep) Start

func (s *RescreenSweep) Start(ctx context.Context)

Start runs the sweep until ctx is cancelled — the same shape as every other ticker in this codebase.

type RescreenSweepDeps

type RescreenSweepDeps struct {
	Repo     repository.CounterpartyRepository
	Service  *Service
	Interval time.Duration
	Logger   *slog.Logger
}

RescreenSweepDeps are RescreenSweep's collaborators; all required except Logger.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service runs the KYB lifecycle described in doc.go.

func NewService

func NewService(deps Deps) *Service

NewService builds the lifecycle service.

func (*Service) ApproveKYB

func (s *Service) ApproveKYB(ctx context.Context, counterpartyID, actor string) error

ApproveKYB approves the counterparty's KYB status, then screens every address already on file — source design doc §13 step 3.

func (*Service) ScreenAndRecord

func (s *Service) ScreenAndRecord(ctx context.Context, addressID string) error

ScreenAndRecord is the core operation: screen one address via pkg/compliance.Screener and apply the source design doc §13 step 4 / §10 verdict branches. Also the admin's "rescreen now" action — screening is idempotent to call again, and address_screenings is append-only, so a manual rescreen is simply another call to this with no separate path.

func (*Service) SubmitAddress

func (s *Service) SubmitAddress(ctx context.Context, counterpartyID, address string) (*models.CounterpartyAddress, error)

SubmitAddress validates address locally before writing anything — "a typo should not cost an API call" (source design doc §13 step 1) — then records it. If the counterparty's KYB is already approved, it is screened immediately; otherwise it waits at AddressStatusPending until ApproveKYB screens it.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL