<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Portal Fone]]></title><description><![CDATA[Portal Fone]]></description><link>https://portalfone.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Wed, 04 Nov 2026 09:17:44 GMT</lastBuildDate><atom:link href="https://portalfone.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Validating CURP and RFC Entirely in the Browser: Structure, Check Digits, and Why No Server Is Needed]]></title><description><![CDATA[Mexico's CURP and RFC identifiers look like random strings, but both carry internal structure that can be checked without ever sending them to a server…]]></description><link>https://portalfone.hashnode.dev/validating-curp-and-rfc-entirely-in-the-browser-structure-check-digits-and-why-no-server-is-needed</link><guid isPermaLink="true">https://portalfone.hashnode.dev/validating-curp-and-rfc-entirely-in-the-browser-structure-check-digits-and-why-no-server-is-needed</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Validation]]></category><category><![CDATA[privacy]]></category><dc:creator><![CDATA[Portal Fone]]></dc:creator><pubDate>Mon, 26 Oct 2026 11:11:23 GMT</pubDate><content:encoded><![CDATA[<p>Mexico's CURP and RFC identifiers look like random strings, but both carry internal structure that can be checked without ever sending them to a server. That matters: teachers paste these identifiers into payroll portals, and a single mistyped character blocks access. A client-side check catches the typo before any login attempt — and, because nothing leaves the device, there is no identifier to leak, log, or breach.</p>
<h2>What the structure actually encodes</h2>
<p>A CURP is 18 characters: initials from name data, birth date, sex, state code, a disambiguator, and a final verifier digit. An RFC for a person is 13 characters (10 for a company) with a similar pattern plus a homoclave. The check is not "does this string look right" — it is a sequence of small, testable rules:</p>
<ol>
<li><strong>Length and character set.</strong> Each position allows only certain characters (letters vs digits). Rejecting early, with the exact position, beats a generic "invalid" message.</li>
<li><strong>Date plausibility.</strong> The embedded birth-date segment must be a real calendar date, not just six digits.</li>
<li><strong>State and category codes.</strong> The state segment must be one of the real two-letter codes; an invented code fails here even if the rest parses.</li>
<li><strong>Verifier digit.</strong> Both identifiers end in a check digit computed from the preceding characters. Recomputing it client-side catches transpositions that pass a regex — the most common real-world typo.</li>
</ol>
<h2>Why client-side, specifically</h2>
<p>A server-side validator would need to receive the identifier, which creates a data-handling obligation for a string that functions as a personal key. Doing the same arithmetic in JavaScript removes that obligation entirely: the page works offline once loaded, returns an answer instantly, and has nothing to store. The trade-off is honest too: structure validation proves format, not existence. A well-formed CURP is not proof that a person is registered — only the official registry can say that, and a good validator says so in plain language instead of implying otherwise.</p>
<h2>Testing without real identifiers</h2>
<p>Test cases must never use real people's identifiers. The safe set is: a synthetically constructed valid example, one mutation per rule (wrong length, wrong character class, impossible date, bad state code, wrong verifier digit), and boundary cases such as leap-day dates. Each mutation should fail exactly one rule, so a regression points at the rule that broke, not at "validation" in general.</p>
<p>We built this as a small, dependency-free page — the live validator is at <a href="https://portalfone.com.mx/validador-curp-rfc/">https://portalfone.com.mx/validador-curp-rfc/</a> — and the same discipline (one rule, one test, one clear error) is what we applied when turning the official pay calendar into a single canonical page: <a href="https://portalfone.com.mx/calendario-pagos-sep-2026/">https://portalfone.com.mx/calendario-pagos-sep-2026/</a></p>
<p><em>Disclosure: I am part of PortalFone, the independent guide linked above. PortalFone is not an official SEP website; the validator checks format only and does not query any government registry.</em></p>
]]></content:encoded></item></channel></rss>