CommunityPay

Enforcement Ledger &
Audit Trail

14 enforcement guards evaluate every transaction before it posts. Immutable decision records. SHA-256 integrity verification. The audit trail is not a feature. It is the architecture.

Guard chain evaluation before posting · Immutable EnforcementDecision on every journal entry · Two-phase persist design.
Six automated integrity checks · CPA audit portal · Institutional artifact generation with content hashing.

14 Enforcement Guards
6 Integrity Checks
12 Packet Generators
100% Decisions Logged
The ledger does not just record what happened. It governs what can happen. Every journal entry passes through the Enforcement Dispatcher before it persists. The dispatcher evaluates a chain of guards, captures the decision with a full signals snapshot, and creates an immutable record. No decision logged means a precise signal of bypass or bug. No exceptions.
01

The Enforcement Dispatcher

Every financial transaction flows through a single mandatory choke point. The Enforcement Dispatcher resolves the transaction type to a flow configuration, gathers signals, executes the guard chain, computes the outcome, and creates an immutable decision record. No journal entry is created without a decision.

Single Posting Interface
All journal entries are created via JournalEngine.post_transaction(). No direct model creation. The choke point is architectural, not procedural.
Two-Phase Enforcement
PRE_PERSIST evaluates before the atomic save. POST_PERSIST links to the persisted entry. PERSIST_ERROR captures failures. Enforcement telemetry is outside the atomic block so it never rolls back a valid journal entry.
10 Enforcement Flows
Flow Registry maps transaction types to guard sequences: bill_payment, fund_transfer, payment_receipt, invoice_creation, year_end_close, loan_origination, loan_payment, loan_accrual, trust_transaction, and journal_entry (catch-all).
Tenant isolation: All dispatcher queries are HOA-scoped. A journal entry lookup uses both the entry ID and the HOA foreign key. Cross-tenant access is structurally impossible, not just policy-prohibited.
02

The Guard Chain

Guards are stateless, independent, and composable. Same inputs produce the same outputs. Each guard checks one specific invariant. The Flow Registry maps transaction types to guard sequences, so different transactions face different enforcement paths.

Guard Category Enforces Override
BalanceGuard Invariant Validates debits equal credits on every journal entry No
ClosedPeriodGuard Temporal Blocks posting to closed fiscal years Yes
FundSegregationGuard Policy Prevents cross-fund cash movement in non-transfer entries Yes
TrustSegregationGuard Trust Prevents commingling of trust and operating funds (regulatory requirement) No
SubledgerGuard Invariant Validates subledger references exist on journal entry lines No
InvariantGuard Invariant Enforces transaction type invariants (correct account types, line counts) No
FundEligibilityGuard Eligibility Reserve fund eligibility checks Yes
BillPaymentGuard Policy Bill approval status and duplicate payment prevention No
VendorRiskGuard Compliance Blocks payment to vendors with debarment, expired license, or expired insurance Yes
DisbursementComplianceGuard Compliance State-specific disbursement rules: board approval thresholds, dual signature, reserve restrictions Yes
ReversalGuard Invariant Validates reversal source entry exists and is valid No
LoanCovenantGuard Debt Evaluates debt covenants (DSCR, reserve ratio, delinquency) at loan and HOA scope Yes
PaymentSplitGuard Debt Validates principal + interest + fees split in schedule-locked and schedule-flex modes No
InterestCalculationGuard Debt Recomputes accrual math against loan terms, day-count convention, and index rates No
Guard manifest is CI-enforced. Guards cannot be silently removed or renamed. Every guard ID is stable across the entire history of the system. Changing an ID would break the audit trail linkage to historical decisions.
03

Immutable Decision Records

Every journal entry has a corresponding EnforcementDecision record. The decision captures the full guard chain results, the policy_snapshot_hash (SHA-256 of the guard manifest for tamper detection), and the outcome: ALLOW, BLOCK, OVERRIDE, or ERROR. The record is immutable after creation via ImmutableModelMixin. Unique constraints prevent duplicate POST_PERSIST decisions per journal entry.

Guard Results
guard_results JSON stores each guard's outcome (PASS, FAIL, SKIP), reason codes, and elapsed_ms. guards_expected vs. guards_ran shows if any guards were skipped. blocking_guard, blocking_code, and blocking_reason identify what stopped a transaction.
Correlation & Tracing
correlation_id links PRE_PERSIST, POST_PERSIST, and PERSIST_ERROR records for the same transaction attempt. decision_seq (0, 1, 2) enforces ordering. funds_touched and amount_cents capture the financial scope of the decision.
Posting Rationale
The journal entry's posting_rationale field contains structured JSON explaining why the entry was posted: policies evaluated, approval chain, and decision reference.
Append-Only Ledger
Journal entries are never modified or deleted. Corrections are made with reversal entries that pass through the same guard chain. Complete history is preserved.
Period Locking
Fiscal periods transition through OPEN, CLOSED, and LOCKED states. The ClosedPeriodGuard blocks posting to any non-open period. No backdating. No silent adjustments.
Decision Explorer
HOA admins browse enforcement decisions with filters by outcome, flow name, and date range. Detail view shows full guard chain with pass/fail badges. Linked to the associated journal entry.
04

Ledger Integrity Verification

The Ledger Integrity Scan runs six automated checks against the general ledger. It produces an immutable IntegritySnapshot with a SHA-256 content hash. Findings are categorized by severity. The scan runs daily via Celery and is available on-demand from the Integrity Scan Viewer.

Balance Check
Every journal entry is verified: debits must equal credits. An imbalance is a CRITICAL finding.
Orphan Line Check
Journal entry lines without a parent entry are flagged. Orphaned data indicates a data integrity issue.
Enforcement Decision Check
Every journal entry must have a corresponding POST_PERSIST enforcement decision. A missing decision is CRITICAL.
Fund Assignment Check
Journal entries with null fund assignment are flagged. WARNING severity (legacy data may predate fund tracking). Finding type: ENTRY_FUND_CODE_NULL.
Closed Period Check
Counts journal entries posted within closed or locked fiscal period date ranges. Informational — the ClosedPeriodGuard prevents new entries at posting time.
Control Account Reconciliation
GL control account balances are compared against subledger totals for AR, AP, and Loans. Tolerance: $0.02. Variances above $100 are CRITICAL.
Every scan produces an immutable snapshot. The IntegritySnapshot includes a SHA-256 content hash computed from the snapshot ID, HOA, as-of date, checks run, check results, and invariant counts (total JEs, orphaned, unbalanced). Snapshots use ImmutableModelMixin — .save() rejects updates. IntegrityFinding records use fingerprint-based deduplication (one open finding per HOA per fingerprint); repeat occurrences increment occurrence_count. CRITICAL findings block money movement via has_blocking_findings().
05

Override Governance

Overrides are scope-based, expiring, and tracked. An override is not a bypass. It is a documented, authorized, time-limited exception with complete audit telemetry. Five guards cannot be overridden at all.

Override Scope Target Max Duration
CLOSED_PERIOD Post to a closed period (requires fiscal year + date range) 30 days
FUND_SEG Cross-fund cash movement (requires specific fund) 14 days
YEAR_CLOSE Close with imbalance (requires fiscal year) 90 days
INTEGRITY_GATE Override integrity gate block 24 hours
VENDOR_RISK Override vendor risk block (requires documented reason) 24 hours

Override Structure

  • Required expiration date on every override (no permanent overrides)
  • Minimum 20-character reason (immutable after creation)
  • Authorized-by user, timestamp, and IP address captured
  • original_check_result preserves the bypassed check as JSON snapshot
  • Scope-specific target constraints validated in .clean()

Usage Telemetry

  • Every usage logged as an AuditOverrideUsage record
  • Links to the journal entry that consumed the override
  • times_used counter on the override record
  • last_used_at timestamp for monitoring
  • Full usage context captured as JSON
Eight non-overridable guards: BalanceGuard, TrustSegregationGuard, SubledgerGuard, InvariantGuard, BillPaymentGuard, ReversalGuard, PaymentSplitGuard, and InterestCalculationGuard cannot be overridden under any circumstance. Six guards accept documented, expiring overrides.
06

Fund Integrity & Non-Commingling

Operating funds, reserve funds, trust funds, and special funds are structurally separated. Two guards enforce the boundary: FundSegregationGuard prevents operating/reserve cross-posting, and TrustSegregationGuard prevents trust/operating commingling. The trust guard cannot be overridden.

Workflow-Based Controls Ledger-Driven Authorization
Did the right people click approve? Is this transaction structurally permissible?
Controls depend on human compliance Controls enforced by the guard chain before posting
Violations detected after the fact Violations prevented before the journal entry persists
Audit trail shows what humans did Audit trail proves system correctness with signal snapshots
Board turnover breaks institutional memory Guards are encoded in code, survive every turnover
07

Institutional Artifacts

The audit trail produces institutional-grade artifacts for external consumption. Every artifact is generated from live ledger data, hashed with SHA-256, version-chained, and stored in the Vault. Board members can attest to artifacts with content-hash binding at signing time.

Packet Name Audience
CEP Close Evidence Pack Auditors. 12 evidence sections, 14 risk flags. Generated at period close and lock.
RC Resale Certificate Title companies, escrow officers. 10 compliance profiles across 7 states.
RSR Reserve Funding Status Report Boards, reserve study firms. 30-year projection, component register.
LDS Loan Disclosure Statement Lenders. Schedule hash, subledger/GL reconciliation, covenant status.
FADR Funds Authorization & Disbursement Record Boards. Payment evidence chain from approval to settlement.
GCA Governance Controls Attestation Boards. Controls effectiveness summary with scoring.
FSR Fiduciary Shield Record Boards, D&O insurers. Board fiduciary duty compliance evidence.
BP Board Packet Board meetings. Bundled financial statements for monthly review.
CARI 4 Report Types (Lender, Insurer, Title, Buyer) Third-party consumers. Consent-gated risk reports via authenticated API.
Content hash binding at signing. When a board member attests to an artifact, the SHA-256 content hash is frozen into the ArtifactAttestation record at signing time. If the underlying artifact is restated after signing, the attestation's is_valid property detects the hash drift. Restatement creates a new InstitutionalPacket with restatement_of FK, is_restatement=True, and restatement_reason. The original receives a RESTATED PacketEvent. PII redaction is the one exception to packet immutability — uses QuerySet.update() with a PII_REDACTED PacketEvent for GDPR compliance.
08

CPA Audit Portal

External CPAs access HOA financial data through a token-gated, unauthenticated, read-only portal. No Django login required. Every page access creates an immutable AuditEngagementEvent with resource_type tracking. Engagement types: Review, Audit, Compilation, Tax Preparation, and Agreed-Upon Procedures.

Token Security
Raw access token shown once at creation. Only the SHA-256 hash and 12-character prefix are stored. Lookup via prefix, constant-time hash comparison via hmac.compare_digest(). Same pattern as CARI API keys.
13 Portal Sections
Scope manifest controls access per engagement. Sections: overview, trial balance, fund reconciliation, fund statements, journal register, chart of accounts, AR/AP aging, enforcement decisions, integrity scans, close packages, artifacts. Plus 6 CSV export endpoints.
Access Telemetry
Every page view, download, and data export logged as an immutable AuditEngagementEvent (CREATED, ACCESSED, DOWNLOADED, EXPIRED, REVOKED). IP address, user agent, and resource_type captured on each event. .save() rejects updates.
09

Compliance Reporting

Enforcement Reports

  • Decision Explorer: filter by outcome, flow_name, date range
  • Detail view: full guard chain with PASS/FAIL/SKIP badges
  • Override report: scope, reason, times_used, expiration
  • Staff enforcement dashboard (platform-wide, per-HOA drill-down)
  • policy_snapshot_hash tamper detection across decisions

Financial Verification

  • Integrity scan history with fingerprint-based deduplication
  • Fund reconciliation verification
  • Control account reconciliation (AR, AP, Loans vs. GL, $0.02 tolerance)
  • Bank statement import (BAI2, OFX/QFX, CSV with format auto-detection)
  • Debt subledger/GL reconciliation via LoanReconciliationRun audit trail

Governance is not a workflow. It is a system property. The architecture ensures that money cannot move unless the guard chain has determined it is permissible. Every decision is preserved. Every signal is captured. Every artifact is hashed. Fiduciary duty is encoded in code, not delegated to manual controls.

Audit-Grade Compliance.
Built Into the Architecture.

14 enforcement guards. Immutable decision records. SHA-256 integrity verification. The audit trail that fiduciary duty demands.

CommunityPay