Skip to content

Decision log

The calls, with the receipts

One architecture decision record at a time, in the format I use with teams: the situation, the call, and what it did. Anonymised where it has to be, dated, and never edited after the fact. RSS

  1. ADR-006 · Prompt-driven deployments with MCP

    Put an OAuth shim in front of Coolify instead of sharing API tokens

    Context
    Letting Claude deploy through MCP needed per-user identity, consent and rate limits. Coolify only offers static tokens.
    Decision
    A small Node service implementing OAuth 2.0 for MCP clients, sessions in Supabase, scoped tools and an audit log. Tokens never leave the server.
    Result
    Prompt-driven deployments with a consent trail security could sign off on, supporting 25+ deploys a week.
  2. ADR-005 · REConnect

    Measure AI by cost per resolved ticket, not tokens

    Context
    Model bills grow silently. The team needed a number the business understood and a lever to pull.
    Decision
    Frozen system prompts for cache hits, model routing by task difficulty, evals before any model switch, and a dashboard of cost per resolved conversation.
    Result
    Quality tracked on an eval set and spend tied to a business outcome, so model changes became routine instead of risky.
  3. ADR-004 · REConnect

    Agents get typed, scoped tools. Never free-form data access

    Context
    The support agent needed live account and listing data, and the risk of a model issuing broad queries or actions was unacceptable.
    Decision
    Every capability is a tool with a schema, an allow-list of roles, and consent for anything destructive. Retrieval is grounded; the model cannot reach the database directly.
    Result
    About 90% of tickets resolved end to end with an auditable trail and no incident from an agent action.
  4. ADR-003 · REConnect

    Normalize every MLS feed into one internal model at ingestion

    Context
    REConnect pulls listings from many boards with different RESO dialects. Early code branched per board inside features.
    Decision
    A single canonical listing model, with per-board adapters at the edge and a normalization pipeline that owns all mapping. Features never see raw feeds.
    Result
    100+ brokerages on one codebase. Adding a board is an adapter, not a feature change.
  5. ADR-002 · ACP Multi-Tenant CRM

    Shared schema with hard tenant scoping, not a database per provider

    Context
    The ACP CRM had to serve about 10 internet providers with strict data separation, a small team and a fast onboarding target.
    Decision
    One database with a tenant key on every table, enforced by global query scopes and RBAC, plus per-tenant encryption of sensitive fields. Database-per-tenant was rejected for operational cost.
    Result
    New providers onboard in configuration. 50,000+ customers tested with zero cross-tenant leaks found in audits.
  6. ADR-001 · Tour27

    Server-render every marketplace page, hydrate only what users touch

    Context
    Tour27's growth depended on organic search, and a client-rendered SPA left tour pages invisible to crawlers.
    Decision
    Next.js with static generation for tour pages and SSR for search, a modular NestJS API, and a CMS so operators change content without deploys.
    Result
    Every tour page is indexable and fast, and operators self-serve content.

Facing a decision like these? Try the free first-pass review, or get in touch.