The five stages

  1. Connect, and let the database prove the role is read-only

    Paste a connection string. Before reading anything, LEDAR asks PostgreSQL what the role is permitted to do and shows you the answer. A role the database reports as a superuser is refused outright, with no override, because a promise made by an application about its own behaviour is not evidence.

  2. Answer five questions, or skip them

    Login, database, payments, file storage, scheduled jobs. Every question offers "I do not know", which is the default, and every step has a "skip all of this, just go and find out" button. For someone who inherited a system, that button is the one most often pressed, and that is expected rather than a failure.

  3. The scan starts immediately, without waiting for your answers

    Tables, columns, constraints, relationships, row counts and sizes. What you said and what the scan found are then compared, and the differences are brought back to you: "you said you use Stripe — I can see a stripe_customer_id column on public.users. Is that the one?"

  4. A map is built, and the guesses are marked as guesses

    Foreign keys the database declares are one tier. Links inferred from column names are a second, lower tier. A guessed link that is then checked by counting real values is promoted to a third tier and carries the count. The tiers are visible beside every hop, so a route built on an assumption never looks like a route built on a constraint.

  5. Ask a question in your own words

    Type what a customer told you: "I paid but no order appeared." LEDAR walks the map from the subject to the related records and answers with a timeline — what happened, when, where the trail breaks, and how many other cases show the same break today.

Why a map, and not a fresh scan every time

Rescanning a real database for every question is slow enough that people stop asking. The map is built once during the scan and costs no extra queries — the foreign keys and column names were already read for another purpose.

It also makes the answer explainable. A timeline that came from walking customer → payment → rental can show you those three hops and the tier of each one. An answer assembled from a fresh scan each time has nothing to show you.

The three tiers a relationship can have
TierWhat it meansWhere it comes from
declaredThe database enforces this linkA foreign key constraint in the catalogue
measuredValues were counted and they line upReading real values and recording the match rate
guessedThe names suggest a link; nothing checked itColumn naming conventions only

What the answer looks like

Not a list of findings. A sequence, ordered by the clock rather than by the route that was walked — which matters, because the route order and the time order often disagree, and a timeline printed in route order looks plausible and is wrong.

Payment recorded 28 January. Rental never reached. One other subject shows the same break.

The shape of an answer, from a real run against the Pagila sample
  • A step that did not happen is reported as "did not arrive", not as zero. Those are different facts and the product refuses to blur them.
  • A route the budget could not afford to walk is named as unwalked, not silently dropped.
  • The count of other subjects showing the same break is there so you can tell one incident from a pattern.

What this costs to run

Scanning is free — it is your database and your machine. Asking a question costs whatever your model provider charges for the tokens. Three questions against a real schema, measured on the wire, came to under a cent in total across 3 turns.

The schema menu sent for a large database was the binding constraint rather than the price: an early version tried to send a 2 MB menu for a 368-table schema, which does not fit in a context window at any price. Splitting it into two rounds brought that to about a fortieth of the size.