Member equity and share registry¶
| ID | MOD-118 |
| System | SD01 |
| Repo | bank-core |
| Build status | Deployed |
| Deployed | Yes |
| Last commit | f88c7cc2f3e7873b53bc8bed1a5a7afcc38980d4 |
Purpose¶
Maintains the definitive record of member shareholdings for mutual institutions (building societies, credit unions, mutual banks). Records all share transactions — purchase, redemption, transfer, dividend reinvestment, and correction — manages the dividend declaration and distribution workflow, and enforces the capital-gate on share redemptions. This module only activates when the tenant's institution type is configured as mutual.
Configuration flag¶
The module is governed by a tenant-level flag at SSM path /bank/{stage}/tenant/institution-type (values: mutual | proprietary). The Lambda reads this at cold-start. When proprietary, all MOD-118 handlers return immediately (404 or 501). This allows the same platform to serve both company-structured banks and mutual institutions without separate deployments. The flag is set at tenant provisioning time and is not changeable at runtime.
Compliance rationale¶
Mutual institutions have regulatory obligations that differ materially from proprietary banks. Member share capital may qualify as Common Equity Tier 1 (CET1) capital under Basel III/IV, but only if redemption is at the full discretion of the institution — i.e. the institution can block redemption without member consent. This module implements that discretionary block as a hard gate: no redemption proceeds until MOD-033 confirms that the post-redemption CET1 ratio would remain at or above the regulatory minimum.
Failure to implement this gate would result in member shares being classified as a liability (AT1 at best) rather than CET1, which would materially reduce reported capital ratios and could trigger prudential intervention by the RBNZ or APRA. The gate is therefore a regulatory compliance requirement, not an operational feature.
In NZ, the relevant standards are RBNZ BS2A and BS2B. In AU, the relevant standard is APRA APS 110. Both require the same underlying control.
Commercial rationale¶
Building societies and credit unions use member equity as both a regulatory capital tool and a customer loyalty mechanism. Membership confers voting rights, access to surplus distributions, and a sense of institutional ownership that differentiates mutual institutions from proprietary banks. A well-managed dividend workflow — with transparent calculation, automatic payment, and clear tax documentation — is a core element of the mutual institution brand proposition and directly supports member retention.
Data model¶
Five tables in the core schema. Full schemas in SD01 data model. Key design points:
party_idnotcustomer_id—core.member_register.party_idisUUID NOT NULLwith no Postgres FK (cross-domain boundary; mirrors the pattern inaccounts.account_party_relationships).core.customersdoes not exist in bank-core's DB.- Uppercase enums — all
CHECKenum values are uppercase per SD04 standard. core.share_transactionsis Cat 1 immutable — INSERT only; each share capital movement is one row in terminal state. Status transitions are recorded as new rows (CORRECTION tx_type for reversals), not updates.core.redemption_queue— mutable FIFO queue for redemptions blocked by the capital gate. Replayer processes this daily in FIFO order when headroom allows.
See SD01 data model for full column definitions.
Key operations¶
Share purchase¶
Validate that the party holds member or applicant status in MOD-007 (via accounts.account_state_history). Eligibility rule evaluation (MOD-105) is deferred to v2 — v1 accepts any status='member' party (Gap #4 ruling). Process payment for the share purchase amount (par value × number of shares). Call MOD-001 to post the debit to the member's payment account and a credit to equity.share_capital. Insert a row in core.share_transactions with tx_type = 'purchase' and update shares_held on the member register. If this is the initial share purchase (first-time member), set status to member via MOD-007. Issue membership certificate via MOD-073, storing the document reference on the member register.
Redemption gate¶
CapitalGateProvider interface. The capital gate is implemented behind a CapitalGateProvider interface (src/lib/capital-gate-provider.ts). v1 ships with MOD033CapitalGateProvider (reads GET /capital/current/{jurisdiction} on the MOD-033 Lambda wrapper — see Gap #1). Dev/uat uses a StubCapitalGateProvider (always returns a healthy ratio) so the build is not blocked pending the MOD-033 wrapper. The interface is the same pattern as MOD-087's EnrichmentProvider — swapping implementations is mechanical.
Before processing any redemption request: invoke CapitalGateProvider.getCET1Ratio(jurisdiction). Compute the post-redemption CET1: (current_tier1_capital − redemption_amount) / current_rwa. If the result would fall below the configured floor (/bank/{stage}/tenant/cet1-minimum), insert a BLOCKED row in core.share_transactions and a corresponding row in core.redemption_queue. Notify the member via bank.core.member_status_changed event (MOD-063 delivers). The blocked-redemption-replayer runs daily: evaluates FIFO queue, calls CapitalGateProvider for current ratio, processes queued redemptions when headroom allows. This gate cannot be bypassed by any back-office role.
Dividend declaration¶
Board-initiated via the back-office administration interface. Input parameters: record date, payment date, rate per share, board resolution reference. The system calculates total declared amount from the current member register as SUM(shares_held) × rate_per_share at the record date snapshot. A dividend declaration record is created with status = 'declared'. MOD-001 posts the journal entry: debit equity.retained_earnings, credit liabilities.dividend_payable.
On the payment date, a batch job iterates all active members as at the record date. For each member: calculate gross_dividend = shares_at_record × rate_per_share; apply applicable withholding tax per jurisdiction; post net credit to the member's nominated account via MOD-001; insert a row in core.dividend_payments with paid_at set to the payment timestamp. Update declaration status to PAID when all payments are settled. At financial year end, MOD-118 publishes a bank.core.tax_certificate_due event per member who received a dividend during the year, carrying the full calculation payload. MOD-113 subscribes to this event when deployed and renders the tax certificate before storing in MOD-073. FR-535 certificate delivery is deferred until MOD-113 is active (Gap #2 ruling — Option C).
AGM voting record¶
When a member casts a vote at the AGM (via the app or in-person verification), update last_voted_at on the member register to the AGM date. This field is included in the annual member statement generated by MOD-113. Voting eligibility is determined by status = 'member' as at the AGM record date.
Requirements satisfied¶
FR-533 covers share register management — creation, update, and audit trail of member shareholding records. FR-534 covers capital-gate enforcement on redemptions — the requirement that no redemption proceeds if it would breach the minimum CET1 ratio. FR-535 covers dividend declaration and distribution workflow — board declaration, per-member calculation, ledger posting, and payment. FR-536 covers tax certificate generation — annual dividend tax certificate per member, integrated with MOD-113.
Module dependencies¶
Depends on¶
| Module | Title | Required? | Contract | Reason |
|---|---|---|---|---|
| MOD-001 | Double-entry posting engine | Required | — | All share capital movements (purchases, redemptions, dividends) are posted as double-entry ledger entries via the posting engine — equity accounts not deposit accounts. |
| MOD-033 | RWA & capital ratio engine | Required | — | The RWA and capital ratio engine must receive member share capital data to determine whether member shares qualify as CET1 and to enforce the redemption gate. |
| MOD-007 | Account state machine | Required | — | Membership status transitions (applicant, member, suspended, former) are managed within the account state machine. |
| MOD-073 | Document vault | Required | — | Membership certificates are stored and delivered via the document vault. Tax certificates and member statements are dispatched via events and stored by MOD-113 when deployed. |
| MOD-076 | Observability platform | Required | — | ADOT Lambda layer and observability infrastructure are required for OTel tracing and structured logging. |
| MOD-140 | Chart of accounts and GL configuration | Required | — | GL chart of accounts must be seeded (EQU.SHARE_CAPITAL, EQU.RETAINED_EARNINGS, LIA.DIVIDEND_PAYABLE codes) before MOD-118 can post equity-account journal entries via MOD-001. |
| MOD-103 | Neon database platform bootstrap | Required | — | Neon database and schema provisioned by MOD-103 must exist before this module can read or write Postgres. |
| MOD-104 | AWS shared infrastructure bootstrap | Required | — | AWS shared infrastructure provisioned by MOD-104 (IAM role, EventBridge bus, SNS, KMS) is required before this module can be deployed. |
| MOD-113 | Statement generation | Optional | — | Statement and tax-certificate rendering is dispatched via bank.core.member_statement_due and bank.core.tax_certificate_due events; MOD-113 subscribes when deployed. FR-535/FR-536 delivery is complete only when MOD-113 is active. |
| MOD-105 | Product eligibility engine | Optional | — | Eligibility rule evaluation is deferred to v2; v1 accepts any party with status='member'. MOD-105 dependency activates when eligibility gating is implemented. |
Required by¶
| Module | Title | As | Contract |
|---|---|---|---|
| MOD-131 | Mutual governance and AGM administration | Hard dependency | — |
Policies satisfied¶
| Policy | Title | Mode | How |
|---|---|---|---|
| CLQ-001 | Capital Adequacy Policy | GATE |
Share redemption requests that would reduce CET1 capital below the regulatory minimum are blocked — the redemption queue is held until capital headroom is restored. |
| GOV-001 | Board Charter | LOG |
All share transactions, dividend declarations, and member register changes are logged as immutable governance events for board and regulatory review. |
| CON-001 | Customer Fairness & Conduct Policy | AUTO |
Dividend distributions are calculated consistently across all members using the declared rate and recorded shareholding — no discretionary variation. |
| CON-004 | Product Disclosure & Sales Practice Policy | AUTO |
Members receive their annual member statement and dividend tax certificate automatically without requiring a manual request. |
Capabilities satisfied¶
(No capabilities mapped)
Part of SD01 — Core Banking Platform
Compiled 2026-05-22 from source/entities/modules/MOD-118.yaml