fixed rail & operation names

This commit is contained in:
Stephan D
2026-02-27 02:33:40 +01:00
parent 82cf91e703
commit 747153bdbf
73 changed files with 877 additions and 667 deletions

View File

@@ -5,6 +5,7 @@ import (
"crypto/sha256"
"encoding/hex"
"errors"
"github.com/tech/sendico/pkg/discovery"
"sort"
"strconv"
"strings"
@@ -375,11 +376,11 @@ func routeContainsCardPayout(snapshot *model.PaymentQuoteSnapshot) bool {
if hop == nil {
continue
}
if model.ParseRail(hop.Rail) == model.RailCardPayout {
if model.ParseRail(hop.Rail) == discovery.RailCardPayout {
return true
}
}
if model.ParseRail(snapshot.Route.Rail) == model.RailCardPayout {
if model.ParseRail(snapshot.Route.Rail) == discovery.RailCardPayout {
return true
}
return false

View File

@@ -3,6 +3,7 @@ package sexec
import (
"github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/xplan"
"github.com/tech/sendico/payments/storage/model"
"github.com/tech/sendico/pkg/discovery"
)
type route int
@@ -26,28 +27,28 @@ func classifyRoute(step xplan.Step) route {
rail := normalizeRail(step.Rail)
switch action {
case model.RailOperationObserveConfirm:
case discovery.RailOperationObserveConfirm:
return routeObserveConfirm
case model.RailOperationSend:
case discovery.RailOperationSend:
switch rail {
case model.RailCrypto:
case discovery.RailCrypto:
return routeCrypto
case model.RailCardPayout:
case discovery.RailCardPayout:
return routeCardPayout
default:
return routeUnknown
}
case model.RailOperationFXConvert:
case discovery.RailOperationFXConvert:
switch rail {
case model.RailProviderSettlement:
case discovery.RailProviderSettlement:
return routeProviderSettlement
case model.RailLedger:
case discovery.RailLedger:
return routeLedger
default:
return routeUnknown
}
case model.RailOperationFee:
if rail == model.RailCrypto {
case discovery.RailOperationFee:
if rail == discovery.RailCrypto {
return routeCrypto
}
return routeUnknown
@@ -65,13 +66,13 @@ func isGuardStep(step xplan.Step) bool {
func isLedgerAction(action model.RailOperation) bool {
switch action {
case model.RailOperationDebit,
model.RailOperationCredit,
model.RailOperationExternalDebit,
model.RailOperationExternalCredit,
model.RailOperationMove,
model.RailOperationBlock,
model.RailOperationRelease:
case discovery.RailOperationDebit,
discovery.RailOperationCredit,
discovery.RailOperationExternalDebit,
discovery.RailOperationExternalCredit,
discovery.RailOperationMove,
discovery.RailOperationBlock,
discovery.RailOperationRelease:
return true
default:
return false

View File

@@ -3,12 +3,12 @@ package sexec
import (
"context"
"errors"
"github.com/tech/sendico/pkg/discovery"
"strings"
"testing"
"github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/agg"
"github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/xplan"
"github.com/tech/sendico/payments/storage/model"
"github.com/tech/sendico/pkg/merrors"
)
@@ -18,7 +18,7 @@ func TestExecute_DispatchLedger(t *testing.T) {
out, err := registry.Execute(context.Background(), ExecuteInput{
Payment: &agg.Payment{PaymentRef: "p1"},
Step: xplan.Step{StepRef: "s1", StepCode: "ledger.debit", Action: model.RailOperationDebit, Rail: model.RailLedger},
Step: xplan.Step{StepRef: "s1", StepCode: "ledger.debit", Action: discovery.RailOperationDebit, Rail: discovery.RailLedger},
StepExecution: agg.StepExecution{},
})
if err != nil {
@@ -58,7 +58,7 @@ func TestExecute_DispatchRailsAndObserve(t *testing.T) {
{
name: "send crypto",
step: xplan.Step{
StepRef: "s1", StepCode: "crypto.send", Action: model.RailOperationSend, Rail: model.RailCrypto,
StepRef: "s1", StepCode: "crypto.send", Action: discovery.RailOperationSend, Rail: discovery.RailCrypto,
},
wantCalls: func(t *testing.T) {
t.Helper()
@@ -70,7 +70,7 @@ func TestExecute_DispatchRailsAndObserve(t *testing.T) {
{
name: "fx convert provider settlement",
step: xplan.Step{
StepRef: "s2", StepCode: "provider.fx_convert", Action: model.RailOperationFXConvert, Rail: model.RailProviderSettlement,
StepRef: "s2", StepCode: "provider.fx_convert", Action: discovery.RailOperationFXConvert, Rail: discovery.RailProviderSettlement,
},
wantCalls: func(t *testing.T) {
t.Helper()
@@ -82,7 +82,7 @@ func TestExecute_DispatchRailsAndObserve(t *testing.T) {
{
name: "send card payout",
step: xplan.Step{
StepRef: "s3", StepCode: "card.send", Action: model.RailOperationSend, Rail: model.RailCardPayout,
StepRef: "s3", StepCode: "card.send", Action: discovery.RailOperationSend, Rail: discovery.RailCardPayout,
},
wantCalls: func(t *testing.T) {
t.Helper()
@@ -94,7 +94,7 @@ func TestExecute_DispatchRailsAndObserve(t *testing.T) {
{
name: "observe confirm",
step: xplan.Step{
StepRef: "s4", StepCode: "observe", Action: model.RailOperationObserveConfirm, Rail: model.RailCardPayout,
StepRef: "s4", StepCode: "observe", Action: discovery.RailOperationObserveConfirm, Rail: discovery.RailCardPayout,
},
wantCalls: func(t *testing.T) {
t.Helper()
@@ -106,7 +106,7 @@ func TestExecute_DispatchRailsAndObserve(t *testing.T) {
{
name: "crypto fee",
step: xplan.Step{
StepRef: "s5", StepCode: "crypto.fee", Action: model.RailOperationFee, Rail: model.RailCrypto,
StepRef: "s5", StepCode: "crypto.fee", Action: discovery.RailOperationFee, Rail: discovery.RailCrypto,
},
wantCalls: func(t *testing.T) {
t.Helper()
@@ -142,8 +142,8 @@ func TestExecute_DispatchGuard(t *testing.T) {
StepRef: xplan.QuoteReadinessGuardStepRef,
StepCode: string(xplan.GuardOperationQuoteReadinessGuard),
Kind: xplan.StepKindLiquidityCheck,
Action: model.RailOperationUnspecified,
Rail: model.RailUnspecified,
Action: discovery.RailOperationUnspecified,
Rail: discovery.RailUnspecified,
DependsOn: nil,
},
StepExecution: agg.StepExecution{
@@ -171,7 +171,7 @@ func TestExecute_UnsupportedStep(t *testing.T) {
_, err := registry.Execute(context.Background(), ExecuteInput{
Payment: &agg.Payment{PaymentRef: "p1"},
Step: xplan.Step{StepRef: "s1", StepCode: "bad.send", Action: model.RailOperationSend, Rail: model.RailLedger},
Step: xplan.Step{StepRef: "s1", StepCode: "bad.send", Action: discovery.RailOperationSend, Rail: discovery.RailLedger},
StepExecution: agg.StepExecution{StepRef: "s1", StepCode: "bad.send", Attempt: 1},
})
if !errors.Is(err, ErrUnsupportedStep) {
@@ -199,7 +199,7 @@ func TestExecute_UnsupportedProviderSettlementSend(t *testing.T) {
_, err := registry.Execute(context.Background(), ExecuteInput{
Payment: &agg.Payment{PaymentRef: "p1"},
Step: xplan.Step{StepRef: "s1", StepCode: "provider.send", Action: model.RailOperationSend, Rail: model.RailProviderSettlement},
Step: xplan.Step{StepRef: "s1", StepCode: "provider.send", Action: discovery.RailOperationSend, Rail: discovery.RailProviderSettlement},
StepExecution: agg.StepExecution{StepRef: "s1", StepCode: "provider.send", Attempt: 1},
})
if !errors.Is(err, ErrUnsupportedStep) {
@@ -212,7 +212,7 @@ func TestExecute_MissingExecutor(t *testing.T) {
_, err := registry.Execute(context.Background(), ExecuteInput{
Payment: &agg.Payment{PaymentRef: "p1"},
Step: xplan.Step{StepRef: "s1", StepCode: "crypto.send", Action: model.RailOperationSend, Rail: model.RailCrypto},
Step: xplan.Step{StepRef: "s1", StepCode: "crypto.send", Action: discovery.RailOperationSend, Rail: discovery.RailCrypto},
StepExecution: agg.StepExecution{StepRef: "s1", StepCode: "crypto.send", Attempt: 1},
})
if !errors.Is(err, ErrMissingExecutor) {
@@ -231,21 +231,21 @@ func TestExecute_ValidationErrors(t *testing.T) {
{
name: "missing payment",
in: ExecuteInput{
Step: xplan.Step{StepRef: "s1", Action: model.RailOperationDebit},
Step: xplan.Step{StepRef: "s1", Action: discovery.RailOperationDebit},
},
},
{
name: "missing step ref",
in: ExecuteInput{
Payment: &agg.Payment{},
Step: xplan.Step{StepRef: " ", Action: model.RailOperationDebit},
Step: xplan.Step{StepRef: " ", Action: discovery.RailOperationDebit},
},
},
{
name: "mismatched step execution ref",
in: ExecuteInput{
Payment: &agg.Payment{},
Step: xplan.Step{StepRef: "s1", StepCode: "s1", Action: model.RailOperationDebit},
Step: xplan.Step{StepRef: "s1", StepCode: "s1", Action: discovery.RailOperationDebit},
StepExecution: agg.StepExecution{StepRef: "s2"},
},
},

View File

@@ -1,6 +1,7 @@
package xplan
import (
"github.com/tech/sendico/pkg/discovery"
"testing"
"github.com/tech/sendico/payments/storage/model"
@@ -47,15 +48,15 @@ func TestCompile_ExternalToExternal_BridgeExpansion(t *testing.T) {
t.Fatalf("expected 9 steps, got %d", len(graph.Steps))
}
assertStep(t, graph.Steps[0], "hop.10.crypto.send", model.RailOperationSend, model.RailCrypto, model.ReportVisibilityBackoffice)
assertStep(t, graph.Steps[1], "hop.10.crypto.observe", model.RailOperationObserveConfirm, model.RailCrypto, model.ReportVisibilityBackoffice)
assertStep(t, graph.Steps[2], "edge.10_20.ledger.credit", model.RailOperationExternalCredit, model.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[3], "edge.10_20.ledger.block", model.RailOperationBlock, model.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[4], "hop.20.card_payout.send", model.RailOperationSend, model.RailCardPayout, model.ReportVisibilityUser)
assertStep(t, graph.Steps[5], "hop.20.card_payout.observe", model.RailOperationObserveConfirm, model.RailCardPayout, model.ReportVisibilityUser)
assertStep(t, graph.Steps[6], "edge.10_20.ledger.debit", model.RailOperationExternalDebit, model.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[7], "edge.10_20.ledger.release", model.RailOperationRelease, model.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[8], "edge.10_20.ledger.release", model.RailOperationRelease, model.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[0], "hop.10.crypto.send", discovery.RailOperationSend, discovery.RailCrypto, model.ReportVisibilityBackoffice)
assertStep(t, graph.Steps[1], "hop.10.crypto.observe", discovery.RailOperationObserveConfirm, discovery.RailCrypto, model.ReportVisibilityBackoffice)
assertStep(t, graph.Steps[2], "edge.10_20.ledger.credit", discovery.RailOperationExternalCredit, discovery.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[3], "edge.10_20.ledger.block", discovery.RailOperationBlock, discovery.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[4], "hop.20.card_payout.send", discovery.RailOperationSend, discovery.RailCardPayout, model.ReportVisibilityUser)
assertStep(t, graph.Steps[5], "hop.20.card_payout.observe", discovery.RailOperationObserveConfirm, discovery.RailCardPayout, model.ReportVisibilityUser)
assertStep(t, graph.Steps[6], "edge.10_20.ledger.debit", discovery.RailOperationExternalDebit, discovery.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[7], "edge.10_20.ledger.release", discovery.RailOperationRelease, discovery.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[8], "edge.10_20.ledger.release", discovery.RailOperationRelease, discovery.RailLedger, model.ReportVisibilityHidden)
if got, want := graph.Steps[1].DependsOn, []string{graph.Steps[0].StepRef}; !equalStringSlice(got, want) {
t.Fatalf("step[1] deps mismatch: got=%v want=%v", got, want)
@@ -122,12 +123,12 @@ func TestCompile_InternalToExternal_UsesHoldAndSettlementBranches(t *testing.T)
if len(graph.Steps) != 6 {
t.Fatalf("expected 6 steps, got %d", len(graph.Steps))
}
assertStep(t, graph.Steps[0], "edge.10_20.ledger.block", model.RailOperationBlock, model.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[1], "hop.20.card_payout.send", model.RailOperationSend, model.RailCardPayout, model.ReportVisibilityUser)
assertStep(t, graph.Steps[2], "hop.20.card_payout.observe", model.RailOperationObserveConfirm, model.RailCardPayout, model.ReportVisibilityUser)
assertStep(t, graph.Steps[3], "edge.10_20.ledger.debit", model.RailOperationExternalDebit, model.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[4], "edge.10_20.ledger.release", model.RailOperationRelease, model.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[5], "edge.10_20.ledger.release", model.RailOperationRelease, model.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[0], "edge.10_20.ledger.block", discovery.RailOperationBlock, discovery.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[1], "hop.20.card_payout.send", discovery.RailOperationSend, discovery.RailCardPayout, model.ReportVisibilityUser)
assertStep(t, graph.Steps[2], "hop.20.card_payout.observe", discovery.RailOperationObserveConfirm, discovery.RailCardPayout, model.ReportVisibilityUser)
assertStep(t, graph.Steps[3], "edge.10_20.ledger.debit", discovery.RailOperationExternalDebit, discovery.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[4], "edge.10_20.ledger.release", discovery.RailOperationRelease, discovery.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[5], "edge.10_20.ledger.release", discovery.RailOperationRelease, discovery.RailLedger, model.ReportVisibilityHidden)
if got, want := graph.Steps[4].CommitAfter, []string{graph.Steps[1].StepRef}; !equalStringSlice(got, want) {
t.Fatalf("send-failure release commit_after mismatch: got=%v want=%v", got, want)
}
@@ -156,9 +157,9 @@ func TestCompile_ExternalToInternal_UsesCreditAfterObserve(t *testing.T) {
if len(graph.Steps) != 3 {
t.Fatalf("expected 3 steps, got %d", len(graph.Steps))
}
assertStep(t, graph.Steps[0], "hop.10.crypto.send", model.RailOperationSend, model.RailCrypto, model.ReportVisibilityBackoffice)
assertStep(t, graph.Steps[1], "hop.10.crypto.observe", model.RailOperationObserveConfirm, model.RailCrypto, model.ReportVisibilityBackoffice)
assertStep(t, graph.Steps[2], "edge.10_20.ledger.credit", model.RailOperationExternalCredit, model.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[0], "hop.10.crypto.send", discovery.RailOperationSend, discovery.RailCrypto, model.ReportVisibilityBackoffice)
assertStep(t, graph.Steps[1], "hop.10.crypto.observe", discovery.RailOperationObserveConfirm, discovery.RailCrypto, model.ReportVisibilityBackoffice)
assertStep(t, graph.Steps[2], "edge.10_20.ledger.credit", discovery.RailOperationExternalCredit, discovery.RailLedger, model.ReportVisibilityHidden)
}
func TestCompile_ExternalViaSettlement_UsesFXConvertOnSettlementHop(t *testing.T) {
@@ -201,13 +202,13 @@ func TestCompile_ExternalViaSettlement_UsesFXConvertOnSettlementHop(t *testing.T
convertCount := 0
sendCount := 0
for _, step := range graph.Steps {
if step.Rail != model.RailProviderSettlement {
if step.Rail != discovery.RailProviderSettlement {
continue
}
if step.Action == model.RailOperationFXConvert {
if step.Action == discovery.RailOperationFXConvert {
convertCount++
}
if step.Action == model.RailOperationSend {
if step.Action == discovery.RailOperationSend {
sendCount++
}
}
@@ -239,7 +240,7 @@ func TestCompile_InternalToInternal_UsesMove(t *testing.T) {
if len(graph.Steps) != 1 {
t.Fatalf("expected 1 step, got %d", len(graph.Steps))
}
assertStep(t, graph.Steps[0], "edge.10_20.ledger.move", model.RailOperationMove, model.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[0], "edge.10_20.ledger.move", discovery.RailOperationMove, discovery.RailLedger, model.ReportVisibilityHidden)
}
func TestCompile_GuardsArePrepended(t *testing.T) {
@@ -300,8 +301,8 @@ func TestCompile_SingleExternalFallback(t *testing.T) {
if len(graph.Steps) != 2 {
t.Fatalf("expected 2 steps, got %d", len(graph.Steps))
}
assertStep(t, graph.Steps[0], "hop.0.card_payout.send", model.RailOperationSend, model.RailCardPayout, model.ReportVisibilityUser)
assertStep(t, graph.Steps[1], "hop.0.card_payout.observe", model.RailOperationObserveConfirm, model.RailCardPayout, model.ReportVisibilityUser)
assertStep(t, graph.Steps[0], "hop.0.card_payout.send", discovery.RailOperationSend, discovery.RailCardPayout, model.ReportVisibilityUser)
assertStep(t, graph.Steps[1], "hop.0.card_payout.observe", discovery.RailOperationObserveConfirm, discovery.RailCardPayout, model.ReportVisibilityUser)
if got, want := graph.Steps[1].DependsOn, []string{graph.Steps[0].StepRef}; !equalStringSlice(got, want) {
t.Fatalf("observe dependency mismatch: got=%v want=%v", got, want)
}

View File

@@ -2,6 +2,7 @@ package xplan
import (
"errors"
"github.com/tech/sendico/pkg/discovery"
"testing"
"github.com/tech/sendico/payments/storage/model"
@@ -12,8 +13,8 @@ import (
func TestCompile_PolicyOverrideByRailPair(t *testing.T) {
compiler := New()
cardRail := model.RailCardPayout
ledgerRail := model.RailLedger
var cardRail model.Rail = discovery.RailCardPayout
var ledgerRail model.Rail = discovery.RailLedger
graph, err := compiler.Compile(Input{
IntentSnapshot: testIntent(model.PaymentKindPayout),
@@ -29,18 +30,18 @@ func TestCompile_PolicyOverrideByRailPair(t *testing.T) {
{
ID: "crypto-to-card-override",
Match: EdgeMatch{
Source: EndpointMatch{Rail: railPtr(model.RailCrypto)},
Target: EndpointMatch{Rail: railPtr(model.RailCardPayout)},
Source: EndpointMatch{Rail: railPtr(discovery.RailCrypto)},
Target: EndpointMatch{Rail: railPtr(discovery.RailCardPayout)},
},
Steps: []PolicyStep{
{Code: "custom.review", Action: model.RailOperationMove, Rail: &ledgerRail},
{Code: "custom.submit", Action: model.RailOperationSend, Rail: &cardRail, Visibility: model.ReportVisibilityUser},
{Code: "custom.review", Action: discovery.RailOperationMove, Rail: &ledgerRail},
{Code: "custom.submit", Action: discovery.RailOperationSend, Rail: &cardRail, Visibility: model.ReportVisibilityUser},
},
Success: []PolicyStep{
{Code: "custom.finalize", Action: model.RailOperationDebit, Rail: &ledgerRail},
{Code: "custom.finalize", Action: discovery.RailOperationDebit, Rail: &ledgerRail},
},
Failure: []PolicyStep{
{Code: "custom.release", Action: model.RailOperationRelease, Rail: &ledgerRail},
{Code: "custom.release", Action: discovery.RailOperationRelease, Rail: &ledgerRail},
},
},
},
@@ -52,10 +53,10 @@ func TestCompile_PolicyOverrideByRailPair(t *testing.T) {
if len(graph.Steps) != 4 {
t.Fatalf("expected 4 steps, got %d", len(graph.Steps))
}
assertStep(t, graph.Steps[0], "custom.review", model.RailOperationMove, model.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[1], "custom.submit", model.RailOperationSend, model.RailCardPayout, model.ReportVisibilityUser)
assertStep(t, graph.Steps[2], "custom.finalize", model.RailOperationDebit, model.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[3], "custom.release", model.RailOperationRelease, model.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[0], "custom.review", discovery.RailOperationMove, discovery.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[1], "custom.submit", discovery.RailOperationSend, discovery.RailCardPayout, model.ReportVisibilityUser)
assertStep(t, graph.Steps[2], "custom.finalize", discovery.RailOperationDebit, discovery.RailLedger, model.ReportVisibilityHidden)
assertStep(t, graph.Steps[3], "custom.release", discovery.RailOperationRelease, discovery.RailLedger, model.ReportVisibilityHidden)
if graph.Steps[2].CommitPolicy != model.CommitPolicyAfterSuccess {
t.Fatalf("expected custom.finalize AFTER_SUCCESS, got %q", graph.Steps[2].CommitPolicy)
@@ -67,7 +68,7 @@ func TestCompile_PolicyOverrideByRailPair(t *testing.T) {
func TestCompile_PolicyPriorityAndCustodyMatching(t *testing.T) {
compiler := New()
cardRail := model.RailCardPayout
var cardRail model.Rail = discovery.RailCardPayout
on := true
external := CustodyExternal
@@ -91,17 +92,17 @@ func TestCompile_PolicyPriorityAndCustodyMatching(t *testing.T) {
Source: EndpointMatch{Custody: &external},
Target: EndpointMatch{Custody: &external},
},
Steps: []PolicyStep{{Code: "generic.submit", Action: model.RailOperationSend, Rail: &cardRail}},
Steps: []PolicyStep{{Code: "generic.submit", Action: discovery.RailOperationSend, Rail: &cardRail}},
},
{
ID: "specific-crypto-card",
Enabled: &on,
Priority: 10,
Match: EdgeMatch{
Source: EndpointMatch{Rail: railPtr(model.RailCrypto), Custody: &external},
Target: EndpointMatch{Rail: railPtr(model.RailCardPayout), Custody: &external},
Source: EndpointMatch{Rail: railPtr(discovery.RailCrypto), Custody: &external},
Target: EndpointMatch{Rail: railPtr(discovery.RailCardPayout), Custody: &external},
},
Steps: []PolicyStep{{Code: "specific.submit", Action: model.RailOperationSend, Rail: &cardRail}},
Steps: []PolicyStep{{Code: "specific.submit", Action: discovery.RailOperationSend, Rail: &cardRail}},
},
},
})
@@ -195,11 +196,11 @@ func TestCompile_ValidationErrors(t *testing.T) {
Enabled: &enabled,
Priority: 1,
Match: EdgeMatch{
Source: EndpointMatch{Rail: railPtr(model.RailLedger)},
Target: EndpointMatch{Rail: railPtr(model.RailCardPayout)},
Source: EndpointMatch{Rail: railPtr(discovery.RailLedger)},
Target: EndpointMatch{Rail: railPtr(discovery.RailCardPayout)},
},
Steps: []PolicyStep{
{Code: "bad.step", Action: model.RailOperationUnspecified},
{Code: "bad.step", Action: discovery.RailOperationUnspecified},
},
},
},

View File

@@ -1,6 +1,7 @@
package xplan
import (
"github.com/tech/sendico/pkg/discovery"
"strings"
"github.com/tech/sendico/payments/storage/model"
@@ -81,7 +82,7 @@ func normalizeCommitPolicy(policy model.CommitPolicy) model.CommitPolicy {
func defaultVisibilityForAction(action model.RailOperation, role paymenttypes.QuoteRouteHopRole) model.ReportVisibility {
switch action {
case model.RailOperationSend, model.RailOperationFXConvert, model.RailOperationObserveConfirm:
case discovery.RailOperationSend, discovery.RailOperationFXConvert, discovery.RailOperationObserveConfirm:
if role == paymenttypes.QuoteRouteHopRoleDestination {
return model.ReportVisibilityUser
}
@@ -101,15 +102,15 @@ func defaultUserLabel(
return ""
}
switch action {
case model.RailOperationSend:
if kind == model.PaymentKindPayout && rail == model.RailCardPayout {
case discovery.RailOperationSend:
if kind == model.PaymentKindPayout && rail == discovery.RailCardPayout {
return "Card payout submitted"
}
return "Transfer submitted"
case model.RailOperationFXConvert:
case discovery.RailOperationFXConvert:
return "FX conversion submitted"
case model.RailOperationObserveConfirm:
if kind == model.PaymentKindPayout && rail == model.RailCardPayout {
case discovery.RailOperationObserveConfirm:
if kind == model.PaymentKindPayout && rail == discovery.RailCardPayout {
return "Card payout confirmed"
}
return "Transfer confirmed"

View File

@@ -2,6 +2,7 @@ package xplan
import (
"fmt"
"github.com/tech/sendico/pkg/discovery"
"slices"
"strings"
@@ -17,16 +18,16 @@ func internalRailForBoundary(from normalizedHop, to normalizedHop) model.Rail {
if isInternalRail(to.rail) {
return to.rail
}
return model.RailLedger
return discovery.RailLedger
}
func isInternalRail(rail model.Rail) bool {
return rail == model.RailLedger
return rail == discovery.RailLedger
}
func isExternalRail(rail model.Rail) bool {
switch rail {
case model.RailCrypto, model.RailProviderSettlement, model.RailCardPayout, model.RailFiatOnRamp:
case discovery.RailCrypto, discovery.RailProviderSettlement, discovery.RailCardPayout, discovery.RailFiatOnRamp:
return true
default:
return false
@@ -58,7 +59,7 @@ func edgeCode(from normalizedHop, to normalizedHop, rail model.Rail, op string)
}
func railToken(rail model.Rail) string {
if rail == model.RailCardPayout {
if rail == discovery.RailCardPayout {
return "card_payout"
}
return strings.ToLower(strings.TrimSpace(string(rail)))
@@ -75,7 +76,7 @@ func normalizeRouteHops(route *paymenttypes.QuoteRouteSpecification, intent mode
if len(route.Hops) == 0 {
rail := normalizeRail(route.Rail)
if rail == model.RailUnspecified {
if rail == discovery.RailUnspecified {
return nil, merrors.InvalidArgument("quote_snapshot.route.rail is required")
}
return []normalizedHop{
@@ -98,7 +99,7 @@ func normalizeRouteHops(route *paymenttypes.QuoteRouteSpecification, intent mode
}
rail := normalizeRail(firstNonEmpty(hop.Rail, route.Rail))
if rail == model.RailUnspecified {
if rail == discovery.RailUnspecified {
return nil, merrors.InvalidArgument("quote_snapshot.route.hops[" + itoa(i) + "].rail is required")
}

View File

@@ -1,6 +1,7 @@
package xplan
import (
"github.com/tech/sendico/pkg/discovery"
"strings"
"github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/batchmeta"
@@ -20,7 +21,7 @@ func (s *svc) expandSingleHop(ex *expansion, hop normalizedHop, intent model.Pay
ex.appendMain(Step{
StepCode: singleHopCode(hop, "debit"),
Kind: StepKindFundsDebit,
Action: model.RailOperationDebit,
Action: discovery.RailOperationDebit,
Rail: hop.rail,
HopIndex: hop.index,
HopRole: hop.role,
@@ -30,7 +31,7 @@ func (s *svc) expandSingleHop(ex *expansion, hop normalizedHop, intent model.Pay
ex.appendMain(Step{
StepCode: singleHopCode(hop, "credit"),
Kind: StepKindFundsCredit,
Action: model.RailOperationCredit,
Action: discovery.RailOperationCredit,
Rail: hop.rail,
HopIndex: hop.index,
HopRole: hop.role,
@@ -40,7 +41,7 @@ func (s *svc) expandSingleHop(ex *expansion, hop normalizedHop, intent model.Pay
ex.appendMain(Step{
StepCode: singleHopCode(hop, "move"),
Kind: StepKindFundsMove,
Action: model.RailOperationMove,
Action: discovery.RailOperationMove,
Rail: hop.rail,
HopIndex: hop.index,
HopRole: hop.role,
@@ -70,7 +71,7 @@ func (s *svc) applyDefaultBoundary(
if err != nil {
return err
}
if to.rail == model.RailCardPayout && len(targets) > 0 {
if to.rail == discovery.RailCardPayout && len(targets) > 0 {
return s.applyBatchCardPayoutBoundary(ex, from, to, internalRail, intent, targets)
}
ex.appendMain(makeFundsBlockStep(from, to, internalRail))
@@ -167,8 +168,8 @@ func appendGuards(ex *expansion, conditions *paymenttypes.QuoteExecutionConditio
StepRef: QuoteReadinessGuardStepRef,
StepCode: string(GuardOperationQuoteReadinessGuard),
Kind: StepKindLiquidityCheck,
Action: model.RailOperationUnspecified,
Rail: model.RailUnspecified,
Action: discovery.RailOperationUnspecified,
Rail: discovery.RailUnspecified,
Visibility: model.ReportVisibilityHidden,
})
}
@@ -178,8 +179,8 @@ func appendGuards(ex *expansion, conditions *paymenttypes.QuoteExecutionConditio
StepRef: PrefundingGuardStepRef,
StepCode: string(GuardOperationPrefundingEnsure),
Kind: StepKindPrefunding,
Action: model.RailOperationUnspecified,
Rail: model.RailUnspecified,
Action: discovery.RailOperationUnspecified,
Rail: discovery.RailUnspecified,
Visibility: model.ReportVisibilityHidden,
})
}
@@ -207,22 +208,22 @@ func makeRailSendStep(hop normalizedHop, intent model.PaymentIntent) Step {
}
func railActionForHop(hop normalizedHop) (model.RailOperation, string) {
if hop.rail == model.RailProviderSettlement {
return model.RailOperationFXConvert, "fx_convert"
if hop.rail == discovery.RailProviderSettlement {
return discovery.RailOperationFXConvert, "fx_convert"
}
return model.RailOperationSend, "send"
return discovery.RailOperationSend, "send"
}
func makeRailObserveStep(hop normalizedHop, intent model.PaymentIntent) Step {
visibility := defaultVisibilityForAction(model.RailOperationObserveConfirm, hop.role)
visibility := defaultVisibilityForAction(discovery.RailOperationObserveConfirm, hop.role)
userLabel := ""
if visibility == model.ReportVisibilityUser {
userLabel = defaultUserLabel(model.RailOperationObserveConfirm, hop.rail, hop.role, intent.Kind)
userLabel = defaultUserLabel(discovery.RailOperationObserveConfirm, hop.rail, hop.role, intent.Kind)
}
return Step{
StepCode: singleHopCode(hop, "observe"),
Kind: StepKindRailObserve,
Action: model.RailOperationObserveConfirm,
Action: discovery.RailOperationObserveConfirm,
Rail: hop.rail,
Gateway: hop.gateway,
InstanceID: hop.instanceID,
@@ -237,7 +238,7 @@ func makeFundsCreditStep(from normalizedHop, to normalizedHop, rail model.Rail)
return Step{
StepCode: edgeCode(from, to, rail, "credit"),
Kind: StepKindFundsCredit,
Action: model.RailOperationExternalCredit,
Action: discovery.RailOperationExternalCredit,
Rail: rail,
HopIndex: to.index,
HopRole: paymenttypes.QuoteRouteHopRoleTransit,
@@ -249,7 +250,7 @@ func makeFundsBlockStep(from normalizedHop, to normalizedHop, rail model.Rail) S
return Step{
StepCode: edgeCode(from, to, rail, "block"),
Kind: StepKindFundsBlock,
Action: model.RailOperationBlock,
Action: discovery.RailOperationBlock,
Rail: rail,
HopIndex: to.index,
HopRole: paymenttypes.QuoteRouteHopRoleTransit,
@@ -261,7 +262,7 @@ func makeFundsMoveStep(from normalizedHop, to normalizedHop, rail model.Rail) St
return Step{
StepCode: edgeCode(from, to, rail, "move"),
Kind: StepKindFundsMove,
Action: model.RailOperationMove,
Action: discovery.RailOperationMove,
Rail: rail,
HopIndex: to.index,
HopRole: paymenttypes.QuoteRouteHopRoleTransit,
@@ -312,7 +313,7 @@ func appendSettlementBranchesWithMetadata(
successStep := Step{
StepCode: edgeCode(from, to, rail, "debit"),
Kind: StepKindFundsDebit,
Action: model.RailOperationExternalDebit,
Action: discovery.RailOperationExternalDebit,
DependsOn: []string{anchorObserveRef},
Rail: rail,
HopIndex: to.index,
@@ -328,7 +329,7 @@ func appendSettlementBranchesWithMetadata(
sendFailureStep := Step{
StepCode: edgeCode(from, to, rail, "release"),
Kind: StepKindFundsRelease,
Action: model.RailOperationRelease,
Action: discovery.RailOperationRelease,
DependsOn: []string{anchorSendRef},
Rail: rail,
HopIndex: to.index,
@@ -344,7 +345,7 @@ func appendSettlementBranchesWithMetadata(
failureStep := Step{
StepCode: edgeCode(from, to, rail, "release"),
Kind: StepKindFundsRelease,
Action: model.RailOperationRelease,
Action: discovery.RailOperationRelease,
DependsOn: []string{anchorObserveRef},
Rail: rail,
HopIndex: to.index,

View File

@@ -1,6 +1,7 @@
package xplan
import (
"github.com/tech/sendico/pkg/discovery"
"strings"
"github.com/tech/sendico/payments/storage/model"
@@ -127,12 +128,12 @@ func policyStepToStep(spec PolicyStep, from normalizedHop, to normalizedHop, int
}
action := normalizeAction(spec.Action)
if action == model.RailOperationUnspecified {
if action == discovery.RailOperationUnspecified {
return Step{}, merrors.InvalidArgument("action is required")
}
rail := inferPolicyRail(spec, action, from, to)
if rail == model.RailUnspecified {
if rail == discovery.RailUnspecified {
return Step{}, merrors.InvalidArgument("rail could not be inferred")
}
@@ -166,30 +167,30 @@ func policyStepToStep(spec PolicyStep, from normalizedHop, to normalizedHop, int
func normalizeAction(action model.RailOperation) model.RailOperation {
switch strings.ToUpper(strings.TrimSpace(string(action))) {
case string(model.RailOperationDebit):
return model.RailOperationDebit
case string(model.RailOperationCredit):
return model.RailOperationCredit
case string(model.RailOperationExternalDebit):
return model.RailOperationExternalDebit
case string(model.RailOperationExternalCredit):
return model.RailOperationExternalCredit
case string(model.RailOperationMove):
return model.RailOperationMove
case string(model.RailOperationSend):
return model.RailOperationSend
case string(model.RailOperationFee):
return model.RailOperationFee
case string(model.RailOperationObserveConfirm):
return model.RailOperationObserveConfirm
case string(model.RailOperationFXConvert):
return model.RailOperationFXConvert
case string(model.RailOperationBlock):
return model.RailOperationBlock
case string(model.RailOperationRelease):
return model.RailOperationRelease
case string(discovery.RailOperationDebit):
return discovery.RailOperationDebit
case string(discovery.RailOperationCredit):
return discovery.RailOperationCredit
case string(discovery.RailOperationExternalDebit):
return discovery.RailOperationExternalDebit
case string(discovery.RailOperationExternalCredit):
return discovery.RailOperationExternalCredit
case string(discovery.RailOperationMove):
return discovery.RailOperationMove
case string(discovery.RailOperationSend):
return discovery.RailOperationSend
case string(discovery.RailOperationFee):
return discovery.RailOperationFee
case string(discovery.RailOperationObserveConfirm):
return discovery.RailOperationObserveConfirm
case string(discovery.RailOperationFXConvert):
return discovery.RailOperationFXConvert
case string(discovery.RailOperationBlock):
return discovery.RailOperationBlock
case string(discovery.RailOperationRelease):
return discovery.RailOperationRelease
default:
return model.RailOperationUnspecified
return discovery.RailOperationUnspecified
}
}
@@ -199,18 +200,18 @@ func inferPolicyRail(spec PolicyStep, action model.RailOperation, from normalize
}
switch action {
case model.RailOperationSend, model.RailOperationFXConvert, model.RailOperationObserveConfirm, model.RailOperationFee:
case discovery.RailOperationSend, discovery.RailOperationFXConvert, discovery.RailOperationObserveConfirm, discovery.RailOperationFee:
return to.rail
case model.RailOperationBlock,
model.RailOperationRelease,
model.RailOperationDebit,
model.RailOperationCredit,
model.RailOperationExternalDebit,
model.RailOperationExternalCredit,
model.RailOperationMove:
case discovery.RailOperationBlock,
discovery.RailOperationRelease,
discovery.RailOperationDebit,
discovery.RailOperationCredit,
discovery.RailOperationExternalDebit,
discovery.RailOperationExternalCredit,
discovery.RailOperationMove:
return internalRailForBoundary(from, to)
default:
return model.RailUnspecified
return discovery.RailUnspecified
}
}
@@ -220,7 +221,7 @@ func resolveStepContext(
from normalizedHop,
to normalizedHop,
) (uint32, paymenttypes.QuoteRouteHopRole, string, string) {
if rail == to.rail && (action == model.RailOperationSend || action == model.RailOperationFXConvert || action == model.RailOperationObserveConfirm || action == model.RailOperationFee) {
if rail == to.rail && (action == discovery.RailOperationSend || action == discovery.RailOperationFXConvert || action == discovery.RailOperationObserveConfirm || action == discovery.RailOperationFee) {
return to.index, to.role, to.gateway, to.instanceID
}
if rail == from.rail {
@@ -234,19 +235,19 @@ func resolveStepContext(
func kindForAction(action model.RailOperation) StepKind {
switch action {
case model.RailOperationSend, model.RailOperationFXConvert:
case discovery.RailOperationSend, discovery.RailOperationFXConvert:
return StepKindRailSend
case model.RailOperationObserveConfirm:
case discovery.RailOperationObserveConfirm:
return StepKindRailObserve
case model.RailOperationCredit, model.RailOperationExternalCredit:
case discovery.RailOperationCredit, discovery.RailOperationExternalCredit:
return StepKindFundsCredit
case model.RailOperationDebit, model.RailOperationExternalDebit:
case discovery.RailOperationDebit, discovery.RailOperationExternalDebit:
return StepKindFundsDebit
case model.RailOperationMove:
case discovery.RailOperationMove:
return StepKindFundsMove
case model.RailOperationBlock:
case discovery.RailOperationBlock:
return StepKindFundsBlock
case model.RailOperationRelease:
case discovery.RailOperationRelease:
return StepKindFundsRelease
default:
return StepKindUnspecified