logicsrc/apps/logicsrc-web
Anthony Ettinger 7aeba32908 OpenListing 0.1: one file a seller serves about a thing on offer
A house for sale, an apartment to rent, a car. One document per listing,
on the seller's own origin, so a directory reads the seller's file
instead of licensing somebody else's database or scraping a marketplace
that forbids it.

**The name `OpenRental` was the obvious one and it is taken.** It
already means renting OpenAgent and OpenSwarm members through CoinPay,
with a published schema, SDK, validators and fixtures. Its own document
records surviving one collision already: it was OpenFleet until
2026-09-13. Reusing the name for housing would have broken a shipped
0.1 spec, so the family is OpenListing instead.

Two axes rather than a spec per combination. A house for sale and a
house to rent are the same house; only the offer differs. A house for
sale and a car for sale are the same offer; only the subject differs.
Writing OpenHouseForSale, OpenHouseForRent, OpenCarForSale and the rest
produces one spec per cell of a grid, each repeating most of the others.
So `offer.type` carries sale/rent/lease/auction/free/wanted and
`subject.type` carries property/vehicle, and a subject profile adds only
the fields peculiar to its subject. A reader that knows OpenListing but
not a profile still reads price, location, offer and dates correctly.

`openhouse` is not used as a name: in real estate an open house is a
viewing event, not a kind of listing. An actual one is an entry in
`showings`.

The problem section is grounded rather than asserted: RESO tracks 484
separate MLSs as of August 2026, down from nearly twice that in 2015;
each does publish a RESO Web API feed, and each requires a real estate
licence, a signed per-MLS data agreement and vendor credentials. Four
hundred and eighty-four negotiations for one national view, not
redistributable. Vehicle parts are the same shape with different
letters (ACES/VCdb, TecDoc).

Decisions worth naming. Prices are decimal STRINGS, because 2450.10 is
not representable in binary floating point and a listing is a price.
Absent means unstated, never zero -- with `bedrooms: 0` called out in
the property profile as the one place where zero genuinely differs and a
studio is not an unstated bedroom count. `location.precision` lets a
seller publish a postal code rather than a street for an occupied home,
and forbids a reader from drawing a pin on a building anyway. A closed
listing SHOULD stay served for 90 days with `closed_at`, because a
directory that learns from a 404 cannot tell "sold" from "outage" --
the failure that makes every coupon site a graveyard.

The vehicle profile treats a VIN as a claim rather than a proof, points
readers at NHTSA vPIC (free, keyless, public domain) for decoding rather
than making sellers restate what the VIN encodes, and puts parts fitment
explicitly out of scope: that is ACES/VCdb or TecDoc, and a public spec
cannot restate licensed data.

Registered as one parent and two blocks under it, using the registry's
existing `parent` field the way OpenServer's blocks already do. Flat
slugs rather than nested paths because /docs/[slug] is a single dynamic
segment, not a catch-all -- a nested slug would not have routed at all.

nichedb.dev is named as the reference directory.

50 contract tests pass including spec-discovery and page-metadata.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-25 10:10:21 +00:00
..
contract OpenModel 0.1: what a model costs, from the provider that bills you (#212) 2026-09-24 11:21:10 -07:00
e2e
public OpenIcon: the agentic styles re-render brand marks, and a style says which ground it needs (#211) 2026-09-24 07:24:08 -07:00
src OpenListing 0.1: one file a seller serves about a thing on offer 2026-09-25 10:10:21 +00:00
.gitignore
next.config.ts
package.json
playwright.config.ts
tsconfig.json
vitest.config.ts