rosneri / doorloop
Senior Full-Stack Engineer · ~2.7 years · payments & banking

DoorLoop

Senior software engineer specializing in payments, banking, and platform infrastructure. Over ~2.7 years at DoorLoop (a property-management SaaS), I grew from feature delivery into owning the company's embedded payments & banking domain end-to-end, while building cross-cutting libraries the rest of the backend depends on and setting engineering conventions adopted across the codebase.

This page describes the engineering patterns, ownership, and outcomes of the work. Internal identifiers, business-rule constants, and security implementation details are intentionally omitted.

$ cat ~/doorloop/at-a-glance.txt

At a glance

~2.7 yr
tenure (primary monorepo)
760 +
non-merge commits
100 +
pull requests reviewed
25
shared libraries authored
4
custom code generators
25
Claude Code plugins
2
internal repositories founded
$ git log --grep="highlight" --oneline

Highlights

The work I'd point to first — where I owned the architecture, drove the project, or built the foundation the rest of the team builds on.

Embedded Financing / Flow of Funds domain owner

Lead engineer on the money-movement engine behind embedded banking — balances, transfers, and the accounting side-effects they produce. I established the reactive event-bus + Ports-&-Adapters architecture the banking team now follows, and mentored contributors through design review.

Jump to the write-up ↓
Cash Payments (in-person cash rail) project lead

Drove a new cash rent-payment rail end-to-end, letting residents without a bank account or card pay rent in cash at retail locations. Owned the request-path hardening and a staged beta rollout.

Jump to the write-up ↓
Platform foundations cross-cutting / tech-lead-level

Built the libraries the whole server relies on — compile-time money safety, a standard scheduling library, a vendor-agnostic feature-flag layer, messaging topology, and DDD code generators — and authored the conventions and guides others build on.

Jump to the write-up ↓
Founded two internal repositories founder / co-lead

An internal Claude Code plugin marketplace (team-wide AI tooling) and an internal back-office banking dashboard (full-stack). Created and (co-)led both.

Jump to the write-up ↓
Autopay project lead

Automatic recurring rent collection with a fraud-aware payment-limit model; drove the platform-fee and grace-buffer precedence design.

Jump to the write-up ↓
Skills & toolkit breadth

Deepest in TypeScript, fintech (payments, treasury, double-entry accounting), and platform engineering — plus the AI agent tooling I build for the team.

Jump to the write-up ↓
$ cat ~/doorloop/leadership.md

Engineering leadership & breadth

Code review & mentoring

100+ pull requests reviewed. Anchored the banking effort as a multi-engineer workstream — guiding and reviewing colleagues' contributions through design and code review.

Conventions & standards

Authored the repository's engineering guides and 20+ library README/guide files; introduced the standards lint ruleset and the DDD architecture conventions encoded in the code generators.

Reusable foundations

25 libraries and 4 code generators — money, scheduling, feature toggles, messaging topology, a payment-provider client, durable-workflow common code — that the broader server consumes.

Internal repositories founded

An internal Claude Code plugin marketplace packaging 25 plugins (the team's AI-tooling ecosystem), and an internal back-office banking dashboard — a full-stack app (Nx · NestJS + Fastify · React + Vite + Tailwind · Prisma/PostgreSQL · Zod · Playwright) co-led as one of its two primary engineers.

$ ls ~/doorloop/work — tap any item to expand

Engineering work

Everything I owned, led, or contributed — grouped by domain. Filter by area or by involvement, and tap any item for the full write-up: problem, the decision I drove, architecture, and outcome.

Payments & Banking
ledCash Payments

In-person cash payments for rent, end to end: payment slips, money-transfer tracking, account-number generation, and partial/duplicate guards, shipped behind a staged beta rollout with a hardened request path.

Resident pays cash
Retail network
Control number → receive
Partial/duplicate guard
Post to lease
Payment-slip PDF

Problem. Residents without a bank account or card had no way to pay rent digitally, and building an in-person cash rail meant standing up a regulated, fraud-sensitive money path demanding idempotency, a hardened request path, and careful rollout.

Decision I drove. Integrate a retail money-transfer network as a cash rail — propagate the control number through transaction IDs and the receive-payment flow, detect partial/duplicate payments, generate payment account numbers on demand, produce branded payment-slip PDFs, harden the request path, and ship behind fine-grained feature targeting as a staged beta.

Impact. Residents can pay rent in cash at retail locations, with duplicate/partial protection on a real-money path.

Leadership. Drove the request-path hardening (described at the outcome level) and the staged rollout.

  • Control-number propagation — the money-transfer control number flows through transaction IDs and receive-payment so a cash payment reconciles to the right lease.
  • Duplicate/partial safety — detection of partial and duplicate payments on the cash path.
  • On-demand account numbers + slips — payment account-number generation and branded slip PDF generation, extracted into a dedicated service.
  • Hardened, staged rollout — request-path security hardening and a staged beta gated by feature targeting.
ownedEmbedded Financing / Flow of Funds / Treasury

Money-movement engine that routes accounting side-effects reactively off an event bus, tracks per-transaction availability, and promotes balances between account tiers.

Treasury webhooks
Event producer
Money-movement bus
Accounting / Availability / Ledger
Lazy tier promotion

Problem. Treasury money movement produces many side-effects (journal entries, availability tracking, balance promotion) that were tightly coupled to webhook handlers, making the flow brittle and hard to extend.

Decision I drove. Make accounting reactive — handlers publish money-movement events to a bus, and independent consumers react — structured as Ports & Adapters (DDD) and gated behind a feature flag.

Impact. Decoupled ingestion from accounting so new consumers attach without touching the payment-provider path, enabling safer rollout.

Leadership. Set the event-driven + hexagonal pattern the banking team now follows.

  • Reactive routing — side-effects published as events and consumed off the bus, decoupling provider ingestion from accounting.
  • Lazy promotion — account rows are promoted lazily when funds are received, with telemetry and resilience around the persist/publish step.
  • Observability — promotion emitted as a distributed-tracing span via a dedicated tracer; telemetry awaited so failures surface.
  • Honest domain modeling — typed domain errors with read-only codes, real system-account validation, and precise transfer types instead of loose casts.
  • Read-only transfer UX — embedded transfers render a read-only dialog with per-line attribution, redirecting edits away from the standard flow.
  • Resilience — log-and-rethrow on persist/publish failure; surfaced outbound balance-step failures for retry; tracked non-retryable provider rejections.
ownedBanking Record Service

The canonical ledger of money movement, built as a DDD library partitioned for a future lift into its own microservice.

Money-movement events
Event listener
ApplyRecord use-case
Transaction / Transfer / Audit
Persistence adapter

The canonical record of money movement, deliberately built as a DDD library partitioned into domain / application / infrastructure so it can later be lifted into its own microservice without rewrites. It is event-fed and agnostic of which money-movement event produced a record — the semantic translation lives on the producer side, behind a generic contract block.

  • Domain entities — Transaction (end-to-end movement), Transfer (a single hop linked to its parent), Audit (append-only, discriminated).
  • Minimal lifecycle — transactions and transfers share a started → finished status; richer human-facing labels are derived, not stored.
  • Single entrypoint — one use-case branches on recordType × status; the listener calls it once per record.
  • Clean layering — domain + application in one library, persistence adapter as infrastructure, message-queue consumer/publisher as the server adapter.
ledIncoming-Transactions processing

Risk assessment, reserve guardrails, and platform-account → connected-account transfers for incoming funds.

Incoming transaction
Activate
Risk assessment
Platform→connected transfer
Reserve guardrails

Problem. Incoming funds must be risk-assessed and reserve-guarded before money moves from the platform account to a connected account; the legacy path did this imperatively with no durable state.

Decision I drove. Model incoming-transaction processing as a durable workflow delivered in discrete iterations — activate → risk assessment → transfer → reserve guardrails — and extract reusable foundations (a typed money value object and a payment-provider client) out of it.

Impact. Established the risk-and-reserve model for incoming funds and libraries that outlived the feature.

Leadership. Later set the direction to supersede the durable-workflow orchestration with the reactive event-driven architecture — a deliberate pivot carrying the learnings forward.

  • Iterative delivery — each iteration a standalone, independently-shippable change, reducing risk on a money path.
  • Foundations extracted — a money value object and a payment-provider client lifted out for reuse across banking.
  • Honest pivot — the durable-workflow approach was deliberately retired in favor of the event-driven model; direction set, not just executed.
ownedBalance Process

Scheduled batch computation and reconciliation of merchant balances, with expedited ACH for outbound treasury transfers.

Scheduled run
Discover merchants
Batch fan-out
Process-balance use-case
Reconcile
Outbound / expedited ACH

Problem. Every merchant's treasury balance must be reconciled regularly and excess funds paid out, reliably and idempotently across a large, growing merchant set.

Decision I drove. Separate business logic from orchestration — a pure single-merchant use-case (DDD) plus a scheduling layer built on my own scheduling library that discovers eligible merchants, fans out in batches on a cron, and is feature-flag-guarded and idempotent per run.

Impact. Automated balance reconciliation and payouts, including expedited ACH for outbound transfers.

Leadership. Set the orchestration-vs-business-logic boundary and used the scheduling library as the team standard.

  • Clean separation — the process use-case knows nothing about scheduling; the scheduling layer owns discovery, cron, batching, and idempotency.
  • Operability — feature flag to disable the schedule, a payout-eligibility endpoint with back-office UI, and manual-trigger endpoints for debugging.
ledAutopay

Automatic recurring rent collection: platform fees, manager-side recurring payments, payment-method editing, and a payment-limit grace buffer.

Scheduled run
Validation (limit + grace)
Charge via merchant
Apply platform fee

Problem. Automatic recurring rent collection had to handle manager-initiated recurring payments, platform fees, payment-method edits, and monthly-limit validation — while a legacy daily-processing model was error-prone and a fraud-aware limit policy was missing.

Decision I drove. A facade-fronted feature (service / data-access / validation layers) that retired daily processing for the correct schedule, added platform-fee handling and manager-side recurring payments, enforced monthly-limit validation, and integrated a payment-limit grace buffer.

Impact. Reliable automated collections with a correct fee-and-limit model.

Leadership. Led the effort and drove the fee, grace-buffer, and validation design.

ownedPayment-Limit Grace Buffer

Lets payments slightly exceed monthly limits for low-risk merchants while guarding against fraud.

Encodes a nuanced business rule — allow payments to slightly exceed monthly limits for low-risk merchants — as an explicit precedence of “working limits” rather than scattered conditionals, implemented as a use-case-driven application layer. The grace buffer is granted only to merchants without disputes, and the working-limit precedence is expressed once and reused.

ledEmbedded lending

Loan offers, distribution of a single advance across multiple properties, and deposit accounting.

Problem. Offering merchants embedded loans required a loan-offer flow, a way to allocate a single advance across multiple properties, correct phased deposit accounting, and operational visibility to support a money product in beta.

Decision I drove. A loan-offer flow with multi-property distribution of a single advance, phased deposit accounting, dedicated logging and an API error page for diagnosis, an accounts migration, and a pause capability for safe operation.

Impact. Shipped embedded lending with multi-property allocation and operational visibility.

Leadership. Led the epic end-to-end.

  • Multi-property allocation — distribute one advance across multiple properties with correct per-property accounting.
  • Phased deposit accounting — deposit accounting delivered in phases to de-risk the money path.
  • Operability — dedicated logging, an API error page, an accounts migration, and a pause capability.
ownedGeneric webhook handler

A reusable, message-queue-backed webhook ingestion library with tuned retry/TTL semantics.

Provider webhook
Enqueue to queue
Async consumer
Process / bounded retries

Problem. Payment-provider webhooks arrive synchronously with tight acknowledgement timeouts; a slow or failing handler risks dropped events with no real retry story — dangerous on a money path.

Decision I drove. A generic handler that immediately enqueues each event to a message queue and processes it asynchronously with bounded retries and correct queue TTL, decoupling ingestion from processing so a failure retries instead of losing the event.

Impact. Reliable event processing across banking.

Leadership. Set the durable-ingestion pattern that other consumers reuse.

  • Decoupled ingestion — the webhook endpoint acknowledges fast; processing happens off a durable queue.
  • Bounded retries — TTL-aligned retry timing so retries are not silently dropped.
ownedTreasury Income

Recognizes funds landing in the treasury account: tracks received credits/debits, confirms payouts, handles failed credits, and reverses direct/platform transfers.

Received credit/debit
Event predicate
Track / Confirm / Payout / Failed / Reverse

Problem. Funds landing in the treasury account arrive as async events with several meanings — an approved credit, a payout received, a failed credit, or a transfer to reverse — each needing distinct income recognition and accounting.

Decision I drove. Model each event-meaning as its own use-case behind ports and isolate event branching into pure domain predicates, so the semantics are unit-testable and the library is decoupled from the provider and the database.

Impact. Correct income recognition, payout confirmation, and transfer reversal.

Leadership. Set the convention of pushing event-classification into testable predicates rather than handler if-trees.

  • Use-case per semantic — a distinct, single-purpose use-case for each event meaning.
  • Pure domain predicates — classification isolated from side-effects and unit-tested.
  • Ports & adapters — accounting, merchant, telemetry, and feature-toggle ports; fed by the generic webhook handler.
ownedBanking Alerts

Configuration-driven operational alerting on money-movement events for real-time visibility.

Problem. Money movements can fail or reach states the team must hear about immediately, but there was no operational alerting on the bus.

Decision I drove. A small DDD library that maps configured money-movement events to alerts behind a port, with a domain config declaring which events alert — so alerting is declarative and decoupled from the transport.

Impact. Real-time operational visibility.

Leadership. Set the config-driven alerting convention.

  • Declarative config — a config lists which events trigger alerts; adding an alert is a config change, not new code.
  • Port-isolated transport — the alert transport is abstracted behind a port so the service stays testable.
ownedFlow-of-Funds Tracking / Banking Identity

Stamps merchant and account identity onto tracked money-movement events, with reusable identity-access methods.

Problem. Tracing a payment through the system was hard because tracked events lacked consistent identity — which merchant, and which account a step belonged to — making support and debugging slow.

Decision I drove. A tracking layer that stamps merchant and account identity onto every tracked event, with charge handling extracted into the tracking layer, plus a shared identity library exposing reusable access methods.

Impact. End-to-end traceable money movement with consistent identity context.

Leadership. Set the identity-access convention reused by other banking libraries.

ownedMerchant Onboarding

Atomically provisions a new merchant's chart-of-accounts tree and external-account link, then publishes an onboarding-completed event.

Onboarding triggered
Transaction
Create account tree
Link external account
Lock system parent
Publish completed event

Problem. When a merchant onboards, its accounting structure must be provisioned correctly — a parent + financial-account chart-of-accounts tree, a linked external account, a locked system parent — and done ad-hoc this risks partial trees and missed notification.

Decision I drove. An onboarding handler that creates the account tree, links the external account, and locks the system parent inside a single transaction, with typed errors and an onboarding-completed event published behind a port.

Impact. Consistent, atomic merchant provisioning with reliable downstream notification.

Leadership. Owned the transactional-provisioning + typed-error pattern, with live integration tests for the flow.

contributedPlaid

Bank-feed transaction matching with write-conflict resilience and correct pending-transaction handling.

Problem. Transaction auto-matching hit write conflicts under concurrency, pending transactions were miscounted, and counts mismatched between sources.

Decision I drove. Make auto-match concurrency-safe — retry on write conflict within a session, correct pending-transaction handling, and reconcile the count mismatch, with null-safety hardening throughout.

Impact. Dependable bank-feed reconciliation and fewer support escalations.

Leadership. Executed precise fixes on an existing integration.

contributedCheckbook (printed checks)

Printed-check disbursement with double-payment prevention and voided-check handling.

Problem. The integration could double-issue payments (real money), re-send already-voided checks, and a mapping error could crash the process.

Decision I drove. Make disbursement idempotent, stop resending voided checks, and harden response mapping so a bad payload cannot crash the process.

Impact. Eliminated a duplicate-disbursement risk and a crash on a money path.

Leasing & Tenants
ledListing Syndication

Publishes rental listings to major partners (Zillow, Apartments.com, Zumper) via versioned MITS XML, with validation before publish and per-environment separation.

Problem. Each listing partner speaks its own XML dialect, and a malformed feed — or a test listing reaching a live feed — has real consequences.

Decision I drove. Versioned MITS-XML generation with per-partner generators (Zillow, Apartments.com, Zumper), a validation endpoint that catches malformed XML before publish, manual MITS-version selection, and separate syndication environments so test listings never reach live feeds.

Impact. Reliable multi-partner listing syndication.

Leadership. Led the feature end-to-end.

ledRental Applications

The applicant wizard (identity, employment, income), group/“join” applications, prospect discovery, invite/resend abuse controls, and credit-bureau screening.

Problem. The applicant funnel had gaps across a multi-step wizard, group (“join”) applications, prospect/tenant discovery, and credit-bureau screening — validation holes, region-specific screening fees, dispute handling, and resume-after-leave.

Decision I drove. A typed-subdoc wizard with per-section validation, group applications modeled as a group + participants, a discovery surface unifying tenants and prospects, and credit-bureau integration with dispute logging and region-specific fee defaults.

Impact. A more reliable applicant intake and screening funnel feeding lease creation.

Leadership. Led the discovery effort and drove wizard/validation/screening correctness.

ledFuture Charges / Rent Reminders

Pre-posts upcoming rent charges and reminders on a per-lease, per-date job schedule with strict timezone correctness.

Per lease
Job per date
Pre-post charge
Send reminder
Balance recalc (guarded)

Problem. Pre-posting upcoming rent charges and sending reminders accurately is a scheduling-granularity and timezone problem — charges must post on the right local date per lease, and balance recalculation must not double-count.

Decision I drove. A per-lease, per-date job model with an overdue job and awaited cancellation, strict timezone correctness across server and tenant-portal date displays, and a carefully iterated balance recalculation with mismatch logging.

Impact. Accurate upcoming-charge visibility and reminders for residents and managers.

Leadership. Led the feature end-to-end.

  • Per-lease, per-date scheduling — a job per lease per date, with an overdue job and awaited cancellation.
  • Timezone correctness — consistent local-date handling across server and tenant-portal displays.
  • Balance integrity — total-balance recalculation with daily lease-stats updates and mismatch logging.
contributedTenant Portal

Resident-facing UI for upcoming charges, lease details, and payment dialogs.

Problem. Residents needed accurate visibility into upcoming charges and reliable payment dialogs, with correct dates/timezones and predictable auto-apply behavior.

Decision I drove. Surface future charges (recurring transactions + outstanding balance) in the portal with timezone-correct dates reusing the rent-reminder date logic, refresh the payment dialogs, and make tenant-side auto-apply explicit.

Impact. A clearer resident payment experience, consistent with the Future Charges and Cash Payments work.

Leadership. Executed the UX + integration on the tenant side.

contributedOwner Contributions — Auto Deposit

Automatic deposit of owner contributions.

Problem. When an owner contributed funds, the matching deposit had to be handled manually, and an inappropriate digital-payment option was exposed on the contribution path.

Decision I drove. Automatically create the deposit accounting entry on an owner contribution (design + implementation) and remove the inappropriate payment option so the flow matches how owner money actually arrives.

Impact. Less manual accounting on owner contributions and a cleaner contribution UX.

Leadership. Drove the feature end-to-end, from design through build.

Accounting & Reporting
ledJournal Entry Printing

Printable journal entries and deposit slips with correct currency formatting and quick actions.

Problem. Property managers needed accurate, printable accounting documents — deposit slips, payment receipts, journal-entry printouts — with correct currency formatting and quick access, and printed entries had to be protected from silent edits or duplication.

Decision I drove. A printing system spanning deposit slips (routing number + dates), payment-dialog print, tenant filtering, currency-sign formatting, and quick-action entry points, plus disable-duplicate/edit guards on printed entries — underpinned by a register/transactions refactor.

Impact. Reliable printable accounting documents for PM workflows.

Leadership. Led the effort end-to-end, including the UX review.

contributedQuickBooks Online integration

Links payments/deposits to QuickBooks and mirrors the chart-of-accounts hierarchy.

Problem. Syncing accounting to QuickBooks Online was incomplete (payments/deposits not linked, account hierarchy not reflected) and opaque when it failed.

Decision I drove. Link payments and deposits into QuickBooks, mirror the chart-of-accounts parent hierarchy so structures match, and intercept outbound requests with structured logging so failures are debuggable.

Impact. More accurate sync and far faster diagnosis of sync failures.

Leadership. Contributed the link/mirror logic and the observability layer.

contributedReconciliation

Bank-reconciliation drafts and relevant-transaction reporting.

Problem. A reconciliation could not be saved as a draft once the difference reached zero (forcing rework), and the report did not scope to the transactions actually relevant to the period.

Decision I drove. Allow saving/forcing a reconciliation draft even at a zero difference, and scope the reconciliation report to relevant transactions only.

Impact. A smoother reconciliation flow and accurate period reports.

Leadership. Executed targeted workflow/report fixes.

ledChart of Accounts

Classic chart-of-accounts UX plus a merchant-account chart-of-accounts facade and payout/deposit account routing.

Payout event
Resolve deposit account
Financial / external chart
By-intent facade

Problem. The classic chart-of-accounts UI had usability gaps, and embedded financing needed a merchant-account chart-of-accounts whose payout/deposit routing was correct, free of duplicate names, and accessed consistently across many call sites.

Decision I drove. Ship the classic UX fixes, then introduce a facade that migrates call sites “by intent” so every account access goes through one intent-revealing API, route deposits to the correct account tier by destination, and guard against duplicate group-account names.

Impact. Consistent, intent-driven account access and correct payout/deposit routing.

Leadership. Owned the facade design — a codebase-wide refactor of how account access is expressed.

contributedReporting correctness

Precision and correctness fixes across trial balance, balance sheet, AR aging, rent roll, and owner/account statements.

Problem. Several core reports produced wrong or incomplete numbers — trial-balance precision drift, an incorrect balance-sheet condition, a missing AR-aging as-of-date filter, rent-roll missing totals.

Decision I drove. Fix the trial-balance precision calculation, correct the balance-sheet condition, add the AR-aging as-of-date filter, restore rent-roll totals and owner-statement PDF columns, and enrich debit/credit-imbalance logging.

Impact. Trustworthy financial reports for PM and owner workflows.

Leadership. Executed precise correctness fixes across the suite.

Platform & Infrastructure
ownedFeature Toggles → OpenFeature

Migrated a bespoke flag system to the vendor-agnostic OpenFeature standard, with local evaluation and targeted rollouts.

Replaced a bespoke toggle system with the OpenFeature standard to get a vendor-agnostic API while keeping existing types and behavior — a drop-in migration rather than a rewrite, backed by a provider supporting local evaluation for low-latency reads.

  • Server and client APIs over the OpenFeature SDKs.
  • Context-aware targeting (specific users, tenants, test accounts, after-date) with graceful fallbacks.
  • Migration utilities for legacy flags and decision de-duplication.
ownedLogging Infrastructure

Structured logging, faithful error preservation, production source maps, and an application-logs query endpoint.

Focused on diagnostic fidelity — preserving the original error and stack rather than wrapping or flattening it — plus making logs queryable in production.

  • Middleware that preserves the original error, with appropriate levels and undefined-safety.
  • Source maps for production stack traces and release-correlation metadata.
  • An application-logs query endpoint and improved log identification.
ownedDurable Workflows

Durable workflow execution with client bootstrapping, a code generator, and full observability.

Introduced durable workflow execution to the server with first-class observability and developer ergonomics — a code generator so new workflow libraries follow the same shape, and distributed tracing wired in from the start.

  • Server-side client initialization with clean worker shutdown on restart.
  • A code generator for workflow libraries plus an example workflow with a trigger route.
  • Observability: distributed tracing, metrics, logs, and alerts.
ownedScheduler

A framework-agnostic, fully type-inferred cron/batch scheduling library (now the repo default).

A framework-agnostic scheduling library whose headline feature is automatic type inference across the pipeline: types flow fetchItems → payloadMapper → handler with no manual generics, so a schedule is defined once and stays type-safe end to end. An adapter abstraction lets the same definition run under real cron, in-memory tests, or manual triggers.

  • A single defineSchedule entrypoint with inferred item/payload types, registered via a schedule registry.
  • Pluggable adapters: real cron, no-op, in-memory, and manual-trigger — selected by environment.
  • Environment-scoped execution so schedules only fire where intended. Now the repo's default for cron/polling jobs.
ownedshared-money / shared-math

Branded money value objects and extracted math utilities for financial precision.

Money correctness made a type-system concern. Amounts are branded as minor/major units so a cents value can never be silently treated as dollars, and the unit field is mandatory so every call site declares intent.

  • A Money value object extracted into a shared library consumed across server and client.
  • Branded minor/major unit types prevent unit-confusion bugs at compile time.
  • Split into client/server entrypoints, with a formatting helper for display.
ownedOperation Manager

A library for running multi-step business operations with execution tracking, per-error-type handlers, and database-transaction management.

Operation
Step 1
Step 2
Step 3
Execution history

Problem. Complex business operations span multiple steps with database transactions and need consistent error handling, rollback, and traceability — but were written ad-hoc per feature, so failures were hard to recover from and debug.

Decision I drove. A type-safe library that runs operations step-by-step with automatic execution-history tracking, per-error-type handlers, and session/transaction management, returning a structured result per step.

Impact. A reusable, debuggable pattern for multi-step transactional operations.

Leadership. Owned the library and its API design.

contributedAI Snapshot

A reusable client library presenting AI-generated report snapshots, with AI usage gated through feature flags.

Problem. Surfacing AI-generated report snapshots in the client risked one-off, unthemed UI and ungoverned AI usage.

Decision I drove. Package the feature as a reusable client library (components / hooks / reports + a Tailwind theme + Storybook stories) and route AI usage through the feature-flag layer so rollout is controlled.

Impact. A reusable, themed AI-reports surface with governed AI usage.

Leadership. Contributed the client library, design review, and feature-flag integration alongside the feature owner.

ownedMessaging Infrastructure

The message-queue backbone for webhooks and money-movement events, with a declarative topology registry.

Producer (port)
Topic exchange
Queue
Consumer
Retry → dead-letter

Problem. Banking needed reliable async messaging — durable publish/consume with retries and dead-lettering — but ad-hoc exchange/queue setup caused type mismatches and topology drift between services.

Decision I drove. Split into a client library (connection, producer, consumer, retry, dead-letter) and a declarative topology registry that asserts every exchange and queue on startup; standardize on topic exchanges with dotted naming and put publishing behind ports.

Impact. The messaging backbone for webhooks, money-movement events, onboarding, and balance processing — with consistent, asserted topology and no silent drift.

Leadership. Owned the messaging foundation and set the topology and naming conventions used across banking.

ownedDDD Backend Libraries + Code Generators

Scaffolding and conventions for domain-driven, hexagonal backend libraries.

Problem. The team's target architecture (Domain-Driven, hexagonal) was applied by convention, so new backend libraries drifted in shape and layering.

Decision I drove. Codify the architecture into code generators so new libraries are consistent by construction — a backend-library generator with domain/application/infrastructure layers and subdomain support, a migration generator to move existing libraries into the pattern, and supporting generators for workflow libraries and Storybook.

Impact. New backend libraries are domain-driven and hexagonal by default.

Leadership. Owned the conventions and the generators that enforce them.

contributedControlled data interventions / deferred events

Gated, reviewable tooling for production data fixes and delayed execution.

Problem. Production data fixes were done with ad-hoc one-off scripts (risky, untracked, hard to gate), and some side-effects needed to run later rather than inline.

Decision I drove. Move data fixes onto a feature-toggle-gated intervention mechanism (retiring custom one-offs) so interventions are controlled and reversible, and add a deferred/delayed-actions facility to schedule side-effects for later.

Impact. Safer, auditable data corrections and a clean way to defer work.

Leadership. Contributed to shifting the team off ad-hoc scripts toward a gated, reviewable mechanism.

contributedBack-office Client

Internal admin app, migrated to a modern monorepo build, with banking views.

Problem. The back-office client build ran on legacy, non-monorepo-aligned infrastructure, and banking operations lacked admin surfaces for banking state and payout eligibility.

Decision I drove. Migrate the back-office build to modern monorepo targets (Nx + Vite) so it matches the rest of the codebase, then add banking back-office views and a payout-eligibility UI.

Impact. A maintainable, monorepo-consistent admin app with the operability surfaces banking needs.

Leadership. Contributed the build-infra migration and the banking admin views.

ledEngineering Health

Standards lint ruleset, strict-null-check migration, CI parallelization, and test reorganization.

Problem. The codebase lacked shared quality guardrails — null-safety was not enforced, there were no shared lint standards, CI was slow, and tests were disorganized.

Decision I drove. Introduce a standards lint ruleset with explicit warning budgets, migrate to strict null checks, parallelize CI and adopt run-many execution, and load test-config module mappings dynamically so config stays single-sourced.

Impact. A higher baseline of code quality, faster CI, and far less test-config drift.

Leadership. Drove codebase-wide standards and quality conventions.

Developer-tooling frameworks
ownedAI background agents

A containerized agent environment plus codebase rule files encoding repo conventions.

Problem. Running agentic/background coding on the codebase needed a reproducible, containerized environment and codebase-specific rules, or agents would run inconsistently and ignore repo conventions.

Decision I drove. A full agent setup — a Docker environment for background agents, agent configuration, codebase rule files encoding conventions, and workspace-graph MCP wiring — so agents execute in a reproducible container and respect the repo's standards.

Impact. Enabled AI-assisted and background-agent development on the codebase; a precursor to the broader AI-tooling ecosystem.

Leadership. Owned the AI dev-environment direction for the team.

ownedAutonomous-agent loop framework

A phased loop (research → plan → exec → review → done) with checklist and scaffold templates, packaged for reuse.

Research
Plan
Exec
Review
Done

Problem. Long-running, multi-step engineering tasks (migrations, multi-iteration features, large refactors) need an agent that researches, plans, executes, and reviews iteratively — but there was no structured self-iterating workflow on the codebase.

Decision I drove. Built a phased loop (research → plan → exec → review → done) with checklist and scaffold templates, packaged it for reuse, configured it (model, in-progress label, base branch), and consolidated the config into a single annotated workflow document.

Impact. Structured autonomous iteration on long tasks.

Leadership. Owned the framework through several generations of its own design — directing the tool, not just using it.

ownedSpec-driven-development setup

Steering docs and worked specs that prime agents with consistent project context.

Author steering docs encoding project conventions plus a worked spec that follows the requirements → design → tasks flow, so AI agents get persistent project context and a disciplined decomposition rather than improvising.

  • Steering docs — product, structure, tech, and testing conventions that prime the agent.
  • Worked spec — a feature decomposed into requirements / design / tasks.
ownedMCP tooling

Runtime observability and workspace-graph access for agents, plus local error capture for development.

Problem. Local development and AI agents lacked context — no lightweight local error capture, and no way for agents to see runtime state or the workspace graph.

Decision I drove. Wire runtime observability (accessible to agents), workspace-graph access (so agents understand the monorepo), and local error capture into the dev environment.

Impact. Faster local debugging and agents that can reason over real runtime/workspace state.

Leadership. Owned the agent-context dev-tooling direction.

Smaller product areas
contributedAcross search, mobile & UI

Global Search · Smart App Banner (Android/iOS) · Identity refactor · Dashboard/Overview widgets · Leases-page UX redesign · Bulk property upload · Combined account-statement PDFs · Property creation (mobile UI, images) · Bank Connect · Single-tenant move-out · Payment-provider API upgrade · Design-system primitives (switch/checkbox/radio).

$ stripe listen --events payment,treasury,payout

Stripe, end to end

Years of production Stripe — Payments, Connect, and Treasury — moving real customer money. The interesting half is what happens when a charge, transfer, or payout doesn't go to plan.

Payments

PaymentIntents and SetupIntents, cards and ACH, off-session and recurring charges, with a fraud-aware limit model.

Connect

Connected accounts and onboarding, platform → connected fund flows, reserve guardrails, and risk assessment on incoming funds.

Treasury & embedded banking

Financial accounts, balances, received credits/debits, and scheduled reconciliation with expedited-ACH payouts.

Capital (embedded lending)

Loan offers, distributing a single advance across multiple properties, and phased deposit accounting.

Webhooks & idempotency

Signature-verified, queue-backed ingestion processed idempotently with bounded, TTL-aligned retries — no dropped events on a money path.

Payouts & reconciliation

A canonical ledger of every movement, payout confirmation, balance reconciliation, and transfer reversal.

Failure modes

Disputes, refunds, failed credits, and the dead-letter paths that make money movement observable and recoverable.

$ cat ~/doorloop/skills.md

Skills

The toolkit behind the work above — deepest in TypeScript, fintech, and platform engineering.

Languages & runtimes

  • TypeScript (advanced)
  • Node.js
  • React

Architecture

  • Domain-Driven Design
  • Ports & Adapters / hexagonal
  • event-driven systems
  • reactive pipelines
  • type-system-driven correctness

Fintech

  • payment-provider integrations
  • treasury/money-movement
  • double-entry accounting
  • idempotent money handling
  • reconciliation
  • fraud-aware limit modeling

Platform

  • message-queue topology
  • durable workflows
  • scheduling
  • structured logging
  • distributed tracing
  • feature-flag platforms
  • CI optimization

Data

  • MongoDB / Mongoose
  • PostgreSQL / Prisma
  • transactional consistency

Frontend

  • React
  • Vite
  • Tailwind
  • design-system component work

Testing

  • unit/integration discipline
  • live-Docker integration tests
  • Playwright E2E

AI engineering

  • Claude Code plugin/skill authoring
  • MCP servers
  • autonomous-agent frameworks
  • agent dev-environments
Libraries & generators authored (25 + 4)
Banking / Treasury embedded-financing, flow-of-funds, flow-of-funds-contracts, payment-limit grace buffer
Money / Math shared-money, shared-math
Payment provider provider SDK wrapper, server provider client
Messaging message-queue client, message-queue topology
Scheduling / Workflows Scheduler, durable-workflow common
Feature toggles / AI openfeature, AI feature-toggles, AI snapshot (client)
Operation Manager operation-manager, server operation-manager
Shared primitives zod schemas, enums, types, mongo utils, analytics metadata
Observability / config telemetry, eslint-config, examples

Code generators: DDD backend library, durable-workflow library, move-to-domain migration, Storybook setup.