@readystack/loeschkonzept-fristen-lint 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.txt CHANGED
@@ -1,11 +1,11 @@
1
- Löschkonzept-Prüfer – Aufbewahrungsfristen 2026 — Licence
1
+ Aufbewahrungsfristen-Lint für Löschkonzepte (BEG IV) — Licence
2
2
 
3
3
  Free scope
4
- Prüft jedes offene Löschkonzept (.md) mit allen 16 Regeln und zeigt die Befunde zeilengenau im Editor und im Browser — ohne Key. is free for any use, personal or commercial, for as long as you keep the
4
+ Prüft das offene Löschkonzept gegen alle 10 rules und zeigt jede falsche Aufbewahrungsfrist mit Zeile, Rechtsgrundlage und korrekter Frist — ohne Schlüssel, offline. is free for any use, personal or commercial, for as long as you keep the
5
5
  extension installed, and the online check at the product page is free without registration.
6
6
 
7
7
  Paid scope
8
- Ordner-Prüfbericht über alle Löschkonzepte und Löschfristen-Tabellen eines Workspace als Datei, als Nachweis nach Art. 5 Abs. 2 DSGVO für Audit und Datenschutzbeauftragte. is the paid part. It asks for a licence key issued at purchase (one seat, one key). The key is checked against the payment provider and
8
+ Löschkalender-Export: pro Datenkategorie und Jahrgang das konkrete Löschdatum als CSV, plus Scan aller Löschkonzepte im Workspace in einem Bericht. is the paid part. It asks for a licence key issued at purchase (one seat, one key). The key is checked against the payment provider and
9
9
  cached locally for 30 days so it keeps working offline.
10
10
 
11
11
  Redistribution
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
- # Löschkonzept-Prüfer – Aufbewahrungsfristen 2026
1
+ # Aufbewahrungsfristen-Lint für Löschkonzepte
2
2
 
3
- Löschkonzept und Löschfristen-Tabelle prüfen: 16 Regeln zu § 147 AO, § 257 HGB, § 14b UStG, § 41 EStG, § 15 AGG und Art. 5 DSGVO, direkt in VS Code und im Browser.
3
+ ![Aufbewahrungsfristen-Lint für Löschkonzepte — finds the line](https://getreadystack.com/img/promo/loeschkonzept-fristen-lint_demo.gif)
4
+
5
+ BEG IV: Buchungsbelege 8 statt 10 Jahre — prüft jede Zeile Ihres Löschkonzepts gegen AO, HGB und DSGVO
4
6
 
5
7
  ## Install
6
8
 
@@ -8,22 +10,22 @@ Löschkonzept und Löschfristen-Tabelle prüfen: 16 Regeln zu § 147 AO, § 257
8
10
  npx @readystack/loeschkonzept-fristen-lint file
9
11
  ```
10
12
 
11
- Node 18+. The same 16 rules as the VS Code extension, from a terminal or CI.
13
+ Node 18+. The same 10 rules as the VS Code extension, from a terminal or CI.
12
14
 
13
15
  ## Free
14
16
 
15
- - Prüft jedes offene Löschkonzept (.md) mit allen 16 Regeln, ohne Key, in VS Code und im Browser. Die Beispiel-Vorlage (Stand 2023) liefert 18 Befunde, darunter: Buchungsbelege 10 statt 8 Jahre, Rechnungen 10 statt 8 Jahre, Geschäftsbriefe 10 statt 6 Jahre, Lohnkonten 10 statt 6 Jahre, Jahresabschlüsse 6 statt 10 Jahre, Newsletter-Daten unbegrenzt.
17
+ - Prüft das offene Löschkonzept gegen alle 10 rules und zeigt jede falsche Aufbewahrungsfrist mit Zeile, Rechtsgrundlage und korrekter Frist — ohne Schlüssel, offline.
16
18
  - `--rules` lists every rule
17
19
 
18
20
  ## With a licence ($29 once)
19
21
 
20
- - $29 einmalig: Ordner-Prüfbericht über alle Löschkonzepte und Löschfristen-Tabellen eines Workspace als Datei, als Nachweis nach Art. 5 Abs. 2 DSGVO für Audit und Datenschutzbeauftragte. Ein Lizenzschlüssel pro Person oder Team-Platz.
22
+ - Löschkalender-Export: pro Datenkategorie und Jahrgang das Löschdatum als CSV, plus Scan aller Löschkonzepte im Workspace.
21
23
 
22
24
  ```
23
25
  @readystack/loeschkonzept-fristen-lint --dir ./templates --report html --out report.html
24
26
  ```
25
27
 
26
- Steuerberater nach § 13 StBVV: Zeitgebühr €16,50 bis €41 je angefangene Viertelstunde.
28
+ TÜV Rheinland Akademie: Tagesseminar Löschkonzepte nach DIN 66398 ab 760 Euro netto
27
29
 
28
30
  ## Use from an AI agent (MCP)
29
31
 
@@ -38,7 +40,7 @@ Tools: `check_text` and `check_file` (free) · `check_dir` (licence). The agent
38
40
  ## Use in CI
39
41
 
40
42
  ```yaml
41
- - name: Löschkonzept-Prüfer – Aufbewahrungsfristen 2026
43
+ - name: Aufbewahrungsfristen-Lint für Löschkonzepte
42
44
  run: npx -y @readystack/loeschkonzept-fristen-lint --dir . --ci
43
45
  ```
44
46
 
@@ -49,4 +51,4 @@ The folder sweep, reports and CI mode need one licence — one payment, no subsc
49
51
  [Get a licence](https://buy.polar.sh/polar_cl_j0sYK5M2L5REhRw2p2PONeb8WtblzQWGCbVU82rwl6B)
50
52
 
51
53
 
52
- <!-- Löschkonzept -->
54
+ <!-- Aufbewahrungsfristen -->
package/engine.js CHANGED
@@ -1,63 +1,105 @@
1
- /* Löschkonzept-Prüfer engine: runs in Node (VS Code) and in the browser (index.html). */
1
+ /* Aufbewahrungsfristen-Lint: prüft Löschkonzept-Tabellen (Markdown) gegen AO/HGB (BEG IV) und DSGVO. */
2
2
  (function () {
3
- var RULES = (typeof module !== 'undefined') ? require('./rules.json') : window.LF_RULES;
4
- var WORDS = { zwei: 2, drei: 3, vier: 4, 'fünf': 5, sechs: 6, sieben: 7, acht: 8, neun: 9, zehn: 10, 'elf': 11, 'zwölf': 12 };
5
- var INST = /kreditinstitut|\bKWG\b|versicherungsaufsicht|versicherungsunternehmen|\bVAG\b|wertpapierinstitut|\bWpIG\b/i;
6
- var CITE = /§|art\.?\s*\d|dsgvo|\bAO\b|\bHGB\b|\bUStG\b|\bEStG\b|\bAGG\b|\bBDSG\b|einwilligung/i;
7
- function rx(s) { return new RegExp(s, 'i'); }
8
- function years(line) {
9
- var m = line.match(/(\d{1,2}|zwei|drei|vier|fünf|sechs|sieben|acht|neun|zehn|elf|zwölf)\s*(jahren?|jahre|jahr|j\.)(?![a-zäöü])/i);
10
- if (!m) return 0;
11
- var v = m[1].toLowerCase();
12
- return /^\d+$/.test(v) ? parseInt(v, 10) : WORDS[v];
3
+ var RULES = (typeof module !== 'undefined' && module.exports) ? require('./rules.json') : window.LK_RULES;
4
+ var BY_ID = {};
5
+ RULES.forEach(function (r) { BY_ID[r.id] = r; });
6
+
7
+ function norm(s) {
8
+ return String(s || '').toLowerCase().replace(/ä/g, 'ae').replace(/ö/g, 'oe').replace(/ü/g, 'ue').replace(/ß/g, 'ss').replace(/\s+/g, ' ').trim();
13
9
  }
14
- function months(line) {
15
- var m;
16
- if ((m = line.match(/(\d{1,3})\s*monat/i))) return parseInt(m[1], 10);
17
- if ((m = line.match(/(\d{1,3})\s*woche/i))) return parseInt(m[1], 10) / 4.345;
18
- if ((m = line.match(/(\d{1,3})\s*tag/i))) return parseInt(m[1], 10) / 30.4;
19
- if (/sofort|unverzüglich|umgehend|direkt nach|mit (der )?absage/i.test(line)) return 0;
20
- return -1;
10
+ function cells(line) {
11
+ var t = line.trim().replace(/^\|/, '').replace(/\|$/, '');
12
+ return t.split('|').map(function (c) { return c.replace(/\s+/g, ' ').trim(); });
21
13
  }
22
- function isRow(l) { return /^\s*\|/.test(l) && !/^\s*\|[\s:|-]+\|?\s*$/.test(l); }
14
+ function isSep(line) { return /^\s*\|?[\s|:\-]+\|?\s*$/.test(line) && line.indexOf('-') >= 0; }
15
+
16
+ var CATS = [
17
+ ['lohn', /lohnkont|lohnunterlag|lohnabrechn|gehaltsabrechn|lohnjournal|entgeltabrechn/],
18
+ ['abschluss', /jahresabschluss|bilanz|inventar|lagebericht|handelsbuch|handelsbuech|hauptbuch|journal/],
19
+ ['bewerb', /bewerb/],
20
+ ['brief', /handelsbrief|geschaeftsbrief|korrespondenz|angebot|auftragsbestaetigung/],
21
+ ['beleg', /buchungsbeleg|rechnung|kontoauszu|quittung|kassenbon|kassenbeleg|gutschrift|beleg/]
22
+ ];
23
+ function category(c) {
24
+ var n = norm(c);
25
+ for (var i = 0; i < CATS.length; i++) if (CATS[i][1].test(n)) return CATS[i][0];
26
+ return null;
27
+ }
28
+ function period(c) {
29
+ var n = norm(c);
30
+ if (/unbegrenzt|unbefristet|dauerhaft|fuer immer|zeitlich unbeschraenkt|ohne frist/.test(n)) return { unbounded: true };
31
+ var m = n.match(/(\d+(?:[.,]\d+)?)\s*(jahr|monat|woche|tag)/);
32
+ if (!m) return null;
33
+ var v = parseFloat(m[1].replace(',', '.'));
34
+ var months = m[2] === 'jahr' ? v * 12 : m[2] === 'monat' ? v : m[2] === 'woche' ? v / 4.345 : v / 30.44;
35
+ return { months: months, text: String(c).replace(/\s+/g, ' ').trim() };
36
+ }
37
+ function todayYear(opts) {
38
+ var m = String((opts && opts.today) || '').match(/(\d{4})-(\d{2})-(\d{2})/);
39
+ return m ? parseInt(m[1], 10) : new Date().getFullYear();
40
+ }
41
+ var BAD_START = /\bab (dem )?(rechnungs|beleg|buchungs|ausstellungs|erstellungs)?datum|\bab (erstellung|eingang|zugang|ausstellung|buchung|belegdatum)/;
42
+
23
43
  function check(text, opts) {
24
44
  var lines = String(text || '').split(/\r?\n/);
25
- var all = lines.join('\n');
26
- var inst = INST.test(all);
27
- var out = [];
28
- function hit(r, line, msg) { out.push({ check: r.id, sev: r.sev, msg: msg || r.msg, line: line, ref: r.ref }); }
29
- var cats = RULES.filter(function (r) { return /^(period|period_any|min_months)$/.test(r.kind); });
30
- lines.forEach(function (l, i) {
31
- var r = null;
32
- for (var k = 0; k < cats.length; k++) if (rx(cats[k].re).test(l)) { r = cats[k]; break; }
33
- if (!r) return;
34
- if (r.kind === 'period') {
35
- var y = years(l); if (!y) return;
36
- var want = (inst && r.inst_years) ? r.inst_years : r.years;
37
- if (y > want && r.over) hit(r, i + 1, r.label + ': ' + y + ' Jahre im Konzept, gesetzlich ' + want + ' Jahre (' + r.ref + '). ' + r.over);
38
- else if (y < want) hit(r, i + 1, r.label + ': ' + y + ' Jahre im Konzept, gesetzlich ' + want + ' Jahre (' + r.ref + '). ' + r.under);
39
- } else if (r.kind === 'period_any') {
40
- if (years(l) && !(r.unless && rx(r.unless).test(l))) hit(r, i + 1);
41
- } else if (r.kind === 'min_months') {
42
- if (years(l)) return;
43
- var mo = months(l);
44
- if (mo >= 0 && mo < r.months) hit(r, i + 1);
45
+ var findings = [];
46
+ var T = todayYear(opts);
47
+ var pCol = -1, sCol = -1, header = null;
48
+ function add(id, line, msg) {
49
+ var r = BY_ID[id];
50
+ findings.push({ check: id, sev: r.sev, msg: msg + ' — ' + r.basis, line: line });
51
+ }
52
+ for (var i = 0; i < lines.length; i++) {
53
+ var ln = lines[i];
54
+ if (!/^\s*\|/.test(ln)) { header = null; pCol = sCol = -1; continue; }
55
+ if (isSep(ln)) {
56
+ if (header) {
57
+ pCol = sCol = -1;
58
+ header.forEach(function (h, k) {
59
+ var n = norm(h);
60
+ if (/beginn|start/.test(n)) { if (sCol < 0) sCol = k; }
61
+ else if (/frist|aufbewahr|dauer|speicher/.test(n) && pCol < 0) pCol = k;
62
+ });
63
+ header = 'done';
64
+ }
65
+ continue;
45
66
  }
46
- });
47
- RULES.forEach(function (r) {
48
- var re = rx(r.re);
49
- if (r.kind === 'require') {
50
- if (!re.test(all)) hit(r, 1);
51
- } else if (r.kind === 'forbid') {
52
- lines.forEach(function (l, i) { if (re.test(l)) hit(r, i + 1); });
53
- } else if (r.kind === 'row_ref') {
54
- lines.forEach(function (l, i) { if (isRow(l) && re.test(l) && !CITE.test(l)) hit(r, i + 1); });
67
+ if (header === null) { header = cells(ln); continue; }
68
+ if (header !== 'done') continue;
69
+ var c = cells(ln);
70
+ var name = c[0] || '';
71
+ if (!name) continue;
72
+ var cat = category(name);
73
+ var pText = pCol >= 0 ? (c[pCol] || '') : c.slice(1).join(' ');
74
+ var sText = sCol >= 0 ? (c[sCol] || '') : c.slice(1).join(' ');
75
+ var p = period(pText);
76
+ var L = i + 1;
77
+ if (p && p.unbounded) { add('unbegrenzt', L, name + ': „' + pText + '“ — jede Datenkategorie braucht eine Löschfrist'); continue; }
78
+ if (!p) { add('frist_fehlt', L, name + ': keine Frist in Jahren/Monaten angegeben'); continue; }
79
+ var y = p.months / 12;
80
+ if (cat === 'beleg') {
81
+ if (y > 8) {
82
+ var extra = Math.round(y - 8);
83
+ var from = T - 1 - Math.round(y) + 1, to = T - 9;
84
+ add('beleg_zu_lang', L, name + ': ' + p.text + ' → seit 2025-01-01 gilt 8 Jahre. Stand ' + T + ': Jahrgänge bis ' + (T - 9) + ' sind löschreif; mit ' + p.text + ' behalten Sie ' + (extra === 1 ? to : from + '–' + to) + ' (' + extra + ' Jahrgänge) zu lange');
85
+ } else if (y < 8) add('beleg_zu_kurz', L, name + ': ' + p.text + ' → mindestens 8 Jahre');
86
+ } else if (cat === 'abschluss') {
87
+ if (y < 10) add('abschluss_zu_kurz', L, name + ': ' + p.text + ' → 10 Jahre (BEG IV hat nur Buchungsbelege verkürzt)');
88
+ } else if (cat === 'brief') {
89
+ if (y > 6) add('brief_zu_lang', L, name + ': ' + p.text + ' → 6 Jahre');
90
+ else if (y < 6) add('brief_zu_kurz', L, name + ': ' + p.text + ' → mindestens 6 Jahre');
91
+ } else if (cat === 'lohn') {
92
+ if (y < 6) add('lohnkonto_zu_kurz', L, name + ': ' + p.text + ' → bis Ende des 6. Kalenderjahres nach der letzten Lohnzahlung');
93
+ } else if (cat === 'bewerb') {
94
+ if (p.months > 6.01) add('bewerber_zu_lang', L, name + ': ' + p.text + ' → üblich 6 Monate nach Absage');
55
95
  }
56
- });
57
- out.sort(function (a, b) { return a.line - b.line; });
58
- return { findings: out };
96
+ if (cat && cat !== 'bewerb' && BAD_START.test(norm(sText)))
97
+ add('fristbeginn_falsch', L, name + ': Fristbeginn „' + sText + '“ → die Frist beginnt mit Ablauf des Kalenderjahres, in dem der Beleg entstand');
98
+ }
99
+ return { findings: findings };
59
100
  }
101
+
60
102
  var api = { engine: { check: check }, RULES: RULES, RULE_COUNT: RULES.length };
61
- if (typeof module !== 'undefined') module.exports = api;
62
- if (typeof window !== 'undefined') window.LFENGINE = api;
103
+ if (typeof module !== 'undefined' && module.exports) module.exports = api;
104
+ if (typeof window !== 'undefined') window.LKENGINE = api;
63
105
  })();
package/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "@readystack/loeschkonzept-fristen-lint",
3
- "version": "1.0.1",
4
- "description": "Löschkonzept und Löschfristen-Tabelle prüfen: 16 Regeln zu § 147 AO, § 257 HGB, § 14b UStG, § 41 EStG, § 15 AGG und Art. 5 DSGVO, direkt in VS Code und im Browser.",
3
+ "version": "1.0.3",
4
+ "description": "BEG IV: Buchungsbelege 8 statt 10 Jahre — prüft jede Zeile Ihres Löschkonzepts gegen AO, HGB und DSGVO",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "publishConfig": {
7
7
  "access": "public"
8
8
  },
9
9
  "keywords": [
10
- "löschkonzept",
11
- "löschfristen",
12
- "aufbewahrungsfristen",
13
- "dsgvo",
14
- "gobd",
15
- "§ 147 ao",
16
- "beg iv",
17
- "datenschutz"
10
+ "Löschkonzept",
11
+ "Aufbewahrungsfristen",
12
+ "DSGVO",
13
+ "BEG IV",
14
+ "147 AO",
15
+ "257 HGB",
16
+ "Datenschutz",
17
+ "Loeschkonzept"
18
18
  ],
19
19
  "homepage": "https://getreadystack.com",
20
20
  "funding": "https://buy.polar.sh/polar_cl_j0sYK5M2L5REhRw2p2PONeb8WtblzQWGCbVU82rwl6B",
package/rules.json CHANGED
@@ -1,156 +1,62 @@
1
1
  [
2
2
  {
3
- "id": "LF01",
4
- "kind": "period",
3
+ "id": "beleg_zu_lang",
5
4
  "sev": "error",
6
- "label": "Zollunterlagen",
7
- "re": "zollanmeldung|zollunterlagen|zolldokument|präferenznachweis|zollkodex",
8
- "years": 10,
9
- "ref": "§ 147 Abs. 1 Nr. 4a, Abs. 3 AO",
10
- "over": "",
11
- "under": "Unterlagen nach Art. 15 und Art. 163 Zollkodex der Union sind zehn Jahre aufzubewahren."
5
+ "title": "Buchungsbelege länger als 8 Jahre",
6
+ "basis": "§ 147 Abs. 3 AO, § 257 Abs. 4 HGB i. d. F. BEG IV (seit 2025-01-01); Art. 5 Abs. 1 lit. e DSGVO"
12
7
  },
13
8
  {
14
- "id": "LF02",
15
- "kind": "period",
16
- "sev": "warning",
17
- "label": "Lohnkonten",
18
- "re": "lohnkont",
19
- "years": 6,
20
- "ref": "§ 41 Abs. 1 S. 9 EStG",
21
- "over": "Lohnkonten sind bis zum Ablauf des sechsten Kalenderjahres nach der letzten Lohnzahlung aufzubewahren; länger gespeicherte Beschäftigtendaten verletzen die Speicherbegrenzung (Art. 5 Abs. 1 lit. e DSGVO).",
22
- "under": "Lohnkonten sind bis zum Ablauf des sechsten Kalenderjahres nach der letzten Lohnzahlung aufzubewahren."
23
- },
24
- {
25
- "id": "LF03",
26
- "kind": "period_any",
27
- "sev": "warning",
28
- "label": "Lieferscheine",
29
- "re": "lieferschein",
30
- "unless": "buchungsbeleg",
31
- "ref": "§ 147 Abs. 3 S. 3 und 4 AO",
32
- "msg": "Lieferscheine, die keine Buchungsbelege sind: die Aufbewahrungsfrist endet mit Erhalt bzw. Versand der Rechnung (§ 147 Abs. 3 S. 3 und 4 AO), nicht nach Jahren."
33
- },
34
- {
35
- "id": "LF04",
36
- "kind": "period",
37
- "sev": "error",
38
- "label": "Verfahrensdokumentation / Organisationsunterlagen",
39
- "re": "verfahrensdoku|arbeitsanweisung|organisationsunterlage",
40
- "years": 10,
41
- "ref": "§ 147 Abs. 1 Nr. 1, Abs. 3 AO",
42
- "over": "",
43
- "under": "Die zum Verständnis der Bücher erforderlichen Arbeitsanweisungen und Organisationsunterlagen sind zehn Jahre aufzubewahren."
44
- },
45
- {
46
- "id": "LF05",
47
- "kind": "period",
48
- "sev": "error",
49
- "label": "Bücher / Jahresabschlüsse",
50
- "re": "jahresabschl|bilanz|inventar|lagebericht|hauptbuch|kassenbuch|handelsbüch|journal",
51
- "years": 10,
52
- "ref": "§ 147 Abs. 3 AO, § 257 Abs. 4 HGB",
53
- "over": "",
54
- "under": "Bücher, Inventare, Jahresabschlüsse und Lageberichte sind zehn Jahre aufzubewahren."
55
- },
56
- {
57
- "id": "LF06",
58
- "kind": "period",
9
+ "id": "beleg_zu_kurz",
59
10
  "sev": "error",
60
- "label": "Buchungsbelege",
61
- "re": "buchungsbeleg|kontoauszug|kassenbeleg|\\bbelege\\b",
62
- "years": 8,
63
- "inst_years": 10,
64
- "ref": "§ 147 Abs. 3 AO, § 257 Abs. 4 HGB",
65
- "over": "Seit 01.01.2025 (BEG IV) gelten für Buchungsbelege acht statt zehn Jahre; zwei Jahre länger gespeicherte Namen, IBAN und Adressen verletzen die Speicherbegrenzung (Art. 5 Abs. 1 lit. e DSGVO). Zehn Jahre nur für Kreditinstitute, Versicherer und Wertpapierinstitute (§ 257 Abs. 4 S. 2 HGB).",
66
- "under": "Buchungsbelege sind acht Jahre aufzubewahren."
11
+ "title": "Buchungsbelege kürzer als 8 Jahre",
12
+ "basis": "§ 147 Abs. 1 Nr. 4, Abs. 3 AO; § 257 Abs. 1 Nr. 4, Abs. 4 HGB"
67
13
  },
68
14
  {
69
- "id": "LF07",
70
- "kind": "period",
15
+ "id": "abschluss_zu_kurz",
71
16
  "sev": "error",
72
- "label": "Rechnungen",
73
- "re": "rechnung(en)?\\b|eingangsrechnung|ausgangsrechnung",
74
- "years": 8,
75
- "ref": "§ 14b Abs. 1 UStG",
76
- "over": "Seit 01.01.2025 (BEG IV) sind Rechnungen acht statt zehn Jahre aufzubewahren; danach löschen (Art. 5 Abs. 1 lit. e, Art. 17 DSGVO).",
77
- "under": "Rechnungen sind acht Jahre aufzubewahren."
17
+ "title": "Jahresabschlüsse/Bücher kürzer als 10 Jahre",
18
+ "basis": "§ 147 Abs. 1 Nr. 1, Abs. 3 AO; § 257 Abs. 1 Nr. 1, Abs. 4 HGB"
78
19
  },
79
20
  {
80
- "id": "LF08",
81
- "kind": "period",
21
+ "id": "brief_zu_lang",
82
22
  "sev": "warning",
83
- "label": "Handels- und Geschäftsbriefe",
84
- "re": "geschäftsbrief|handelsbrief|geschäftskorrespondenz",
85
- "years": 6,
86
- "ref": "§ 147 Abs. 3 AO, § 257 Abs. 4 HGB",
87
- "over": "Empfangene und abgesandte Handels- und Geschäftsbriefe: sechs Jahre, nicht zehn; der Rest ist Speicherung ohne Rechtsgrundlage (Art. 5 Abs. 1 lit. e DSGVO).",
88
- "under": "Handels- und Geschäftsbriefe sind sechs Jahre aufzubewahren."
23
+ "title": "Handels-/Geschäftsbriefe länger als 6 Jahre",
24
+ "basis": "§ 257 Abs. 1 Nr. 2-3, Abs. 4 HGB; § 147 Abs. 1 Nr. 2-3 AO; Art. 5 Abs. 1 lit. e DSGVO"
89
25
  },
90
26
  {
91
- "id": "LF09",
92
- "kind": "min_months",
93
- "sev": "warning",
94
- "label": "Bewerbungsunterlagen",
95
- "re": "bewerb",
96
- "months": 2,
97
- "ref": "§ 15 Abs. 4 AGG, Art. 17 Abs. 3 lit. e DSGVO",
98
- "msg": "Bewerbungsunterlagen vor Ablauf von zwei Monaten nach Zugang der Absage gelöscht: in dieser Frist kann ein AGG-Anspruch geltend gemacht werden (§ 15 Abs. 4 AGG); zur Verteidigung von Rechtsansprüchen darf gespeichert werden (Art. 17 Abs. 3 lit. e DSGVO)."
99
- },
100
- {
101
- "id": "LF10",
102
- "kind": "forbid",
27
+ "id": "brief_zu_kurz",
103
28
  "sev": "error",
104
- "re": "unbegrenzt|unbefristet|dauerhaft gespeichert|\\bdauerhaft\\b|für immer|nie gelöscht",
105
- "ref": "Art. 5 Abs. 1 lit. e DSGVO",
106
- "msg": "Unbegrenzte Speicherung: Art. 5 Abs. 1 lit. e DSGVO verlangt eine Speicherdauer, die nicht länger ist als für den Zweck erforderlich. Eine konkrete Frist oder ein Löschereignis eintragen."
29
+ "title": "Handels-/Geschäftsbriefe kürzer als 6 Jahre",
30
+ "basis": "§ 257 Abs. 1 Nr. 2-3, Abs. 4 HGB; § 147 Abs. 1 Nr. 2-3 AO"
107
31
  },
108
32
  {
109
- "id": "LF11",
110
- "kind": "forbid",
111
- "sev": "warning",
112
- "re": "(pauschal|alle|sämtliche|grundsätzlich).{0,60}(10|zehn) jahre",
113
- "ref": "§ 147 Abs. 3 AO",
114
- "msg": "Pauschal zehn Jahre für alle Unterlagen: § 147 Abs. 3 AO kennt zehn, acht und sechs Jahre. Buchungsbelege acht, Geschäftsbriefe sechs Jahre."
33
+ "id": "lohnkonto_zu_kurz",
34
+ "sev": "error",
35
+ "title": "Lohnkonto kürzer als 6 Jahre",
36
+ "basis": "§ 41 Abs. 1 Satz 9 EStG"
115
37
  },
116
38
  {
117
- "id": "LF12",
118
- "kind": "row_ref",
39
+ "id": "bewerber_zu_lang",
119
40
  "sev": "warning",
120
- "re": "\\d+\\s*(jahre?|monate?|wochen?|tage?)\\b|sofort|unverzüglich",
121
- "ref": "Art. 5 Abs. 2 DSGVO",
122
- "msg": "Tabellenzeile mit Frist, aber ohne Rechtsgrundlage (§ oder Art.). Für die Rechenschaftspflicht nach Art. 5 Abs. 2 DSGVO die Norm eintragen."
41
+ "title": "Bewerberdaten länger als 6 Monate",
42
+ "basis": "§ 15 Abs. 4 AGG (2 Monate) + § 61b Abs. 1 ArbGG (3 Monate); Art. 17 DSGVO"
123
43
  },
124
44
  {
125
- "id": "LF13",
126
- "kind": "require",
127
- "sev": "warning",
128
- "re": "schluss des kalenderjahr|ende des kalenderjahr|ablauf des kalenderjahr|jahresende|31\\.12\\.",
129
- "ref": "§ 147 Abs. 4 AO, § 257 Abs. 5 HGB",
130
- "msg": "Fristbeginn fehlt: die Aufbewahrungsfrist beginnt mit dem Schluss des Kalenderjahres (§ 147 Abs. 4 AO, § 257 Abs. 5 HGB), nicht mit dem Belegdatum."
45
+ "id": "unbegrenzt",
46
+ "sev": "error",
47
+ "title": "Unbegrenzte Speicherung",
48
+ "basis": "Art. 5 Abs. 1 lit. e DSGVO (Speicherbegrenzung)"
131
49
  },
132
50
  {
133
- "id": "LF14",
134
- "kind": "require",
51
+ "id": "fristbeginn_falsch",
135
52
  "sev": "warning",
136
- "re": "festsetzungsfrist|ablaufhemmung|§\\s*169",
137
- "ref": "§ 147 Abs. 3 S. 5 AO",
138
- "msg": "Hinweis auf die Festsetzungsfrist fehlt: die Aufbewahrungsfrist läuft nicht ab, solange die Unterlagen für Steuern mit offener Festsetzungsfrist von Bedeutung sind (§ 147 Abs. 3 S. 5 AO). Vor der Löschung prüfen."
139
- },
140
- {
141
- "id": "LF15",
142
- "kind": "require",
143
- "sev": "info",
144
- "re": "art\\.?\\s*5 abs\\.?\\s*1 lit\\.?\\s*e|speicherbegrenzung|art\\.?\\s*17",
145
- "ref": "Art. 5 Abs. 1 lit. e, Art. 17 DSGVO",
146
- "msg": "Kein Bezug auf Speicherbegrenzung (Art. 5 Abs. 1 lit. e DSGVO) oder das Recht auf Löschung (Art. 17 DSGVO). Das Löschkonzept sollte seinen Zweck nennen."
53
+ "title": "Fristbeginn ab Belegdatum statt ab Jahresende",
54
+ "basis": "§ 147 Abs. 4 AO; § 257 Abs. 5 HGB"
147
55
  },
148
56
  {
149
- "id": "LF16",
150
- "kind": "forbid",
151
- "sev": "warning",
152
- "re": "\\bTTDSG\\b",
153
- "ref": "TDDDG",
154
- "msg": "TTDSG heißt seit 14.05.2024 TDDDG (Telekommunikation-Digitale-Dienste-Datenschutz-Gesetz). Verweis aktualisieren."
57
+ "id": "frist_fehlt",
58
+ "sev": "error",
59
+ "title": "Keine Löschfrist angegeben",
60
+ "basis": "Art. 30 Abs. 1 lit. f DSGVO"
155
61
  }
156
62
  ]
package/strings.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
- "name": "Löschkonzept-Prüfer – Aufbewahrungsfristen 2026",
3
- "subtitle": "Löschkonzept und Löschfristen-Tabelle prüfen: 16 Regeln zu § 147 AO, § 257 HGB, § 14b UStG, § 41 EStG, § 15 AGG und Art. 5 DSGVO, direkt in VS Code und im Browser.",
2
+ "name": "Aufbewahrungsfristen-Lint für Löschkonzepte",
3
+ "subtitle": "BEG IV: Buchungsbelege 8 statt 10 Jahre — prüft jede Zeile Ihres Löschkonzepts gegen AO, HGB und DSGVO",
4
4
  "bin": "loeschkonzept-fristen-lint",
5
5
  "price": 29,
6
- "free": "Prüft jedes offene Löschkonzept (.md) mit allen 16 Regeln, ohne Key, in VS Code und im Browser. Die Beispiel-Vorlage (Stand 2023) liefert 18 Befunde, darunter: Buchungsbelege 10 statt 8 Jahre, Rechnungen 10 statt 8 Jahre, Geschäftsbriefe 10 statt 6 Jahre, Lohnkonten 10 statt 6 Jahre, Jahresabschlüsse 6 statt 10 Jahre, Newsletter-Daten unbegrenzt.",
7
- "paid": "$29 einmalig: Ordner-Prüfbericht über alle Löschkonzepte und Löschfristen-Tabellen eines Workspace als Datei, als Nachweis nach Art. 5 Abs. 2 DSGVO für Audit und Datenschutzbeauftragte. Ein Lizenzschlüssel pro Person oder Team-Platz.",
8
- "need_key": "This option needs a licence (Löschkonzept-Prüfer – Aufbewahrungsfristen 2026).",
6
+ "free": "Prüft das offene Löschkonzept gegen alle 10 rules und zeigt jede falsche Aufbewahrungsfrist mit Zeile, Rechtsgrundlage und korrekter Frist — ohne Schlüssel, offline.",
7
+ "paid": "Löschkalender-Export: pro Datenkategorie und Jahrgang das Löschdatum als CSV, plus Scan aller Löschkonzepte im Workspace.",
8
+ "need_key": "This option needs a licence (Aufbewahrungsfristen-Lint für Löschkonzepte).",
9
9
  "exts": []
10
10
  }