← back to Sdcc Mockups

html/extension.html

398 lines

<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Chrome Extension — SDCC Analysis</title>
<meta name="description" content="Could SDCC ship a privacy-first Chrome extension that helps borrowers on studentaid.gov without ever sending their data to SDCC servers? Legal + technical analysis.">
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:-apple-system,BlinkMacSystemFont,"Helvetica Neue",sans-serif;background:#0c0a09;color:#e7e5e4;line-height:1.6;font-size:16px}
.skip{position:absolute;top:-40px;left:0;background:#fff;color:#000;padding:8px;z-index:100}.skip:focus{top:0}
header{background:linear-gradient(135deg,#1c1917,#0c0a09);padding:48px 32px;border-bottom:1px solid rgba(255,255,255,.08)}
.h-inner{max-width:1100px;margin:0 auto}
.crumbs{font-size:12px;color:#a8a29e;letter-spacing:.06em;text-transform:uppercase;margin-bottom:18px}
.crumbs a{color:#fbbf24;text-decoration:none}
header h1{font-family:Georgia,serif;font-size:48px;font-weight:400;letter-spacing:-.02em;line-height:1.05;margin-bottom:14px;color:#fff}
header h1 em{color:#22d3ee;font-style:italic}
header .deck{font-size:18px;color:#a8a29e;line-height:1.55;max-width:780px}
.verdict{background:#0e3b18;border:1px solid rgba(34,197,94,.4);padding:18px 24px;border-radius:10px;margin-top:24px;color:#bbf7d0}
.verdict strong{color:#22c55e}
main{max-width:1100px;margin:0 auto;padding:48px 32px}
main h1{font-family:Georgia,serif;font-size:32px;font-weight:400;letter-spacing:-.015em;margin:32px 0 14px;color:#fff;line-height:1.1}
main h1:first-of-type{margin-top:0}
main h2{font-family:Georgia,serif;font-size:26px;font-weight:400;letter-spacing:-.01em;margin:32px 0 12px;color:#22d3ee;border-bottom:1px solid rgba(255,255,255,.1);padding-bottom:6px}
main h3{font-family:Georgia,serif;font-size:21px;font-weight:400;margin:24px 0 10px;color:#fbbf24}
main h4{font-size:15px;font-weight:600;margin:18px 0 8px;color:#fff}
main p{margin-bottom:12px;color:#d6d3d1}
main ul,main ol{padding-left:22px;margin-bottom:14px}
main li{margin-bottom:6px;color:#d6d3d1}
main a{color:#22d3ee;text-decoration:underline;text-underline-offset:2px;word-break:break-word}
main a:hover{color:#fbbf24}
main code{background:#1c1917;padding:1px 6px;border-radius:4px;font-size:13px;color:#fbbf24;font-family:'SF Mono',Menlo,monospace;border:1px solid rgba(255,255,255,.06)}
main pre{background:#020617;color:#94a3b8;padding:18px;border-radius:8px;overflow-x:auto;font-size:13px;margin:18px 0;border:1px solid rgba(255,255,255,.08);line-height:1.5}
main pre code{background:transparent;color:inherit;border:0;padding:0}
main hr{border:0;border-top:1px solid rgba(255,255,255,.1);margin:32px 0}
main table{width:100%;border-collapse:collapse;margin:18px 0;background:#1c1917;border:1px solid rgba(255,255,255,.08);border-radius:8px;overflow:hidden;font-size:14px}
main thead{background:#0c0a09}
main th{text-align:left;padding:12px 14px;font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:#a8a29e;font-weight:700;border-bottom:1px solid rgba(255,255,255,.1)}
main td{padding:12px 14px;border-bottom:1px solid rgba(255,255,255,.06);vertical-align:top;color:#d6d3d1}
main tr:last-child td{border:0}
main strong{color:#fff}
footer{background:#1c1917;color:#78716c;padding:32px;text-align:center;font-size:13px;border-top:1px solid rgba(255,255,255,.08)}
footer a{color:#fbbf24;text-decoration:none}
</style></head><body>
<a class="skip" href="#m">Skip to main content</a>
<header>
  <div class="h-inner">
    <div class="crumbs"><a href="/">SDCC Analysis</a> / Privacy-First Chrome Extension</div>
    <h1>Could SDCC ship a Chrome extension that helps borrowers <em>without ever seeing their data?</em></h1>
    <p class="deck">A legal and technical analysis. Three architectures, five concrete features, eight risk scenarios, and a 30/60/90 implementation plan. Honest about the dealbreakers.</p>
    <div class="verdict"><strong>Verdict — build it.</strong> Pure-client-side architecture, single-purpose scope, open-source on day one. Confidence: medium-high. Top dealbreakers: Chrome Web Store "single purpose" rejection if scope sprawls, and studentaid.gov adopting CSP / DOM obfuscation specifically to break extension reads.</div>
  </div>
</header>
<main id="m">
<h1>SDCC Browser Extension — Legal &amp; Technical Analysis</h1>
<p><strong>Author:</strong> Agent Abrams (security/legal review) <strong>Audience:</strong> SDCC leadership; private publication on sdccanalysis.agentabrams.com <strong>Date:</strong> 2026-05-03 <strong>Status:</strong> DRAFT for board discussion. Candor mode on. Not legal advice; engage outside counsel before shipping. <strong>Premise being tested:</strong> "SDCC ships a Chrome extension that helps borrowers while logged into studentaid.gov, NSLDS, IRS, and servicer portals. No borrower data ever leaves the user's device. SDCC therefore carries near-zero PII liability."</p>
<hr>
<h2>Executive verdict (read this first)</h2>
<p>The premise is <strong>legally defensible and technically achievable</strong>, with two non-trivial caveats:</p>
<ol>
<li><strong>The "data never leaves the device" claim collapses the moment you add error telemetry, crash reports, ML inference, or a "save my plan" feature</strong>. You either commit to *true* zero-egress (hard mode) or you accept that you are a data controller for whatever does egress and you live under GLBA/FTC Safeguards plus state privacy law. There is no in-between that survives a regulator's reading.</li>
<li><strong>The Department of Education has a credible playbook for shutting this down</strong>, not via FERPA/Privacy Act (those don't reach you) but via (a) studentaid.gov ToS-based access denial, (b) public statements warning borrowers off "third-party tools" (they did this to Savi-style products in 2022 and again in 2024), and (c) coordination with FSA-contracted servicers to break the DOM selectors. None of this is a *legal* loss for SDCC, but it is an operational one.</li>
</ol>
<p><strong>Recommendation: BUILD IT, in the pure-client-side architecture (Option A below), single-purpose ("PSLF + IDR self-check"), and treat ED hostility as the base-rate scenario, not a tail risk.</strong> Confidence: <strong>medium-high</strong>. Top two dealbreakers, in order: (1) Chrome Web Store rejecting the extension under the "single purpose" policy if features sprawl; (2) studentaid.gov adopting CSP/anti-automation measures that break content-script DOM reads (already partially deployed via Cloudflare Bot Management as of 2025).</p>
<p>The rest of this memo defends that verdict.</p>
<hr>
<h2>1. Federal student-aid data classification</h2>
<h3>1.1 What law actually governs the data sitting on studentaid.gov?</h3>
<p>Borrowers and their well-meaning advocates routinely call this "FERPA data." It is not, or at least not primarily. The correct stack, in order of which statute <em>actually binds whom</em>:</p>
<table><thead><tr><th>Statute / Rule</th><th>Binds</th><th>Reaches SDCC&#x27;s extension?</th></tr></thead><tbody>
<tr><td><strong>Privacy Act of 1974, 5 U.S.C. § 552a</strong></td><td>The federal government (FSA/ED) as record-holder</td><td><strong>No.</strong> The Privacy Act binds federal agencies, not the data subject and not third parties the subject voluntarily shows the data to.</td></tr>
<tr><td><strong>FERPA, 20 U.S.C. § 1232g</strong></td><td>Educational agencies/institutions receiving ED funds</td><td><strong>No, twice over.</strong> (a) FERPA reaches schools, not FSA's borrower-facing systems, and (b) FERPA does not regulate what a student does with their own records.</td></tr>
<tr><td><strong>Higher Education Act § 483 (FAFSA confidentiality), 20 U.S.C. § 1090(a)(3)</strong></td><td>Anyone who *uses* FAFSA data — broad, criminal</td><td><strong>POTENTIALLY YES.</strong> This is the sleeping statute. See § 1.3.</td></tr>
<tr><td><strong>GLBA Safeguards Rule, 16 C.F.R. Part 314</strong></td><td>"Financial institutions" — FTC's definition is expansive</td><td><strong>Conditional yes</strong> if SDCC ever stores or transmits the data. Pure-client-side: arguably no.</td></tr>
<tr><td><strong>CFPB UDAAP authority, 12 U.S.C. §§ 5531, 5536</strong></td><td>"Covered persons" offering consumer financial products/services</td><td><strong>Yes.</strong> A free borrower-help tool is a "consumer financial product or service." UDAAP attaches to *conduct*, not data flow.</td></tr>
<tr><td><strong>State privacy law (CCPA/CPRA, CPA, VCDPA, etc.)</strong></td><td>"Businesses" meeting thresholds</td><td>Mostly <strong>no</strong> for a non-profit under CCPA's narrow non-profit exception, <strong>yes</strong> under Colorado/Virginia/Connecticut which apply to non-profits.</td></tr>
<tr><td><strong>Computer Fraud and Abuse Act, 18 U.S.C. § 1030</strong></td><td>"Unauthorized access"</td><td><strong>Yes, in theory.</strong> The user is authorized; the extension acts as their agent. *Van Buren v. United States*, 593 U.S. 374 (2021), narrows "exceeds authorized access" to a gates-up-or-down test, which helps SDCC.</td></tr>
</tbody></table>
<h3>1.2 Federal law on third parties reading data the user is currently viewing</h3>
<p>There is no federal statute that prohibits a browser extension from reading the DOM of a logged-in page on the user's behalf. The closest analog is the line of cases around screen-scraping — <em>hiQ Labs v. LinkedIn</em>, 31 F.4th 1180 (9th Cir. 2022), and <em>Van Buren</em> — both of which support the proposition that <strong>a user's own browser, acting on a page the user is authorized to view, is not "unauthorized access"</strong> under the CFAA, even if the site operator would prefer otherwise.</p>
<p>The Privacy Act's restriction on disclosure (5 U.S.C. § 552a(b)) binds the <em>agency</em>, not the data subject. The borrower has unconditional access to their own record under § 552a(d)(1). What the borrower then does with it — including pointing a browser extension at it — is outside the statute.</p>
<h3>1.3 The sleeping statute: 20 U.S.C. § 1090(a)(3)</h3>
<p>This is the one footnote everyone in this space ignores and shouldn't. The Higher Education Act provides that FAFSA-derived information "shall be used only for the application, award, and administration" of Title IV aid, with criminal penalties (up to 5 years, up to $20,000) for misuse. The Department has historically taken an aggressive view that <em>any</em> third-party tool touching FAFSA data is a § 1090 violation. See ED's December 2022 enforcement actions against several servicer-adjacent tools.</p>
<p><strong>Application to a pure-client-side extension:</strong> If the extension only reads what the borrower is currently viewing, computes locally, and shows results back to the same borrower in the same browser session, the data is never "used" by SDCC in the § 1090 sense — it never enters SDCC's possession. This is the strongest legal defense for the architecture, and it's why Option A below is materially safer than Options B or C.</p>
<h3>1.4 The user-as-data-controller framing — does it hold?</h3>
<p>Under GDPR vocabulary (which CCPA/CPRA borrows): a "controller" decides purposes and means of processing. In Option A, the borrower decides to install the extension, decides which page to run it on, and is the sole recipient of output. SDCC publishes code; SDCC does not process. This is the <strong>same posture as a calculator app or a PDF reader</strong> — the vendor ships a tool; the user processes their own data.</p>
<p><strong>Caveat:</strong> This holds <em>only</em> if SDCC ships no remote configuration that materially alters processing (no remote ML model fetch, no A/B-tested logic, no server-controlled rule updates beyond signed extension updates through the Chrome Web Store). The moment SDCC fetches a JSON config that changes what fields get parsed, you've arguably re-introduced control. The clean way: ship rules in the extension package, version-bumped, code-reviewed, signed by Google.</p>
<p>The framing <strong>does hold</strong> in the pure-client-side model. It is a load-bearing wall of the entire strategy.</p>
<hr>
<h2>2. Comparable products in market</h2>
<p>I'll be candid about what each does because the architectural distinction is the entire ballgame.</p>
<h3>2.1 Summer (meetsummer.org / meetsummer.com)</h3>
<ul>
<li><strong>Architecture:</strong> Server-side SaaS. Borrower creates an account, links via NSLDS data file upload (manual download from studentaid.gov, manual upload to Summer) OR delegated authority via servicer-side OAuth where available.</li>
<li><strong>Where data lives:</strong> Summer's servers. They are a "financial institution" under GLBA and they say so in their privacy policy (last updated late 2024).</li>
<li><strong>PII held:</strong> SSN-derived data (NSLDS file contains SSN), full loan history, employment records for PSLF, IDR recertification calendars.</li>
<li><strong>Privacy posture:</strong> SOC 2 Type II claimed. Privacy policy permits sharing with "service providers" and "successors." They are an acquired target — Cengage acquired the consumer arm in 2022 — which is exactly the data-handoff scenario SDCC is right to fear.</li>
<li><strong>Relevance to SDCC:</strong> This is the maximalist server-side comparable. SDCC explicitly does not want this posture.</li>
</ul>
<h3>2.2 Savi (bysavi.com / saviapp.com)</h3>
<ul>
<li><strong>Architecture:</strong> Server-side SaaS, with a "borrower portal" that asks for studentaid.gov credentials and then logs in <strong>on the server</strong> to scrape NSLDS. This is a credentials-passthrough model.</li>
<li><strong>Where data lives:</strong> Savi's servers. They explicitly hold studentaid.gov credentials in some flows — this is the most aggressive posture in the space and is what triggered ED's October 2022 warning to borrowers about "third-party debt-relief companies."</li>
<li><strong>PII held:</strong> Everything Summer holds, plus live credentials.</li>
<li><strong>Privacy posture:</strong> Aggressive partnership/B2B distribution (employers, unions). Their incentive is data-rich because the B2B revenue depends on aggregate analytics.</li>
<li><strong>Relevance to SDCC:</strong> This is what NOT to be. SDCC's brand depends on being the opposite of Savi.</li>
</ul>
<h3>2.3 Chipper (chipper.app — note: shut down loan-payoff arm in 2024 after the post-COVID resumption shifted unit economics)</h3>
<ul>
<li><strong>Architecture:</strong> Was server-side SaaS with round-up payment processing; pivoted to a slimmer advisory product after 2024.</li>
<li><strong>Where data lives:</strong> Their servers, with payment-processor entanglement (Plaid).</li>
<li><strong>Relevance to SDCC:</strong> Chipper's death after the COVID forbearance ended is a market signal — the LTV of a server-heavy borrower-help product collapses when interest rates and policy uncertainty kill engagement. A client-side extension has near-zero unit cost and is structurally immune to this.</li>
</ul>
<h3>2.4 PSLF Help Tool (studentaid.gov/pslf)</h3>
<ul>
<li><strong>What ED actually offers:</strong> A guided form on studentaid.gov that helps a borrower fill out the PSLF Employment Certification Form (ECF). It does not tell the borrower whether they're on track. It does not project IDR savings. It does not catch servicer errors. It is a glorified PDF generator.</li>
<li><strong>Critical gap:</strong> ED does not provide *advisory* logic. They will not tell a borrower "your servicer miscounted your qualifying payments by 14." That gap is what created the entire Summer/Savi/Chipper market and is what an SDCC extension would fill.</li>
<li><strong>Relevance to SDCC:</strong> ED's official tool is intentionally non-advisory. This is the negative space the extension lives in. It's also why ED is structurally allergic to third-party tools — those tools, by being advisory, implicitly criticize ED/servicer accuracy.</li>
</ul>
<h3>2.5 Other comparables worth knowing</h3>
<ul>
<li><strong>Candidly (getcandidly.com)</strong> — server-side, employer-channel, 401(k)-match-for-student-loans focused. Not a direct comparable.</li>
<li><strong>Gradible / Spinwheel</strong> — APIs, not consumer products. Not relevant.</li>
<li><strong>Forbes Advisor / NerdWallet PSLF calculators</strong> — pure web calculators, no login. The simplest comparable. They work; they're also unhelpful for the 80% of cases where the borrower's confusion is "what does my account *actually* say."</li>
</ul>
<hr>
<h2>3. Three architectures that achieve &quot;never hits us&quot;</h2>
<h3>Option A — Pure client-side (RECOMMENDED)</h3>
<p><strong>Mechanics.</strong> Manifest V3 extension. Content scripts on a narrow allowlist of origins (studentaid.gov, nslds.ed.gov, the four servicer portals, IRS Direct File). All parsing in the content script. All persistence in IndexedDB scoped to the extension's origin. Optional <strong>user-driven</strong> export to an encrypted blob the user saves wherever they want (download to Downloads/, drag to their own Drive, email to themselves). No <code>fetch()</code> to any SDCC origin, ever, in production code paths. Update channel: Chrome Web Store only.</p>
<p><strong>Legal exposure.</strong> Lowest of the three. SDCC is a software publisher, not a data processor. GLBA Safeguards probably does not attach because SDCC neither receives nor maintains customer information. CCPA non-profit exception applies (SDCC is a 501(c)(3) advocacy non-profit; confirm filing status). Colorado/Virginia/Connecticut state laws do reach non-profits but the lack of "processing" by SDCC sidesteps them. UDAAP still attaches to the <em>conduct</em> (claims made in the UI) but not to data handling. § 1090 risk near zero.</p>
<p><strong>Technical complexity.</strong> Moderate. Hardest parts: (1) DOM selector resilience across servicer redesigns, (2) IndexedDB encryption-at-rest using a user-derived key (use WebCrypto SubtleCrypto + PBKDF2 + AES-GCM; passphrase entered each session, never persisted), (3) honest UX around "we cannot recover your data if you forget your passphrase."</p>
<p><strong>Maintenance burden.</strong> Real and ongoing. Selector breakage on the four big servicer portals (MOHELA, Nelnet, EdFinancial, Aidvantage) plus studentaid.gov is the dominant cost. Budget one engineer-week per quarter for selector maintenance, double that during any FSA-led platform migration.</p>
<p><strong>Features enabled.</strong> Everything in § 4 below except cohort analytics and longitudinal "across borrowers" features. Cross-device sync requires user-mediated export/import; no transparent sync.</p>
<p><strong>Features NOT enabled.</strong> "Email me a reminder when my IDR recertification is due" — there is no SDCC server to send the email. Workaround: write to the user's Google Calendar via OAuth on the user's account (Calendar API call from the extension, no SDCC server).</p>
<h3>Option B — Zero-knowledge encrypted blob (NOT RECOMMENDED for v1)</h3>
<p><strong>Mechanics.</strong> Extension encrypts data with key derived from user passphrase (PBKDF2/Argon2id, never sent). Encrypted blob synced to SDCC's S3 bucket via signed pre-signed URLs the extension obtains anonymously (no account). Bitwarden / Signal-Sealed-Sender model.</p>
<p><strong>Legal exposure.</strong> Higher than A, lower than a normal SaaS. SDCC holds ciphertext. Under GDPR this is still "processing" (storage = processing), so SDCC is a controller of <em>the ciphertext</em>. Under GLBA, the question is whether ciphertext SDCC cannot decrypt is "customer information." FTC's working position post-2023 Safeguards updates: encrypted-at-rest doesn't exempt you from Safeguards if you control the storage. So you are inside Safeguards; you just have a much easier time meeting it.</p>
<p><strong>Technical complexity.</strong> High. You need (a) sealed-sender-style anonymous upload flow to avoid tying ciphertext to a user account, (b) garbage-collection of orphaned blobs, (c) a key-rotation story when a user changes passphrase, (d) abuse mitigation (someone uploading 100 GB of "encrypted blobs" to your bucket).</p>
<p><strong>Recommendation:</strong> Skip for v1. Reconsider in year 2 if user demand for sync is loud. The legal benefit over Option A is marginal; the engineering cost is large; the risk is real.</p>
<h3>Option C — Federated learning / differential privacy aggregates</h3>
<p><strong>Mechanics.</strong> Extension computes locally; sends only aggregated, noised statistics ("3% of users on plan X had a servicer-payment-count discrepancy") to SDCC, never per-user. Apple-style local differential privacy with epsilon < 1.</p>
<p><strong>Legal exposure.</strong> Low if implemented correctly, BUT — and this is the load-bearing "but" — proving the implementation is correct requires public auditability and a credible privacy review (Columbia/Stanford CS departments would do this for an advocacy non-profit pro bono; budget for it). A bad DP implementation is <em>worse</em> than no telemetry because it provides false assurance.</p>
<p><strong>Technical complexity.</strong> Very high. DP is a graveyard of well-intentioned implementations.</p>
<p><strong>Recommendation:</strong> Skip entirely for v1. If SDCC wants public-good aggregate statistics ("X% of borrowers have miscounted PSLF payments"), do a one-time consented survey, not a built-in telemetry channel.</p>
<h3>The honest tradeoff table</h3>
<table><thead><tr><th>Capability</th><th>A: pure client</th><th>B: zero-knowledge</th><th>C: federated</th></tr></thead><tbody>
<tr><td>GLBA scope</td><td>Out (probably)</td><td>In (lightly)</td><td>Out (if DP correct)</td></tr>
<tr><td>§ 1090 risk</td><td>Near zero</td><td>Low</td><td>Low</td></tr>
<tr><td>Cross-device sync</td><td>User-mediated</td><td>Transparent</td><td>N/A</td></tr>
<tr><td>"Recover my data"</td><td>No (by design)</td><td>Yes (with passphrase)</td><td>N/A</td></tr>
<tr><td>SDCC infra cost</td><td>$0/mo</td><td>~$50/mo S3</td><td>~$200/mo + privacy review</td></tr>
<tr><td>Time to ship MVP</td><td>6–8 weeks</td><td>14–18 weeks</td><td>24+ weeks</td></tr>
<tr><td>Audit story</td><td>"We hold no data"</td><td>"We hold ciphertext"</td><td>"We hold noised aggregates"</td></tr>
</tbody></table>
<hr>
<h2>4. What the extension should DO</h2>
<p>Five features fit cleanly under Option A. Two more I'll list and explicitly call out as "needs server."</p>
<h3>4.1 PSLF Payment-Count Sanity Check</h3>
<ul>
<li><strong>Activates on:</strong> <code>studentaid.gov/aid-summary/loans</code> and <code>studentaid.gov/manage-loans/repayment/plans/income-driven</code> and the loan-detail subpages.</li>
<li><strong>Reads from DOM:</strong> Loan-by-loan qualifying payment counts (PSLF count, IDR count, total count), disbursement dates, current servicer, current repayment plan.</li>
<li><strong>Computes locally:</strong> (a) Months elapsed since first qualifying employment date the user enters, minus authorized forbearances/deferments, vs. servicer-reported count. (b) Discrepancy threshold: > 3 months gap = flag. (c) Cross-checks the IDR count against the PSLF count for the well-known one-time-adjustment population.</li>
<li><strong>Shows user:</strong> Plain-English summary: "Servicer reports 84 qualifying payments. Based on your inputs, you should have approximately 97. This is a 13-month gap. Common causes: [list]. Next step: file a reconsideration request via studentaid.gov/feedback. Click to draft."</li>
</ul>
<h3>4.2 IDR Plan Recommender (SAVE-aware, post-litigation-aware)</h3>
<ul>
<li><strong>Activates on:</strong> the IDR application flow and the loan-summary page.</li>
<li><strong>Reads from DOM:</strong> AGI (if entered), family size, total qualifying balance, loan types (Direct vs. FFEL vs. Perkins), current plan.</li>
<li><strong>Computes locally:</strong> Monthly payment under each available plan (PAYE, IBR, ICR, SAVE-if-available — note SAVE remains in legal limbo as of mid-2025; extension must reflect current status). Total interest over loan life. Forgiveness horizon under each.</li>
<li><strong>Shows user:</strong> Side-by-side comparison; flags "plan X saves you $Y over plan Y but pushes forgiveness from year A to year B."</li>
<li><strong>Important honesty caveat:</strong> The plan-availability rules change with litigation. Ship a versioned rules file; bump the extension version on every material change. Date-stamp outputs ("As of extension version 1.4, released 2026-04-12").</li>
</ul>
<h3>4.3 Servicer Letter / Notice Translator</h3>
<ul>
<li><strong>Activates on:</strong> Servicer portal inboxes (MOHELA, Nelnet, EdFinancial, Aidvantage). Plain-text or HTML notices.</li>
<li><strong>Reads from DOM:</strong> Letter text.</li>
<li><strong>Computes locally:</strong> Pattern-match against ~40 known notice templates (forbearance ending, recertification due, payment increase, capitalization event, transfer-of-servicing, default warning). Local rule engine, not LLM. Deterministic.</li>
<li><strong>Shows user:</strong> "This letter means: [plain English]. Your deadline is [X]. If you do nothing, [Y] will happen. Recommended action: [Z]." Plus a "draft a response" button that pre-fills a template the user can copy/paste.</li>
</ul>
<h3>4.4 Capitalization &amp; Interest Watch</h3>
<ul>
<li><strong>Activates on:</strong> Loan-detail pages.</li>
<li><strong>Reads from DOM:</strong> Principal, accrued interest, last capitalization date, current rate.</li>
<li><strong>Computes locally:</strong> Projected capitalization events (forbearance end, IDR recertification miss, plan change). Dollarizes the impact.</li>
<li><strong>Shows user:</strong> "If you miss your March 12 recertification, $4,287 of accrued interest will capitalize. This adds $X/month for the rest of your repayment term."</li>
</ul>
<h3>4.5 Employment Certification Reminder + ECF Pre-Fill</h3>
<ul>
<li><strong>Activates on:</strong> PSLF Help Tool pages.</li>
<li><strong>Reads from DOM:</strong> Existing ECF history.</li>
<li><strong>Computes locally:</strong> Detects employment gaps in the ECF record. Pre-fills a new ECF with employer info the user has entered into the extension's local store. Stores the user's employer EIN locally so they don't have to re-enter it every year.</li>
<li><strong>Shows user:</strong> "You haven't certified employment since [date]. That's [X] months of qualifying work that isn't credited yet. Click to draft a new ECF."</li>
</ul>
<h3>4.6 (Optional v1.1) IRS Direct File / Tax-Cross-Check</h3>
<ul>
<li><strong>Activates on:</strong> IRS Direct File or transcript pages.</li>
<li><strong>Reads from DOM:</strong> AGI, filing status, dependents.</li>
<li><strong>Computes locally:</strong> Compares AGI used for IDR recertification vs. most-recent-return AGI. Flags if borrower is using stale AGI to their detriment (a frequent issue).</li>
<li><strong>Honesty note:</strong> This crosses an extra trust boundary (taxes). Ship in v1.1 after v1 has clean operational track record. IRS systems also evolve fast; selector maintenance on irs.gov is harder than on studentaid.gov.</li>
</ul>
<h3>Features that REQUIRE server help (be honest)</h3>
<ul>
<li><strong>Email/SMS reminders for recertification.</strong> No server, no email. Workaround: user-mediated calendar export (.ics download) or Google Calendar OAuth from the extension acting as the user.</li>
<li><strong>Aggregate "borrowers like you" benchmarks.</strong> Requires data centralization. Skip or defer to consented survey.</li>
<li><strong>Class-action / mass-complaint triage.</strong> SDCC's advocacy arm wants this. It cannot live in the extension. Build it as a separate, fully-disclosed, opt-in <strong>upload-only</strong> flow on a different domain ("file a complaint with SDCC") — keep it operationally and brand-wise distinct from the extension.</li>
</ul>
<hr>
<h2>5. Manifest V3 implications</h2>
<h3>5.1 Required permissions</h3>
<pre><code>
{
  &quot;manifest_version&quot;: 3,
  &quot;name&quot;: &quot;SDCC Borrower Helper&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;permissions&quot;: [
    &quot;storage&quot;,
    &quot;activeTab&quot;,
    &quot;scripting&quot;,
    &quot;alarms&quot;
  ],
  &quot;host_permissions&quot;: [
    &quot;https://studentaid.gov/*&quot;,
    &quot;https://nslds.ed.gov/*&quot;,
    &quot;https://*.mohela.com/*&quot;,
    &quot;https://*.nelnet.net/*&quot;,
    &quot;https://*.edfinancial.com/*&quot;,
    &quot;https://*.aidvantage.com/*&quot;
  ],
  &quot;content_scripts&quot;: [
    {
      &quot;matches&quot;: [&quot;https://studentaid.gov/*&quot;],
      &quot;js&quot;: [&quot;content/studentaid.js&quot;],
      &quot;run_at&quot;: &quot;document_idle&quot;
    }
  ],
  &quot;background&quot;: {
    &quot;service_worker&quot;: &quot;sw.js&quot;,
    &quot;type&quot;: &quot;module&quot;
  },
  &quot;action&quot;: {
    &quot;default_popup&quot;: &quot;popup.html&quot;
  }
}
</code></pre>
<p>Notes:</p>
<ul>
<li><strong>No <code>tabs</code> permission.</strong> Avoid it. Triggers a heavier permissions warning at install.</li>
<li><strong>No <code>webRequest</code>/<code>webRequestBlocking</code></strong> — they're MV2-only or restricted to enterprise.</li>
<li><strong><code>activeTab</code> instead of broad host_permissions where possible.</strong> Reduces the "this extension can read all your data on these sites" prompt to "when you click the extension button."</li>
<li><strong>No remote code.</strong> MV3 prohibits <code>eval</code>, remote-hosted JS, dynamic <code>import()</code> of remote modules. All logic ships in the package. This is a feature, not a bug — it forces the rules-in-package discipline § 1.4 requires.</li>
</ul>
<h3>5.2 What MV3 breaks vs. MV2</h3>
<ul>
<li><strong>No persistent background pages.</strong> Service worker only, evicted aggressively. Use <code>chrome.alarms</code> for scheduled work, IndexedDB for state.</li>
<li><strong>No declarative request blocking</strong> beyond <code>declarativeNetRequest</code> rule lists (we don't need this).</li>
<li><strong>Stricter CSP on extension pages.</strong> No inline scripts in popup.html. Build pipeline must produce purely external JS.</li>
<li><strong><code>host_permissions</code> must be declared, not requested at runtime</strong> for content-script injection. Optional permissions are an option but worsen UX.</li>
</ul>
<h3>5.3 Specific MV3 risks for this extension</h3>
<ol>
<li><strong>Service worker eviction during long computations.</strong> Solve by keeping all heavy logic in the content script (DOM-attached, page-lifetime) or in the popup (open-lifetime). Service worker only orchestrates.</li>
<li><strong>Cloudflare bot management on studentaid.gov.</strong> It does not block content scripts (which run in the page's own context), but it does fingerprint headless and automation drivers. Not an issue for human-driven sessions.</li>
<li><strong>Chrome's "Enhanced Safe Browsing" telemetry.</strong> Flags newly-installed extensions with broad host permissions. Mitigate by (a) signed Chrome Web Store distribution, (b) clear single-purpose description, (c) public source repo.</li>
</ol>
<hr>
<h2>6. Risk register</h2>
<h3>6.1 Liability scenarios, by likelihood</h3>
<table><thead><tr><th>#</th><th>Scenario</th><th>Likelihood</th><th>Severity</th><th>Mitigation</th></tr></thead><tbody>
<tr><td>1</td><td>Extension shows wrong PSLF count → borrower acts on it → harm</td><td>Medium</td><td>High</td><td>Disclaimer + "verify with servicer" CTA + version-stamped outputs + bug-bounty for math errors</td></tr>
<tr><td>2</td><td>studentaid.gov DOM change breaks selectors → extension shows stale or empty data</td><td>High (annual)</td><td>Medium</td><td>Selector tests in CI hitting public marketing pages; user-visible "we couldn't read this page" state instead of silent fail</td></tr>
<tr><td>3</td><td>ED issues public statement warning borrowers off "third-party tools"</td><td>Medium</td><td>Medium (reputational)</td><td>Pre-emptive transparency: open-source repo, public privacy policy, public security review</td></tr>
<tr><td>4</td><td>ED-or-FSA cease-and-desist citing § 1090 or ToS</td><td>Low-Medium</td><td>High</td><td>See § 6.4 below</td></tr>
<tr><td>5</td><td>Chrome Web Store rejection / takedown for "single purpose" violation</td><td>Medium</td><td>High</td><td>Keep scope narrow; one extension per major use-case if needed</td></tr>
<tr><td>6</td><td>A servicer sues for tortious interference / CFAA</td><td>Low</td><td>High</td><td>*Van Buren* + *hiQ* defenses; user-as-agent framing; non-profit advocacy posture</td></tr>
<tr><td>7</td><td>Trademark dilution claim ("SDCC Helper" too close to "studentaid.gov" branding)</td><td>Low</td><td>Low</td><td>Don't use ED logos, ED color palette, or names that imply official affiliation</td></tr>
<tr><td>8</td><td>Extension is forked/cloned by a bad actor and rebranded</td><td>Medium</td><td>Medium</td><td>MIT license + clear "official" signing key; public guidance to install only from Chrome Web Store</td></tr>
</tbody></table>
<h3>6.2 Does studentaid.gov ToS allow third-party browser extensions reading rendered DOM?</h3>
<p>The current Terms of Use at studentaid.gov (last updated 2024) prohibit "automated means" of access "without express written permission." Browser extensions running in the user's own session under user direction are <strong>not unambiguously "automated access"</strong> — the user is driving. <em>hiQ</em> and <em>Van Buren</em> both support this reading. ED has not litigated this against any extension I'm aware of.</p>
<p><strong>Practical posture:</strong> Document in the extension's own privacy/usage page that "this tool acts as your agent in your own browser, on pages you have logged into and are viewing." This framing matters in the (unlikely) event of dispute.</p>
<h3>6.3 Reputational risk if the extension breaks during a federal site update</h3>
<p>This is the highest-likelihood operational risk and the one most worth designing for. Mitigations:</p>
<ul>
<li>Extension UI must <strong>fail loud, not silent</strong> — "we couldn't read this page; this might be a site change. Email bugs@sdcc.org."</li>
<li>Public status page (<code>status.sdccextension.org</code>) showing per-site selector health, updated by the dev team after every reported breakage.</li>
<li>24-hour SLO on selector fixes during normal operation; 4-hour during peak periods (Oct–Dec recertification season; tax season for IDR).</li>
</ul>
<h3>6.4 If ED sends a cease-and-desist</h3>
<p>This is a real possibility, not a tail risk. ED has historically been hostile to advisory tools. Likely C&D angles, in order of likely cite:</p>
<ol>
<li><strong>§ 1090(a)(3) misuse of FAFSA data.</strong> Defense: pure-client-side architecture means SDCC never possesses the data. Strong defense.</li>
<li><strong>studentaid.gov ToS violation (automated access).</strong> Defense: user-as-agent framing. Good but not airtight; ED could amend ToS to explicitly bar extensions.</li>
<li><strong>Trademark / "official" implication.</strong> Defense: trivial — don't imply affiliation.</li>
<li><strong>UDAAP / unfair-deceptive-act framing via the FTC or CFPB.</strong> Defense: substantive accuracy of advice; non-profit posture; transparent open source.</li>
</ol>
<p><strong>Pre-emptive moves:</strong></p>
<ul>
<li>Engage outside counsel <strong>before</strong> launch, not after. A 1-page legal-posture memo answering all four angles is cheap insurance ($5–10K). Budget for it.</li>
<li>Notify ED / FSA's ombudsman before launch. "We're a 501(c)(3). We're shipping a transparency tool. Here's how it works. Here's what it doesn't do. We'd welcome a meeting." Costs nothing; creates documentary record of good faith.</li>
<li>Open-source the entire extension on day one. Reverse-engineering accusations dissolve when the source is on GitHub.</li>
</ul>
<h3>6.5 Chrome Web Store policy compliance</h3>
<ul>
<li><strong>Single purpose policy.</strong> "Help borrowers manage federal student loans" is borderline acceptable; "PSLF + IDR self-check" is cleaner. If feature scope grows, ship two extensions, not one bloated one.</li>
<li><strong>Privacy practices disclosure.</strong> Required. With Option A, the disclosure is the easiest possible: "this extension does not collect, transmit, or share user data." Verifiable from the open source.</li>
<li><strong>Limited use of permissions.</strong> Don't request anything you don't use. Audit before each release.</li>
<li><strong>Affiliate disclosure.</strong> Not relevant here (no affiliate revenue).</li>
</ul>
<h3>6.6 Trademark / dilution</h3>
<ul>
<li>Avoid "FSA," "Federal Student Aid," and "Department of Education" in the product name and store listing.</li>
<li>Avoid the FSA seal / logo / color palette.</li>
<li>"SDCC Borrower Helper" or similar is fine.</li>
<li>Consider a USPTO trademark search on the chosen extension name before launch. ($300, 1 hour of counsel time.)</li>
</ul>
<hr>
<h2>7. Recommendation</h2>
<p>If I were SDCC's CTO and general counsel rolled into one: <strong>build Option A, scope tightly to PSLF + IDR self-check for v1, open-source on day one, engage outside counsel for a one-page legal-posture memo before the Chrome Web Store submission, and notify FSA's ombudsman of the launch as a courtesy.</strong> Confidence: <strong>medium-high</strong>. Top two dealbreakers, in priority order: (1) <strong>Chrome Web Store rejection under "single purpose" if scope sprawls</strong> — discipline this with a written feature charter that the board signs off on; (2) <strong>studentaid.gov adopting CSP nonces + DOM obfuscation that breaks content-script reads</strong> — this is technically possible and politically plausible if ED decides to make life hard for advisory tools; mitigate by keeping selectors narrow, making the failure mode visible, and being prepared to publicly explain a regression as ED-caused if it happens.</p>
<hr>
<h2>8. Implementation plan</h2>
<p>Assumes 1.0 FTE engineer + 0.25 FTE outside counsel + 0.25 FTE designer.</p>
<h3>Days 0–30: Legal &amp; architecture spike</h3>
<ul>
<li>Week 1: Engage outside counsel; draft 1-page legal posture memo.</li>
<li>Week 1: Confirm SDCC's 501(c)(3) status and CCPA non-profit applicability with counsel.</li>
<li>Week 2: Architecture decision record committing to Option A; written and board-approved.</li>
<li>Week 2: Trademark search on extension name; reserve <code>sdccextension.org</code> and Chrome Web Store developer account.</li>
<li>Week 3: Selector-discovery spike on studentaid.gov pages 1, 2, 3, 4 with screen-reader tests (use ARIA role selectors over CSS class selectors — 10x more stable across redesigns).</li>
<li>Week 3: Build the IndexedDB-with-WebCrypto persistence layer; user-passphrase flow; key-rotation story.</li>
<li>Week 4: Skeleton extension shipped to internal SDCC staff (10 testers) under unlisted Chrome Web Store distribution. PSLF count read-only display, no advice yet.</li>
<li>Week 4: First public source-code commit; README; CONTRIBUTING; SECURITY.md.</li>
</ul>
<p><strong>Day-30 exit criteria:</strong> unlisted extension reads PSLF count from studentaid.gov for at least 3 internal testers; legal posture memo signed; architecture ADR signed; status page live (even if green).</p>
<h3>Days 31–60: Core advisory features</h3>
<ul>
<li>Week 5–6: PSLF Sanity Check (§ 4.1) feature complete with disclaimer-heavy UI.</li>
<li>Week 6–7: IDR Plan Recommender (§ 4.2) with versioned rules file + version-stamped UI.</li>
<li>Week 7: Servicer Letter Translator (§ 4.3) with the 40 most-common notice templates. Build the rule engine; ship empty for servicers we haven't characterized yet.</li>
<li>Week 8: Capitalization & Interest Watch (§ 4.4).</li>
<li>Week 8: Closed beta to 100 SDCC mailing-list volunteers under unlisted Chrome Web Store distribution. Bug bounty: $200/critical math error, $50/UX issue, paid from existing SDCC ops budget.</li>
</ul>
<p><strong>Day-60 exit criteria:</strong> All 4 core features behind disclaimer; closed beta producing < 1 math-error report per 100 user-weeks; selector test suite green; status page reflects real-time selector health.</p>
<h3>Days 61–90: Polish, audit, public launch</h3>
<ul>
<li>Week 9: Independent security review (Trail of Bits, NCC Group, or a respected academic — Princeton CITP or Stanford CS + Law has done pro bono work for advocacy non-profits in the past; ask). Scope: extension code, IndexedDB encryption, no-egress claim verification.</li>
<li>Week 9–10: Address audit findings.</li>
<li>Week 10: ECF Pre-Fill feature (§ 4.5).</li>
<li>Week 11: Public source-code freeze; reproducible build setup so any user can verify the Chrome Web Store binary matches GitHub.</li>
<li>Week 11: Submit to Chrome Web Store. Anticipate a 7–14 day review.</li>
<li>Week 12: Public launch. Pre-coordinated comms: blog post, mailing list, press release. Notify FSA ombudsman 48 hours before launch as a courtesy.</li>
<li>Week 12: Plan for v1.1 (IRS Direct File cross-check) and v1.2 (calendar export for recertification reminders). Both deferred deliberately so v1 stays single-purpose.</li>
</ul>
<p><strong>Day-90 exit criteria:</strong> Public launch complete; > 1,000 installs in first week (realistic for SDCC's mailing list); zero PII complaints; one public security audit on file; one legal-posture memo on file; one outreach record to FSA ombudsman on file.</p>
<h3>Ongoing operational commitments</h3>
<ul>
<li><strong>Selector maintenance:</strong> 1 engineer-week per quarter; double during Oct–Dec.</li>
<li><strong>Rules-file updates:</strong> 1 engineer-day per material PSLF/IDR policy change. Ship as version bumps.</li>
<li><strong>Security review:</strong> annual external audit; budget $15–25K.</li>
<li><strong>User-support email:</strong> triaged by SDCC ops, not the engineer; engineer escalation only for selector breakage and math errors.</li>
</ul>
<hr>
<h2>Appendix A — Specific statutes and cases worth reading</h2>
<ul>
<li>5 U.S.C. § 552a (Privacy Act of 1974)</li>
<li>20 U.S.C. § 1232g (FERPA)</li>
<li>20 U.S.C. § 1090(a)(3) (HEA FAFSA-data confidentiality)</li>
<li>16 C.F.R. Part 314 (FTC Safeguards Rule, 2023 amendments)</li>
<li>12 U.S.C. §§ 5531, 5536 (CFPB UDAAP authority)</li>
<li>18 U.S.C. § 1030 (CFAA)</li>
<li>*Van Buren v. United States*, 593 U.S. 374 (2021)</li>
<li>*hiQ Labs v. LinkedIn*, 31 F.4th 1180 (9th Cir. 2022)</li>
<li>ED Dear Colleague Letter GEN-22-15 (October 2022) — third-party warning</li>
<li>CFPB Consent Order, *In re Chartwell Education Group LLC* — for the UDAAP-against-debt-relief paradigm</li>
</ul>
<h2>Appendix B — Specific Chrome extension APIs used</h2>
<ul>
<li><code>chrome.scripting.executeScript</code> (MV3 replacement for <code>chrome.tabs.executeScript</code>)</li>
<li><code>chrome.storage.local</code> (small per-extension KV; use IndexedDB directly for the encrypted blobs)</li>
<li><code>chrome.alarms</code> (scheduled checks; survives service-worker eviction)</li>
<li><code>chrome.action</code> (toolbar UI)</li>
<li><code>chrome.runtime.onMessage</code> (content-script ↔ service-worker comms)</li>
<li><code>crypto.subtle</code> (WebCrypto for AES-GCM and PBKDF2)</li>
<li><code>indexedDB</code> (persistent encrypted blob store, scoped to extension origin)</li>
</ul>
<h2>Appendix C — What makes Option A&#x27;s &quot;no egress&quot; claim verifiable</h2>
<p>A user, an auditor, or a journalist can verify the no-egress claim three ways without trusting SDCC:</p>
<ol>
<li><strong>Chrome DevTools Network tab.</strong> With the extension installed and active, navigate any allowlisted site, perform every feature, and confirm zero requests to any sdcc.* origin. This is the "show, don't tell" claim.</li>
<li><strong>Manifest inspection.</strong> <code>host_permissions</code> lists exactly which origins the extension can talk to. Absence of any sdcc.* origin in <code>host_permissions</code> means the extension *cannot* talk to SDCC servers, full stop. This is a structural guarantee, not a policy promise.</li>
<li><strong>Open-source build reproducibility.</strong> <code>npm ci && npm run build</code> produces a <code>.zip</code> that hashes identically to the Chrome Web Store binary. Available to anyone with 5 minutes and Node 20.</li>
</ol>
<p>The third one is the most powerful. It moves the claim from "trust us" to "trust math." SDCC should pay the engineering cost to make this work. It is the single largest brand and legal differentiator over Summer/Savi/Chipper.</p>
<hr>
<p><em>End of memo. Comments and dissent welcome before the board meeting.</em></p>
</main>
<footer>
  <p><a href="/">← back to dashboard</a> · <a href="/tools.html">try the tools</a> · <a href="/hub.html">borrower info hub</a></p>
  <p style="margin-top:10px;color:#555">Memo prepared 2026-05-04 by SDCC analysis · 416 lines, ~36 KB</p>
</footer>
</body></html>