Kennisbank — het schema

Van B, voor A en E · 24 september 2026 · hoort bij KENNISBANK-NL.md

Eén schema dat op SQLite (nu, kennis.db in STATE_DIR achter de bestaande Hono-server) en op PostgreSQL (later, in een container op zilch33; met Apache AGE als paden nodig zijn) hetzelfde is. Alleen gewone SQL, geen engine-specifieke types; id's zijn tekst, tijd is ISO-tekst, JSON is tekst. De kennisbank kent geen personen die onze gebruikers zijn: alleen stenen, namen, tijd, bronnen en beelden. De mensenlaag (jij, zinnen, zaken, ♥) blijft in de app-database en raakt de kennisbank alleen via gedeelde sleutels.

1 · Uitgangspunten

  1. Feit = relatie + bron; zin = weergave. Er is geen tabel met zinnen als feit. Een zin is óf een weergave die de code of het model maakt uit relaties, óf een citaat dat als bewijs aan een relatie hangt.
  2. Gedeelde sleutels. Een ding heeft één rij, hoe vaak het ook voorkomt: straat op BAG-openbareruimte-id, persoon/plaats/ding op Wikidata-Q, buurt op CBS-code, pand op BAG-pand-id, monument op RCE-nummer, jaar op het getal.
  3. Elke relatie draagt zijn bron, peildatum, zekerheid en licentie. Zonder bron geen rij.
  4. Versie en herkomst per rij, zodat een nieuwe prompt of regel alleen opnieuw doet wat verouderd is, en zodat een rij die een agent schreef altijd terug te vinden is (welke run, welk model, welke citaat).
  5. Niets wissen wat een bron heeft; wel intrekken. ingetrokken_op in plaats van DELETE, zodat een weergave die ooit klonk herleidbaar blijft.

2 · Tabellen

ding

kolom type betekenis
id tekst, PK straat:0344300000012345 (BAG-openbareruimte-id) · q:Q282708 (Wikidata) · buurt:BU03440532 · pand:0344100000123456 · monument:514405 · jaar:1495 · plaats:utrecht · gemeente:GM0344 · water:top10nl:… · bron:bag · beeld:<media-id>
soort tekst straat · plaats · gemeente · buurt · persoon (alleen met een Wikidata-Q; nooit een levende privépersoon) · plek-elders · ding · gebeurtenis · organisatie · jaar · pand · monument · water · park · station · bron · beeld · kaart
label_nl, label_en tekst "Jan van Scorelstraat", "Jan van Scorel"
omschrijving_nl, omschrijving_en tekst, leeg mag korte typering uit de bron ("kunstschilder uit de Noordelijke Nederlanden")
extern tekst (JSON) andere sleutels: { "bag": "…", "wikidata": "Q282708", "osm": "…", "rce": "…", "cbs": "…" }
eigenschappen tekst (JSON) alleen wat geen relatie is: voor een straat type (Weg), woonplaats, gemeentecode; voor een jaar niets
rd_x, rd_y getal, leeg mag centroïde in RD voor straat- en pand-dingen, als eigen kolommen (voor de zaal-kaart, zonder JSON) (A)
gemaakt_op, bijgewerkt_op tekst (ISO)

Index: (soort, label_nl); uniek op id.

werkwoord

De vaste lijst; een relatie mag alleen een werkwoord uit deze tabel dragen.

kolom type betekenis
id tekst, PK genoemd_naar, leerling_van, aangelegd_in, …
groep tekst naam · ligging · tijd · mens_en_werk · stenen · verhaal
nl, en tekst "heet naar" / "is named after" — zoals de werkwoorden in web-graaf.mjs, leesbaar als zin met onderwerp ervoor
omkering_nl, omkering_en tekst, leeg mag "geeft zijn naam aan" / "gives its name to"
object_soort tekst ding · getal · jaar · tekst (alleen voor een citaatloos label)
wikidata_prop tekst, leeg mag P138, P1066, P569 … voor de import

Beginlijst (kan groeien, nooit vrij): naam: genoemd_naar, zelfde_naam_als, heette_vroeger, naam_vastgesteld_in; ligging: ligt_in, grenst_aan, kruist, voortzetting_van, loopt_van, loopt_naar, hoofdas_van; tijd: aangelegd_in, gebouwd_in, gesloopt_in, geboren_in, overleden_in, geboren_te, overleden_te; mens en werk: is_een, beroep, leerling_van, leraar_van, maakte, ontworpen_door, gebouwd_door, opdracht_van; stenen: staat_aan, is_monument, dakvorm, telt_panden, bomen_van_soort, hoogte_nap; verhaal: staat_op (beeld), in_de_krant (jaar, aantal), weetje_van (jaar → weetje). Erbij sinds de landelijke oogst (S8, 24-09, in code als WERKWOORDEN): mens en werk: stroming, opgeleid_aan, werkte_voor, werkte_in, bekleedde_ambt, ontving_onderscheiding, lid_van, nationaliteit, geslacht, en alleen voor historische personen vader, moeder, gehuwd_met, kind; plaats: land, gesticht_in, inwoners, hoofdstad; ding: soort_van, hoort_bij (taxon), genoemd_naar; gebeurtenis en organisatie: vond_plaats_in, vond_plaats_te, zetelt_in.

relatie

kolom type betekenis
id tekst, PK ulid
van tekst, FK ding
werkwoord tekst, FK werkwoord
naar tekst, FK ding, leeg mag het ding, óf leeg als naar_waarde gevuld is
naar_waarde tekst, leeg mag getal of jaar als tekst ("1495", "12.2"), alleen als het werkwoord getal/jaar toestaat
eenheid tekst, leeg mag "m", "jaar", "stuks"
sinds, tot tekst (ISO of jaar), leeg mag geldigheid in de wereld ("heette vroeger", "van–tot")
zekerheid tekst zeker · vrij_zeker · vermoeden (uit R10/huis-zelf: gemeten of geteld = zeker; afgeleid uit geometrie = vrij_zeker; model uit tekst zonder getal = vermoeden)
bron tekst, FK bron
bron_url tekst de precieze pagina of record
citaat tekst, leeg mag letterlijk fragment uit de bron waarop de relatie rust; verplicht als de bron tekst is
citaat_taal tekst, leeg mag nl · en — voor de taalwacht en de keuring op namen (A)
peildatum tekst (ISO) wanneer wij de bron raadpleegden
geldig_sinds tekst, leeg mag wat de bron zelf meegeeft (registratiedatum)
licentie tekst CC0 · CC-BY-4.0 · CC-BY-SA-4.0 · ODbL · eigen — van de bron; bepaalt of we de rij mogen tonen en delen
herkomst tekst code · model:claude-haiku-4-5 · hand:<rol> (hand:regie, hand:e; nooit een volledige naam) · bezoeker (alleen opgeteld, nooit hier)
run tekst, leeg mag run-id (proef, datum, portie)
versie tekst prompt/schema-versie waarmee de rij is gemaakt
gevoelig 0/1 oorlog, koloniaal, politiek — vertellen mag (regie), maar gemarkeerd
boeiend tekst, leeg mag leuk · gewichtig · leeg — gezet door de keuzestap (Sonnet) of de regie
ingetrokken_op tekst, leeg mag nooit DELETE

Indexen: (van, werkwoord), (naar, werkwoord), (werkwoord, naar_waarde), (bron), (herkomst, run). Uniek (logisch): (van, werkwoord, naar, naar_waarde, bron, bron_url_genormaliseerd) — bron_url wordt vóór de vergelijking genormaliseerd (host in kleine letters, zonder querystring en fragment); dezelfde relatie uit dezelfde bron staat er één keer; uit een andere bron mag hij nog eens (twee bronnen die hetzelfde zeggen zijn twee rijen, dat is zekerheid).

bron

kolom type betekenis
id tekst, PK bag, wikidata, osm, rce, wikipedia-nl, duic, gemeente-utrecht, rotterdam-straatnamen, europeana, …
naam tekst de korte naam voor de onderrand ("BAG (Kadaster)")
uitgever tekst
url tekst
licentie tekst standaardlicentie van de bron
naamsvermelding tekst wat de licentie vraagt (letterlijk, zoals 3DBAG dat wil)
soort tekst register · open_data · encyclopedie · archief · redactie

beeld

kolom type betekenis
id tekst, PK beeld:<ulid> (ook als ding.id, soort beeld)
url tekst in onze beeldbank (/beeld/<bron>/<id>.jpg, later beeld.micasa.bijt.me)
oorsprong_url tekst waar hij vandaan komt
bron tekst, FK bron
licentie tekst alleen CC0 · PD · CC-BY-4.0 · CC-BY-SA-4.0; nooit NC
maker tekst, leeg mag
jaar tekst, leeg mag opnamejaar
breedte, hoogte, bytes getal
mensen_herkenbaar 0/1 dan niet tonen
peildatum tekst

Een beeld hangt aan een straat of ding via relatie met werkwoord staat_op.

sleutel (opzoeken op externe sleutels)

kolom type betekenis
ding_id tekst, FK ding
stelsel tekst bag · wikidata · osm · rce · cbs · top10nl
waarde tekst de sleutel in dat stelsel

Uniek op (stelsel, waarde); ding.extern blijft als kopie voor het lezen. Opzoeken op BAG-id, Q, OSM, RCE of CBS gaat altijd via deze tabel (A).

toonbaar (view, geen tabel)

Eén afgeleide toonbaar die de app-routes gebruiken: relatie niet ingetrokken, licentie toegestaan (CC0, PD, CC BY, CC BY-SA, ODbL als eigen zin, eigen), en bij een beeld mensen_herkenbaar = 0. De regel staat op één plek (A).

weergave (cache, geen waarheid)

kolom type betekenis
id tekst, PK
ding tekst, FK ding over welk ding de zin gaat
context tekst deur · kamer · tafel · atlas
taal tekst nl · en
vorm tekst gezegd (de menselijke zin, kort) · gedrukt (de precieze regel met getal en bron) — de deur haalt beide uit dezelfde grond (A)
tekst tekst de zin
relaties tekst (JSON) de relatie-id's waarop hij rust (de code keurt: niets in de zin dat niet in een relatie zit)
herkomst, versie, gemaakt_op

Wordt gevuld door sjablonen (code) of door Haiku met de relaties als enige invoer; mag altijd weggegooid en opnieuw gemaakt worden. Dit is waar "gezegd" (kort, menselijk) en "gedrukt" (de relatie met bron) elkaar ontmoeten.

run (boekhouding)

kolom betekenis
id, gestart_op, klaar_op
soort import_bag · naamgevers_wikidata · verrijk_ding · extract_tekst · kies_boeiend · weergave
transport api · claude-code
model
tokens_in, tokens_uit, kosten_usd
portie tekst (JSON): wat gevraagd is (straten, dingen, --vanaf)

3 · Voorbeeld: de Jan van Scorelstraat

ding  straat:0344300000010213  soort=straat  label_nl="Jan van Scorelstraat"  eigenschappen={type:Weg, woonplaats:Utrecht}
ding  q:Q282708                soort=persoon label_nl="Jan van Scorel"  omschrijving_nl="kunstschilder uit de Noordelijke Nederlanden"
ding  buurt:BU0344….           soort=buurt   label_nl="Schildersbuurt"
ding  straat:0344300000010287  soort=straat  label_nl="Stadhouderslaan"
ding  jaar:1495, jaar:1562, q:Q…(Jacob Cornelisz. van Oostsanen), q:Q…(Maarten van Heemskerck)

relatie  straat:…10213  genoemd_naar   q:Q282708         bron=duic   citaat="…genoemd naar de zestiende-eeuwse Utrechtse schilder Jan van Scorel…"  zekerheid=zeker  licentie=eigen  herkomst=hand:regie
relatie  q:Q282708      beroep         q:Q1028181 (kunstschilder)  bron=wikidata  licentie=CC0  herkomst=code
relatie  q:Q282708      geboren_in     naar_waarde=1495  bron=wikidata  geldig_sinds=1495-08-10
relatie  q:Q282708      overleden_in   naar_waarde=1562  bron=wikidata
relatie  q:Q282708      leerling_van   q:Q…Oostsanen     bron=wikidata
relatie  q:Q282708      leraar_van     q:Q…Heemskerck    bron=wikidata
relatie  straat:…10213  hoofdas_van    buurt:BU0344…     bron=duic   citaat="…vormt de hoofdas van de Schildersbuurt…"
relatie  straat:…10213  voortzetting_van straat:…10287   bron=duic   citaat="…waarvan je zuidwaarts, voorbij de Minstroom, de voortzetting bent."
relatie  straat:…10213  aangelegd_in   naar_waarde=~1935 bron=duic   zekerheid=vermoeden  citaat="…aangelegd zo'n vijftien jaar na de Stadhouderslaan…"

Elke andere straat met genoemd_naar → q:Q282708 (er zijn er 22) erft alles wat aan q:Q282708 hangt. Wat aan straat:…10213 hangt, blijft van Utrecht.

4 · API (achter de bestaande Hono-server, later ongewijzigd op Postgres)

Route Wie Wat
GET /api/kennis/ding/:id app, atlas het ding met zijn relaties (beide richtingen), bronnen, beelden; cache 5 min
GET /api/kennis/straat?bag=… of ?naam=…&plaats=… app een straat met alles wat hij erft van zijn naamgever(s)
GET /api/kennis/zoek?q=… atlas dingen op label
GET /api/kennis/stand regie tellingen per soort, per bron, per herkomst; laatste runs
POST /api/kennis/relaties agents, met sleutel KENNIS_AGENT_SLEUTEL een portie relaties met bron en citaat; de server keurt (werkwoord bestaat, ding bestaat of wordt aangemaakt met sleutel, bron bestaat, citaat verplicht bij tekstbron, licentie gevuld) en schrijft de run
POST /api/kennis/beeld agents, met sleutel upload naar de beeldbank (STATE_DIR, buiten git), metadata in beeld
POST /api/kennis/intrek/:relatieId regie/beheer ingetrokken_op zetten

Geen route geeft ooit iets uit de mensenlaag; de kennisbank heeft daar geen tabel voor. De grens loopt in twee richtingen: de app-database verwijst naar ding.id (een zaak → straat:…, q:…); de kennisbank kent geen enkele verwijzing terug (geen huis-id van een persoon, geen bewaarde adressen). POST /api/reset, "wis alles" en DELETE /api/ik raken de kennisbank niet (A).

Keuring en remmen op de API (A): POST /api/kennis/relaties keurt per rij en geeft per rij ok of afgekeurd met reden terug (geen alles-of-niets); hoogstens 500 rijen en 1 MB per portie; rem per sleutel; KENNIS_AGENT_SLEUTEL alleen in de env (demo en Mac), nooit in git; GET-routes met ETag zodat de app-cache goedkoop ververst. GET /api/kennis/straat?naam=&plaats= normaliseert de naam precies zoals straat.mjs (normaliseer), zodat de deur en de kennisbank dezelfde treffer geven; bij meerdere woonplaatsen met dezelfde straatnaam komen ze allemaal terug, elk met woonplaats.

5 · Migratie van wat er al is

Nu Wordt
naamgevers-bundel (339): naamgever {qid, soort, geboren, beroep} ding q:… + relaties genoemd_naar, beroep, geboren_in, overleden_in; bron wikidata/osm; de zin wordt weergave
jaarweetjes (176 jaren, 1.121, met citaat) ding jaar:1910 + relatie weetje_van naar een ding weetje:<id> met citaat en bron; later verder ontleed (persoon, gebeurtenis)
huis-zelf, straatmaten (soort + getal) relaties dakvorm, hoogte_nap, telt_panden, bomen_van_soort, grenst_aan (water, park) met naar_waarde
oogst en proza (zinnen met citaat en broncache) relatie-extractie door Haiku uit de broncache; de zin blijft als weergave tot de relaties er zijn
handgeschreven (102) door de regie ontleed met hulp van Haiku, gekeurd door de regie (E's Scorel-zin als eerste)

6 · Wat de code keurt (hetzelfde als nu, maar op relaties)

7 · Volgorde

  1. Dit schema lezen (A, E). 2. Migratie 0004-kennis.sql + lib/kennis/bank.mjs (SQLite in STATE_DIR) + de routes (Opus, één sessie; B's paden plus routes na akkoord van A). 3. Import: werkwoorden, bronnen, alle BAG-openbare ruimten (code). 4. Naamgevers en hun Wikidata-relaties (code; gestart als meting). 5. Relatie-extractie op de broncache (Haiku, porties, abonnement). 6. Weergave uit relaties aan de deur achter een vlag, met meting: de voorraad (straten-*.json) blijft de bron tot de weergave uit relaties op de tien buurten hetzelfde of beter oplevert (dezelfde steekproef als vandaag); pas dan omzetten (A). Atlas op relaties. 7. Postgres zodra E de container zet: zelfde schema, deploy/kennisbank/ van A.

8 · Opmerkingen van A (24-09), verwerkt

Alle tien zijn in de tekst hierboven opgenomen: sleuteltabel; genormaliseerde bron_url en bron in de unieke sleutel; weergave.vorm gezegd/gedrukt; citaat_taal; personen alleen met Q en hand:<rol>; view toonbaar; de grens in twee richtingen en de reset-zin in §4; keuring per rij, grenzen en ETag; straat op naam met dezelfde normalisatie; de deur achter een vlag met meting; rd_x/rd_y als kolommen; run.kosten_usd 0 bij claude-code met tokens geteld. Bouw na zaterdag, in de volgorde van §7; A maakt deploy/kennisbank/ zodra de migratie er is.