Files
aml/cmd/amld/main.go
T
zeekayandHanzo Dev 07e69e3ee2 luxfi/aml — real-time AML/CFT transaction monitoring
A Go AML engine: a configurable rules DSL over expr-lang with weight-of-evidence
scoring, sanctions screening against OFAC/UN/EU/HMT, case management, and scored
alerting. Single binary, embedded SQLite per org, embedded UI.

Surface (all /v1, org-scoped):
  /v1/aml/transactions        ingest and score
  /v1/aml/rules  /rules/test  the rules DSL and its dry-run
  /v1/aml/sanctions/search    list screening
  /v1/aml/cases               investigation workflow
  /v1/aml/health

Build: make build produces one static binary with the UI embedded (embedui tag);
bare Go tooling needs no Node. Third-party license and notice texts are generated
from the module graph the linker actually walks and ship beside every artifact.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-28 22:51:25 -07:00

95 lines
2.2 KiB
Go

// amld is the AML engine daemon. It provides real-time transaction monitoring,
// sanctions screening, case management, and webhook delivery.
//
// Usage:
//
// amld serve Start the HTTP server
// amld version Print version
package main
import (
"fmt"
"os"
"github.com/hanzoai/base"
"github.com/hanzoai/base/apis"
"github.com/hanzoai/base/core"
"github.com/hanzoai/base/tools/hook"
"github.com/spf13/cobra"
"github.com/luxfi/aml/pkg/api"
"github.com/luxfi/aml/pkg/cases"
"github.com/luxfi/aml/pkg/engine"
"github.com/luxfi/aml/pkg/rules"
"github.com/luxfi/aml/pkg/sanctions"
uiaml "github.com/luxfi/aml/ui"
)
var version = "(dev)"
func main() {
app := base.New()
var serveCmd *cobra.Command
for _, c := range app.RootCmd.Commands() {
if c.Use == "serve" {
serveCmd = c
break
}
}
// Wire AML engine into Base's serve lifecycle.
defaultOrg := os.Getenv("AML_DEFAULT_ORG")
if defaultOrg == "" {
defaultOrg = "default"
}
starterRules := rules.StarterRules(defaultOrg)
eng := engine.New(starterRules)
caseStore := cases.NewStore()
alertStore := api.NewAlertStore()
sanctionsStore := api.NewSanctionsStore()
handler := &api.Handler{
Engine: eng,
Cases: caseStore,
Alerts: alertStore,
Sanctions: sanctionsStore,
}
app.OnServe().Bind(&hook.Handler[*core.ServeEvent]{
Func: func(se *core.ServeEvent) error {
// Wire TransactionStore (Base-backed) into engine helpers.
txStore := engine.NewBaseStore(app)
engine.RegisterStoreHelpers(eng, txStore)
// Wire SanctionsStore (Base-backed) and register refresh cron.
baseSanctionsStore := sanctions.NewBaseSanctionsStore(app)
sanctions.RefreshCron(app, baseSanctionsStore)
handler.Register(se)
// Mount embedded admin UI at /_/aml/
se.Router.GET("/_/aml/{path...}", apis.Static(uiaml.DistDirFS(), true))
return se.Next()
},
})
// Add version subcommand.
app.RootCmd.AddCommand(&cobra.Command{
Use: "version",
Short: "Print version",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("amld", version)
},
})
_ = serveCmd // Base already provides "serve" — we just hook into it.
if err := app.Start(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}