Skip to content

MOD-036 — Prudential return builder (RBNZ / APRA)

Purpose

Assembles RBNZ BS-series and APRA ARS-series prudential returns from upstream MOD-032 (LCR/NSFR) and MOD-033 (capital/RWA) Snowflake-native published views via dbt Dynamic Tables. Validates every cell against the regulator-published rules (FR-218), maintains a per-return submission calendar (FR-219), and submits to RBNZ / APRA endpoints — but only after a Finance officer approves the assembled return in MOD-170's Streamlit form, recorded as a row in REGULATORY.RETURN_APPROVALS (REP-005 GATE / FR-807).

REP-005's GATE policy is the central contract — the submission orchestrator Lambda runs four sequential checks (validation status, approval exists, approver ≠ assembler, content hash matches snapshot) and refuses any regulator POST that fails any check.

Functional requirements

Code Requirement
FR-217 Compile and submit all RBNZ + APRA prudential returns by their respective statutory due dates, with no return submitted past the deadline.
FR-218 Validate every return against regulator-published validation rules before submission, blocking submission of any return that fails validation and alerting the Finance team.
FR-219 Maintain a submission calendar showing all return codes, due dates, and submission status, updated within 1 hour of any submission or acknowledgement event.
FR-220 Record submission reference, transmission timestamp, regulator acknowledgement, and return content hash for every submitted prudential return, retaining records for 7 years.
FR-807 Require a valid REGULATORY.RETURN_APPROVALS record for the current (run_id, return_code) pair before the submission orchestrator may post to a regulator endpoint.
NFR-010 Regulatory submissions produced without manual intervention ≥ 90% — the orchestrator + dbt DTs satisfy the auto-assembly path; only the dual-control approval click requires a human (by design).
NFR-011 Tier 1 availability.
NFR-019 RTO ≤ 4h / RPO ≤ 1h.
NFR-024 Audit log record mutability = 0 — RETURN_RUNS, RETURN_SUBMISSIONS, RETURN_APPROVALS have no UPDATE/DELETE/TRUNCATE grants.

Policies satisfied

Policy Mode How
REP-001 AUTO Four return DTs (DT_RBNZ_BS2A, DT_RBNZ_BS13, DT_APRA_ARS_110_0, DT_APRA_ARS_210_0) materialised as Snowflake Dynamic Tables with target_lag='1 hour' + refresh_mode='FULL'. No manual assembly path (verified by tests/policy/REP-001-auto.test.ts + tests/integration/snowflake-objects.test.ts asserting SCHEDULING_STATE=ACTIVE).
REP-002 LOG Every cell row carries _source_lineage VARIANT (source_module + source_view + jurisdiction + position_date + fetched_at). The lineage is constructed in the staging models (stg_capital_ratios, stg_liquidity_ratios) and propagated through every UNION ALL in the return DTs (verified by tests/policy/REP-002-log.test.ts + dbt not_null test).
REP-005 GATE The submission orchestrator Lambda evaluates four sequential checks via src/orchestrator/gate.ts::evaluateGate(...). Any refusal aborts the submission, publishes return_gate_refused to MOD-076, and updates RETURN_RUNS.STATUS to APPROVAL_REQUIRED or FAILED. NO code path reaches the regulator HTTP client unless decision.allow === true — structurally enforced (one call site for regClient.submit(...), gated by the if (!decision.allow) return; early-out). Tests in tests/unit/gate.test.ts cover every refusal reason; tests/policy/REP-005-gate.test.ts verifies the orchestrator-level "regulator client never called on refusal" invariant.
NFR-024 LOG RETURN_RUNS, RETURN_SUBMISSIONS, RETURN_APPROVALS have no UPDATE/DELETE/TRUNCATE grants. INSERT on RETURN_RUNS + RETURN_SUBMISSIONS goes to ingest_role (orchestrator); INSERT on RETURN_APPROVALS goes ONLY to REGULATORY_SUBMISSIONS_PORTAL_ROLE (MOD-170 Streamlit form) — orchestrator must NOT write its own approval, separation-of-duties (verified by tests/policy/NFR-024-log.test.ts + tests/integration/return-approvals-immutability.test.ts).

Architecture

Hybrid module: - dbt + DCM for transformations and base tables (REGULATORY schema, 3 DCM-managed tables, 4 return DTs, 2 published views, 1 calendar DT, 2 Snowflake Alerts). - Lambda for the submission orchestrator (the REP-005 GATE owner; thin runner per ADR-046 "When Lambda IS appropriate" — orchestrator reads Snowflake state, evaluates the gate, and POSTs to external regulator endpoints. Does NOT execute SQL transforms or mediate intra-SD06 control flow). - Streamlit-in-Snowflake for the cell viewer + Finance approval form (legacy infra/snowflake/streamlits/ path per ADR-054 §"DCM v2 limitations — no Streamlit"). MOD-170 embeds this Streamlit.

Snowflake objects owned by MOD-036

Object Type Schema Notes
REGULATORY SCHEMA (DCM) Authoritative declaration. MOD-037/057/060/170 reference under this schema but do NOT redeclare it (DCM v2 error 001531).
RETURN_RUNS TABLE (DCM) REGULATORY Append-only audit; FR-220 + NFR-024. One row per assembly attempt.
RETURN_SUBMISSIONS TABLE (DCM) REGULATORY FR-220 — submission ref + ack + content hash; 7y retention.
RETURN_APPROVALS TABLE (DCM) REGULATORY REP-005 GATE / FR-807 / bank-wiki #35 Action B. Append-only. Written by MOD-170; read by submission orchestrators in MOD-036/037/057/060.
DT_RBNZ_BS2A DT (dbt) REGULATORY refresh_mode=FULL, target_lag='1 hour'. NZ jurisdiction. 7 cells per period.
DT_RBNZ_BS13 DT (dbt) REGULATORY NZ liquidity. 6 cells.
DT_APRA_ARS_110_0 DT (dbt) REGULATORY AU capital. 7 cells.
DT_APRA_ARS_210_0 DT (dbt) REGULATORY AU liquidity. 6 cells.
SUBMISSION_CALENDAR DT (dbt) REGULATORY FR-219; target_lag='1 hour' satisfies the 1h freshness requirement directly.
V_RETURN_PREVIEW VIEW (dbt) REGULATORY Unified cell + lineage view; the contract MOD-170's Streamlit consumes (ADR-046 §3).
V_RETURN_VALIDATION VIEW (dbt) REGULATORY Per-run validation summary; ALERT_RETURN_VALIDATION_FAILED reads this.
ALERT_RETURN_VALIDATION_FAILED ALERT (DCM) REGULATORY FR-218 — 15-min schedule; routes via BANK_SNS_INTEGRATION to MOD-076.
ALERT_DUE_DATE_APPROACHING ALERT (DCM) REGULATORY FR-217 — 60-min schedule; fires when due_date within 5 days.
MOD_036_STREAMLIT_STAGE STAGE REGULATORY Streamlit source stage (legacy infra/snowflake/ — ADR-054).
STREAMLIT_RETURN_BUILDER STREAMLIT REGULATORY Cell viewer + approval form; embedded by MOD-170.

SSM outputs

Path Value Consumer
/bank/{env}/risk-platform/prudential-return-builder/return-approvals-table REGULATORY.RETURN_APPROVALS MOD-037 / MOD-057 / MOD-060 (Action C — REP-005 gate clients), MOD-170 (Action D writes).
/bank/{env}/risk-platform/prudential-return-builder/return-runs-table REGULATORY.RETURN_RUNS MOD-170 (SoD display), MOD-171/172 (hub status).
/bank/{env}/risk-platform/prudential-return-builder/return-submissions-table REGULATORY.RETURN_SUBMISSIONS MOD-076 audit, MOD-171/172.
/bank/{env}/risk-platform/prudential-return-builder/return-preview-view REGULATORY.V_RETURN_PREVIEW MOD-170 embedded Streamlit cell viewer.
/bank/{env}/risk-platform/prudential-return-builder/submission-calendar REGULATORY.SUBMISSION_CALENDAR MOD-171 (executive risk view), MOD-172 (operations view).
/bank/{env}/risk-platform/prudential-return-builder/submission-orchestrator-arn (Lambda ARN) MOD-170 — publishes mod-036.submit-return EB events targeting this Lambda.
/bank/{env}/risk-platform/prudential-return-builder/event-source-name bank.risk-platform EB subscribers (MOD-076).
/bank/{env}/risk-platform/prudential-return-builder/streamlit-url REGULATORY.STREAMLIT_RETURN_BUILDER MOD-170 (embed), MOD-171/172.

Dependencies

Module Surface consumed Why optional?
MOD-032 RISK_CAPITAL.V_LCR_CURRENT, V_NSFR_CURRENT No — required for BS13 + ARS 210.0.
MOD-033 RISK_CAPITAL.V_CAPITAL_CURRENT, V_CAPITAL_BY_PORTFOLIO No — required for BS2A + ARS 110.0.
MOD-038 GOVERNANCE_META.V_QUALITY_SCORES, V_OPEN_BREAKS No — Finance signs off knowing DQ state.
MOD-102 Snowflake account + roles; REGULATORY_SUBMISSIONS_PORTAL_ROLE (outbound issue #37) No — but the role is conditional; the conditional grant block no-ops cleanly until MOD-102 ships.
MOD-104 KMS key, EventBridge bus No.
MOD-170 Reverse — MOD-170 writes RETURN_APPROVALS, publishes mod-036.submit-return No (runtime). MOD-036 is buildable independently; approval gate is dead-air until MOD-170 lands (by design — return state stuck at VALIDATED/APPROVAL_REQUIRED).

Event flow

  • Published (external boundary, ADR-046 §5):
  • bank.risk-platform / return_submitted → MOD-076 audit + MOD-048 ledger
  • bank.risk-platform / return_gate_refused → MOD-076 alarm-intake
  • Consumed (external trigger, ADR-046 §5):
  • bank.risk-platform / mod-036.submit-return ← MOD-170 (after Finance officer approves a return in the Streamlit form)
  • NOT used: intra-SD06 EB signals. MOD-036 reads MOD-032/033/038 output via dbt source() per ADR-046 §1/§2.

Build sequence references

  • bank-wiki entity: ../bank-wiki/source/entities/modules/MOD-036.yaml, .md
  • bank-wiki #35 Action B handoff: docs/handoffs/SD06-streamlit-dashboard-layer.handoff.md
  • Outbound issue #37 (MOD-102 role provisioning): ../bank-platform/docs/handoffs/MOD-102-sd06-streamlit-roles.handoff.md
  • env_role CI gap (affects MOD-038 today; MOD-036 unaffected — HAS_DCM=true): bank-wiki #39