Package Structure
The pkg/ directory is organized into three tiers: shared infrastructure, the installment loan product, and the credit line product. Product packages import from shared infrastructure but never from each other.
pkg/
├── dynamo/ # Shared: DynamoDB client, ID struct, helpers, distributed lock
├── iterable/ # Shared: Iterable notification client
├── payments/ # Shared: PayEngine client (ACH, RTP, Pinless)
├── floats/ # Shared: Float service client
├── growthbook/ # Shared: Feature flag client
├── underwriting/ # Shared: Underwriting service client
├── users/ # Shared: User service client
├── txns/ # Shared: Transaction service client
├── notification/ # Shared: Notification abstraction
├── slack/ # Shared: Slack alerting
├── s3/ # Shared: S3 helpers
├── sqs/ # Shared: SQS helpers
├── lambdadispatch/ # Shared: Lambda-to-Lambda invocation
├── utils/ # Shared: Math and general utilities
├── version/ # Shared: Build version metadata
│
├── installmentloan/ # Product: installment loans
│ ├── api/ # OpenAPI handlers (oapi-codegen, chi router)
│ ├── collections/ # Collection engine, job, worker, webhook handler
│ ├── service/ # Repository interfaces
│ ├── dynamo/ # DynamoDB models: Loan, Payment, Installment, LoanApplication
│ ├── expiration/ # TTL expiry logic (LOAN# prefix)
│ ├── loanbalanceworker/ # Balance reconciliation handler
│ ├── log/ # Audit log DynamoDB stream handler
│ ├── latex/ # LaTeX PDF rendering for loan agreements
│ ├── receipts/ # Payment receipt types
│ ├── precheck/ # Eligibility pre-check logic
│ └── datadog/ # DataDog metric constants
│
└── creditline/ # Product: revolving credit line
├── api/ # OpenAPI handlers
├── billing/ # loc_billing: interest accrual, statement gen, MinPaymentDue
├── collections/ # loc_due, loc_overdue, loc_upcoming
├── statements/ # LocStatement struct, PDF invoke, GET endpoints
├── draws/ # Draw handler, RTP→Pinless→ACH disbursement
├── dynamo/ # DynamoDB models: LineOfCredit, LocApplication, LocStatement, LocPayment
└── expiration/ # TTL expiry logic (LOCAPP# prefix)
Shared Infrastructure (pkg/dynamo)
pkg/dynamo contains only infrastructure that both products depend on:
-
dynamo.go—Clientinterface,IDstruct (PK/SK/GSI keys),ErrNotFound,BatchWriteItems,ExhaustiveQuery, DynamoDB type constants (LOAN,PAYMENT,LOANAPP,USER,STATUS,DUEDATE) -
lock.go—Lockerinterface andcirello.io/dynamolock/v2implementation for distributed locking -
mocks/—ClientandLockermocks (shared by both products' tests)
Lock key format: loc-{process}:user_id:{userID}:item_id:{itemID}
Installment Loan Product (pkg/installmentloan)
dynamo/
Product-specific DynamoDB repositories. All models embed pkg/dynamo.ID for the composite key fields and import pkg/dynamo for shared helpers.
| File | Contents |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
collections/
Handles all automated payment collection for installment loans.
-
engine.go—PaybackEngineinterface + implementation; ACH and pinless debit payment execution -
job.go— CloudWatch-triggered scheduler; queries installments and enqueues SQS messages -
worker.go— SQS-triggered worker; dispatches to engine per collection process type -
webhook_handler.go— Kinesis webhook handler for ACH returns and pinless chargebacks -
latefee.go— Late fee calculation and application logic
Credit Line Product (pkg/creditline)
billing/
The loc_billing job runs at 08:00 UTC on each billing cycle close date:
-
Accrue interest on
PrincipalBalance -
Generate
LocStatement(snapshot of draws, payments, interest) -
Calculate
NextMinPaymentDue—Interest + Fees + (1%–5% × PrincipalBalance) -
Write
LastBillingCycleDateto guardloc_duefrom running before billing completes
collections/
Three scheduled jobs, all separate CloudWatch rules:
| Job | Schedule | Description |
|---|---|---|
|
08:00 UTC |
Cycle close — see |
|
15:00 UTC |
Reads |
|
14:00 UTC |
Notifies ~7 days before |
|
16:00 UTC |
Daily; skips if |
draws/
Draw request handler with payment method priority:
-
Disbursement: RTP → Pinless → ACH
-
Repayment: Pinless → ACH (RTP not used for payback)
ACH balance timing: balances applied immediately on ACH submission (not on webhook). Webhook LOAN_DEBIT_COMPLETED marks COMPLETED only — no balance change. LOAN_DEBIT_RETURNED / CHARGED_BACK reverses balances and sends loc_payment_failed Iterable event.
Dependency Rules
pkg/installmentloan/* → pkg/dynamo ✅ (shared infra)
pkg/installmentloan/* → pkg/iterable ✅ (shared infra)
pkg/creditline/* → pkg/dynamo ✅ (shared infra)
pkg/creditline/* → pkg/iterable ✅ (shared infra)
pkg/installmentloan/* → pkg/creditline/* ❌ (no cross-product imports)
pkg/creditline/* → pkg/installmentloan/* ❌ (no cross-product imports)
Adding a New Product
-
Create
pkg/{product}/with subdirectories mirroring the credit line layout -
Add product-specific DynamoDB models to
pkg/{product}/dynamo/— embedpkg/dynamo.ID, importpkg/dynamofor shared helpers -
Add the product’s interfaces to
.mockery.yamlundergithub.com/floatme-corp/loc-service/pkg/{product}/… -
Create
cmd/{product}-api/and any scheduler/worker entry points -
Extend
cmd/expiration-handlerif the product has TTL-expirable records (add SK prefix check)