[Feature] Dismiss a single privacy finding, not just the whole rule #651
Labels
No labels
accepted
bug
declined
docs
duplicate
enhancement
good first issue
in-progress
needs-info
privacy
security
triage
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
LibreKAT/Ocideck#651
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Split off from #608, where the reported false positive is fixed but the second half of the proposal is a feature in its own right.
Today a privacy finding offers exactly one action: "Never report this rule again" — a global switch. That is the wrong granularity for the common case. A single finding you have looked at and judged fine (a colleague's name that belongs on the slide, an address that is the client's own) forces a choice between living with the warning forever or turning off the whole rule for every deck.
Turning off a rule is the loudest possible response to the quietest possible problem, and it is irreversible in the way that matters: the next real finding of that class never appears.
Shape, and why it is not a bolt-on
.miauw.jsonsidecar is the precedent), or in preferences (then it does not travel with the deck, which may be right — a dismissal is a judgement about this deck).Decide before building: per deck or per user. That determines whether this touches the file format, and the project's rule is that a format change gets a design first.
Not urgent: #608 removed the case that made this hurt on first run.
Gewogen, niet gebouwd — dit issue zegt zelf dat het besluit per deck of per gebruiker vóór de bouw komt omdat het het bestandsformaat raakt, en dat is een keuze van de stichting, niet iets wat een bouwronde namens haar neemt. Hieronder mijn aanbeveling, zodat de keuze scherp is.
Aanbeveling: per deck, in een sidecar — niet in de voorkeuren.
De redenering in het issue draait één kant op tegen zichzelf in: "in preferences … which may be right — a dismissal is a judgement about this deck". Maar juist "een oordeel over dít deck" pleit voor per deck, niet per gebruiker. Een terzijdelegging hoort bij de collega-naam-die-op-de-slide-mag; verhuist het deck naar een andere machine of een andere reviewer, dan hoort het oordeel mee te reizen. In de voorkeuren blijft het achter, en dan ziet de tweede reviewer de bevinding opnieuw — of, erger, ziet de eerste reviewer op een ánder deck een bevinding onterecht onderdrukt omdat de match toevallig hetzelfde hasht.
Waar het landt: niet in
deck.mdmaar in een sidecar, dezelfde grens die de notities en het zegel al volgen (formaatgrens: het.mdblijft maximaal uitwisselbaar, het OciDeck-specifieke staat ernaast). Een.miauw.json-achtigedeck.dismissals.jsonmet per terzijdelegging: regel-id + een salted commitment over de match-span (géén ruwe waarde — dezelfde reden als het redactiemanifest), plus een tijdstempel. Dat is precies de vorm die het issue voorstelt, alleen in een sidecar in plaats van in de voorkeuren.De vier eigenschappen die het issue noemt blijven overeind:
privacyRawScanProvideren de paneelweergave.Wat dit tot een eigen ronde maakt en niet tot bijvangst: het is een formaatwijziging, en die vraagt eerst een afgetoetst ontwerp in
FILE_FORMAT.md(nieuwe sidecar, versieverhoging, leespad voor oude decks) plus de sidecar-merge-semantiek — een teruggelegde bevinding die via git terugkomt is dezelfde vraag als bij de notities (#541/D7). Zeg welke kant je op wilt en of je het ontwerp eerst apart wilt zien; dan bouw ik het in die volgorde.Niet urgent, zoals je zelf schreef — #608 haalde het geval weg dat pijn deed bij de eerste run.
Ik volg de aanbeveling.
Ontwerp en opslaglaag staan op main:
0122d910en19f183ff(PR #732). Het issue blijft open voor het paneel; zie onderaan.Het ontwerp staat in FILE_FORMAT §6.7, zoals dit issue zelf vroeg: eerst op papier, dan bouwen. Per deck in een sidecar
<naam>.dismissals.json, niet in de voorkeuren.Eén correctie op mijn eigen aanbeveling hierboven. Ik schreef: commitment in plaats van ruwe waarde, "dezelfde reden als het redactiemanifest". Die reden klopt niet. Dat manifest verbergt waarden omdat ze uít het artefact zijn gehaald; hier staan ze nog gewoon in de
.md, dus tegen wie de sidecar heeft koopt een commitment niets — die leest de dia. De twee redenen die het wél dragen:.mdbeheert de auteur; deze sidecar is machinerie met een eigen levensduur — mee de git-historie in, mee de synchronisatiemap in. Een naam die je erin schrijft blijft staan nadat de auteur hem van de dia heeft gehaald.Het ontwerp zegt er expliciet bij dat het zout géén geheim is — het staat in dezelfde sidecar — zodat er geen bescherming wordt gesuggereerd die er niet is.
Identiteit is regel + commitment, niet de positie. Elke positie in
PrivacyFindingschuift zodra iemand er een woord boven typt, dus een positie-gebonden terzijdelegging zou stil verlopen.seen_atreist mee om te tónen wáár je oordeelde, en is nadrukkelijk geen matchsleutel. Gevolg, en het is bedoeld: een naam die je op dia 4 goedkeurt blijft ook op dia 9 stil — je oordeelde over de naam in dit deck.De vier eigenschappen die je noemde: identiteit ✔; de scan blijft vinden ✔ (verbergen is geen wegscannen, de ongefilterde telling die MIAUW EIS 1.1 leest ziet het volle aantal); UI en l10n staan nog open.
Samenvoegen is een unie op regel + commitment, latere
atwint, met grafstenen. Die zijn dragend: zonder hen verdwijnt een ongedaan-making bij de eerstvolgende samenvoeging — de andere kant draagt de terzijdelegging nog — en blijft de bevinding verborgen. Daarom ruimt "alles herroepen" de sidecar ook níét op, anders dan bij de MIAUW-sidecar. Bij een gelijk tijdstempel wint zichtbaarheid.Wat er nu werkt, met 22 tests: de codec, het samenvoegen, opslaan, heropenen, opruimen, en de reis in de prullenbak en het pakket.
Wat nog moet, en waarvoor dit open blijft: het paneel dat filtert, de tweede actie op de bevindingskaart, de terzijdegelegd-lijst met ongedaan-maken, twee interfaceteksten × 31 vertalingen, en het git-schrijfpad.
Besluit genomen: per deck. Daarmee is dit een sidecar en dus een formaatwijziging, en die krijgt in deze repo eerst een afgetoetst ontwerp. Dat ontwerp staat op main: `docs/design/PRIVACY_DISMISSALS.md` (`
c5b2d50f`, PR #734). Er staat nog geen regel code.Eerst een correctie op dit issue, want die scheelt in wat er gebouwd moet worden. De opening zegt dat een bevinding maar één actie kent — "Never report this rule again", een globale schakelaar. Er zijn er drie:
PrivacyDispositionop het deckPrivacyDispositionop een slideacceptop een slide is dus al een oordeel per deck dat andere slides en andere decks ongemoeid laat. Het gat zit binnen één slide: een slide met twee bevindingen — de collega-naam die er hoort en het adres dat er niet hoort — kent alleen alles-of-niets. Dát is wat ontbreekt, en het is één stap fijner dan het issue schetst, niet een hele nieuwe as.Dat verandert de kostenschatting in je oorspronkelijke tekst niet fundamenteel, maar wel de framing: dit is granulariteit toevoegen aan iets dat bestaat, niet een nieuw mechanisme.
Wat het ontwerp vastlegt, kort:
<naam>.privacy-dismissals.json, niet een sleutel in de front matter — dezelfde reden die in 0.1.0 zeven sleutels daaruit haalde. Een disposition is één woord en leest prima in een editor; een salted commitment is precies de base64-achtige ruis waar dat besluit over ging.privacyRawScanProviderverandert niet, dus MIAUW EIS 1.1 ziet het volle aantal — dat is jouw eis uit de issue-tekst.accept. Anders houdt de auteur een permanent geblokkeerde export met als enige uitweg de globale schakelaar — precies wat deze functie moet voorkomen. Dat staat als besluit opgeschreven en niet als bijzaak, want het is de enige plek waar dit ontwerp iets toestaat in plaats van iets tegenhoudt.Drie lessen die deze repo al betaald heeft zijn hergebruikt in plaats van opnieuw ontdekt: het salted commitment (redactiemanifest), de grafsteen bij ongedaan maken in plaats van verwijderen (inklaag, D7) en één regel per entry zodat git's tekst-merge werkt (notities, #541).
Twee dingen die ik van je nodig heb voor de bouw:
Label op
needs-infotot die twee er zijn.OQ-1 bevestigd, bouw gestart. Tak:
feat/privacy-terzijdelegging-651. Volgorde volgens het ontwerp: model + sidecarcodec met het salted commitment, dan het filter inprivacyScanProvider, dan de interface (actie op de kaart + de lijst met ongedaan maken), dan de reisroutes (pakket, prullenbak, herstelmomentopname).De knop en de lijst staan op main:
c1ee69ab(PR #736) en24523ffb(PR #738). Het issue blijft open voor één ding; zie onderaan.De knop. "Deze is beoordeeld en mag blijven", bóven "Deze regel nooit meer melden". De volgorde is de boodschap: déze ene treffer is bijna altijd wat iemand bedoelt, de hele regel uitzetten is het zware middel. In 31 talen, met het onderscheid tussen "deze ene" en "de regel" in elke taal expliciet gemaakt.
De lijst. Onder Beveiliging staan de terzijdegelegde bevindingen als chips; tikken zet er een terug. Jouw eigen zin uit dit issue — a dismissal you cannot find again is a deletion — was de maat.
Op een chip staat de regel plus waar je oordeelde, nooit de gevonden waarde. Die staat niet in de sidecar (daar zit een commitment) en hoort niet in een instellingenscherm. Er staat een test op.
Terugzetten schrijft een grafsteen in plaats van de terzijdelegging te verwijderen. Weggooien zou hem bij de eerstvolgende samenvoeging laten terugkeren van de andere kant, en dan was de bevinding weer verborgen zonder dat iemand daarvoor koos.
Over de vier eigenschappen die je noemde: identiteit ✔, UI ✔, l10n ✔ (twee nieuwe strings × 31), en de scanner blijft vinden ✔ — de ongefilterde telling die MIAUW EIS 1.1 leest ziet het volle aantal, en "beoordeeld en akkoord" blijft te onderscheiden van "opgelost".
Twee dingen die de opruiming opleverde. Het instellingenvenster zat 63 regels over zijn plafond; in plaats van dat plafond te verhogen is de lijst een eigen widget geworden — en toen bleek de bestaande uitgezette-regels-lijst exact dezelfde vorm te hebben en er net zomin in te horen. Allebei staan ze nu in
widgets/dialogs/settings/; de klasse ging van 6106 naar 5992 regels. En een doc-commentaar bleek bij de verkeerde methode te staan sinds79f302bfer een schakelaar tussen schoof.Wat openblijft: het git-schrijfpad. Het ontwerp stelt dat deze sidecar — anders dan de inktlaag — wél in een commit hoort: een terzijdelegging is een reviewbesluit over het rapport, en een tweede reviewer moet niet opnieuw langs wat een collega al beoordeeld heeft. De samenvoeglogica ligt er (
mergeDismissals, met de grafstenen), maar het schrijfpad inservices/git/niet. Dat raakt direct aan #541, waar op dit moment aan de sidecars-in-git wordt gewerkt — beter daar meenemen dan er dwars doorheen bouwen.Het meeste van wat ik hier bouwde was duplicaatwerk. Een parallelle sessie bouwde tegelijk hetzelfde, en dat is drie keer op rij gebeurd op dit ene issue: het ontwerp, de opslaglaag én het filter. Wat er van mijn kant overblijft staat op main (`
71397ddc`, PR #739); de rest heb ik laten vallen.Het dubbele ontwerp is ingetrokken. Het hunne (FILE_FORMAT §6.7, PR #732) landde eerst; het mijne (
docs/design/PRIVACY_DISMISSALS.md, PR #734) merge er schoon bovenop omdat git alleen een nieuw bestand zag — de botsing was semantisch en dus onzichtbaar voor de poort. Twee ontwerpen voor één bestandsformaat is erger dan geen ontwerp, dus het mijne is weg, mét registratie en 31 vertaalsleutels.En hun redenering is op het punt dat ertoe doet beter dan de mijne. Ik schreef dat het commitment de waarde beschermt. Dat is niet waar tegen iemand die het deck heeft — die leest de dia gewoon. Hun tekst zegt dat met zoveel woorden en geeft de twee eerlijke redenen: geen tweede kopie van een persoonsgegeven met een eigen levensduur, en een zout per deck tegen kruisverbanden. Dat is scherper, en het is een correctie op wat ik je eerder schreef.
Twee dingen uit mijn versie zijn bewaard, in §6.7:
Eén toets toegevoegd die er nog niet was: dat
matchedTextOfnull geeft wanneer een bevinding nergens meer op wijst. Gaf het een afgekapt stuk tekst terug, dan hasht dat ooit toevallig naar een terzijdelegging en verbergt de app iets wat niemand heeft bekeken. Nagelopen dát hij vangt — met de begrenzing vervangen door een clamp valt hij om.Eén aanwijzing die ik niet als verbetering indien omdat ik hem niet gemeten heb:
matchedTextOfbouwt de fragmentenlijst van een dia opnieuw op per bevinding. Op een dia met veel treffers is dat kwadratisch werk in een pad dat bij élke deckwijziging draait. Voor wie er ooit met de prestatiebril naar kijkt.Wat er nog te bouwen is: de knop om een bevinding terzijde te leggen en de lijst om dat ongedaan te maken. Die twee horen bij elkaar — een terzijdelegging die je niet terugvindt is een verwijdering — en ze staan er nog niet.
Ik heb
in-progresseraf gehaald, zodat wie dit oppakt niet weer naast een ander werkt.Opgepakt — het laatste deel, het git-schrijfpad. Tak: feat/terzijdelegging-naar-git-651. De route van #541 (deel 2) ligt er nu: deck.dismissals.json volgt dezelfde _repoSidecarState-regels als de notities en de ink, mergeDeckVersions krijgt de al bestaande mergeDismissals-unie erbij (regel+commitment, latere at wint, grafstenen), plus de uitzondering in de sync-delete-lus en de docs (FILE_FORMAT §6.7, GIT_STORAGE §9.1/9.7). Daarna kan dit issue dicht.
Af, en op main geverifieerd:
ab06c11(PR #761). Het laatste deel — het git-schrijfpad — is gebouwd op de route van #541: deck.dismissals.json naast deck.md, gedeelde aanraak-/verwijderregels, en mergeDeckVersions past de al ontworpen unie toe (regel + commitment, latere at wint, herroepingen overleven — geen heranker-stap, want de identiteit is geen dia-positie). De sidecar draagt commitments en nooit de gevonden waarde; daar staat een test op.Daarmee zijn alle onderdelen uit dit issue en het ontwerp af: identiteit ✔, UI (knop + terzijdegelegd-lijst met ongedaan maken) ✔, l10n ✔, de scanner blijft vinden ✔ (de ongefilterde telling die MIAUW EIS 1.1 leest ziet het volle aantal), en het besluit per-deck-in-een-sidecar is nu ook in git werkelijkheid.
Wat er bewust níét in zat: de MIAUW-dispositie zelf reist nog niet (#756, eerst een merge-semantiek-besluit), en de bewaker liet één klein punt herstellen vóór de merge: het zout-divergentiebesluit van mergeDismissals staat nu in FILE_FORMAT §6.7 in plaats van alleen in een codecommentaar. Poort: make check groen, secrets/SAST schoon. Dicht.
Correctie op mezelf. In PR #739 en in mijn reactie hierboven noteerde ik dat
matchedTextOfde fragmentenlijst van een dia per bevinding opnieuw opbouwt, en dat dat "kwadratisch werk in een pad dat bij élke deckwijziging draait" zou zijn. Ik zette erbij dat ik het níét had gemeten. Nu wel, en de bewering houdt geen stand.Geïsoleerd gemeten — alleen het opzoeken, op één dia met álle bevindingen erop:
En door de hele provider heen, met en zonder terzijdeleggingen:
Geen meetbaar verschil. De scan zelf domineert met een factor tien; het filter verdwijnt in de ruis.
De kwadratische term bestáát wel —
matchedTextOfloopt de fragmenten van een dia langs tot hij de juiste vindt, dus bevinding i kost i stappen — maar de constante is zo klein dat zelfs 800 treffers op één dia binnen 15 ms blijven. En het pad draait alleen op een deck dat mínstens één terzijdelegging draagt; zonder valt het predicaat meteen terug op(_) => false.Dus geen issue. Ik had die aanwijzing niet moeten opschrijven zonder meting, ook niet met een voorbehoud erbij: een niet-gemeten prestatiezorg in een PR-tekst leest de volgende lezer als werk dat nog moet gebeuren.