Spaces:
Running
Running
File size: 47,286 Bytes
20ab519 0aadaaa 6ce312c 0aadaaa 6ce312c 0aadaaa 6ce312c 0aadaaa 6ce312c 0aadaaa 6ce312c 20ab519 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 | <!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>DSA Terms of service check — check missing duties in your terms</title>
<meta name="description" content="This browser tool reads terms-of-service markdown and identifies missing Digital Services Act duties by article number.">
<style>
:root{color-scheme:light}body{margin:0;font:15px/1.55 system-ui,-apple-system,"Segoe UI",sans-serif;background:#faf9f5;color:#1a1512}
.wrap{max-width:960px;margin:0 auto;padding:28px 18px 60px}h1{font-size:26px;margin:0 0 6px}.lede{color:#4a403a;margin:0 0 16px}
textarea{width:100%;min-height:260px;font:13px/1.45 ui-monospace,Menlo,Consolas,monospace;padding:12px;border:1px solid #d9d0c4;border-radius:8px;box-sizing:border-box}
.bar{display:flex;gap:10px;align-items:center;margin:12px 0}button{font:600 15px system-ui;padding:10px 18px;border:0;border-radius:8px;background:#1a1512;color:#fff;cursor:pointer}
input[type=date]{font:14px system-ui;padding:8px;border:1px solid #d9d0c4;border-radius:6px}
table{border-collapse:collapse;width:100%;font-size:14px;margin-top:10px}th,td{text-align:left;padding:8px 10px;border-bottom:1px solid #eee;vertical-align:top}th{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:#7a6e65}
.sev.error{color:#a8551f;font-weight:700}.sev.warn,.sev.warning{color:#96691f}.ok{color:#2a6446;font-weight:600}.sum{font-weight:600}
.note{font-size:13px;color:#7a6e65;margin-top:18px}#paid{margin-top:22px;padding:14px 16px;border:1px solid #e2d8cb;border-radius:10px;background:#fffdfa}
</style>
<script data-grow-initializer="">!(function(){window.growMe||((window.growMe=function(e){window.growMe._.push(e);}),(window.growMe._=[]));var e=document.createElement("script");(e.type="text/javascript"),(e.src="https://faves.grow.me/main.js"),(e.defer=!0),e.setAttribute("data-grow-faves-site-id","U2l0ZTphZjljMzgyMC0yMmU5LTRhYjgtYTIxNS03OTRhMGY1N2ExYzM=");var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t);})();</script>
<!--yj-canon-s101--><link rel="canonical" href="https://getreadystack.com/tools/dsa-terms-lint"></head>
<body>
<div class="wrap">
<h1>DSA Terms of service check — check missing duties in your terms</h1>
<p class="lede">Reads your terms-of-service markdown and names every Digital Services Act duty it is missing, by article number. Runs entirely in your browser — nothing is uploaded.</p>
<textarea id="src" spellcheck="false"># Terms of Service - Loomcast
Last updated: 2023-11-02
Welcome to Loomcast, where anyone can publish a clip and follow other creators. By using Loomcast
you agree to these terms. We have tried to keep them short.
## 1. Your account
You must be able to form a binding contract to open an account. You are responsible for everything
posted from your account. Keep your password to yourself.
## 2. Your content
You keep ownership of what you upload and you give us a worldwide licence to host and show it.
Do not upload anything unlawful, hateful, or that you do not have the rights to.
## 3. Content moderation
We run content moderation across the service. We use automated tools to detect spam and copyright
matches, and flagged clips are reviewed by a person before we act. We may remove anything that
breaks these terms at our discretion.
## 4. Getting in touch
Questions about these terms go to support@loomcast.example and we answer as quickly as we can.
## 5. If we remove something
If we take a clip down, you may appeal our decision by email within six months of being notified,
and we will look at it again free of charge.
## 6. Payments
Paid plans renew monthly until cancelled. Refunds are handled under our refund policy.
## 7. Liability
Loomcast is provided as is. To the maximum extent permitted by law we are not liable for indirect
or consequential loss.
## 8. Changes to these terms
We will notify you by email before material changes to these terms take effect.
## 9. Governing law
These terms are governed by the laws of the State of Delaware, United States, and the courts of
Wilmington shall have exclusive jurisdiction.</textarea>
<div class="bar"><button id="go">Check</button><label>as of <input type="date" id="today"></label></div>
<div id="out" aria-live="polite"></div>
<div id="paid"><strong>Free here:</strong> Names every Digital Services Act duty missing from the terms file you have open, with the article number and the sentence that is absent.. <strong>In the editor:</strong> Scans every legal page and every language version in the workspace at once and exports a dated DSA gap report you can hand to counsel. — that part asks for a licence key.</div>
<p class="note">Same engine as the VS Code extension, byte for byte.</p>
</div>
<script>var DSA_RULES = [
{
"check": "art11_authority_contact",
"sev": "err",
"msg": "Art. 11 DSA: no single point of contact for Member State authorities, the Commission and the Board. Publish one electronic contact (email or form) and say it is for authorities.",
"need": ["single point of contact[^.]{0,120}(authorit|commission|board|digital services coordinator)", "point of contact for (member state )?authorit", "authorities may contact us (at|by|via)"]
},
{
"check": "art11_contact_languages",
"sev": "warn",
"msg": "Art. 11(3) DSA: the languages used for communication with authorities are not stated. Name them, and one must be an official language of your Member State of main establishment.",
"need": ["languages? (used |available )?for communicat", "we communicate with authorities in", "official language"]
},
{
"check": "art12_recipient_contact",
"sev": "err",
"msg": "Art. 12 DSA: no single point of contact for users. Publish a direct contact for recipients of the service, separate from the authority contact.",
"need": ["point of contact for (users|recipients|customers)", "contact us[^.]{0,80}(support@|legal@|help@|privacy@|@)", "you can (reach|contact) us (at|by|via)[^.]{0,60}@"]
},
{
"check": "art12_human_channel",
"sev": "err",
"msg": "Art. 12(1) DSA: users must be able to reach you by a means that is not solely automated. Say in the terms that a human answers, not only a chatbot or ticket robot.",
"need": ["not (solely|only|exclusively) (automated|an automated)", "a (human|person|member of our team) (will |does )?(reply|respond|review|answer)", "human review of (your |every )?(message|request|enquiry)", "without (relying )?(solely|only) on automated"]
},
{
"check": "art13_legal_representative",
"sev": "err",
"msg": "Art. 13 DSA: providers without an establishment in the Union must name a legal representative in a Member State where they offer the service. State your EU establishment or name the representative.",
"need": ["legal representative", "established in (the )?(european union|eu)\\b", "our (place of )?establishment (is )?in (the )?(european union|eu|ireland|germany|france|netherlands|spain|italy|poland|sweden|belgium)"]
},
{
"check": "art14_moderation_policy",
"sev": "err",
"msg": "Art. 14(1) DSA: the terms must describe the policies, procedures, measures and tools used for content moderation. Describe what you remove and how you find it.",
"need": ["content moderation", "moderation (policy|policies|procedures?|measures|tools)", "how we (review|moderate) (content|posts|uploads)"]
},
{
"check": "art14_algorithmic_human_review",
"sev": "err",
"msg": "Art. 14(1) DSA: the terms must say whether moderation uses algorithmic decision-making and whether a human reviews it. Name both.",
"need": ["algorithmic decision[- ]?making", "automated (tools|systems|detection)[^.]{0,120}(human review|reviewed by (a )?(human|person|staff))", "human review[^.]{0,120}(automated|algorithm)"]
},
{
"check": "art14_plain_language",
"sev": "warn",
"msg": "Art. 14(1) DSA: the terms must be in clear, plain, intelligible, user-friendly and unambiguous language, and Art. 14(3) requires a version minors can understand where the service targets them. Say which you have done.",
"need": ["plain (and )?(intelligible )?language", "clear,? (plain|simple) (and )?(intelligible|understandable)", "written in plain (english|language)", "plain-language summary"]
},
{
"check": "art14_change_notice",
"sev": "warn",
"msg": "Art. 14(2) DSA: significant changes to the terms must be notified to users. State the channel and the notice period.",
"need": ["(notify|inform|tell) (you|users|recipients)[^.]{0,120}(chang|amend|updat)", "(significant|material) chang[^.]{0,120}(notice|notify|inform)", "we will give[^.]{0,60}days'? notice"]
},
{
"check": "art16_notice_action",
"sev": "err",
"msg": "Art. 16 DSA: hosting services must offer an electronic notice-and-action mechanism for reporting illegal content, easy to access and user-friendly. Link it from the terms.",
"need": ["notice[- ]and[- ]action", "report illegal content", "(report|flag) (allegedly )?illegal (content|material|items)", "illegal content (report|notice) (form|mechanism|channel)"]
},
{
"check": "art16_receipt_confirmation",
"sev": "warn",
"msg": "Art. 16(4) DSA: you must confirm receipt of a notice to the notifier without undue delay. Say that a confirmation is sent.",
"need": ["confirm(ation)? of receipt", "we (will )?(send|issue) (you )?(a )?confirmation", "acknowledge receipt", "confirm receipt of (your |the )?(notice|report)"]
},
{
"check": "art17_statement_of_reasons",
"sev": "err",
"msg": "Art. 17 DSA: every restriction (removal, demotion, suspension, demonetisation) needs a clear and specific statement of reasons to the affected user. Promise it in the terms.",
"need": ["statement of reasons", "we (will )?(tell|explain to) you why[^.]{0,80}(remov|restrict|suspend|disabl)", "reasons for (the )?(removal|restriction|suspension) (will be|are) (given|provided)"]
},
{
"check": "art20_internal_complaints",
"sev": "err",
"msg": "Art. 20 DSA: hosting services must run a free internal complaint-handling system open for at least six months after the decision. State that it is free and state the six-month window.",
"need": ["internal complaint[- ]handling", "appeal (a|the|our) (decision|removal)[^.]{0,120}(six months|6 months|180 days)", "complaint[- ]handling system[^.]{0,120}(free|no charge)"]
},
{
"check": "art21_out_of_court",
"sev": "err",
"msg": "Art. 21 DSA: users must be told they may take a dispute to a certified out-of-court dispute settlement body. Name the right and where to find the certified bodies.",
"need": ["out[- ]of[- ]court dispute settlement", "certified dispute settlement body", "alternative dispute resolution body certified"]
},
{
"check": "art23_misuse_suspension",
"sev": "warn",
"msg": "Art. 23 DSA: state the policy for suspending accounts that frequently post manifestly illegal content, and notifiers who frequently file unfounded notices, after a prior warning.",
"need": ["prior warning", "manifestly (illegal|unfounded)", "repeated(ly)? (unfounded|abusive) (notices|reports)", "frequently (post|submit)[^.]{0,80}(illegal|unfounded)"]
},
{
"check": "art26_ad_transparency",
"sev": "err",
"msg": "Art. 26 DSA: this service shows advertising, so each ad must be marked as an ad, name who paid for it, and explain the main parameters used to target it. Say so in the terms.",
"when": "advertis|sponsored (post|content|listing)|promoted (post|content)",
"need": ["(marked|labelled|labeled|identified) as (an )?(ad|advertis)", "on whose behalf (the )?(ad|advertis)", "main parameters used to determine"]
},
{
"check": "art28_minor_profiling_ads",
"sev": "err",
"msg": "Art. 28(2) DSA: where the service is accessible to minors you may not show advertising based on profiling of their personal data. State the ban in the terms.",
"when": "minor|under 18|under-18|child(ren)?|teen",
"need": ["no (advertis|ads)[^.]{0,120}profil", "profiling[^.]{0,120}(minors?|children)[^.]{0,60}(not|never|prohibited)", "we do not (show|serve) (profil|targeted) (ads|advertis)[^.]{0,80}(minor|child)"]
},
{
"check": "terms_dated_before_dsa",
"sev": "err",
"kind": "date",
"msg": "The DSA has applied to every intermediary service since 17 February 2024. Terms that carry no version date, or a date before it, were not written against these duties."
}
]
;</script>
<script>/* dsa-terms-lint engine - EU Digital Services Act (Regulation (EU) 2022/2065)
Same file runs in Node (VS Code extension) and in the browser (free web page). */
(function () {
'use strict';
var RULES = (typeof module !== 'undefined') ? require('./rules.json') : window.DSA_RULES;
/* The DSA has applied to all providers of intermediary services since this date. */
var DSA_APPLIES = '2024-02-17';
var STALE_MONTHS = 18;
var DATE_RE = /(last\s+updated|last\s+revised|effective\s+(?:date|from)|version\s+date|in\s+force\s+from)\s*[:–—-]*\s*(\d{4}-\d{2}-\d{2})/i;
function rx(pattern) {
return new RegExp(pattern, 'i');
}
function lineOfMatch(text, pattern) {
if (!pattern) return 1;
var re = new RegExp(pattern, 'i');
var lines = text.split(/\r?\n/);
for (var i = 0; i < lines.length; i++) {
if (re.test(lines[i])) return i + 1;
}
return 1;
}
function monthsBetween(fromISO, toISO) {
var a = fromISO.split('-').map(Number);
var b = toISO.split('-').map(Number);
return (b[0] - a[0]) * 12 + (b[1] - a[1]) - (b[2] < a[2] ? 1 : 0);
}
function dateFindings(rule, text, today) {
var out = [];
var m = text.replace(/\s+/g, ' ').match(DATE_RE);
if (!m) {
out.push({
check: rule.check,
sev: 'err',
msg: 'No version date found. ' + rule.msg + ' Add a "Last updated: YYYY-MM-DD" line.',
line: 1
});
return out;
}
var found = m[2];
var line = lineOfMatch(text, m[0].replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
if (found < DSA_APPLIES) {
out.push({
check: rule.check,
sev: 'err',
msg: 'Version date ' + found + ' is before ' + DSA_APPLIES + '. ' + rule.msg,
line: line
});
} else if (monthsBetween(found, today) >= STALE_MONTHS) {
out.push({
check: rule.check,
sev: 'warn',
msg: 'Version date ' + found + ' is ' + monthsBetween(found, today) + ' months old as of ' + today +
'. Art. 14(2) DSA expects the published terms to match what you actually do.',
line: line
});
}
return out;
}
function check(text, opts) {
text = String(text == null ? '' : text);
opts = opts || {};
var today = opts.today || '2026-09-18';
var findings = [];
/* Real terms files are hard-wrapped, so a clause routinely straddles two lines.
Rules are matched against a whitespace-flattened copy; line numbers stay on the original. */
var flat = text.replace(/\s+/g, ' ');
for (var i = 0; i < RULES.length; i++) {
var rule = RULES[i];
if (rule.when && !rx(rule.when).test(flat)) continue;
if (rule.kind === 'date') {
findings = findings.concat(dateFindings(rule, text, today));
continue;
}
var satisfied = false;
var need = rule.need || [];
for (var j = 0; j < need.length; j++) {
if (rx(need[j]).test(flat)) { satisfied = true; break; }
}
if (!satisfied) {
findings.push({
check: rule.check,
sev: rule.sev || 'warn',
msg: rule.msg,
line: lineOfMatch(text, rule.anchor)
});
}
}
findings.sort(function (a, b) { return a.line - b.line; });
return { findings: findings };
}
var api = { engine: { check: check }, RULES: RULES, RULE_COUNT: RULES.length };
if (typeof module !== 'undefined') module.exports = api;
if (typeof window !== 'undefined') window.DSAENGINE = api;
})();
</script>
<script>// ⛔뼈대 — kit/scaffold.py 가 찍는다 (s143). findings [{check,sev,msg,line?}] → 글/HTML. 같은 파일이 Node 와 브라우저에서 산다.
'use strict';
function escapeHtml(s) { return String(s == null ? '' : s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'); }
function summaryLine(res) {
const f = (res && res.findings) || []; const e = f.filter(function (x) { return String(x.sev || 'error').toLowerCase().startsWith('err'); }).length;
return f.length ? (f.length + ' finding' + (f.length === 1 ? '' : 's') + ' (' + e + ' error' + (e === 1 ? '' : 's') + ')') : 'Clean — no findings.';
}
function toText(res, label) {
const f = (res && res.findings) || [];
const lines = ['== ' + (label || '') + ' — ' + summaryLine(res)];
f.forEach(function (x) { lines.push(' ' + String(x.sev || 'error').toUpperCase().slice(0, 4) + ' ' + (x.line ? 'L' + x.line + ' ' : '') + (x.check || x.id || '') + ' ' + (x.msg || x.message || '')); });
return lines.join('\n');
}
function toHtml(res) {
const f = (res && res.findings) || [];
if (!f.length) return '<p class="ok">' + escapeHtml(summaryLine(res)) + '</p>';
const rows = f.map(function (x) { return '<tr><td class="sev ' + escapeHtml(String(x.sev || 'error')) + '">' + escapeHtml(String(x.sev || 'error')) + '</td><td>' + (x.line ? 'L' + escapeHtml(x.line) : '') + '</td><td><code>' + escapeHtml(x.check || x.id || '') + '</code></td><td>' + escapeHtml(x.msg || x.message || '') + '</td></tr>'; }).join('');
return '<p class="sum">' + escapeHtml(summaryLine(res)) + '</p><table><thead><tr><th>Level</th><th>Line</th><th>Check</th><th>What</th></tr></thead><tbody>' + rows + '</tbody></table>';
}
var DSAREPORT = { escapeHtml: escapeHtml, summaryLine: summaryLine, toText: toText, toHtml: toHtml };
if (typeof module !== 'undefined' && module.exports) module.exports = DSAREPORT;
else window.DSAREPORT = DSAREPORT;
</script>
<script>
(function(){
var src=document.getElementById('src'), out=document.getElementById('out'), go=document.getElementById('go'), today=document.getElementById('today');
today.value=new Date().toISOString().slice(0,10);
function run(){ try { var res=window.DSAENGINE.engine.check(src.value,{today:today.value}); out.innerHTML=window.DSAREPORT.toHtml(res); } catch(e){ out.innerHTML='<p class="sev error">Could not run: '+String(e.message||e)+'</p>'; } }
go.onclick=run; if (src.value.trim()) run();
})();
</script>
<section data-yj-install="free" style="margin:2rem auto 1rem;max-width:46rem;padding:1.25rem 1.25rem;border:1px solid #cfe3d6;border-radius:12px;background:#f6fbf8;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .4rem;font-size:1.2rem">Install free</h2><p style="margin:0 0 .8rem;color:#41505f">Free for the file open in your editor - no key, no limit. The workspace sweep and the report ask for a key.</p><a href="https://marketplace.visualstudio.com/items?itemName=ReadyStack.dsa-terms-lint" rel="noopener" data-yj-install-door="mp" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'dsa-terms-lint',src:'mp',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">VS Code Marketplace</a><a href="https://open-vsx.org/extension/readystack/dsa-terms-lint" rel="noopener" data-yj-install-door="ovsx" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'dsa-terms-lint',src:'ovsx',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">Open VSX (Cursor, VSCodium)</a><a href="https://www.npmjs.com/package/@readystack/dsa-terms-lint" rel="noopener" data-yj-install-door="npm" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'dsa-terms-lint',src:'npm',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">npm</a><a href="https://hub.docker.com/r/getreadystack/dsa-terms-lint" rel="noopener" data-yj-install-door="docker" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'dsa-terms-lint',src:'docker',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">Docker Hub</a><pre style="margin:.5rem 0 0;padding:.6rem .8rem;background:#f3f5f8;border-radius:8px;font-size:.9rem;overflow:auto">ext install ReadyStack.dsa-terms-lint
npx @readystack/dsa-terms-lint <file>
docker run --rm -v "$PWD:/w" getreadystack/dsa-terms-lint /w</pre><p style="margin:.6rem 0 0;font-size:.92rem;color:#41505f"><a href="https://getreadystack.com/api/buy/cl/polar_cl_l6iN1uWt0FwWu7tBsczD0jWpP2vxFM54Wdwqb3KPi1G" rel="nofollow" style="color:#0f7b3f;text-decoration:underline">Team? One key for every ReadyStack linter, 5 seats, $149 once</a></p></section>
<section data-yj-alert="rule" style="margin:1rem auto 1.5rem;max-width:46rem;padding:1.1rem 1.25rem;border:1px solid #d9dee6;border-radius:12px;background:#fbfcfd;font:15px/1.55 system-ui,-apple-system,Segoe UI,sans-serif"><b style="font-size:1.05rem">Get the full rule table as a PDF</b><div style="opacity:.78;margin:.35rem 0 .8rem">All 18 rules DSA Terms Lint - EU Digital Services Act checks, each with its source and date, on printable pages you can hand to your team or auditor. We email it now, and once more only if a rule changes. No newsletter.</div><div style="display:flex;gap:8px;flex-wrap:wrap"><input id="yjae" type="email" placeholder="you@example.com" style="flex:1;min-width:210px;padding:11px 13px;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:#fff;color:inherit"><button id="yjab" style="padding:11px 18px;border-radius:8px;border:0;cursor:pointer;background:#0f7b3f;color:#fff;font:600 15px system-ui,sans-serif">Email me the PDF</button></div><div id="yjao" hidden style="margin-top:.6rem;color:#0f7b3f">Sent. It arrives within the hour - check spam too.</div><script>(function(){var b=document.getElementById("yjab"),e=document.getElementById("yjae");if(!b||!e)return;b.addEventListener("click",function(){var v=e.value.trim();if(!/.+@.+\..+/.test(v))return;try{localStorage.setItem("yj_em","1");}catch(_){}fetch(location.origin+"/api/subscribe",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:v,slug:"dsa-terms-lint",lang:"en",source:"rule_table"+((b.closest&&b.closest("section")&&b.closest("section").getAttribute("data-yj-moved"))?"_at_result":"")})}).then(function(r){var o=document.getElementById("yjao");o.hidden=false;if(!r.ok){o.textContent="Could not save - please try again.";}}).catch(function(){var o=document.getElementById("yjao");o.hidden=false;o.textContent="Could not save - please try again.";});});})();</script><script>(function(){var e=document.getElementById("yjae"),s=e&&e.closest?e.closest("section"):null,o=document.getElementById("out");if(!s||!o)return;var d=false;function mv(ev){if(d)return;if(ev&&ev.target&&s.contains(ev.target))return;d=true;var b=o;while(b.parentNode&&b.parentNode!==document.body&&b.parentNode.tagName!=="MAIN"&&b.parentNode.tagName!=="ARTICLE")b=b.parentNode;if(!b.parentNode||b===s||b.contains(s))return;try{b.parentNode.insertBefore(s,b.nextSibling);s.setAttribute("data-yj-moved","1");}catch(_){}}document.addEventListener("input",mv,true);document.addEventListener("change",mv,true);})();</script></section>
<section data-yj-cta="paid" style="margin:3rem auto;max-width:46rem;padding:1.5rem 1.25rem;border:1px solid #d8dee9;border-radius:12px;background:#fbfcfe;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .5rem;font-size:1.25rem">Get the complete version <span class="yj-price">$29</span></h2><p style="margin:.25rem 0 1rem;color:#41505f">This page is the working piece. The full pack has everything below.</p><p style="margin:0 0 1rem;color:#41505f">Reads your terms-of-service markdown and names every DSA duty it is missing, by article number.</p><p style="margin:0 0 1rem;color:#5b6b7c;font-size:.94rem">EU technology counsel bills roughly $250-$500 an hour to read the same six pages of terms.</p><a href="https://getreadystack.com/api/buy/cl/polar_cl_cvvpOHUl0trDgV1H4FITDdGO0eTfT4jX9Olem3MhKMp" rel="nofollow" style="display:inline-block;padding:.7rem 1.3rem;border-radius:8px;background:#1b64f2;color:#fff;text-decoration:none;font-weight:600">Buy the full version — $29</a></section>
<!--yj-share-s101--><div style="margin:28px 0 8px;text-align:center"><button id="yjcp" type="button" style="font:inherit;padding:10px 18px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Copy link</button><button id="yjimg" type="button" style="font:inherit;padding:10px 18px;margin-left:8px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Save result as image</button></div><script>(function(){var b=document.getElementById("yjimg");if(!b)return;b.addEventListener("click",function(){var o=document.getElementById("out");var txt=(o&&(o.innerText||o.textContent)||"").trim();if(!txt){b.textContent="(no result yet)";setTimeout(function(){b.textContent="Save result as image";},1500);return;}var lines=txt.split(String.fromCharCode(10)).filter(function(x){return x.trim();}).slice(0,10);var W=1200,P=56,c=document.createElement("canvas");c.width=W;var lh=38,H=P*2+70+lines.length*lh+60;c.height=H;var x=c.getContext("2d");x.fillStyle="#1a1512";x.fillRect(0,0,W,H);x.fillStyle="#f3e9d2";x.font="600 34px system-ui,Segoe UI,Arial";var t=(document.title||"").split("|")[0].trim();x.fillText(t.slice(0,54),P,P+34);x.font="22px ui-monospace,Menlo,Consolas,monospace";x.fillStyle="#e8dcc4";for(var i=0;i<lines.length;i++){x.fillText(lines[i].slice(0,88),P,P+70+i*lh+22);}x.font="600 22px system-ui,Segoe UI,Arial";x.fillStyle="#c9a227";var d=location.hostname.replace("www.","");x.fillText(d,W-P-x.measureText(d).width,H-P+6);c.toBlob(function(bl){var u=URL.createObjectURL(bl),a=document.createElement("a");a.href=u;a.download=(t||"result").replace(/[^a-z0-9]+/gi,"-").toLowerCase()+"-"+d+".png";document.body.appendChild(a);a.click();setTimeout(function(){URL.revokeObjectURL(u);a.remove();},2000);},"image/png");});})();</script><script>(function(){var b=document.getElementById("yjcp");if(!b)return;var t=b.textContent;b.addEventListener("click",function(){var u=location.href.split("#")[0];function d(){b.textContent="Link copied";setTimeout(function(){b.textContent=t;},1800);}if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(u).then(d,function(){prompt("",u);});}else{prompt("",u);}});})();</script>
<div class="yj-home-find"><div class="yj-lgbar"><a href="/" class="yj-lg on">EN</a><a href="/de/" class="yj-lg">DE</a><a href="/ja/" class="yj-lg">JA</a><a href="/es/" class="yj-lg">ES</a><a href="/pt/" class="yj-lg">PT</a></div><section class="yj-find"><h2>Find a tool</h2><input id="yjq" type="search" autocomplete="off" placeholder="Type a product name, format or task"><div id="yjr"></div></section><style>.yj-lgbar{position:absolute;top:14px;right:18px;display:flex;gap:6px;z-index:60}.yj-lg{font:600 12px/1 system-ui,sans-serif;padding:6px 9px;border-radius:4px;text-decoration:none;color:#8b96a3;border:1px solid rgba(140,150,165,.28)}.yj-lg:hover{color:#e8eaed;border-color:rgba(160,175,195,.6)}.yj-lg.on{color:#0e1116;background:#cfd6de;border-color:#cfd6de}.yj-find{max-width:760px;margin:34px auto 8px;padding:0 20px}.yj-find h2{font:600 20px/1.3 system-ui,sans-serif;margin:0 0 10px}#yjq{width:100%;box-sizing:border-box;padding:13px 15px;font:400 15.5px system-ui,sans-serif;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:rgba(255,255,255,.04);color:inherit}#yjq:focus{outline:none;border-color:#7FD1C4}#yjr{margin-top:10px;display:flex;flex-direction:column;gap:6px}#yjr a{display:flex;justify-content:space-between;gap:12px;padding:11px 14px;border:1px solid rgba(140,150,165,.22);border-radius:6px;text-decoration:none;font:400 14.5px/1.4 system-ui,sans-serif;color:inherit}#yjr a:hover{border-color:#7FD1C4}#yjr .pr{font:600 13px system-ui,sans-serif;color:#5fbf9a;white-space:nowrap}</style><script>(function(){var q=document.getElementById("yjq"),r=document.getElementById("yjr"),D=null;function load(){if(D)return Promise.resolve(D);return fetch("/search-index.json").then(function(x){return x.json();}).then(function(j){D=j;return j;}).catch(function(){D=[];return D;});}function esc(t){return String(t).replace(/[&<>"]/g,function(c){return {"&":"&","<":"<",">":">",'"':"""}[c];});}function run(){var v=q.value.trim().toLowerCase();if(v.length<2){r.innerHTML="";return;}load().then(function(j){var w=v.split(/\s+/),o=[];for(var i=0;i<j.length&&o.length<12;i++){var t=j[i].t.toLowerCase();var ok=true;for(var k=0;k<w.length;k++){if(t.indexOf(w[k])<0){ok=false;break;}}if(ok)o.push(j[i]);}r.innerHTML=o.length?o.map(function(x){return "<a href=\""+esc(x.u)+"\">"+"<span>"+esc(x.t)+"</span>"+(x.p?"<span class=\"pr\">$"+x.p+"</span>":"")+"</a>";}).join(""):"";});}q.addEventListener("input",run);q.addEventListener("focus",load);})();</script></div>
<script data-yj="yj-view-beacon">(function(){try{var p=location.pathname;var k='yjv:'+p;if(sessionStorage.getItem(k))return;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",ref:(document.referrer||''),src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}catch(e){}})();</script>
<script data-yj="yj-use-beacon">(function(){try{var o=document.getElementById('out');if(!o)return;var p=location.pathname,k='yju:'+p,sent=false;function fire(){if(sent||sessionStorage.getItem(k))return;if(!(o.textContent||'').replace(/\s+/g,'').length)return;sent=true;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",t:'use',src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}var mo=new MutationObserver(function(){fire();if(sent)mo.disconnect();});mo.observe(o,{childList:true,characterData:true,subtree:true});}catch(e){}})();</script>
<section data-yj="yj-facts-v1" style="max-width:920px;margin:48px auto 0;padding:0 20px;font-family:system-ui,sans-serif"><style>.yj-article p{font:400 15.5px/1.7 system-ui,sans-serif;color:#26313b;margin:0 0 12px;max-width:72ch}.yj-article h2,.yj-article h3,.yj-article h4{font:600 17px/1.35 system-ui,sans-serif;color:#1b1f24;margin:22px 0 8px}.yj-article table{border-collapse:collapse;margin:10px 0 16px;font:14px/1.45 system-ui,sans-serif}.yj-article th,.yj-article td{border:1px solid #e2e6ea;padding:6px 10px;text-align:left}.yj-article th{background:#f4f6f8}.yj-article pre{background:#0f1720;color:#e6edf3;padding:12px 14px;border-radius:8px;overflow:auto;font:13px/1.5 ui-monospace,Menlo,monospace}.yj-article code{font:13px ui-monospace,Menlo,monospace;background:#f1f3f5;padding:1px 4px;border-radius:3px}.yj-article pre code{background:none;padding:0}.yj-article ul,.yj-article ol{font:15px/1.6 system-ui,sans-serif;color:#26313b}</style><p style="font:400 13px/1.5 system-ui,sans-serif;color:#6b7680;margin:0 0 14px"><time datetime="2026-09-18">Updated 2026-09-18</time> · ReadyStack</p><script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","dateModified":"2026-09-18","author":{"@type":"Organization","name":"ReadyStack"}}</script><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Worked example</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 16px;color:#5b6570">Real numbers from this tool, line by line.</p><div class="yj-article"><p><img src="https://getreadystack.com/img/promo/sku111453_result_card.jpg" alt="DSA Terms Lint - EU Digital Services Act" loading="lazy" style="max-width:100%;border-radius:6px"></p>
<p>Eight blocking Digital Services Act gaps sat in the terms.md of a four-person clip-hosting app, and nobody had touched the file since 2 November 2023.</p>
<p>That date is most of the story. The EU Digital Services Act - Regulation (EU) 2022/2065 - has applied to every provider of an intermediary or hosting service offered to users in the Union since 17 February 2024, not only to the very large platforms. If people can upload, post, comment or message on the thing you built, the regulation puts named clauses in your terms of service and names the articles they come from. A terms file dated before that day was, by definition, not written against those duties.</p>
<p>So I put eighteen DSA rules into a VS Code extension and ran them over two files. The first, clean.md, answers all eighteen: 0 findings. The second, dirty.md, is the kind of file most repositories contain - short, friendly, competently drafted for 2023 - and it comes back with 12 findings, 8 of them blocking.</p>
<p>The eight blocking ones were these. No single point of contact for Member State authorities, the Commission and the Board (Art. 11). No separate point of contact for users (Art. 12). No statement that a user can reach a human rather than only an automated channel (Art. 12(1)). No legal representative in a Member State and no claim of establishment in the Union - the file said Delaware (Art. 13). No electronic notice-and-action mechanism for reporting illegal content (Art. 16). No promise of a statement of reasons when something is removed, demoted or suspended (Art. 17). No mention of the user's right to a certified out-of-court dispute settlement body (Art. 21). And the version date itself, 2023-11-02, sitting on the third line, older than the regulation it was supposed to satisfy.</p>
<p>Four more came back as warnings: the languages you accept from authorities (Art. 11(3)), a plain-language claim (Art. 14(1)), confirmation of receipt to whoever files a notice (Art. 16(4)), and a suspension-after-prior-warning policy for repeat abuse (Art. 23).</p>
<p>None of that is exotic; each of the eight is a paragraph you could write in an afternoon. They are missing because absence is invisible: you reread your terms and they look complete, because everything you can see is there.</p>
<p>That is also why asking a chatbot does not solve it. A language model will draft you fluent, plausible terms and never volunteer that Article 16 is absent, because what is not in the document is not in front of it. A markdown linter has the same blind spot from the other side: it checks heading levels, not statute.</p>
<p>Two of the eighteen rules are conditional. Art. 26 - label the ad, name who paid, explain the targeting parameters - fires only when the file mentions advertising. Art. 28(2), the ban on profiling-based ads where the service is open to minors, fires only when the file mentions minors or children. A plain B2B tool is never nagged about either.</p>
<p>The stakes are asymmetric in a way that makes the afternoon worth spending. DSA fines reach 6% of worldwide annual turnover, and a national Digital Services Coordinator can start from one user's complaint. On the other side, EU technology counsel bills roughly $250 to $500 an hour to read the same six pages.</p>
<p>The gap list is free, for the file you have open and for anyone who pastes their terms into the web page: all eighteen rules, every article number, no watermark and no cut-off. What the full version adds is scope - every legal page and every language version in the workspace in one pass, exported as a dated report with article citations you can hand to a lawyer.</p></div><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:30px 0 10px;color:#1b1f24">15 seconds — what it actually does</h2><video controls muted playsinline preload="none" poster="/img/promo/sku111453_result_card.jpg" style="width:100%;max-width:360px;border-radius:10px;display:block;margin:0 auto"><source src="/media/sku111453_short.mp4" type="video/mp4"></video><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:34px 0 6px;color:#1b1f24">Questions people ask</h2><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What does DSA Terms Lint actually do?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">It reads a terms-of-service markdown file and reports which EU Digital Services Act duties the text does not express. Eighteen rules cover Articles 11, 12, 13, 14, 16, 17, 20, 21, 23, 26 and 28, plus the version date. Each finding names the article and the sentence that is missing, in the VS Code Problems panel.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Who is this for?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Developers and founders who host user content and wrote their own terms: a two-person SaaS with comments, a forum, a marketplace, a mobile app with profiles. The Digital Services Act has applied to every provider of intermediary services offering them in the EU since 17 February 2024, not only to very large platforms.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Why will a free tool or a chatbot not do this?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">A language model will happily draft fluent terms and never tell you that Article 16 is absent, because absence is what it cannot see. Generic markdown linters check style, not statute. This tool reports the missing clause by article number, and its conditional rules stay quiet on advertising and minors unless your own text raises them.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What is free and what is in the full version?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Free gives the complete gap list for the file you have open: all eighteen rules, every article number, no watermark and no cut-off. The full version works across scope instead: it scans every legal page and every language version in the workspace at once and exports a dated report with article citations for counsel.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What would this cost without the tool?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">EU technology counsel bills roughly $250 to $500 an hour to read the same six pages, and a fixed-fee terms review runs into four figures. Enforcement runs the other way: Digital Services Act fines reach 6% of worldwide annual turnover, and national coordinators can act on a single user complaint.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Why not just ask ChatGPT or another AI chat?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">A general AI chat answers from training data with a cutoff date, cannot read your repository and names no rule version. Terms of Service Lint - EU Digital Services Act checks the file you open against 18 rules from a rule set dated 2026-09-20, and points at the exact line. For a filing, an audit or a client you need that dated result on your own files.</p></details><script type="application/ld+json" data-yj="yj-faq-ld">{"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [{"@type": "Question", "name": "What does DSA Terms Lint actually do?", "acceptedAnswer": {"@type": "Answer", "text": "It reads a terms-of-service markdown file and reports which EU Digital Services Act duties the text does not express. Eighteen rules cover Articles 11, 12, 13, 14, 16, 17, 20, 21, 23, 26 and 28, plus the version date. Each finding names the article and the sentence that is missing, in the VS Code Problems panel."}}, {"@type": "Question", "name": "Who is this for?", "acceptedAnswer": {"@type": "Answer", "text": "Developers and founders who host user content and wrote their own terms: a two-person SaaS with comments, a forum, a marketplace, a mobile app with profiles. The Digital Services Act has applied to every provider of intermediary services offering them in the EU since 17 February 2024, not only to very large platforms."}}, {"@type": "Question", "name": "Why will a free tool or a chatbot not do this?", "acceptedAnswer": {"@type": "Answer", "text": "A language model will happily draft fluent terms and never tell you that Article 16 is absent, because absence is what it cannot see. Generic markdown linters check style, not statute. This tool reports the missing clause by article number, and its conditional rules stay quiet on advertising and minors unless your own text raises them."}}, {"@type": "Question", "name": "What is free and what is in the full version?", "acceptedAnswer": {"@type": "Answer", "text": "Free gives the complete gap list for the file you have open: all eighteen rules, every article number, no watermark and no cut-off. The full version works across scope instead: it scans every legal page and every language version in the workspace at once and exports a dated report with article citations for counsel."}}, {"@type": "Question", "name": "What would this cost without the tool?", "acceptedAnswer": {"@type": "Answer", "text": "EU technology counsel bills roughly $250 to $500 an hour to read the same six pages, and a fixed-fee terms review runs into four figures. Enforcement runs the other way: Digital Services Act fines reach 6% of worldwide annual turnover, and national coordinators can act on a single user complaint."}}, {"@type": "Question", "name": "Why not just ask ChatGPT or another AI chat?", "acceptedAnswer": {"@type": "Answer", "text": "A general AI chat answers from training data with a cutoff date, cannot read your repository and names no rule version. Terms of Service Lint - EU Digital Services Act checks the file you open against 18 rules from a rule set dated 2026-09-20, and points at the exact line. For a filing, an audit or a client you need that dated result on your own files."}}]}</script><div id="yj-ask" style="margin:36px 0 0;padding:18px 18px 16px;border:1px solid #e2e6ea;border-radius:10px;background:#fbfbfc"><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:0 0 4px;color:#1b1f24">Ask about this tool</h2><p style="font:400 13.5px/1.5 system-ui,sans-serif;margin:0 0 12px;color:#5b6570">One question, answered by the person who built it. Your email only if you want the answer sent.</p><form onsubmit="return yjAsk(event)" style="display:grid;gap:8px"><textarea name="question" required minlength="10" maxlength="2000" rows="3" placeholder="Your question" style="font:14px/1.5 system-ui,sans-serif;padding:10px;border:1px solid #cfd6dd;border-radius:6px"></textarea><div style="display:flex;gap:8px;flex-wrap:wrap"><input type="email" name="email" placeholder="Email (optional)" style="flex:1;min-width:200px;font:14px system-ui,sans-serif;padding:9px 10px;border:1px solid #cfd6dd;border-radius:6px"><button type="submit" style="font:600 14px system-ui,sans-serif;padding:9px 18px;border:0;border-radius:6px;background:#1b1f24;color:#fff;cursor:pointer">Send</button></div><p id="yj-ask-msg" style="font:13px system-ui,sans-serif;margin:2px 0 0;color:#0a6238;min-height:1em"></p></form><script>function yjAsk(e){e.preventDefault();var f=e.target,m=document.getElementById("yj-ask-msg");m.style.color="#0a6238";fetch(location.origin+"/api/ask",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sku:111453,slug:"dsa-terms-lint",lang:"en",question:f.question.value,email:f.email.value,page:location.pathname})}).then(function(r){if(!r.ok)throw 0;m.textContent="Thanks \u2014 noted. Answers land on this page and, if you left an email, in your inbox.";f.question.value="";}).catch(function(){m.style.color="#a8551f";m.textContent="Could not send. Please try again in a minute.";});return false;}</script></div></section><section class="yj-related" style="max-width:920px;margin:56px auto 40px;padding:0 20px"><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Same job, next tool</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 20px;color:#5b6570">Free in the browser. The full version is a one-time licence.</p><div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:14px"><a class="yj-rel-c" href="https://getreadystack.com/tools/en301549-lint"><span class="yj-rel-t">EN 301 549 Lint — European Accessibility Act rules, with the clause number, in</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/ai-act-article-50-audit"><span class="yj-rel-t">EU AI Act Article 50 Transparency Audit for Your Codebase</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/webflow-restaurant-template"><span class="yj-rel-t">Webflow Restaurant Template — delivered as self-contained HTML you own: 26 pag</span><span class="yj-rel-p">$49</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/ai-disclosure-lint-sb942"><span class="yj-rel-t">AI Output Disclosure Lint SB 942</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/age-gate-lint"><span class="yj-rel-t">Age Gate Lint — UK Online Safety Act</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/cra-24-72-14-reporting-lint"><span class="yj-rel-t">CRA 24/72/14 Reporting Lint (Article 14)</span><span class="yj-rel-p">$29</span></a></div><style>.yj-rel-c{display:flex;flex-direction:column;gap:8px;padding:15px 16px;border:1px solid #e2e6ea;border-radius:6px;text-decoration:none;background:#fff}.yj-rel-c:hover{border-color:#b9c2cb;background:#fafbfc}.yj-rel-t{font:500 14.5px/1.42 system-ui,sans-serif;color:#1b1f24}.yj-rel-p{font:600 13px system-ui,sans-serif;color:#0a6238}</style></section></body>
</html>
|