Vermogen wordt de overkoepeling. Vastgoed is er één onderdeel van.
Dit stuk gaat door de ontwerp-gate: het legt drie serieuze varianten naast elkaar voor hoe Vermogen zich verhoudt tot Vastgoed en de andere geld-modules, met per variant wat het kost én wat je ervoor opgeeft. Onderaan staat één expliciete aanbeveling. Er is nog géén code gebouwd, en die gaat er ook niet in voor jij een variant kiest.
Je leest versie 3. Twee eerdere versies zijn al gecommit en gedeployed; als je de pagina eerder hebt gelezen, is dit wat er sindsdien bij is gekomen:
v3 (deze): nieuw — § Drie · Eén record, meerdere beelden
(balans versus kasstroom als expliciete ontwerpregel, met de bevinding dat leningen de
kosten-hub nu al voeden) en open vraag 7 (hypotheek op meerdere objecten,
vier varianten). Open vraag 2 is daarop aangescherpt.
v2: § Acht herschreven — de afwijzing van Uplisting was
onjuist; Uplisting is nu de voorkeursroute, met een tabel met herkomst en verificatiestatus per
claim.
Wat je besloten hebt
"Het moet meer 'Vermogen' worden, waarbij vastgoed 1 onderdeel is."
"Maar ook de specifieke 'vastgoed' of verhuur opties moeten hier in blijven."
Eigenaar, 2026-07-26
Die twee zinnen samen zijn scherper dan ze los lijken. De eerste zegt: er komt een niveau erboven — Vermogen is niet een nieuwe naam voor Vastgoed en niet een uitbreiding ervan, maar een laag waaronder vastgoed hangt naast schulden, spaargeld en later beleggingen. De tweede zegt: die laag mag niets platslaan. Vastgoed is deze week juist verdiept (verhuurtype, wisseldagbolletjes, opzegtermijn-melding, objectkleur); een abstractie die daarvan "een bezitting met een waarde" maakt, breekt precies wat de tester zelf heeft aangevraagd en getest.
Dit herziet een eerder besluit. ADR-0012 (geaccepteerd 2026-07-22) legde vast dat het Vermogen-overzicht "een scherm/tab binnen het bestaande domein Financieel" zou worden — de allerlichtste vorm, expliciet géén eigen plek in de navigatie. Dat is precies wat de zin van 26 juli omdraait. Die ADR moet dus vervangen worden; zie § Wat er met de ADR's gebeurt.
Wat behouden blijft — de harde randvoorwaarde
Dit is geen terzijde maar een controlelijst: voor de fixer die het bouwt, en voor de
tester die deze functies deze week zelf heeft aangevraagd en getest. Elke regel moet ná de
herpositionering nog exact zo werken. Alles hieronder staat vandaag op main.
Vastgoed verliest niets. Geen enkele variant mag een vastgoed-functie verwijderen, verplaatsen naar een generiek scherm, of achter een extra tik zetten. Waar een variant dat wél zou doen, staat dat expliciet bij "wat je opgeeft".
- ✓Verhuurtype per object — kortverhuur (wisselgasten) versus langlopend contract, en dat verhuurtype bepaalt zowel de agenda-weergave als de melding.
lib/features/vastgoed/vastgoed/domain/rental_mode.dart:15· kolomvastgoed_tables.dart:47 - ✓Boekingen met gast en periode, inclusief de lege-gast-conventie voor de jaarlijkse ligplek-verhuur, plus overlap-waarschuwing bij dubbele boekingen.
vastgoed_tables.dart:80(guest :87, start :90, end :93) ·domain/booking_overlap.dart·presentation/add_booking_sheet.dart - ✓De bolletjes in de agenda-dagkop — één gevuld bolletje van 10 px per object op álle gedekte dagen, met de check-in/check-out-glyph ernaast op de wisseldagen, max 4 +
+n, sortering aankomst → vertrek → doorlopend.TEN-120 fase A (commit39a4611b) - ✓Het dag-sheet "Verhuur · datum" achter één tap-target van 44 px, met per boeking object, gast en fase/einddatum. Zonder dat landen "door wie" en "tot wanneer" nergens meer.TEN-120 fase A
- ✓Langlopend contract = 3 momenten, geen 365 dagbanden — start, opzegdatum (einde − opzegtermijn) en einde, met één melding op de opzegdatum; band en melding delen één berekende datum.TEN-120 fase A · kolom
noticePeriodvastgoed_tables.dart:72 - ✓Check-in/check-out-meldingen bij kortverhuur, met de per-module meldingstermijn, meldtijd en geluid uit de module-instellingen.
presentation/vastgoed_providers.dart(resyncVastgoedReminders) - ✓
showInAgendaals escape-hatch per object — raakt bewust alleen de weergave; de meldingen blijven staan als de vlag uit gaat.vastgoed_tables.dart:53 - ✓Objectkleur en object-avatar als leading in de agenda in plaats van het generieke huisje.
presentation/property_avatar.dart:26+PropertyAgendaLeading:93·colorHexvastgoed_tables.dart:58·vastgoed_module.dart:49-67 - ✓De agenda-mirror geeft deel-stand en eigenaar door (TEN-129) en
vastgoedstaat inkSelfSurfacedModuleszodat de mirrors niet ook nog in de Vandaag-dagstroom en de gezinsstrip staan. Niet terugdraaien.commitd441045b· TEN-120 fase A - ✓De aanstaande structurele fix op branch
fix/ten-120-nullable-kolommen(twee kolommen client-side nullable) moet vooruit kunnen. Geen enkele variant hier vereist dat die wordt teruggedraaid.lokale branch, nog niet gemerged - ✓Objecttypen incl. "Overige" met vrije categorie (TEN-84) en bijlagen per object.
domain/property_type.dart·presentation/add_property_sheet.dart - ✓De rendement-kaart op het objectdetail (fase 1: bevestigde + afgeronde boekingswaarde per jaar, verwacht, bruto huurrendement, jaarrente-momentopname) blijft op het objectdetail staan — niet verhuizen naar het Vermogen-overzicht.
domain/property_return_calc.dart·presentation/property_detail_screen.dart:170 - ✓Het deelbeleid van vastgoed — configureerbaar met privé als fallback, cascade van object naar zijn boekingen, en de deel-hint bij een uitgezette module.
lib/core/modules/share_policy.dart:120·share_bulk_remapper.dart:120·shared_in_disabled_module_watcher.dart:45 - ✓De per-module instellingen op module-id
vastgoed— aan/uit per lid, meldingstermijn, meldtijd, geluid, verbergen voor bepaalde leden, favoriet in de snelbalk. Dit is opgeslagen data, geen code: het staat op de rij<householdId>:vastgoed.lib/core/database/tables/foundation_tables.dart:185(ModuleStates) en:236(MemberModulePrefs)
Die laatste regel is niet zomaar de laatste. Alle veertien regels hangen aan het bestaan van
een module met id vastgoed. Route, agenda-mirror, item-decoratie, reminder-resync,
deelbeleid en instellingen zijn alle zes op dat id gesleuteld. Zodra vastgoed géén eigen
module meer is, is elk van die zes een migratie in plaats van een gegeven. Dat is de reden
dat de architectuurvraag hieronder eigenlijk al beslecht is — maar ik toets dat expliciet in
plaats van het aan te nemen.
Wat hoort er in Vermogen?
Een vermogensoverzicht dat schulden negeert, is misleidend. Daarom twee lijsten: bezittingen en schulden. En een derde categorie die er bewust niet in hoort: kasstroom. Vaste kosten, abonnementen, verzekeringspremies en inkomsten zeggen iets over wat er per maand stroomt, niet over wat je hebt. Die horen in de kosten-hub en blijven daar.
Bezittingen
| Kandidaat | Tabel | Waar de waarde staat | Nu al bruikbaar? |
|---|---|---|---|
| Vastgoed module vastgoed |
propertiesvastgoed_tables.dart:13 |
current_value (:36), handmatig bijgehouden, met purchase_price (:32) als terugval |
Ja |
| Spaargeld module spaardoelen |
savings_goals + savings_contributionssavings_goals_table.dart:9 |
Géén opgeslagen saldo — afgeleid als start_amount + Σ bijdragen in savings_progress.dart:55 |
Ja |
| Auto's / wagenpark module wagenpark |
vehicleswagenpark_tables.dart:11 |
Alléén purchase_price (:31). Geen actuele waarde — een auto van 8 jaar oud staat er voor zijn nieuwprijs in |
Open vraag 4 |
| Betaal-/spaarrekeningen module bankrekeningen |
bank_accountsbankrekeningen_tables.dart:14 |
Geen saldo-kolom — bewust puur administratief (alleen iban_last4, houder, bank) |
Open vraag 5 |
| Beleggingen / crypto | Bestaat niet. Geen tabel in Drift, PowerSync of Postgres. Wél ontworpen: ADR-0017 (handmatige waarderingsregel per peildatum, expliciet géén live koersfeed) | Fase V3 | |
| Verzekeringen | Alleen premie (kasstroom). Geen afkoop-/opgebouwde waarde — een levensverzekering met waarde kan niet worden vastgelegd | Nee | |
Schulden
| Kandidaat | Tabel | Waar het bedrag staat | Nu al bruikbaar? |
|---|---|---|---|
| Leningen & hypotheek module leningen |
loansleningen_table.dart:10 |
current_balance (:27) = restschuld; interest_rate (:30); totaal via loan_calc.dart:10 (totalDebt) |
Ja |
| Leningdelen (hypotheek in delen) | loan_partsleningen_table.dart:54 |
current_balance (:65) per deel; gewogen rente in loan_calc.dart:29 |
Ja |
| Financieringskoppeling | properties.financing_loan_idvastgoed_tables.dart:42 |
Zwakke, éénzijdige, 1-op-1 referentie (geen FK). Een lening weet niet welk object hij financiert; het object wijst naar de lening. Resolutie in property_return_calc.dart:216 |
Zie open vraag 2 |
| Openstaand kleed-/zakgeld | allowance_ledgergezinsafspraken_tables.dart:71 |
amount_cents met status open/uitbetaald — technisch een kleine huishoudschuld |
Buiten scope (te klein, verkeerd domein) |
Wat dit betekent voor het eerste getal
Met alléén bestaande data en zonder één migratie is dit al te berekenen: panden (waarde of aankoopprijs) + spaargeld (uit het bestaande ledger) − restschuld van alle leningen (met de gekoppelde hypotheek precies één keer geteld). Dat is geen half getal: het dekt bij dit huishouden vermoedelijk het overgrote deel van het vermogen. Alles daarna — auto's, beleggingen, waardehistorie — is verrijking, geen voorwaarde. Zie § Fasering.
Eén record, meerdere beelden — de belangrijkste ontwerpregel
Terechte zorg van de eigenaar: "Een hypotheek of lening kan in meerdere modules terugkomen, dus in meerdere contexten, net zoals een abonnement ook in vaste kosten kan zitten." De angst is een Vermogen-module waar alles in verdwijnt, waarna hypotheken en leningen niet meer in de vaste kosten opduiken.
Vermogen is een balansbeeld: wat je bezit en wat je schuldig bent, op een peilmoment. Vaste kosten is een kasstroombeeld: wat er maandelijks afgaat. Een hypotheek hoort in béíde — hij heeft zowel een restschuld als een maandlast. Dat is géén dubbeling maar de juiste weergave: het zijn twee projecties van hetzelfde record, niet twee records. Er wordt niets verplaatst en niets weggehaald; er komt een beeld bíj.
Bevinding: dit werkt vandaag al — leningen voeden de kosten-hub
Nagekeken in plaats van aangenomen: costHubProvider leest de leningen-stream mee
en zet elke lening om in een kostenpost via _loanItem
(vaste_kosten_providers.dart:517), met amount: loan.monthlyAmount en
frequency: CostFrequency.maand, onder de bron-id
kFixedCostSourceLoans (cost_post.dart:11). Een hypotheek staat dus
nu al in de vaste kosten, en er is niets in dit voorstel dat daar iets aan verandert.
De gevreesde omissie bestaat niet.
Welk veld welk beeld voedt — dit is de tabel die zichtbaar maakt dat niets uit één context verdwijnt doordat het in een andere staat:
| Component | Balans (Vermogen) | Kasstroom (Vaste kosten) | Eigen module |
|---|---|---|---|
| Hypotheek / lening | Ja — currentBalancelet op: via effectiveLoansProvider |
Ja, al gebouwd — monthlyAmount |
Leningen & hypotheek |
| Spaardoel | Ja — afgeleid saldo (savings_progress.dart:55) |
Ja, al gebouwd — monthlyContribution als impliciete post |
Spaardoelen |
| Pand | Ja — currentValue |
Nog niet — komt met property_costs in V2 (TEN-118) |
Vastgoed |
| Abonnement | Nee — geen balanswaarde | Ja — amount + frequency |
Abonnementen |
| Verzekering | Nee — geen afkoopwaarde in het model | Ja — premie | Verzekeringen |
| Bankrekening | Nee — geen saldo-kolom (open vraag 5) | Ja — monthlyFee als rekeningkosten-post |
Bankrekeningen |
| Auto | Nee — alleen aankoopprijs (open vraag 4) | Nee — wagenpark voedt de hub niet | Wagenpark |
Eén regel uit die tabel verdient nadruk, want hij is een concrete bouwinstructie: de twee
beelden lezen verschillende velden van dezelfde lening. De kosten-hub gebruikt de
ruwe lening, want het maandbedrag staat altijd op de parent — leningdelen kennen geen
eigen maandbedrag (loan_calc.dart:58-67). Het balansbeeld moet juist
effectiveLoansProvider (leningen_providers.dart:78) gebruiken, want
bij een hypotheek met delen is de restschuld de som van de delen. Twee projecties, twee
leesroutes, één record.
Het levende voorbeeld: de brug vaste kosten ↔ abonnementen
Dit patroon is geen theorie; het is gisteren gebouwd. TEN-125 (commit 3b34391c)
maakt van een vaste kost met categorie Abonnementen automatisch óók een abonnement in de
Abonnementen-module, met de markering "Vanuit vaste kosten — nog te verrijken". Uit de
commitboodschap: "Geen source-veld op de abonnement-post en geen dedup-guard:
de hub dedupliceert al op linkKey" en "op dezelfde post, er komt er nooit
een tweede bij". Eén onderliggende post, twee plekken waar je hem ziet en verrijkt.
Kunnen leningen datzelfde mechanisme volgen? Ja, maar ze hebben het minder nodig — en het verschil is leerzaam. Die brug bestaat omdat een vaste kost die je zelf intikt nog géén onderliggend record heeft; er wordt er dan één gestubd. Bij leningen is de richting omgekeerd: de lening is er eerst en de kostenpost wordt eruit afgeleid. Dat werkt al zonder koppelrij, omdat de hub live uit de module-repo leest. Een koppelrij is pas nodig als je het bedrag in de hub wilt kunnen afwijken van de lening (het "geaccepteerde bedrag"-mechanisme). Voor de omgekeerde weg — een maandlast intikken in de hub en daar een lening van stubben — geldt hetzelfde bezwaar dat TEN-125 bij verzekeringen liet staan: je zou rente, looptijd en restschuld moeten verzinnen, en die voeden een einddatum-reminder. Voorstel: geen lening-stub vanuit de hub.
Dubbeltelling is geen risico tússen beelden — een hypotheek in zowel de balans als de kasstroom is correct. Het risico zit uitsluitend binnen één beeld: dezelfde schuld twee keer in de balans. Dat gebeurt op twee manieren, en beide worden hieronder afgedekt: dezelfde lening gekoppeld aan twee panden (open vraag 2), en een lening die deels aan objecten is toegerekend én nog eens volledig op huishoudniveau meetelt (open vraag 7).
De hoofdvraag, in drie varianten
De vraag die je nog niet hebt beantwoord: blijft vastgoed een eigen module die ónder Vermogen hangt, of wordt vastgoed een sectie binnen één Vermogen-module? Dat verschil raakt navigatie, module-registratie, per-module-instellingen, deelbeleid en tier-indeling. Hieronder eerst kort de nulmeting (wat er nu besloten staat), dan drie varianten.
Wat je moet weten over het modulesysteem om de varianten te kunnen wegen:
- Er is precies één groeperingsniveau boven modules:
DomainDescriptor→ModuleDescriptor.domainId, een platte string (module_descriptor.dart:74en:113). Er is géénModuleGroup, géénparentModuleId, géén nesting. (Wél een data-container-begrip: object → boekingen. Niet verwarren.) - Domeinen zijn vandaag de zichtbare groepering in Mijn leven: één sectiekop per domein met de modules eronder (
mijn_leven_screen.dart:106-115en:162-186), en collapsible groepen in Modules beheren (modules_beheer_screen.dart:212-257). De route→ Achterhaald, zie de herzieningsnotitie hieronder: die navigatielaag is verwijderd./domein/:idmet een generiekDomainScreenbestáát al (app_router.dart:252,domain_screen.dart:17), maar niets in de app linkt ernaartoe. Er ligt dus een ongebruikte navigatielaag klaar.- Een nieuw module-id kost: registry-regel, route, deelbeleid-regel, tier, en het krijgt automatisch een module-state-rij, member-prefs en een schermsnelkoppeling voor de favorietenbalk (
module_quick_action_providers.dart:39-53). - Tier zit op de descriptor en is runtime overrijdbaar zonder release via
module_tier_overrides(module_tier_overrides.dart:44). Plus-handhaving staat sinds de server-side entitlements aan (plus_entitlement.dart:31) — dat is nieuwer dan de pricing-doc suggereert. - Een domein met
sensitive: truevereist een aparte AI-opt-in per domein-id (ai_gate.dart:36-38). Dat heeft een gevolg bij verhuizen; zie de kosten van variant A.
Er ligt géén ongebruikte navigatielaag klaar; /domein/:id bestaat niet meer
Dit stuk is geschreven op 26 juli 2026 en leunde op de vaststelling dat de route
/domein/:id met een generiek DomainScreen al bestond maar nergens gelinkt
werd — "een ongebruikte navigatielaag". Op 6 augustus 2026 is die route met F1-9
(E-MOD-06) verwijderd, merge
20f1b910. lib/features/shell/screens/domain_screen.dart bestaat niet meer
(die map bevat nu alleen nog mijn_leven_screen.dart), de router-doc benoemt de
uitfasering zelf (lib/core/router/app_router.dart:7-9) en
test/core/router/domein_route_verwijderd_test.dart bewaakt dat de route niet terugkomt.
Wat dit met de afweging doet. De sub-keuze binnen variant A — "maak de domeinkop tikbaar
naar het al bestaande /domein/vermogen" — was een goedkoop-lijkend alternatief juist
omdat het scherm er al lag. Dat argument is weg: dat pad kost nu bouwen in plaats van
aansluiten, en het zou een bewust genomen besluit terugdraaien. Die sub-keuze werd toen al afgeraden;
ze is nu niet alleen onverstandig maar ook niet meer beschikbaar zonder de F1-9-beslissing terug
te draaien. De hoofdafweging tussen de varianten A, B en C hangt hier niet van af — die gaat over
module-id's, tier en deelbeleid, niet over dit scherm — maar wie variant A leest moet weten dat de
goedkope route eronder is weggevallen.
Domeinen zelf blijven bestaan. Ze zijn nog steeds de vaste categorieën van de catalogus
(onboarding, modulebeheer, meldingeninstellingen, AI-instellingen), en DomainDescriptor,
ModuleDescriptor.domainId en modulesForDomain zijn ongewijzigd. Alleen het
domeinscherm is weg. Alles wat dit stuk over domeinen als groepering zegt, geldt dus
nog.
Let ook op de domeinhersnit. Sinds merge 0ea70a81 (6 augustus 2026) zijn er nog
zes domeinen — eten · gezin · huis · geld · gezondheid · bewaren
(lib/features/app_domains.dart:81-120) — en heet financieel voortaan
geld. Waar dit stuk "Financieel" schrijft, leze men "Geld"; een nieuw domein
vermogen zou bovendien botsen met de regel uit dat besluit dat een domein minstens twee
modules draagt. Die weging is niet in dit stuk verwerkt en hoort bij de keuze meegenomen te
worden.
Vermogen als tab in een bestaand scherm
Het besluit van ADR-0012: geen eigen module-id, geen registry-werk — één extra kaart of tab binnen Financieel, precies zoals Besteedbaar nu in het Vaste-kosten-scherm zit.
Dit is geen stroman: het is het goedkoopste pad naar een kloppend getal en er is een levend precedent voor. calculateBesteedbaar (inkomsten/domain/besteedbaar.dart:6) is een pure cross-module-berekening die als kaart in het Vaste-kosten-scherm wordt getoond (vaste_kosten_screen.dart:104-107) — nul registratie, nul migratie, nul navigatiewijziging.
De overkoepeling zelf. Vermogen is dan een kaart in een scherm dat "Vaste kosten" heet — Sandra moet weten dat ze daar moet kijken. Het woord "Vermogen" komt in de navigatie nergens voor, en vastgoed staat er niet ónder maar ernaast. Dit is precies wat het besluit van 26 juli omdraait, dus het staat hier als vertrekpunt, niet als optie.
Vermogen wordt een domein; Vastgoed blijft een module daarbinnen
Een nieuw domein vermogen met daarin de bezittings- en schuld-modules, plus één nieuwe read-only module Vermogensoverzicht die over die modules aggregeert — het cost-hub-patroon, één niveau abstracter.
- Nieuw
DomainDescriptor(id: 'vermogen', name: 'Vermogen', sensitive: true). domainIdvan Vastgoed, Leningen & hypotheek en Spaardoelen gaat vanvastgoed/financieelnaarvermogen. Eén woord per descriptor.- Nieuwe module
vermogen-overzicht(naam "Vermogensoverzicht"), route/module/vermogen, read-only: geen eigen tabel, geen eigen rijen, alleen aggregatie. - Het oude domein
vastgoedverdwijnt (het had toch maar één module). - Bankrekeningen en Wagenpark blijven in Financieel — ze hebben geen waardekolom en zijn vooral administratie/kasstroom.
Ze tikt Mijn leven en ziet een kop Vermogen met vastgoed er letterlijk als één tegel ónder. Tikt ze Vermogensoverzicht, dan krijgt ze het totaal met bezittingen en schulden eronder, en per regel een doorklik naar de bronmodule ("Vakantiewoning € 285.000" → het bestaande vastgoed-objectdetail, met álle verhuurfuncties intact). Tikt ze Vastgoed, dan komt ze in exact het scherm dat er nu is — zelfde route, zelfde boekingen, zelfde bolletjes.
- Eén nieuw
DomainDescriptor+ driedomainId-regels wijzigen. Letterlijk vier regels code, geen migratie. - Eén nieuw module-id: registry-regel, route, tier. Een deelbeleid-regel is niet nodig — de module heeft geen eigen rijen, en onbekende module-ids resolven in de registry fail-closed naar privé/niet-configureerbaar (
share_policy.dart:186-198). Het krijgt automatisch een module-state-rij en een schermsnelkoppeling. - De aggregatielaag: één pure domeinfunctie + één provider + één scherm + tests. Zie § Hergebruik — dit is het middelgrote deel, niet het grote.
- De domein-volgorde in Mijn leven is impliciet de volgorde van
featureModules(feature_modules.dart:71). Vermogen boven Financieel zetten betekent de lijstvolgorde aanpassen; dat raakt de volgorde van álle domeinsecties, dus even kijken of dat prettig blijft.
- Financieel wordt kleiner. Leningen en Spaardoelen verhuizen eruit. Wie gewend is dat "alles met geld" onder Financieel staat, moet één keer opnieuw kijken. Tegenargument: de splitsing is inhoudelijk juist — Financieel = geld dat stroomt, Vermogen = geld dat staat. Maar het is wel een verandering in een navigatie die de tester al kent.
- Een module kan maar in één domein zitten. Leningen hoort eerlijk gezegd in beide: de restschuld is vermogen, de maandlast is kasstroom en voedt de kosten-hub. Verhuizen naar Vermogen betekent dat de kosten-hub een bron heeft die in een ander domein woont. Technisch onschuldig (geen code hangt aan
domainIdvoor de hub), conceptueel een wringpunt dat blijft. - De AI-opt-in per domein moet opnieuw gegeven worden.
sensitiveOptInDomainsis op domein-id gesleuteld (ai_gate.dart:36-38,ai_providers.dart:120). Wie "financieel" had aangezet, moet "vermogen" apart aanzetten voor bijvoorbeeld de leningblad-scan. Klein, maar het is een stille regressie als je er niet op rekent — bewust benoemen in de release-notitie voor de tester. - Eén tegel meer op het startscherm. Vier tegels onder Vermogen in plaats van drie regels in Financieel; dat is drukker, niet stiller.
Het overzicht kan óók zónder nieuw module-id: maak de domeinkop tikbaar naar het
al bestaande
/domein/vermogen en zet het totaal daar bovenaan. Dat scheelt
een registry-regel. Ik raad het af: het introduceert een app-breed
interactiepatroon (alle domeinkoppen worden dan tikbaar, of alleen deze — inconsistent),
en een domeinscherm kan geen favoriet zijn, geen eigen tier hebben en geen eigen
instellingen dragen. Een module is hier het goedkopere geheel.
Deze optie bestaat niet meer. Ze rustte op een scherm dat er al lag; sinds
F1-9 (merge 20f1b910, 6 augustus 2026) is er geen
/domein/:id en geen DomainScreen meer. Een tikbare domeinkop zou nu een
nieuw scherm vergen én een net genomen besluit terugdraaien. De bezwaren die hierboven al golden
— een app-breed interactiepatroon en een scherm dat geen favoriet, tier of instellingen kan
dragen — staan er nog bovenop. Blijft dus: als variant A gekozen wordt, met een eigen
module-id.
Vermogen wordt één nieuwe module binnen Financieel
Geen domein-verhuizing. Eén nieuwe read-only aggregatie-module vermogen in het bestaande domein Financieel, naast de negen die er al staan. Vastgoed blijft ongemoeid in zijn eigen domein.
Exact de constructie die de Vaste-kosten-hub al is: een module die zelf nauwelijks data
heeft en vooral over andere modules aggregeert (financieel_module.dart:55-63,
costHubProvider in vaste_kosten_providers.dart:67). Één nieuw
id, één route, één scherm. Nul verhuizingen.
Ze tikt Mijn leven → Financieel → Vermogen en krijgt hetzelfde overzicht als in A, met dezelfde doorkliks. Functioneel is het overzicht identiek.
- Het minste van de drie: één module-id (registry, route, tier — geen deelbeleid-regel nodig) + dezelfde aggregatielaag als in A. Geen domein-wijziging, geen AI-opt-in-effect, geen navigatie-omzetting.
- Volledig omkeerbaar en later te promoveren naar A: het domein toevoegen is dan nog steeds vier regels.
- De overkoepeling. Vermogen is de tiende tegel in een rij van tien, en Vastgoed staat in een héél ander blok. Vastgoed is dan geen "onderdeel van Vermogen" maar een buur ervan met een streepje ertussen. Dat is niet wat de zin van 26 juli vraagt.
- Het blijft onvindbaar op de plek waar Sandra zoekt. Ze begon haar vraag bij vastgoed ("bij vastgoed wil ik eigenlijk aangeven wanneer we het gekocht hebben … denk ook nog even mee zodat we een overzicht krijgen van wat ons vermogen is"). In B is er vanuit vastgoed geen zichtbaar pad naar dat overzicht, tenzij je er handmatig een link naartoe legt.
- Financieel wordt tien tegels. Dat is al veel; dit maakt het meer. In A wordt het juist rustiger.
Één Vermogen-module die Vastgoed opneemt als sectie
De letterlijke lezing van "één Vermogen-module": vastgoed is geen aparte module meer maar een sectie binnen Vermogen, naast secties voor schulden, spaargeld en beleggingen.
Eén plek, één mentaal model. Geen discussie meer over of een pand nu "vastgoed" of "vermogen" is. Voor een gebruiker die met vermogen begint in plaats van met verhuur, is dit de schoonste indeling: je voegt een bezitting toe, kiest het type, en als het type "pand" is verschijnen de verhuur-velden. Het voorkomt ook dat financiële velden zich over meerdere modules verspreiden. Als vastgoed nog niet gebouwd was, zou dit een verdedigbaar startpunt zijn.
- Het module-id
vastgoedmoet ophouden te bestaan of leeg blijven staan. Aan dat id hangen: de route, de agenda-item-decoratie (vastgoed_module.dart:49-67), de reminder-resync (feature_modules.dart:231), de deelbeleid-regel (share_policy.dart:120), de deel-remap met object→boekingen-cascade (share_bulk_remapper.dart:120), de deel-hint (shared_in_disabled_module_watcher.dart:45) enkSelfSurfacedModules. - En de opgeslagen instellingen. Module aan/uit per lid, meldingstermijn, meldtijd, geluid en verbergen-voor-leden staan op de rij
<householdId>:vastgoedinModuleStates(foundation_tables.dart:185) en inMemberModulePrefs(:236), plus de favorieten in de_shell-prefs (module_quick_action_providers.dart:118). Dat is een data-remap, geen additieve migratie — en die valt niet onder het staande akkoord voor additieve kolom-migraties. - De check-in/check-out-meldingen zouden hun eigen meldingstermijn verliezen: één Vermogen-module heeft één meldingsinstelling, en die moet dan zowel "1 dag voor check-in" als "opzegtermijn-melding" als eventuele waarderings-herinneringen dekken.
Precies de randvoorwaarde. Vastgoed houdt in deze variant geen eigen schermen, eigen
meldingsinstellingen en eigen deelbeleid — het krijgt een sectie in een groter scherm. Om
álle veertien punten van § Wat behouden blijft te bewaren, zou je
in feite een module-in-een-module moeten bouwen: een sub-registratie-mechanisme dat
vandaag niet bestaat (er is geen ModuleGroup, geen
parentModuleId, geen nesting — nagekeken in de hele lib/).
Dat mechanisme bouwen is een raamwerk-project bovenop het Vermogen-project, met een
data-remap in het midden en vier testtoestellen die er doorheen moeten.
Conclusie: C levert een net iets schoner datamodel op tegen de prijs van een nieuw raamwerk en een remap van instellingen, en het schendt de randvoorwaarde tenzij je dat raamwerk eerst bouwt. Afgeraden — niet omdat het idee slecht is, maar omdat het te laat komt.
Naast elkaar
| Nulmeting (ADR-0012) | A · domein | B · module in Financieel | C · opgeslokt | |
|---|---|---|---|---|
| "Vastgoed is 1 onderdeel van Vermogen" zichtbaar | Nee | Ja | Nee | Ja |
| Vastgoed verliest niets | Ja | Ja | Ja | Alleen mét nieuw raamwerk |
| Nieuw module-id | Geen | 1 | 1 | 1, en 1 vervalt |
| Data-remap nodig | Nee | Nee | Nee | Ja (module-states, prefs, favorieten) |
| Migratie nodig voor het eerste getal | Nee | Nee | Nee | Ja |
| Navigatie verandert voor de tester | Niet | Ja, 3 modules verhuizen | Nauwelijks | Ingrijpend |
| Later te promoveren | Naar B of A | Eindvorm | Naar A | — |
| Grofweg werk | Klein | Middel | Middel-klein | Groot |
Aanbeveling
Variant A — Vermogen als domein, met één read-only Vermogensoverzicht-module. Vastgoed blijft een volwaardige module daarbinnen.
En bouw het in de fasering van § Zes: eerst het getal (zonder enige migratie), dan de overkoepeling.
Waarom A en niet C. De vraag "module ónder Vermogen of sectie ín Vermogen" wordt niet
beslecht door welke indeling het mooiste datamodel geeft, maar door wat er al gebouwd is. Aan
het module-id vastgoed hangen zes registraties in code én drie soorten opgeslagen
voorkeuren. Vastgoed heeft daarnaast dingen die geen andere bezitting heeft en ook nooit zal
hebben: een boekingsmodel met gasten en periodes, overlap-detectie, twee verhuurmodi die de
agenda-weergave bepalen, wisseldag-glyphs, een opzegtermijn-melding en een objectkleur die als
avatar in de agenda meeloopt. Dat is geen "bezitting met een waarde" — dat is een mini-PMS. Een
abstractielaag die daar een sectie van maakt, moet al die eigenschappen terugbouwen als
uitzonderingen binnen de generieke laag. Dat is meer werk dan de laag zelf.
Waarom A en niet B. B is goedkoper en volstrekt verdedigbaar, en als het besluit "geef ons een vermogensoverzicht" was geweest, zou ik B adviseren. Maar het besluit is "Vermogen wordt de overkoepeling, vastgoed is er één onderdeel van", en in B is Vermogen de tiende tegel naast Vastgoed in plaats van erboven. Het duurdere deel van A is niet het domein (vier regels) maar de aggregatielaag — en die heb je in B óók nodig. De extra kosten van A boven B zijn dus klein: een domein-regel, drie verhuizingen, en één keer uitleggen aan de tester dat Leningen en Spaardoelen verhuisd zijn.
Waarom het cost-hub-patroon dit goedkoop maakt. Zie de volgende sectie: een vermogens-aggregatie is niet alleen hetzelfde patroon als de kosten-hub, hij is een eenvoudiger geval — de drie zwaarste onderdelen van de kosten-hub vallen weg. Dat is het verschil tussen een groot en een middelgroot project.
Wat A expliciet niet oplost. Leningen hoort inhoudelijk in twee domeinen en kan er maar in één; de AI-opt-in moet één keer opnieuw voor het nieuwe domein-id; en de tester ziet haar navigatie veranderen. Dat zijn de prijzen. Ik vind ze goedkoop tegenover het alternatief, maar ze zijn echt.
Hergebruik: kan de vermogens-aggregatie het cost-hub-patroon volgen?
Ja — en het is een eenvoudiger geval. Dat is de belangrijkste bevinding voor de omvangsschatting.
De kosten-hub bestaat uit een pure bouwfunctie buildCostHub
(vaste_kosten/domain/cost_hub.dart:71) die genormaliseerde
CostModuleItem-objecten uit meerdere modules samenbrengt
(domain/cost_post.dart:58), dedupliceert op de sleutel
'<moduleId>|<sourceRef>' (cost_post.dart:322) en via één
provider aan één scherm wordt gehangen (vaste_kosten_providers.dart:67). Die vorm
is één-op-één over te zetten:
| Kosten-hub (bestaat) | Vermogen (nieuw) | Verschil |
|---|---|---|
CostModuleItem | WealthItem | + kind (bezitting/schuld), + asOf peildatum, + financedByRef |
buildCostHub(...) pure functie | buildVermogen(...) pure functie | Zelfde vorm; sommeert saldi i.p.v. te normaliseren op frequentie |
Dedupe op <moduleId>|<sourceRef> | Idem, plus dedupe per lening-id | Vereist door ADR-0014: één hypotheek aan twee objecten telt één keer |
costHubProvider leest 6 module-streams | vermogenProvider leest 3 (panden, leningen, spaardoelen) | Minder bronnen |
Koppel-rijen in fixed_costs met geaccepteerd bedrag | Vervalt | Er is niets te "accepteren" — geen tabel, dus geen migratie |
| Afwijking-signalering → Vandaag-suggesties | Vervalt | Een waarde die verandert is geen afwijking maar een feit |
| Wees-koppelrijen (bron verwijderd) | Vervalt | Zonder koppel-rijen bestaan er geen wezen |
| — | Onvolledigheid als eerste-klas uitkomst | FinancingUnavailable bestaat al (property_return_calc.dart:203) |
Wat dat betekent voor de omvang. De drie duurste onderdelen van de kosten-hub (koppel-rijen met een eigen tabel en accept-flow, afwijking-signalering met een pijplijn naar Vandaag, en wees-beheer) zijn hier niet nodig. Wat overblijft is: één pure domeinfunctie met tests, één provider, één scherm, en een doorklik per regel naar de bronmodule. Voor de eerste versie: nul migraties, nul schemaVersion-bump, nul sync-config-wijziging — en dus ook geen 4-weg lockstep en geen prod-deploy-afhankelijkheid. Dat is de reden dat dit middelgroot is en niet groot.
Één ontwerpkeuze in de aggregatie: hard gedraad of via de registry
De kosten-hub draadt zijn bronnen hard: zes ref.watch-regels en een
mapper per bron in de provider (vaste_kosten_providers.dart:68-115), plus drie
hardgecodeerde switches in het scherm voor icoon, label en route
(vaste_kosten_screen.dart:727/736/748). Er is géén uitbreidingspunt. Het
alternatief bestaat óók al in deze app: FeatureModule.todayRowSources
(module_descriptor.dart:184, geplat in module_providers.dart:42) laat
modules zichzelf aanmelden.
Voorstel: begin hard gedraad — met drie bronnen is een registry-hook
voorbarig — maar los meteen één bekend gebrek van de kosten-hub op: daar valt de
hele hub in laden of fout zodra één bron dat doet
(vaste_kosten_providers.dart:75-83). Voor een vermogensoverzicht is dat
onaanvaardbaar: dan is het totaal leeg omdat de spaardoelen nog laden. Degradeer per
bron ("spaargeld kon niet geladen worden") en toon de rest. Zodra beleggingen erbij komen
(fase V3) is dat het natuurlijke moment om naar de registry-hook te gaan.
Open vragen — dit moet jij beslissen
Dit zijn geen implementatiedetails maar productkeuzes met een verkeerd antwoord. Ik doe per vraag een voorstel, maar ik ga het niet zelf beslissen.
Hoe wordt de actuele waarde van een pand bepaald?
Vandaag is properties.current_value een handmatig veld
(vastgoed_tables.dart:36) zonder peildatum en zonder geschiedenis. Drie routes:
(a) handmatig bijhouden, (b) afleiden uit aankoopprijs × een indexatie, of
(c) een jaaropgave/WOZ-beschikking scannen met de bestaande AI-extractie-stack
(ontworpen in ADR-0015). Er zit géén WOZ-veld en géén enkele externe waardebron in de app —
geverifieerd: het woord komt in het hele schema niet voor.
Wat ik van jou nodig heb: is een handmatige waarde met peildatum genoeg voor v1, en na hoeveel maanden wil je erop gewezen worden dat hij oud is (voorstel: 12)?
Telt een financieringslening dubbel tegen de waarde van het object dat hij financiert?
Dit is het echte dubbeltelling-risico. Een pand van € 285.000 met een hypotheek van
€ 180.000 is € 105.000 vermogen. Als de hypotheek óók nog los in de schuldenlijst staat,
wordt het € 285.000 − € 180.000 − € 180.000. De koppeling die dit moet voorkomen is
properties.financing_loan_id (vastgoed_tables.dart:42) — een
zwakke, éénzijdige, 1-op-1 referentie zonder FK. De lening weet niet welk object hij
financiert.
FinancingUnavailable).
Preciezer geformuleerd na open vraag 7: de dedupe zit niet in de object-weergave maar in het totaal. De balans telt elke lening precies één keer op huishoudniveau (dedupe op lening-id, ná
effectiveLoans); wat een object over
"zijn" financiering toont, is presentatie en wordt nooit gesommeerd. Daarmee kan een lening
niet zowel los als via een object meetellen.
Wat ik van jou nodig heb: één grensgeval blijft over. Een lening die hangt aan een object dat de kijker niet mag zien: meetellen of niet? Voorstel: niet meetellen en het expliciet zeggen, want de per-kijker-doorsnede is al beleid (ADR-0016). Het geval "één hypotheek op twee objecten" is verhuisd naar open vraag 7, waar het nu volledig is uitgewerkt.
Wat is "vermogen" — bruto bezittingen of netto na schulden?
Beide zijn verdedigbaar en ze verschillen bij dit huishouden vermoedelijk met een factor. Bruto voelt groter; netto is wat je werkelijk hebt.
Wat ik van jou nodig heb: is netto bovenaan het getal dat je wilt zien, of wil je bruto groot en netto klein?
Doen auto's mee?
vehicles heeft alléén purchase_price
(wagenpark_tables.dart:31) en geen actuele waarde. Een auto van acht jaar oud
staat dus voor zijn nieuwprijs in de boeken — dat maakt het totaal aantoonbaar te hoog.
current_value-kolom op
vehicles naar hetzelfde model als bij panden (additief, nullable) — een klein
vervolg, niet iets voor v1.
Wat ik van jou nodig heb: wil je auto's erin, en zo ja, ben je bereid hun actuele waarde net als bij een pand zelf bij te houden?
Doet bankrekening-saldo mee?
bank_accounts heeft bewust geen saldo-kolom
(bankrekeningen_tables.dart:14 — het bestand legt in zijn kop uit dat er alleen
de laatste 4 IBAN-cijfers worden opgeslagen). Zonder saldo is liquide geld alleen indirect
zichtbaar via het spaardoelen-ledger.
Wat ik van jou nodig heb: akkoord dat "liquide middelen" in v1 gelijkstaat aan het spaardoelen-totaal, of wil je een handmatig veld "overig spaargeld"?
Eén gezinsvermogen of per persoon?
Vastgoed en financieel zijn default privé per lid. ADR-0016 legde vast dat cijfers per kijker verschillen: ieder rekent over de eigen zichtbare objecten en leningen. Dat blijft inhoudelijk juist, maar bij een scherm dat "Ons vermogen" heet is het verwarrend als jij en Sandra een ander getal zien.
Wat ik van jou nodig heb: bevestiging dat dat zo blijft, of de wens dat vermogens-data standaard met de partner gedeeld wordt.
Een hypotheek die op meerdere objecten zit
Gangbaar scenario: één hypothecaire inschrijving op twee panden, of een hypotheek op de eigen
woning die deels een tweede object financiert. Wat het model nu aankan:
properties.financing_loan_id is een enkele verwijzing van pand naar lening
(vastgoed_tables.dart:42), dus twee panden kunnen naar dezelfde lening
wijzen — maar er is geen verdeling. Elk pand ziet dan de volledige lening, en de
rentemomentopname toont bij beide objecten hetzelfde volledige bedrag (bewust zo, en in fase 1
nergens opgeteld).
Is loan_parts de natuurlijke plek? Onderzocht: nee. Die tabel
(leningen_table.dart:54, TEN-91 deel b) modelleert een hypotheek die uit
rente-/looptijddelen bestaat — annuïtair naast aflossingsvrij — met per deel een eigen
rente, looptijd en einddatum. Er staat geen propertyId op (nagekeken: geen
enkele treffer in de hele leningen-map) en géén maandbedrag. De assen zijn orthogonaal: één
deel kan over twee objecten lopen en twee delen over één object. Toerekening erin proppen zou
de derivatie in loan_calc.dart besmetten, waar de lening-totalen uit de delen
worden berekend. Wél relevant: als toerekening én delen samen bestaan, moet de toerekening
tegen de effectieve restschuld gevalideerd worden, niet tegen het parent-veld.
Let op — een onvervulde belofte: ADR-0013 zei dat een
koppeltabel pand↔lening "bij TEN-91-deel-b" zou komen. Wat er als TEN-91 deel b is gebouwd, is
loan_parts — iets anders. Die koppeltabel bestaat dus nog niet, en dat is precies
wat hier op tafel ligt.
Vier varianten:
| Variant | Wat het is | Wat het kost | Wat je opgeeft |
|---|---|---|---|
| a · Geen toerekening huishoudniveau |
De lening staat als schuldpost in de balans, niet aan een object gehangen. Netto vermogen blijft correct. | Nul — dit kan vandaag al door financing_loan_id leeg te laten |
Overwaarde of rendement per object wordt onmogelijk. En het objectdetail zegt "geen financiering" terwijl er wél een hypotheek is — misleidend tenzij je het uitlegt. |
| b · Vaste bedragen | Koppeltabel property_loan_allocations(property_id, loan_id, amount). "€ 120.000 van de € 300.000 zit op de vakantiewoning." |
1 tabel + migratie + 4-weg lockstep + invoer-UI + somvalidatie | Loopt scheef bij elke aflossing: de restschuld daalt, het toegerekende bedrag niet. Vraagt onderhoud door de gebruiker — precies het soort veld dat verouderd raakt zonder dat iemand het merkt. |
| c · Percentages aanbevolen |
Zelfde koppeltabel, maar met share_pct. Het bedrag per object = percentage × actuele restschuld. |
Identiek aan b | Bij invoer iets minder intuïtief ("hoeveel procent?" i.p.v. een bedrag), en afrondingsresten in de weergave. Maar blijft automatisch kloppen bij aflossing. |
d · Via loan_parts |
Een deel per object. | Lijkt gratis | Verkeerde as (zie hierboven), besmet de totaal-derivatie, en delen kennen geen maandbedrag. Afgeraden. |
Dat laatste is de kern, en het maakt dubbeltelling structureel onmogelijk in plaats van afhankelijk van een controle: de balans telt elke lening precies één keer op huishoudniveau (dedupe op lening-id, ná
effectiveLoans). Toerekening is
uitsluitend een presentatielaag voor "overwaarde van dít pand" en wordt nergens
gesommeerd. Zo kan een gedeeltelijk toegerekende lening niet één keer volledig én één keer per
object meetellen — die som wordt simpelweg nooit gemaakt.In V0 is dat (a), gratis en correct. (c) hoort bij V2/V3, wanneer overwaarde per object werkelijk gevraagd wordt.
Wat ik van jou nodig heb — drie grensgevallen:
(i) Telt de verdeling niet op tot de restschuld: afdwingen of tolereren? Voorstel: tolereren met waarschuwing, want afdwingen blokkeert je midden in het invullen en de restschuld verandert buiten de app om. Met percentages: som boven 100% is een echte fout (blokkeren), som onder 100% is legitiem — de rest is niet toegerekend en dat toont het scherm ("niet toegerekend: € 45.000").
(ii) Object verkocht, lening blijft? Voorstel: de toerekening vervalt mét het object (dezelfde cascade als object→boekingen), de lening blijft volledig in de balans en het niet-toegerekende deel groeit. Nooit stil de schuld verlagen omdat een pand verdwijnt.
(iii) Wil je dit überhaupt per object kunnen zien, of is één correct netto-vermogen op huishoudniveau genoeg? Als (a) volstaat, valt een tabel, een migratie en een invoerscherm weg.
Kunnen boekingen automatisch binnenkomen?
Onderzoeksvraag van de eigenaar: kunnen we de vastgoed-boekingen eenvoudig aan Uplisting, Airbnb of Booking hangen, zodat boekingen gesynchroniseerd binnenkomen in plaats van dat ze continu handmatig ingevuld moeten worden? Terechte wens: bij kortverhuur verandert de boekingslijst wekelijks, en gast, periode en status worden nu alle drie met de hand ingevoerd.
Een eerdere versie van deze sectie raadde Uplisting af wegens "partnerovereenkomst met revenue share". Dat was onjuist en is hieronder herschreven. De fout: ik haalde twee verschillende dingen door elkaar — integratiepartner van Uplisting worden (om een koppeling in hun marktplaats te distribueren) versus Uplisting-klant die zijn eigen API-key gebruikt. Voor het tweede is géén goedkeuring, géén partnerovereenkomst en géén revenue share nodig. De eigenaar is klant en heeft de key al. De vraag is dus niet óf het kan, maar hoe we het inrichten.
Het onderscheid dat de fout veroorzaakte — en dat het ontwerp bepaalt
| Route | Wat je nodig hebt | Goedkeuring? | Voor ons |
|---|---|---|---|
| Klant met eigen API-key V1-lees-endpoints + webhooks |
De key die de klant zelf aanmaakt in Uplisting onder Connect → API. HTTP Basic met de base64-gecodeerde key. | Geen | Dit is onze route |
| Integratiepartner / marktplaats V2-schrijf-endpoints, V3 OAuth2 |
Een X-Uplisting-Client-Id respectievelijk OAuth-client_id, aan te vragen via partner@uplisting.io; daarbij hoort de partnerovereenkomst (met revenue-share-regeling). |
Ja | Niet nodig — wij hoeven niets te schrijven en niets te distribueren via hun marktplaats |
Wij hoeven alleen te lezen: boekingen ophalen en wijzigingen ontvangen. Dat zit volledig in de eerste rij. Het schrijven van boekingen terug naar Uplisting — het enige waarvoor de partnerroute nodig is — is voor Tendlo geen wens: de bron van waarheid voor een verhuurboeking is de channel manager, niet onze app.
Uplisting is de voorkeursroute
Op elk punt beter dan de iCal-route die hieronder als terugval blijft staan:
- Eén koppeling dekt Airbnb én Booking.com. Uplisting is de channel manager die die
kanalen al bundelt; de boeking draagt een
channel-veld met waarden alsairbnb_officialenbooking_dot_com. We hoeven dus niet per platform iets te bouwen — en we hoeven al helemaal niet langs de gesloten deuren van Airbnb en Booking.com (zie hieronder). - Het is de eigen data van de gebruiker, geautoriseerd met zijn eigen key, in plaats van een publieke geheime kalender-URL. Dat is zowel functioneel als privacy-technisch een betere basis.
- Webhooks in plaats van pollen.
booking_created,booking_updatedenbooking_removed— dus ook een expliciet signaal bij annulering. Precies wat iCal structureel niet kan (daar is een annulering een stille verdwijning). - Annuleringen zijn opvraagbaar, niet alleen als gebeurtenis: de boekingenlijst per pand geeft ook geannuleerde boekingen terug, dus een herstel-na-downtime kan de werkelijkheid opnieuw vaststellen zonder te gokken.
Of gastnaam en bedrag daadwerkelijk meekomen — en hoe we dat vaststellen
De publieke Postman-collectie van Uplisting documenteert een boekings-payload met
onder meer guest_name, guest_email, guest_phone,
check_in, check_out, channel,
external_reservation_id, status, total_payout en
cleaning_fee. Dat is precies waar iCal tekortschiet, en het zou de belofte
"bezette dagen, vul zelf aan" veranderen in échte boekingssync.
Maar dit is niet geverifieerd tegen een live account, en de support-pagina over de API somt de velden niet op. Dus: gedocumenteerd ja, bevestigd nee. Ik heb geen boeking van de eigenaar opgehaald en ga dat ook niet op eigen initiatief doen.
partner@uplisting.io met het
verzoek om de volledige API-documentatie — dat is wat hun support-pagina zelf als route
aangeeft. Je hebt de key al, dus daarnaast kan één enkele leesaanroep op je eigen account
(GET /bookings/<listing_id>) in vijf minuten uitwijzen wélke velden er echt
in staan. Zeg maar of je wilt dat ik dat samen met jou doe; ik doe het niet ongevraagd, want
het gaat om je eigen sleutel en echte gastgegevens.
Airbnb en Booking.com direct: dicht
Direct koppelen kan niet — niet "moeilijk", maar structureel niet beschikbaar. Airbnb neemt geen aanvragen aan: het partnerportaal heeft alleen een inlog, en Airbnb selecteert zelf wie het benadert, op basis van hoeveel woningen je meebrengt. Booking.com heeft nieuwe connectiviteits-partners gepauzeerd ("we are pausing integrations with new connectivity providers until further notice") én zegt expliciet dat ze geen directe koppelingen van individuele woningen accepteren. Dat is geen probleem meer zodra we via Uplisting gaan: die koppeling levert de Airbnb- en Booking-boekingen juist wél.
iCal als terugval — voor wie geen Uplisting heeft
Uplisting is de beste route voor deze eigenaar, maar het vereist wel dat de gebruiker Uplisting-klant is (abonnement vanaf ongeveer £72 per maand). Voor de eigenaar is dat al zo; voor een willekeurige Tendlo-gebruiker met één vakantiewoning niet. Daarom blijft iCal in het ontwerp staan als tweede implementatie — en als vangnet mocht de Uplisting-API onvoldoende blijken. Wat erin zit verschilt sterk per platform, en dat bepaalt de belofte die je erbij zet:
| Feed | Gastnaam | Bedrag | Reserveringsnummer | Tijden |
|---|---|---|---|---|
| Airbnb | Nee | Nee | Nee (alleen een link) | Nee — hele dagen |
| Booking.com | Nee | Nee | Nee | Nee |
| Vrbo | Meestal wel | Nee | Nee | Nee |
| Uplisting / Beds24 | Ja | Via API, niet in de feed | Via API | Ja, met tijdzone |
Airbnb heeft zijn feed op 1 december 2019 bewust uitgekleed om privacyredenen: de titel
is sindsdien letterlijk SUMMARY:Reserved en de omschrijving bevat alleen een link
naar de reservering plus de laatste vier cijfers van het telefoonnummer. Booking.com
geeft alleen datums met een statuslabel. Concreet betekent dat:
Bij een iCal-koppeling met Airbnb of Booking.com is de belofte niet "je boekingen komen automatisch binnen", maar: "je bezette dagen komen automatisch binnen — tik een boeking aan om de gast en het bedrag toe te voegen." Dat verandert het werk van alles typen naar bevestigen en aanvullen. Bij de Uplisting-route valt die beperking vermoedelijk weg en is het wél echte boekingssync — mits de velden uit de open vraag hierboven bevestigd zijn. Twee routes, twee verschillende beloftes: het scherm moet zeggen welke van de twee actief is.
Wat de app al heeft — geldt voor de iCal-route
Dit is de belangrijkste bevinding van de hele sectie: Tendlo importeert al iCal-feeds, in productie, op twee plekken.
- Een volwaardige, tolerante iCal-parser —
lib/features/gezin/sportkalender/data/ical_parser.dart(148 regels), gebouwd op het pakketicalendar_parser(pubspec.yaml:63). Die heeft de klassieke valkuilen al opgelost:UID-stabiliteit met een synthetische terugval als de feed geen UID geeft (:26-29),VALUE=DATEversusDATE-TIME(:40), UTC enTZIDomgerekend naar toesteltijd met een terugval voor onbekende zones zoals Outlook's "W. Europe Standard Time" (:33-38), en eenFormatExceptionals de URL een HTML-foutpagina teruggeeft in plaats van een kalender (:4-5). - Een werkend import-patroon met herkomst —
sport_events.externalUidis nullable met de dartdoc "UID of the source VEVENT when this event was imported; null for hand-entered events" (sportkalender_tables.dart:81-84). De import doet zoek-op-uid-dan-bijwerken-anders-invoegen (drift_sportkalender_repository.dart:304-334), aangestuurd doorimportIcalForTeam(sportkalender_providers.dart:241) met een overrijdbare HTTP-client zodat het testbaar is (:48). - Een tweede, onafhankelijke
.ics-import voor de afvalkalender, mét bestand- én URL-invoer (afvalkalender/data/ics_afval_importer.dart). - En de boekingssemantiek klopt al toevallig precies. Boekingen worden in deze app
behandeld als half-open
[start, end)met einde = check-out-dag, expliciet zodat rug-aan-rug-boekingen niet als overlap gelden (domain/booking_overlap.dart:8-10). Dat is exact de conventie die verhuurplatform-feeds gebruiken voor hunDTEND. De beruchte off-by-one op de vertrekdag is hier dus geen conversie maar een gelijkheid.
Wat dat betekent: een iCal-import voor boekingen is in deze app géén nieuw traject. Het is een derde toepassing van een patroon dat al twee keer draait en getest is.
Eén eigenschap van de bestaande parser is hier juist gevaarlijk
De parser verzint een synthetische UID uit summary + start + eind + locatie als
de feed er geen geeft (ical_parser.dart:26-29). Voor sportwedstrijden is dat
precies goed. Voor verhuurfeeds is het een dubbel-risico, want de Airbnb-feed reikt maar
365 dagen vooruit: een boeking die verder in de toekomst eindigt, wordt gerapporteerd
met een einddatum van exact vandaag + 365 — die schuift dus elke dag een dag op tot de
echte einddatum in beeld komt. Een identiteit waar de einddatum in zit, levert dan elke dag
een "nieuwe" boeking op.
UID, met als terugval (object, startdatum) —
en nooit de einddatum in de identiteit. Airbnb geeft wel UID's, dus de terugval is
zeldzaam, maar hij moet goed staan. Diezelfde 365-dagendrift betekent ook dat een ver
vooruit geboekte periode tijdelijk een verkeerde einddatum toont; dat is een reden om
bij geïmporteerde boekingen de einddatum als "volgens de kalender" te labelen in plaats van
als vaststaand feit. Deze regel geldt voor béíde routes: ook bij Uplisting is de
identiteit het reserveringsnummer of de bron-id, nooit iets waar een datum in zit die kan
schuiven.
Waar de sync draait — en waarom webhooks dat beslissen
Bij de Uplisting-route is dit geen afweging meer maar een gevolg: een webhook heeft een
publiek HTTPS-eindpunt nodig. Dat kan een telefoon niet zijn. De sync hoort dus
server-side, en het patroon staat er al: supabase/functions/revenuecat-webhook is
precies dit — een edge function die een webhook van een externe partij ontvangt. Er staan zes
edge functions in deze repo.
De rate limits maken pollen bovendien onaantrekkelijk: 5 verzoeken per seconde en 100 per minuut per IP, en maximaal 15 per minuut per pand. Eén server die pollt is te doen; vier gezinstoestellen die elk pollen, tikt met meerdere panden snel tegen die grens aan — en de API-key zou dan op elk toestel moeten staan. Bij de iCal-terugval geldt hetzelfde argument: Airbnb beperkt handmatig verversen expliciet ("we're only able to request updates from the other website so many times") en ververst zelf maar elke ~3 uur.
Server-side, webhook-eerst, met pollen als herstelmechanisme. Eén edge function
ontvangt de Uplisting-webhooks (naar het model van revenuecat-webhook) en schrijft
de boekingen weg; daarnaast één periodieke volledige ophaling per pand als
reconciliatie, want webhooks worden minstens-één-keer bezorgd en een endpoint dat
herhaaldelijk niet antwoordt wordt door Uplisting uitgeschakeld — dan mag je niet stil uit
de lucht zijn. Webhook-payloads dragen een tijdstempel, dus buiten-orde-bezorging is af te
vangen door oudere gebeurtenissen te negeren.
Twee dingen die dit server-side maken en aandacht vragen: de API-key hoort niet op
de toestellen maar in de serveromgeving (bij iCal geldt dat net zo voor de geheime
feed-URL), en de boekingsgegevens — inclusief gastnamen — passeren daarmee de backend, wat de
privacyparagraaf hieronder zwaarder maakt dan bij een puur client-side import.
Kanttekening bij de planner: edge functions bestaan hier, maar ik heb in dit project
géén pg_cron aangetroffen in de migraties. Het patroon draait wél in de
feedback-pijplijn (ander Supabase-project), dus het is bekend terrein — maar in
pa_app is de periodieke trigger nieuw werk, geen bestaande voorziening.
Herkomst en conflicten — de regel die dit veilig maakt
Zonder herkomst-veld overschrijft een import het handwerk van de gebruiker, of ontstaan er
dubbele boekingen. bookings heeft nu géén herkomst-veld
(vastgoed_tables.dart:80-106: object, gast, start, eind, status, bedrag). Dat is
een additieve kolom, naar het model dat al bestaat.
external_uid(nullable) — leeg = met de hand ingevoerd; gevuld = uit een externe bron. Exact zoalssport_events.externalUid. Omdat er nu twee bronnen in beeld zijn, hoort er eenexternal_sourcenaast (uplisting/ical): dezelfde boeking via twee routes moet niet twee rijen worden, en het scherm moet kunnen zeggen waar een boeking vandaan komt.- Wie wint: een import mag alléén rijen aanraken met een
external_uiddat hij zelf herkent. Handmatige boekingen worden nooit door een import gewijzigd of verwijderd. Velden die de gebruiker zelf heeft aangevuld op een geïmporteerde rij blijven staan; de import werkt alleen bij wat hij zelf geleverd heeft. Bij Uplisting kantelt dat deels: als gastnaam en bedrag uit de bron komen, is de bron daarvoor gezaghebbend en is de vraag juist omgekeerd — mag de gebruiker ze lokaal overschrijven, en verliest hij die aanpassing dan bij de volgende webhook? Voorstel: een handmatige wijziging op een geïmporteerd veld plakt (wordt niet overschreven) en het scherm laat zien dat het van de bron afwijkt. - Verdwijnen is het lastige geval — bij iCal. Bij Uplisting is dit juist opgelost: er
is een expliciete
booking_removed-gebeurtenis en geannuleerde boekingen zijn opvraagbaar. Dat is een van de sterkste argumenten voor die route. Bij iCal geldt: een annulering levert géén tombstone: er is geenSTATUS:CANCELLEDen geenMETHOD:CANCEL, de gebeurtenis houdt simpelweg op te bestaan. Het gevolg: een afgekapte of half-opgehaalde feed ziet er identiek uit aan "alles is geannuleerd". Voorstel: een verdwenen geïmporteerde boeking wordt gemarkeerd als "niet meer in de kalender" en de gebruiker beslist — precies zoals de kosten-hub een wees-koppelrij zichtbaar houdt in plaats van hem stil te verwijderen. En als er later automatisch geannuleerd wordt, alleen achter een sanity-guard: de feed moet schoon geparseerd zijn én netjes eindigen opEND:VCALENDAR, en een feed die van veel naar bijna niets gaat, is een fout tot de gebruiker hem bevestigt. - Voorlopige boekingen. Airbnb blokkeert de kalender óók voor aanvragen die nog op acceptatie wachten, en er komen "spook"-blokkades voorbij van afgebroken afrekeningen. Uplisting kent een filter hiervoor, de platforms zelf niet. Reken erop dat een klein deel van de geïmporteerde blokkades geen echte boeking is — nog een reden om automatisch verwijderen niet als eerste te bouwen.
- Overlap: de bestaande overlap-detectie blijft gelden. Een geïmporteerde boeking die overlapt met een handmatige is een signaal aan de gebruiker, geen fout die de import zelf oplost.
- Eén bron per object. Bij iCal: één feed-URL per object (twee platforms op hetzelfde object geeft anders twee rijen voor dezelfde week). Bij Uplisting: één koppeling per huishouden die álle panden dekt, waarbij elk Uplisting-pand aan een Tendlo-object gekoppeld moet worden — dat is een eenmalige "welk pand is welk object?"-stap die in het ontwerp hoort en makkelijk vergeten wordt.
Privacy — zwaarder bij de Uplisting-route, niet lichter
Drie dingen die geregeld moeten zijn vóór dit live gaat, en die nu niet in de privacyverklaring
staan (docs/release/privacybeleid-concept.md):
- Gastnamen zijn persoonsgegevens van derden. Die gast heeft geen relatie met Tendlo en heeft nergens iets ingevuld. Hoeveel er meekomt hangt van de route af: uit Airbnb- en Booking-iCal komt geen naam (uit Airbnb wel de laatste vier cijfers van een telefoonnummer); uit Uplisting komt vermoedelijk juist het meeste — naam, e-mail én telefoon. Precies de reden dat de betere route ook de zwaardere privacyroute is. Dit hoort in §3.2 van de verklaring ("de gegevens die je zelf in de app zet" wordt "…en gegevens die via een verhuurkoppeling binnenkomen") met een rechtsgrond in §8, en het verdient een bewuste keuze of we e-mail en telefoon van gasten überhaupt willen opslaan. Voorstel: nee — sla naam en periode op, laat contactgegevens buiten Tendlo. Wat je niet opslaat, hoef je niet te beschermen.
- Er komt een verwerker bij, en de backend gaat meekijken. Uplisting wordt daarmee een ontvanger/verwerker die in §5.2 hoort ("de diensten die we inschakelen"), en omdat de webhook server-side landt, passeren gastgegevens onze eigen backend — anders dan bij een puur client-side import. Dat vraagt een regel in §5.2 en, bij echte uitrol, een verwerkersovereenkomst.
- De sleutel en de feed-URL zijn geheimen. Een iCal-feed-URL is een onbeveiligde geheime link: wie hem heeft, ziet de kalender, voor altijd. De Uplisting-API-key is erger: die geeft toegang tot het hele account. Geen van beide mag in logs, in foutrapportage (Sentry), in een screenshot of in een back-up terechtkomen, en geen van beide hoort op de toestellen — bij een server-side sync staan ze in de serveromgeving, niet in een gesyncte tabel. Dat is een verschil met mijn eerdere schets, waarin de feed-URL nog een kolom op het object was.
Tier
Een externe koppeling is typisch betaald, en dat komt hier gratis mee: Vastgoed is al Plus, dus de import zit automatisch achter de Plus-grens. Er is geen nieuwe tier-regel nodig. Wél een overweging: dit is precies het type feature dat een "Premium"-vlak boven Plus zou kunnen rechtvaardigen (open punt 8 in de pricing-doc). Nu niet beslissen.
Conclusie
Ja, dit kan — en Uplisting is de route. Jij bent klant en hebt de key al; voor lezen is geen goedkeuring en geen partnerovereenkomst nodig. Eén koppeling dekt Airbnb én Booking.com, het is je eigen data in plaats van een publieke kalenderfeed, en annuleringen komen als expliciete gebeurtenis binnen in plaats van als stille verdwijning.
Vorm: één edge function die de webhooks ontvangt (patroon:
revenuecat-webhook), plus een periodieke volledige ophaling per pand als
reconciliatie. Sleutel in de serveromgeving, niet op de toestellen. Herkomst op de boeking
(external_uid + external_source), identiteit nooit met een datum erin,
handmatige rijen blijven onaantastbaar.
iCal blijft in het ontwerp als tweede implementatie achter dezelfde interface — voor gebruikers zonder channel manager en als vangnet. Daar is de belofte wél beperkt tot "bezette dagen komen binnen, vul gast en bedrag zelf aan". Beds24 is de logische derde als er ooit vraag naar is (open, self-service, webhooks).
Niet nastreven: een directe Airbnb- of Booking.com-koppeling — de eerste neemt geen aanvragen aan, de tweede is gepauzeerd en weigert individuele woningen. Via Uplisting is dat ook niet nodig.
Eén eigen ontwerp-gate waard voordat er code in gaat: het raakt een externe partij, een server-side component met een sleutel, twee kolommen, de privacyverklaring (drie paragrafen) en een gebruikersbelofte. Het hangt niet aan de Vermogen-varianten en kan dus los.
Herkomst van de claims in deze sectie
| Claim | Bron | Status |
|---|---|---|
| Klant maakt zelf een API-key aan (Connect → API); HTTP Basic met base64-key; geen goedkeuring nodig voor lezen | Uplisting support: API & webhooks / partner-integratie-artikel | Geverifieerd (eigenaar heeft de pagina zelf gelezen; eigenaar heeft de key) |
| Rate limits 5/s en 100/min per IP, 15/min per pand | Uplisting support: API & webhooks | Geverifieerd |
| Webhooks bestaan; endpoint dat herhaaldelijk niet antwoordt wordt uitgeschakeld | Uplisting support: API & webhooks | Geverifieerd |
| Partnerovereenkomst met revenue share geldt voor de marktplaats-/integratiepartner-route (V2/V3), niet voor een klant met eigen key | Uplisting partner-integratie-artikel | Gedocumenteerd; het onderscheid is de correctie van 26-07 en niet nogmaals onafhankelijk nagetrokken |
Boekings-payload met guest_name, total_payout, channel, external_reservation_id enz. | Publieke Postman-collectie van Uplisting | Niet bevestigd tegen een live account — zie open vraag |
| Airbnb neemt geen API-aanvragen aan; Booking.com heeft nieuwe connectiviteits-partners gepauzeerd | airbnb.com/partner; connect.booking.com | Geverifieerd (citaat van de pagina zelf) |
| Airbnb-iCal uitgekleed per 1 dec 2019; 365-dagenhorizon; verversing ~3 uur | Airbnb Help 99; OwnerRez; Operto | Meerdere onafhankelijke bronnen, niet zelf tegen een feed getest |
Wat de app al heeft (parser, external_uid, half-open interval, edge functions) | Deze repo | Geverifieerd in code, met bestand:regel |
| Géén pg_cron in dit project | supabase/migrations/ | Geverifieerd (grep, geen treffer) |
Waarschuwing voor wie dit later bouwt: er circuleert op GitHub een "Airbnb iCal sample" met volledige gastnamen, e-mailadressen en telefoonnummers. Die is verzonnen — hij spreekt Airbnb's privacywijziging van december 2019 tegen. Bouw je parserverwachtingen daar niet op.
Fasering — vroeg iets bruikbaars
Een leeg vermogensoverzicht dat pas na drie maanden klopt, is waardeloos. Daarom is V0 zo gekozen dat het op zichzelf waarde heeft en geen enkele migratie nodig heeft. Als je na V0 stopt, heb je nog steeds iets dat klopt.
Het getal — de kleinste versie die op zichzelf waarde heeft
Één Vermogen-kaart met: netto vermogen = panden (actuele waarde, of aankoopprijs als die leeg is) + spaargeld (uit het bestaande ledger) − restschuld van alle leningen, met de gekoppelde hypotheek precies één keer geteld. Bezittingen en schulden als twee subregels. Per regel een doorklik naar de bronmodule. Peildatum en de voetnoot "op basis van wat jij kunt zien".
Alle benodigde data bestaat al sinds fase 1 (migratie 0063, gemerged en op de toestellen). Geen migratie, geen schemaVersion-bump, geen sync-config-wijziging, geen 4-weg lockstep. Eén pure domeinfunctie met tests + één provider + één scherm. Waar dat scherm hangt is variant A/B/C — in A is dit meteen de Vermogensoverzicht-module.
De overkoepeling
Het domein Vermogen met Vastgoed, Leningen en Spaardoelen eronder, en het overzicht als eerste tegel. Deel-hint bij financiële velden. Vanuit een pand een zichtbare weg naar het overzicht en terug.
Vier regels domein-werk + één module-registratie + de navigatie-uitleg voor de tester (inclusief de AI-opt-in-notitie). Geen migratie.
Kosten en netto rendement — hier landt TEN-118
De property_costs-entiteit uit ADR-0018 (object-gebonden én optioneel
boeking-gebonden, zodat schoonmaakkosten per boeking en onderhoud per object in één tabel
passen), netto rendement naast bruto, en property_valuations voor
waardegeschiedenis zodat "groei per jaar" een echte reeks wordt in plaats van een
overschrijfbare momentopname.
Wél een migratie (twee tabellen + kolommen), dus 4-weg lockstep met prod-deploy vóór de app-merge. Volgende vrije migratienummer is 0082; schemaVersion gaat van 57 omhoog.
Beleggingen en jaaropgave-scan
Generieke waarderingsregels per peildatum (naam, categorie effecten/crypto/overig, waarde, evt. inleg) volgens ADR-0017 — zonder live koersfeed. Plus de AI-jaaropgave-scan uit ADR-0015 die een waarderingsrij schrijft. Dit is ook het moment om de aggregatie van hard gedraad naar de registry-hook te brengen.
Eén tabel + hergebruik van de bestaande extractie-stack.
Boekingen automatisch binnenhalen via Uplisting
Zie § Acht: één edge function die Uplisting-webhooks ontvangt, plus periodieke reconciliatie; herkomst op de boeking; sleutel server-side. iCal als tweede implementatie achter dezelfde interface, voor gebruikers zonder channel manager. Géén directe Airbnb-/Booking-API — die zijn niet beschikbaar en via Uplisting ook niet nodig. Los te doen en niet afhankelijk van V1–V3, maar wél met een eigen ontwerp-gate.
Tier-indeling
Geldende split (owner-besluit 2026-06-17, vastgelegd in
business/verdienmodel-en-pricing.md):
9 gratis — de vier kern-surfaces plus Maaltijden, Verjaardagen, Schoolvakanties,
Afvalkalender en Bewaarlijsten — en al het overige Plus, inclusief álle AI en cloud-sync.
Registry-default is Plus (module_descriptor.dart:108).
Vermogen is Plus. Zonder discussie, en het hoeft geen nieuwe pricing-beslissing te zijn: het volgt automatisch uit de default.
Redenen: elke bron die Vermogen aggregeert is zelf al Plus (Vastgoed, Leningen, Spaardoelen). Een gratis gebruiker zou dus per definitie een leeg scherm zien — dat is een slechtere ervaring dan een eerlijke Plus-badge. En als aggregatie over meerdere modules is het precies het type "overzicht dat je nergens anders krijgt" waar een abonnement voor is.
Twee dingen om te weten. Ten eerste: Plus-handhaving staat sinds de server-side
entitlements aan (plus_entitlement.dart:31), met een harde router-gate
(app_router.dart:273-295). Dat is nieuwer dan de pricing-doc zegt, die nog van
"enforcement staat uit" uitgaat — die doc loopt achter en moet bijgewerkt worden. Ten tweede:
de tier is runtime instelbaar zonder release via de tabel
module_tier_overrides (module_tier_overrides.dart:44). Als je Vermogen
tijdelijk gratis wilt openzetten als lokkertje, kan dat zonder store-release.
Als er ooit een pakketvlak boven Plus komt (in de pricing-doc staat "Premium" als open punt), is een vermogensoverzicht een plausibele kandidaat daarvoor. Dat is nu geen beslissing die genomen hoeft te worden — noteren is genoeg.
Tickets en ADR's
Hoe de tickets zich tot deze fasering verhouden
| Ticket | Wat het is | Waar het landt |
|---|---|---|
| TEN-87 | De oorspronkelijke vraag ("denk ook nog even mee zodat we een overzicht krijgen van wat ons vermogen is") | Programma-ticket. Overkoepelt V0 t/m V3. Wacht op jouw variantkeuze; geen fixer erop tot die keuze er is. Fase 1 (aankoop/financiering/bedrag op boekingen/bruto rendement, migratie 0063) is hier al uit voortgekomen en staat op de toestellen. |
| TEN-118 | "Bij vastgoed wil ik ook kosten kunnen opvoeren zoals onderhoud of vervangen van spullen" | V2. Blijft gebundeld, zoals de eerdere verrijking adviseerde: los oppakken zou een kostentabel opleveren zonder de boeking-koppeling die TEN-111's schoonmaakkosten nodig hebben, en dat is later opnieuw migreren. Niet starten voor de variantkeuze. |
| TEN-111 | Boeking-flow: "al geweest" moet uit de datum volgen, annuleren hoort niet in de aanmaak-flow | Gaat los vooruit — die kleine veilige subset raakt dit ontwerp niet en is hier niet aangeraakt. Het kosten-deel van dat ticket hoort bij V2. |
Moet er een ADR volgen?
Ja, en er moet er ook één vervangen worden. De conventie in
docs/architecture/adr/ is NNNN-slug.md met een kop
# ADR-NNNN — titel, een **Status:**-regel met datum en ticket, en de
secties Context · Besluit · Alternatieven · Consequenties. Hoogste nummer nu is 0019,
dus het volgende is 0020.
- ADR-0020 — Vermogen-positionering v2, te schrijven na jouw keuze.
docs/architecture/adr/0012-vermogen-positionering.mdmoet dan op superseded met een verwijzing: besluit 2 van die ADR ("scherm/tab binnen Financieel, geen nieuw module-id") is precies wat 26 juli omdraait. ADR-0012 verwijderen mag niet — het archiefbeleid schrijft een banner met datum en verwijzing voor. - ADR-0014 (rekenlaag) blijft grotendeels staan, maar zijn definitie van vermogen moet worden aangevuld met de uitkomst van de open vragen 1–5 (peildatum, dedupe-regel, bruto/netto, auto's, saldo).
- ADR-0018 staat nog op VOORSTEL en is deels ingehaald door de werkelijkheid: zijn sectie C (verhuurmodus + agenda) is inmiddels gebouwd en getest via TEN-120 (migratie 0076). Die ADR moet worden bijgewerkt naar wat er echt staat, en zijn secties A en B doorschuiven naar V2.
- Dit document is géén ADR: het is een levend ontwerpdocument met varianten en open vragen. De ADR's leggen de gekozen uitkomst vast; dit stuk legt de afweging vast.
Wat ik van je nodig heb om verder te kunnen
- Een variant: A (aanbevolen), B, of C.
- De zeven open vragen uit § Zeven — of minimaal 1, 2 en 3, want zonder die drie kan de rekenlaag niet gebouwd worden zonder aannames. Vraag 7 (hypotheek op meerdere objecten) hoeft níet vóór V0: mijn voorstel is dat V0 het huishoudniveau gebruikt, wat al correct is — maar als je wél overwaarde per object wilt, wil ik dat vóór V2 weten, want dan komt er een tabel bij.
- Groen licht voor de Uplisting-route uit § Acht, plus twee kleine dingen die alleen
jij kunt doen: de mail naar
partner@uplisting.iovoor de volledige API-documentatie, en of je wilt dat we samen één leesaanroep op je eigen account doen om te zien welke velden er echt in een boeking zitten. Daarna maak ik daar een eigen ontwerpronde voor. Dit staat los van de variantkeuze en mag later.
Zodra je een variant kiest, is de volgende stap: ADR-0020 schrijven, ADR-0012 op superseded zetten, en een implementatieplan voor V0 (dat is klein en migratievrij, dus dat kan meteen door de gewone fix-poort).