Files
zeekay 29563d0e5f fix(provider): deregister marqeta/plaid lying stubs (honest Capabilities + doc.go)
Both adapters self-registered when their env vars were set, then returned
ErrNotSupported on every call. Routing logic could not distinguish a stub
from a real adapter — dangerous for payment routing.

Per yesterday's audit:
- Capabilities() now returns empty PaymentTypes/Currencies/Features/
  Countries and Status="placeholder" on both. Routers must see them
  as supporting nothing.
- Every method returns wrapped ErrNotSupported with explicit
  "<provider> adapter not implemented (<method>) — see doc.go" so
  the error trail is honest.
- doc.go starts with the required placeholder line pointing at the
  provider's official docs URL.
- cmd/treasuryd/main.go no longer registers either provider; instead
  it logs a warning when the env var is set, pointing at the doc.go
  TODO. Env vars stay in the docs so a future real implementation
  drops in unchanged. Imports kept under blank-import to preserve the
  stable package path.
2026-05-24 18:58:34 -07:00

101 lines
3.1 KiB
Go

package plaid
import (
"context"
"fmt"
"net/http"
"time"
"github.com/luxfi/treasury/pkg/provider"
"github.com/luxfi/treasury/pkg/types"
)
const (
ProdURL = "https://production.plaid.com"
SandboxURL = "https://sandbox.plaid.com"
)
type Config struct {
BaseURL string
ClientID string
Secret string
}
type Provider struct {
cfg Config
client *http.Client
}
// New constructs a placeholder Plaid provider. It is not registered by
// cmd/treasuryd/main.go and every Provider method returns ErrNotSupported.
// See doc.go.
func New(cfg Config) provider.Provider {
return &Provider{
cfg: cfg,
client: &http.Client{Timeout: 30 * time.Second},
}
}
func (p *Provider) Name() string { return "plaid" }
func notImpl(method string) error {
return fmt.Errorf("plaid adapter not implemented (%s) — see doc.go: %w", method, provider.ErrNotSupported)
}
func (p *Provider) CreateAccount(_ context.Context, _ string, _ *provider.CreateAccountRequest) (*types.BankAccount, error) {
return nil, notImpl("CreateAccount")
}
func (p *Provider) GetAccount(_ context.Context, _ string) (*types.BankAccount, error) {
return nil, notImpl("GetAccount")
}
func (p *Provider) ListAccounts(_ context.Context, _ string) ([]*types.BankAccount, error) {
return nil, notImpl("ListAccounts")
}
func (p *Provider) GetBalance(_ context.Context, _ string) (*types.Balance, error) {
return nil, notImpl("GetBalance")
}
func (p *Provider) CreatePayment(_ context.Context, _ *types.CreatePaymentRequest) (*types.Payment, error) {
return nil, notImpl("CreatePayment")
}
func (p *Provider) GetPayment(_ context.Context, _ string) (*types.Payment, error) {
return nil, notImpl("GetPayment")
}
func (p *Provider) ListPayments(_ context.Context, _ string) ([]*types.Payment, error) {
return nil, notImpl("ListPayments")
}
func (p *Provider) CancelPayment(_ context.Context, _ string) error {
return notImpl("CancelPayment")
}
func (p *Provider) GetFXQuote(_ context.Context, _, _, _, _ string) (*types.FXQuote, error) {
return nil, notImpl("GetFXQuote")
}
func (p *Provider) CreateFXConversion(_ context.Context, _ *types.CreateFXConversionRequest) (*types.FXConversion, error) {
return nil, notImpl("CreateFXConversion")
}
func (p *Provider) ListFXConversions(_ context.Context) ([]*types.FXConversion, error) {
return nil, notImpl("ListFXConversions")
}
func (p *Provider) CreateCounterparty(_ context.Context, _ *types.Counterparty) (*types.Counterparty, error) {
return nil, notImpl("CreateCounterparty")
}
func (p *Provider) ListCounterparties(_ context.Context) ([]*types.Counterparty, error) {
return nil, notImpl("ListCounterparties")
}
// Capabilities returns a fully-empty capability set. The Plaid adapter
// has zero real capabilities until a real implementation lands; routing
// logic MUST treat this provider as supporting nothing.
func (p *Provider) Capabilities() *types.ProviderCapability {
return &types.ProviderCapability{
Name: "plaid",
PaymentTypes: []string{},
Currencies: []string{},
Features: []string{},
Countries: []string{},
Status: "placeholder",
}
}