Files
zeekayandClaude Opus 5.5 f8eaf72607 A tightened rule reaches the database that already exists
Each Ensure creates its collection once and returns early ever after, so
the owner-scoped rules of v1.5.0 only ever applied to a fresh database.
One created by an earlier release kept list/view open to anyone on
accounts, balances, transactions, wallets and cards through every
upgrade.

The rules are now one table, used at creation and re-asserted on every
boot. The users collection's anonymous create is closed the same way:
identity is Lux ID, so no anonymous caller makes a users record.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_016dDw5Lp9sZFctwvZLn4nVz
2026-09-22 23:05:09 -07:00

100 lines
2.0 KiB
Go

package collections
import "github.com/hanzoai/base/core"
const BeneficiaryCollectionName = "beneficiaries"
// EnsureBeneficiaryCollection creates the beneficiaries collection if it does
// not exist. Each beneficiary belongs to an account and stores bank routing
// details for outbound payments (wires, SEPA, ACH).
func EnsureBeneficiaryCollection(app core.App) error {
_, err := app.FindCollectionByNameOrId(BeneficiaryCollectionName)
if err == nil {
return nil
}
c := core.NewBaseCollection(BeneficiaryCollectionName, BeneficiaryCollectionName)
readable(c)
c.Fields.Add(
// Parent account.
&core.RelationField{
Name: "account",
CollectionId: AccountCollectionName,
Required: true,
MaxSelect: 1,
},
// CurrencyCloud beneficiary id.
&core.TextField{
Name: "ccBeneficiaryId",
},
// Display name for this beneficiary.
&core.TextField{
Name: "name",
Required: true,
},
// Bank account holder name (may differ from display name).
&core.TextField{
Name: "bankAccountHolder",
Required: true,
},
// ISO 4217 currency code.
&core.TextField{
Name: "currency",
Required: true,
Min: 3,
Max: 3,
},
// ISO-3166 country code.
&core.TextField{
Name: "country",
Required: true,
Min: 2,
Max: 2,
},
// Payment type: regular | priority.
&core.SelectField{
Name: "paymentType",
Values: []string{"regular", "priority"},
MaxSelect: 1,
},
// Bank routing details stored as structured JSON:
// { "iban": "...", "bic": "...", "sortCode": "...", "accountNumber": "..." }
&core.JSONField{
Name: "bankDetails",
Required: true,
MaxSize: 1 << 20,
},
// Beneficiary address (JSON: street, city, postCode, country).
&core.JSONField{
Name: "address",
MaxSize: 1 << 20,
},
&core.BoolField{
Name: "verified",
},
&core.AutodateField{
Name: "created",
OnCreate: true,
},
&core.AutodateField{
Name: "updated",
OnCreate: true,
OnUpdate: true,
},
)
return app.Save(c)
}