My 31 CFR 515 monitor updated smoothly, and I added a second one for the Sept. 30-born 31 CFR 516

avatar
(Edited)

A live test, at last. There is no better trial for the tools I have built over the past months than a real change in the regulations I follow as a researcher of U.S. policy toward Cuba.

This week OFAC made substantive amendments to the Cuban Assets Control Regulations (CACR), the rules in force since 1963 through which it administers the core of the comprehensive sanctions on the island (Federal Register, Sept. 30, 2026). I wanted to confirm that my update mechanism could handle that change, and it did. The monitoring service, a Node server, noticed that the Federal Register had published the amendments before eCFR reflected them, and it kept that gap visible in the interface. Then eCFR activated the changes at around 6:30 pm on October 1. The server downloaded the modified sections from the eCFR API on its own, cached them, and added them to my local archive.

The part that made it interesting: a new Part

The same day, OFAC created the Cuba Sanctions Regulations (CSR), now codified at 31 CFR Part 516 (Federal Register notice). They implement Executive Order 14404, which OFAC reproduces as an appendix to the new part. The regulations are published in abbreviated form, are separate from Part 515, and OFAC says it intends to supplement them later.

This is a different problem from amending a section. On September 30, Part 516 did not exist in eCFR, and it will not appear in an annual CFR edition until next year. I could not simply reuse my Part 515 logic of calling the eCFR API, because there was nothing to call yet. So the tracker needed two phases behind one interface.

Phase 1: read the Federal Register. The server downloads the official XML of the publication (91 FR 61748, document 2026-19977) and converts every section into the same DIV8 structure that eCFR uses. The frontend parses it exactly as it parses an eCFR section, so the page does not know the difference. One detail cost me some attention: in the XML, Appendix A (the Executive Order) sits inside the last section element, § 516.513. If you do not cut it out, the order shows up as part of that section.

// The appendix header arrives inside the last SECTION (§ 516.513):
// everything after it belongs to the appendix, not to the section.
const cut = kids.findIndex(k => k.type === 'tag' && k.name.toUpperCase() === 'HD'
    && /^Appendix\b/i.test(tidyText($(k).text())));
const secNodes = cut >= 0 ? kids.slice(0, cut) : kids;

Phase 2: hand over to eCFR. While the server is in Phase 1, it asks the eCFR versions API every 30 minutes whether Part 516 has any sections. If the answer is empty, it keeps serving the Federal Register copy. When sections appear, it downloads the whole part in a single call, replaces the Federal Register snapshots with eCFR's, rebuilds the index, and switches its source flag. After that, it checks every four hours for later amendments. The original XML stays on disk as an untouched record of the publication.

const resp = await axios.get(
    `${ECFR_API_BASE}/versions/title-31.json?subtitle=B&chapter=V&part=${PART}`,
    { ...FR_UA_HEADERS, timeout: 30000, validateStatus: s => s < 500 });
cv = (resp.status === 200 && resp.data && Array.isArray(resp.data.content_versions))
    ? resp.data.content_versions : [];
// ... keep only entries whose part is '516' ...
if (ids.length === 0) {
    state.ecfr.hasPart = false;
    saveState();
    return false;   // not in eCFR yet: keep serving the Federal Register copy
}
// ... otherwise download the full part at its latest version date
// and set state.source = 'ecfr'
const ms = state.source === 'ecfr' ? SETTLED_CHECK_MS : PENDING_CHECK_MS; // 4 h : 30 min

The page follows the server. A small polling loop compares a key made of the current source, the version hash, and the number of pending documents. When the key changes, the open view reloads itself, index and section included, so I do not have to refresh anything.

const key = `${st.source}|${st.versionKey || ''}|${(st.pendingDocs || []).length}`;
const changed = _status516Key !== null && key !== _status516Key;

The interface now has one tab for Part 515 and one for Part 516. The 516 tab shows where the text currently comes from (Federal Register or eCFR), links to the official PDF, and lists any later Federal Register documents that eCFR has not consolidated yet. When eCFR took over, the source label changed with it.

How I built it

I used Claude to generate most of the code. Before the first real run, we tested the server module against simulated eCFR responses in both phases, and we ran the page in a headless DOM. Those tests caught three small bugs: the "latest changes" box ignored Part 516 when the Federal Register search API had not indexed the document yet; the page did not retry while the server was still loading the part; and the list of pending documents included the original rule itself when no baseline existed. All three were fixed before I ran it against the real services. When the changes went live in eCFR, the Part 515 update and the Part 516 handover both behaved as designed.

Following a Claude, ChatGPT, Claude sequence, I also put together another tool. It queries the Specially Designated Nationals search API and lists the individuals and entities sanctioned under Executive Order 14404, the order that the CSR implements.

What comes next

The next step is to connect the 515/516 view with that SDN list. I also want to link it with the tracker I presented here on Hive about imports from independent Cuban entrepreneurs under 31 CFR 515.582, the OFAC authorization that works together with the State Department's list of eligible goods. On the export side, the same project covers the license exceptions that the Commerce Department's Bureau of Industry and Security enables for items going to Cuba. I will write about it in upcoming posts.



562
0
0.000
0 comments