Seven services, and what a browser with no credential can actually see of them
This site demonstrates lead-routing-system against the deployment that is
running right now. It is not a description of the platform. Where something can be exercised from a
public page it is exercised on that page, live, and you can watch it happen. Where it cannot, the page
says why instead of showing you a number somebody made up.
The rule this site is built on
A demonstration that shows invented data is worth less than one that says this needs an operator login, because the first teaches you to distrust everything else on the page. So there are three kinds of thing here and they are always labelled:
| Kind | What it means | Where you will see it |
|---|---|---|
| live | This page made the request while you were looking at it and is showing you the answer. | The whole of the fraud page, and the status board below. |
| recorded | A transcript of a command that was actually run, kept verbatim so you can run it yourself and compare. | Every curl block on every page. |
| from source | A fact read out of the repository — a migration, a route table, a design decision. True about the code; it does not claim to be the live database's current contents. | Rule tables, route lists, status notes. |
There is a fourth kind, and you will not find it here: a plausible-looking number standing in for one this page could not read.
Live status — checked when you loaded this page
Every service answers GET /api/<name>/health with no credential.
Almost none of them let a browser on this origin read the answer, and the board below tells the
two apart rather than blurring them.
| Service | Health route | What this browser observed |
|---|---|---|
| platform | platform.lrs.amtechhq.com/api/platform/health | not asked |
| corpus | corpus.lrs.amtechhq.com/api/corpus/health | not asked |
| marketplace | marketplace.lrs.amtechhq.com/api/marketplace/health | not asked |
| routing | routing.lrs.amtechhq.com/api/routing/health | not asked |
| fraud | fraud.lrs.amtechhq.com/api/fraud/health | not asked |
| sms | sms.lrs.amtechhq.com/api/sms/health | not asked |
| proxy | proxy.lrs.amtechhq.com/api/proxy/health | not asked |
The four answers, and why there are four
- up — the response was read and it was a 2xx. The bytes shown beside it are what the service sent.
- answering, not ok — the response was read and it was not a 2xx. On
fraudthat specifically means the media root is unusable. - answered, unreadable here — the request completed against that host, but the response carries no
Access-Control-Allow-Originheader, so this page is not permitted to read it. All that can honestly be said is that something answered. - no answer — the request did not complete at all. Nothing answered.
The third state is the normal one here, and it is a configuration choice rather than a fault. A health route exists for the deploy's health-checked auto-revert and for monitoring, not for a stranger's web page, so it publishes no CORS header.
There is one way out of it and this page already tries it: before going cross-origin, each row asks
/health/<service> on this host. Nothing serves that path by default — this site
is static files — so the attempt 404s and the row falls back. If whoever deploys this site adds the small
nginx proxy in the repository's README.md, the same rows start reading real status codes and
real bodies with no change to any page. The note under each badge says which path answered, because
the service says it is up and our own vhost says the service says it is up are not quite
the same sentence.
Exactly one surface in the whole platform is CORS-enabled on
purpose, because it has to run inside a browser on a third party's page: fraud's
/collect boundary. That is why the fraud page is the one that genuinely works and the
other six are honest about their limits.
Verify it without a browser — recorded 2026-09-06
$ for s in platform corpus marketplace routing fraud sms proxy; do
printf '%-12s ' "$s"
curl -s -m 10 "https://$s.lrs.amtechhq.com/api/$s/health"; echo
done
platform {"service":"platform","status":"ok"}
corpus {"service":"corpus","status":"ok"}
marketplace {"service":"marketplace","status":"ok"}
routing {"status":"ok","service":"routing"}
fraud {"media":"writable","service":"fraud","status":"ok"}
sms {"service":"sms","status":"ok"}
proxy {"service":"proxy","status":"ok"}
curl is not a browser and is bound by no same-origin policy, which is
the whole of the difference between this transcript and the board above.
The seven
- platform The operator console and the people who log into it, plus the shared decisions, database conventions and scripts every other repo is built from. console at admin.lrs
- corpus Who a person is, and whether you are allowed to contact them. Every other service asks it before doing anything to a human being. identity substrate
- marketplace The parties — buyers, sellers — and the contracts, offers, endpoints and field dictionary that say who wants what and how it is delivered. carrying its domain
- routing The money path. A lead arrives, is matched against buyers, and is delivered — or is not, with a receipt saying why. live, no campaign cut over
- fraud Watches a form being filled in and tells an operator which submissions deserve a human look. It advises; it never blocks a sale. demonstrable here
- sms Templates, campaigns and drops, with a consent gate in front of every send and a STOP path behind it. built, carries no traffic
- proxy The redirect edge: the short link in a text message, resolved, logged, and handed on. deployed, unrouted
Status wording is taken from platform/docs/ROADMAP.md, which is the
status document of record. Where this site and that file disagree, that file is right.
Why they are seven and not one
One MySQL instance, one schema per service, and two database users each — and no service user holds
any privilege on another service's schema. A cross-schema query is not discouraged here, it is
impossible: no REFERENCES grant, so a cross-schema foreign key cannot even be created, and
no SHOW DATABASES. Services talk over HTTP or they do not talk.
That has a cost and the platform pays it openly: reporting is eventually consistent, which is why the
API envelope carries a meta.stale field. It also has a consequence you can see on the fraud
page — fraud records the seller campaign key it is told and cannot verify it, because the list of
campaigns that ought to exist lives in marketplace and fraud may not read marketplace's schema.