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
- 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.
- 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.
- Elke relatie draagt zijn bron, peildatum, zekerheid en licentie. Zonder bron geen rij.
- 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).
- Niets wissen wat een bron heeft; wel intrekken.
ingetrokken_opin 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)
- werkwoord bestaat; object-soort klopt (jaar is een getal, persoon is een ding);
- bij een tekstbron staat het citaat letterlijk in de brontekst (broncache), en elke naam en elk getal in de relatie staat in het citaat;
- geen stopwoord in het citaat (oorlog, ramp, dood, prijs, verkocht … nl en en);
gevoeligwordt gezet, niet weggelaten, bij naamgevers met militair, koloniaal of politiek verleden (regie: vertellen, droog); - een relatie over een straat rust op een citaat dat die straat noemt (de zevende regel van vandaag);
- licentie gevuld en toegestaan; NC nooit.
7 · Volgorde
- 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.