Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

234 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Latchkey

A learning project in event sourcing + Domain-Driven Design, built as a simulation of the payments seam in residential property management (NSW).

What it is

Latchkey models the boundary between two bounded contexts:

  • Property Management (PM) — the core domain: tenancies, lease terms, expected rent, and therefore arrears. This is the deep context.
  • Accounts — a thin supporting edge that emits payment facts (money received, reversals).

The interesting problem is how a payment fact born in Accounts crosses into PM and reconciles into arrears (arrears = expected − received) — translated at an anti-corruption layer, never folded raw across the seam.

Thesis / deliverable: a tenancy timeline — a complete, hash-chained history of a tenancy (rent falling due, payments, notices, corrections) legible enough to serve as evidence in an NCAT (tribunal) arrears case. That timeline is the payoff of an append-only event log with correction-by-compensation (never mutation).

It's a simulation, not production: events are seeded, and a tenant-behaviour engine plus scheduled jobs advance simulated time so histories accrue realistically rather than all at once. Grounded in the NSW Residential Tenancies Act 2010 for realism — not legal advice.

Design docs (the spec)

The model is worked out in docs/ and is the spec to build against:

  • docs/domain-model.md — the deep model: events, the Tenancy aggregate, invariants, accrual, arrears (the time-based 14-day trigger), the two ACLs, and value objects.
  • docs/context-map.md — the subdomain map: what's core / supporting / generic, and where the seams (language flips) are.
  • CONTEXT.md — the ubiquitous language: terms only (ledger, arrears, property_ref, tenancy), the words the code and docs agree to use.
  • docs/adr/ — the decision log: why the model is shaped the way it is (e.g. ADR 0003 chose raw Commanded over Ash-native events). Read these before proposing a redesign.

Status

The write side is live. Event sourcing runs on raw Commanded + its Postgres EventStore (chosen over Ash-native events in ADR 0003), with Ash for the read model:

  • Property Management (lib/latchkey/property_management/) — the Tenancy aggregate with its commands and events, the arrears projector/fold (the 14-day gate), and the tenancy-timeline read model.
  • Accounts (lib/latchkey/accounts/) — the thin edge emitting payment facts, translated into PM through the payment ACL.
  • Simulation (lib/latchkey/simulation/) — the seeded catalogue, a deterministic world-line, tenant-behaviour profiles, and an Oban-driven sweep. "Now" is wall-clock time (Date.utc_today(), Australia/Sydney — ADR 0005): back-dated history is seeded and the sweep reveals events as they fall due, so histories accrue realistically rather than all at once.
  • Inspector (/inspector, lib/latchkey_web/live/inspector/) — the app's front door: a LiveView for browsing the event log, per-tenancy streams, the ledger, and the timeline. It's the primary way to see the event sourcing at work.

Stack

Phoenix 1.8 · Ash 3 + AshPostgres (read model) · Commanded 1.4 + EventStore (write side) · Oban (simulated-time sweep) · PostgreSQL (Ecto/Postgrex) · Bandit · LiveView · Tailwind.

Getting started

  • mix setup — install deps, provision the Ash and EventStore databases, build assets, seed
  • mix phx.server (or iex -S mix phx.server) — start the server

Then visit localhost:4000 — the root redirects to /inspector, the event-log front door. Start there to see the model running.

Run mix precommit before committing — it compiles with warnings-as-errors, prunes unused deps, formats, and runs the tests.

About

Event-sourced Property Management ↔ Accounts: a DDD / event-sourcing learning project (Elixir · Ash · Phoenix · Postgres)

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages