<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>JavaScript &#8211; Software, Fitness, and Gaming &#8211; Jesse Warden</title>
	<atom:link href="https://jessewarden.com/category/javascript-2/feed" rel="self" type="application/rss+xml" />
	<link>https://jessewarden.com</link>
	<description>Software &#124; Fitness &#124; Gaming</description>
	<lastBuildDate>Wed, 21 Oct 2026 14:44:26 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://jessewarden.com/wp-content/uploads/2016/08/cropped-Lambda2-32x32.png</url>
	<title>JavaScript &#8211; Software, Fitness, and Gaming &#8211; Jesse Warden</title>
	<link>https://jessewarden.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Customizing TypeScript Compiler Errors</title>
		<link>https://jessewarden.com/2026/10/customizing-typescript-compiler-errors.html</link>
					<comments>https://jessewarden.com/2026/10/customizing-typescript-compiler-errors.html#respond</comments>
		
		<dc:creator><![CDATA[JesterXL]]></dc:creator>
		<pubDate>Wed, 21 Oct 2026 14:44:26 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://jessewarden.com/?p=7340</guid>

					<description><![CDATA[HOLY COW, GUZY, you can customize TypeScript compiler errors now! Well&#8230; you probably could before, but&#8230; not easily. This new TypeScript 7.1 API allows you to get info about what the compiler found, and translate it to &#8230; you know, English. Elm did that. Rust became popular, but people were like &#8220;this ain&#8217;t English, bruh&#8221; [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">HOLY COW, GUZY, you can customize TypeScript compiler errors now! Well&#8230; you probably could before, but&#8230; not easily. This new TypeScript 7.1 API allows you to get info about what the compiler found, and translate it to &#8230; you know, English.</p>



<span id="more-7340"></span>



<p class="wp-block-paragraph">Elm did that. Rust became popular, but people were like &#8220;this ain&#8217;t English, bruh&#8221; so then they copied Elm. Now, finally, tooling for TypeScript can copy Elm.</p>



<p class="wp-block-paragraph">k, but what&#8217;s a specific use case beyond &#8220;leveling up TypeScript&#8221; you may ask? Great question! For the past few months, I&#8217;ve been building tooling around improving cyber security for logs; e.g. ensuring we don&#8217;t leak sensitive customer or passwords into our logs.</p>



<p class="wp-block-paragraph">Most dynamic languages, AND typed languages, will use substring and regex searches in sinks; e.g. where your data leaves your application through a log (console.log, AWS Power Tools, pino, etc). This ensures &#8220;the 1 place it exits, we ensure no NPI/PCI leaks occur&#8221;. Rad.</p>



<p class="wp-block-paragraph">&#8230; but devs who are into types are like &#8220;wait a minute, wait a minute&#8230; &#8216;if it compiles, it works&#8217; if that&#8217;s true&#8230; then why can&#8217;t we &#8216;if it compiles, it&#8217;s safe&#8217;?&#8221; So they, and me, will leverage types to ensure:</p>



<ol class="wp-block-list">
<li>sensitive data is typed; could be a Brand, Product, Union&#8230; whatever</li>



<li>sinks (e.g. logs) do not allow sensitive data</li>
</ol>



<p class="wp-block-paragraph">You could do that via types, type proofs, both. So cool, we can now &#8220;If it compiles, it is safe&#8221;, BUT ALSO &#8220;because TypeScript gradually typed and not sound&#8221; still have the runtime redaction too.</p>



<p class="wp-block-paragraph">Except there is one problem: the compiler error messages are trash. Let&#8217;s see an example. Below, we&#8217;re creating an American Social Security Number (aka ssn) as a Sensitive data brand type. We&#8217;re then creating a log function that doesn&#8217;t allow it ssn&#8217;s to be logged.</p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="970" height="560" src="https://jessewarden.com/wp-content/uploads/2026/10/image1.png" alt="" class="wp-image-7341" srcset="https://jessewarden.com/wp-content/uploads/2026/10/image1.png 970w, https://jessewarden.com/wp-content/uploads/2026/10/image1-300x173.png 300w, https://jessewarden.com/wp-content/uploads/2026/10/image1-768x443.png 768w" sizes="(max-width: 970px) 100vw, 970px" /></figure>



<p class="wp-block-paragraph">So that&#8217;s cool; you can see in the image that ssn isn&#8217;t compiling when you pass it as a parameter to the log function.</p>



<p class="wp-block-paragraph">However, what&#8217;s NOT cool is the compiler error you get for it: &#8220;Type &#8216;Sensitive‹string, &#8220;Social Security Number&#8221;›&#8217; is not assignable to type &#8216;undefined&#8217;.&#8221;</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="147" src="https://jessewarden.com/wp-content/uploads/2026/10/image2-1024x147.png" alt="" class="wp-image-7342" srcset="https://jessewarden.com/wp-content/uploads/2026/10/image2-1024x147.png 1024w, https://jessewarden.com/wp-content/uploads/2026/10/image2-300x43.png 300w, https://jessewarden.com/wp-content/uploads/2026/10/image2-768x110.png 768w, https://jessewarden.com/wp-content/uploads/2026/10/image2-1536x221.png 1536w, https://jessewarden.com/wp-content/uploads/2026/10/image2.png 1864w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">So never is weird; it&#8217;s even weird in Elm. However, it&#8217;s used a lot more in TypeScript so you can assert a compiler error. Sometimes, as you can see, the error doesn&#8217;t even say never, it says undefined. That said, it still <em>sounds</em> weird when you say that compiler out loud. Usually from a Domain Driven Design perspective you&#8217;d be like &#8220;A can&#8217;t be B&#8221; or &#8220;a PendingAccount cannot be a ConfirmedAccount&#8221;. But&#8230; &#8220;Cow can&#8217;t be assigned to never/undefined&#8221; like&#8230; wat?</p>



<p class="wp-block-paragraph"><a href="https://devblogs.microsoft.com/typescript/announcing-typescript-7-1-beta/">ENTER TYPESCRIPT 7.1 COMPILER API</a> (e.g. import typescript/sync). You can get all the diagnostic errors, and if it&#8217;s one you recognize, like &#8220;Sensitive SSN to never&#8221; you can map it to &#8220;Social Security Numbers cannot be logged&#8221;</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="150" src="https://jessewarden.com/wp-content/uploads/2026/10/image3-1024x150.png" alt="" class="wp-image-7343" srcset="https://jessewarden.com/wp-content/uploads/2026/10/image3-1024x150.png 1024w, https://jessewarden.com/wp-content/uploads/2026/10/image3-300x44.png 300w, https://jessewarden.com/wp-content/uploads/2026/10/image3-768x112.png 768w, https://jessewarden.com/wp-content/uploads/2026/10/image3-1536x224.png 1536w, https://jessewarden.com/wp-content/uploads/2026/10/image3.png 1848w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">SO BALLER</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jessewarden.com/2026/10/customizing-typescript-compiler-errors.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Update on Quitting Coffee Again</title>
		<link>https://jessewarden.com/2026/10/update-on-quitting-coffee-again.html</link>
					<comments>https://jessewarden.com/2026/10/update-on-quitting-coffee-again.html#respond</comments>
		
		<dc:creator><![CDATA[JesterXL]]></dc:creator>
		<pubDate>Mon, 19 Oct 2026 09:56:58 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://jessewarden.com/?p=7338</guid>

					<description><![CDATA[Spent about a week going from too many cups a day (but cut off at 11-11:30am) to 2 cups only. Then about 2 weeks to 1 cup only. The 1 cup only had 1 positive, 1 familiar weird, and 1 ultra horrible consequence: Positive: While a bit tired from lack of sleep, I don&#8217;t have [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Spent about a week going from too many cups a day (but cut off at 11-11:30am) to 2 cups only. Then about 2 weeks to 1 cup only.</p>



<span id="more-7338"></span>



<p class="wp-block-paragraph">The 1 cup only had 1 positive, 1 familiar weird, and 1 ultra horrible consequence:</p>



<p class="wp-block-paragraph"><strong>Positive</strong>: While a bit tired from lack of sleep, I don&#8217;t have caffeine crashes in afternoon.</p>



<p class="wp-block-paragraph"><strong>Weird</strong>: dreams getting more intense again; not _as_ intense as no coffee, but I can tell.</p>



<p class="wp-block-paragraph"><strong>Horrible</strong>: I wake up, like clockwork, at 4:30 &#8211; 5am, every day. I know 6 hours isn&#8217;t enough. I&#8217;ve tested this on the weekend, and I can nap for up to 2 to 3 hours, so my body is angry or confused about something.</p>



<p class="wp-block-paragraph">I had depression for about 2 days; was NOT the horribleness that was 8 years ago, but it super in the background, and I didn&#8217;t notice it till I really thought about why I was feeling meh. I&#8217;m sure sleep deprivation aggravated it, but passed like last weekend.</p>



<p class="wp-block-paragraph">Despite intense workouts 6 days a week, I wake up early morning, usually from a stomach ache, but I can just tell my brain is WAY more ready to wake up compared to usual if I were to wake up in the middle of the night. Only once in the past 3 weeks of this happening could I fall back asleep till my normal 7am.</p>



<p class="wp-block-paragraph">I was attempting this to be my first day with no coffee, but I&#8217;m going to try another week of just a small cup. I was using those large cups, which I think are like actually &#8220;2 cups&#8221; (I&#8217;ll measure later), and we have this tea cup which is barely 1 cup so&#8230; it&#8217;s a pretty significant drop. I can tell my body knows what&#8217;s coming and is fighting to keep it around. So I&#8217;ll give it another week with these little cups, then try again Monday. Hopefully that fixes this weird, new sleep problem. I wasn&#8217;t supposed to go backwards, but I have empathy my brain chemistry is just confused from decades of caffeine abuse.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jessewarden.com/2026/10/update-on-quitting-coffee-again.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Tech Leads: Teach</title>
		<link>https://jessewarden.com/2026/10/tech-leads-teach.html</link>
					<comments>https://jessewarden.com/2026/10/tech-leads-teach.html#respond</comments>
		
		<dc:creator><![CDATA[JesterXL]]></dc:creator>
		<pubDate>Mon, 19 Oct 2026 09:48:04 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://jessewarden.com/?p=7331</guid>

					<description><![CDATA[Request to Tech Leads to teach Juniors the fundamentals now more than ever. I&#8217;ve seen a disturbing trend where Juniors and mid-level devs are using LLM&#8217;s to generate PR&#8217;s where they didn&#8217;t hand code any of it, and upon questioning, they don&#8217;t understand much of it. When I then explain things in the PR and/or [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Request to Tech Leads to teach Juniors the fundamentals now more than ever. I&#8217;ve seen a disturbing trend where Juniors and mid-level devs are using LLM&#8217;s to generate PR&#8217;s where they didn&#8217;t hand code any of it, and upon questioning, they don&#8217;t understand much of it. When I then explain things in the PR and/or in person, I realize they&#8217;re missing swaths of basics, and while exciting for me, it&#8217;s concerning they&#8217;ve gone this long without someone giving them the rundown of how this all works.</p>



<span id="more-7331"></span>



<p class="wp-block-paragraph">This results in months of building software, but not learning much about building software. This also results in TONS of PR changes requested, and PR&#8217;s, even with an AI to help review the PR&#8217;s, now go from weeks to months to get merged.</p>



<p class="wp-block-paragraph">You can see this reflected in this chart from <a href="https://arstechnica.com/ai/2026/10/ai-coding-agents-generate-more-code-but-not-more-software/">the ArsTechnica article</a> where with AI the number of PR&#8217;s goes up, and so too does the number of requested changes. Correlation does not equal causation, no doubt, but I&#8217;ve seen it myself, so it resonates and seems a legit finding.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="687" src="https://jessewarden.com/wp-content/uploads/2026/10/aiagentcode-1024x687.png" alt="" class="wp-image-7332" srcset="https://jessewarden.com/wp-content/uploads/2026/10/aiagentcode-1024x687.png 1024w, https://jessewarden.com/wp-content/uploads/2026/10/aiagentcode-300x201.png 300w, https://jessewarden.com/wp-content/uploads/2026/10/aiagentcode-768x516.png 768w, https://jessewarden.com/wp-content/uploads/2026/10/aiagentcode.png 1384w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">I have a feeling they&#8217;re also doing multiple of these large batch, slop grenades at once because they&#8217;re waiting on reviews from exhausted Tech Leads / co-workers to review (haven&#8217;t checked out their Github profile to conform, tho). The co-workers/Tech Leads are exhausted because:</p>



<ol class="wp-block-list">
<li>there are more PR&#8217;s</li>



<li>the PR&#8217;s are larger batch</li>



<li>the code _looks_ ok at first, but you realize it&#8217;s missing fundamental architecture/types/testing good practices, so you have to be on your A game when reviewing.</li>



<li>This repeated high-intensity of review tires you out.</li>



<li>When done, there are twice as many PR&#8217;s like this to go.</li>
</ol>



<p class="wp-block-paragraph">Lose-lose for both sides here. Some devs will just tap out, exhausted and &#8220;LGTM&#8221;. That doesn&#8217;t help anybody.</p>



<p class="wp-block-paragraph"><a href="https://en.wikipedia.org/wiki/Automation_bias">Automation Bias</a> is a thing; people who don&#8217;t know a subject well think AI can automate it. In this case Juniors are using a lot of tokens to produce little, usable code.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="575" src="https://jessewarden.com/wp-content/uploads/2026/10/token-usage-1024x575.png" alt="" class="wp-image-7333" srcset="https://jessewarden.com/wp-content/uploads/2026/10/token-usage-1024x575.png 1024w, https://jessewarden.com/wp-content/uploads/2026/10/token-usage-300x168.png 300w, https://jessewarden.com/wp-content/uploads/2026/10/token-usage-768x431.png 768w, https://jessewarden.com/wp-content/uploads/2026/10/token-usage-1536x863.png 1536w, https://jessewarden.com/wp-content/uploads/2026/10/token-usage-2048x1150.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">Microsoft&#8217;s Justin Reock, in Developer Experience <a href="https://youtube.com/watch?v=Se8jHLliLXE">shared their latest data</a> showing that Juniors use more tokens than Seniors to get the same result. Pre-AI, the data showed the code Seniors wrote tended to last longer whereas code Juniors wrote was changed a lot. That same rule holds now, but the changes have skyrocketed because it&#8217;s much easier &amp; faster for them to generate code they don&#8217;t understand.</p>



<p class="wp-block-paragraph">I know many of us feel like the Phoenix from the original X-Men movie when she&#8217;s holding back the lakes worth of water WHILE lifting a jet.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="426" src="https://jessewarden.com/wp-content/uploads/2026/10/Screenshot-2026-10-19-at-5.47.17-AM-1024x426.png" alt="" class="wp-image-7334" srcset="https://jessewarden.com/wp-content/uploads/2026/10/Screenshot-2026-10-19-at-5.47.17-AM-1024x426.png 1024w, https://jessewarden.com/wp-content/uploads/2026/10/Screenshot-2026-10-19-at-5.47.17-AM-300x125.png 300w, https://jessewarden.com/wp-content/uploads/2026/10/Screenshot-2026-10-19-at-5.47.17-AM-768x319.png 768w, https://jessewarden.com/wp-content/uploads/2026/10/Screenshot-2026-10-19-at-5.47.17-AM-1536x639.png 1536w, https://jessewarden.com/wp-content/uploads/2026/10/Screenshot-2026-10-19-at-5.47.17-AM.png 1972w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">You&#8217;re trying to help people WHILE not dying yourself. It&#8217;s rough. Just know, currently, these AI&#8217;s aren&#8217;t learning and are making some things worse. However, your efforts on _people_ are worth it; they learn, the slop gets less, and after a couple of months, they can help you. Keep going.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jessewarden.com/2026/10/tech-leads-teach.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Two Cases On Why We Should Read The Code</title>
		<link>https://jessewarden.com/2026/09/two-cases-on-why-we-should-read-the-code.html</link>
					<comments>https://jessewarden.com/2026/09/two-cases-on-why-we-should-read-the-code.html#respond</comments>
		
		<dc:creator><![CDATA[JesterXL]]></dc:creator>
		<pubDate>Wed, 30 Sep 2026 14:24:48 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://jessewarden.com/?p=7326</guid>

					<description><![CDATA[Two cases to read the code. I know everything is nuanced, skills vary, and the scope of what we&#8217;re building varies. I&#8217;m aware even Kent Beck recently said &#8220;TRY to automate not reviewing the code&#8221;. This is just 2 examples where reading the code is required, even today, with multiple + wonderful LLM support tooling. [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Two cases to read the code. I know everything is nuanced, skills vary, and the scope of what we&#8217;re building varies. I&#8217;m aware even Kent Beck recently said &#8220;TRY to automate not reviewing the code&#8221;. This is just 2 examples where reading the code is required, even today, with multiple + wonderful LLM support tooling.</p>



<span id="more-7326"></span>



<p class="wp-block-paragraph">I&#8217;m reviewing a mid-level dev&#8217;s PR who&#8217;s not on our team. First concern is its on our most important repo with high consequence of failure. The work could be piloted on a less risky repo, but she chose this one. She may not be aware of that context. Nowhere in the docs does it state that for the LLM&#8217;s to know, more is there a &#8220;map between repos&#8221; for our team for the LLM to have context. Should we build that? Yes. Do we have that now for the LLM? No. Does the dev know this? No. So I explain all that. She had no idea. She questioned the entire approach. This is the good part of iterative development; failing quickly; reducing the time it takes to learn. This is normal and good.</p>



<p class="wp-block-paragraph">Second concern is it&#8217;s quite large. Not just many files, but many new files, some are quite long. I explain even without Github Stacks, we should be doing small PR&#8217;s with few changes and architected for a smaller blast radius. She appreciated the review; apparently getting PR reviews, from a human, are rare in some teams. :: face palm :: She had never heard of Github stacks or even just branching off of a branch; I explained the easier version if she wanted to avoid the github complexity rabbit hole that is gh stacks. Newer LLM&#8217;s have some of this in their training data, but unless you specify it, I&#8217;ve not seen them recommend it unless the repo has rules.</p>



<p class="wp-block-paragraph">Third, approaching the work this was new for her. I don&#8217;t know what team experiences she had, nor where they are in in their CD journey, but I explained we don&#8217;t really plan that out. The whole point is to take small steps, learn, and use those learnings to inform where we should go next. So I don&#8217;t really plan or even know what the next PR&#8217;s will be, their size, nor the files. That said, I looked at her original PR and gleaned 3 smaller PR&#8217;s with only a few changes each that might form a great exercise to learn how to work in small steps since she had already trod this path once AND it&#8217;d be easier for me to have a more focus discussion on architecture since the changes are small. The LLM&#8217;s can help here if you know how to ask; I don&#8217;t think she even know you could ask such a thing yet.</p>



<p class="wp-block-paragraph">Fourth, there were various architecture challenges, many of which she&#8217;d have no context unless she was on our team. Much of the code base was OOP, little dependency injection, heavy use of mocks, little types, and a consistent use of exceptions to drive responses. I&#8217;m attempting to move the team towards a more functional, typed, and errors as values approach. LLM&#8217;s _really_ struggle with navigating this as each integration has a flurry of options, and unless you narrow each one, it&#8217;ll just best guess. This is compounded in Brownfield code bases. This takes 110% of my focus just to help navigate this large space frigate through an asteroid field while drinking my coffee using sketchy inertial dampeners. There&#8217;s no way a Junior or Mid-level could both navigate this, know all the options, nor the vision not being on our team. I suggested we pair program on this so I could show how this vision has challenge, and what to do when you&#8217;re presented with a crossroads of architecture decisions to lead by example.</p>



<p class="wp-block-paragraph">Fifth, one architecture one that was prevalent was a lack of DRY around a new framework they are using. It also uses exceptions, but checks the 5 types via instanceof; kind of like their own version of Promise.then/catch. The issue is all the parsing code is on the developer; since they didn&#8217;t use error types, you get error:unknown, and about 20+ lines of type narrowing code ensues in at least 4 call sites. At first I&#8217;m like &#8220;use types&#8221; to prevent all this. Then I was like &#8220;well, geez&#8230; ok, now you need a Zod schema to at least parse to one of the error shapes you&#8217;re expecting&#8221;. Then I was like &#8220;wait a minute, you&#8217;re doing this all over the place, why isn&#8217;t the framework handling this all for you via abstractions and types?&#8221;. Errors as types, types as values, Zod schemas parsing to known shapes, and leaky abstractions are all new concepts to her, and when you throw all of these at once, it&#8217;s quite overwhelming. We had a good brief discussion on perhaps making some new PR&#8217;s to the framework itself to help here since many others are going to run into the same implementation challenge. The framework has 200% docs, rules, and skills setup for LLM&#8217;s to be mostly Spec Driven Development style, but none of that was linked here in our repo, in her rules, or in however this was coded, LLM or not, I suppose. Again, the LLM is having to integrate this framework which has a different style into our repo which has 2 styles, with very little guidance on what to do at crossroads, so you need human in the loop guidance here.</p>



<p class="wp-block-paragraph">Sixth, the shotgun parsing and lack of an anti-corruption layer was heavy, which in turn caused a lot of shotgun parsing because the maybe&#8217;s/optional&#8217;s were everywhere. In Brownfield, that&#8217;s fine, you just slowly add the parsing higher up, leaving it in a better place than you found it. But in the Greenfield code we&#8217;re adding, you have an opportunity to do things better, while still interfacing with the old in clear boundaries. So I explained Parse, Don&#8217;t Validate, Shotgun Parsing, and how you &#8220;design for the types you want, not what you&#8217;re given by some back-end&#8221; and how Zod can handle all this in colocated code. Again, it&#8217;s a lot throw at someone who&#8217;s never heard of all this a cohesive concept. LLM&#8217;s, even Opus 3.5, has all this in its training data. It may not be aware of Zod Codecs or the encoding angle, but even ghetto-fabulous SWE 1.6 can pick that up quickly if you give it a golden example. You have to be clear, though, about all of those rules, AND how to integrate them, (e.g. use Zod .transform/.pipe to map from downstream Data Transfer Objects, aka DTO&#8217;s ,to our domain Value Objects aka VO&#8217;s, so nice types come out).</p>



<p class="wp-block-paragraph">Seventh, the LLM she was using read our code and started throwing custom class exceptions. The miss was we have a mapping layer at the top to ensure the responses match what we tell the user, so both the exception has to be shaped a certain way, the tests have to check for specific id&#8217;s, AND placement has to be thought out because since there are no types, the tests have to be aware of what level this is thrown from to test it. I explained we&#8217;re moving away from this approach to Railway programming using Neverthrow to have typed errors. I still can&#8217;t tell if this landed, but I know LLM&#8217;s can help you a ton here; I still use LLM&#8217;s to help debug Promise/ResultAsync chains when the return type isn&#8217;t requite right; they have an uncanny ability to fix it, even if you use the wrong explicit return type. Errors as Values is a huge mind shift for those used to imperative coding, especially those not from Go or Rust or FP languages. Especially tricky is the boundaries we have to map back to exceptions so our harness to &#8220;read all the errors and translate to the correct user response&#8221;. Easy with a .map, hard if you&#8217;re like &#8220;why do I need a .map?&#8221; LLM&#8217;s can grok that part easily, what&#8217;s hard for them is identifying the correct boundary. I don&#8217;t know all the boundaries, nor does she; we&#8217;d have to explore together to figure them out.</p>



<p class="wp-block-paragraph">Eighth, and this is extremely common among TypeScript devs not from an FP background, the types are more for spelling, not for doing any type of Type Driven Development, or &#8220;if it compiles, it works&#8221; philosophy. So I had to give multiple ideas for certain sections on what could be done to offload to the type system instead of numerous tests, mocks or not. Some situations were impossible, and I had to give a couple of examples to show how you can model it so those impossible situations don&#8217;t occur anymore. There were a few switch statements that had default in them, and I had to explain how exhaustiveness checking in TypeScript works, and how the LLM&#8217;s will tell you to use never, but ignore them, and how some of that wasn&#8217;t her fault because the data they were using was draw DTO&#8217;s with optionals and nulls, and some approaches on how to possibly refactor and fix that. The LLM&#8217;s are extremely aware of how to type well, and they can easily bounce between OCAML pragmatism eschewing currying, to full Scala (feels like Java) where you don&#8217;t need tests &#8220;because we typed the universe&#8221;. You have to know those styles, AND the verbosity that TypeScript entails, AND figure out where your team falls in that extremely long spectrum, AND what to type now vs later given TypeScript is gradually typed. All of that, and if you&#8217;re learning this? Oh man, it&#8217;s harder in TypeScript because it&#8217;s so verbose compared to other languages, so the LLM (or me) has to know the level you&#8217;re at to teach it. Whew!</p>



<p class="wp-block-paragraph">Had I not reviewed the code:</p>



<p class="wp-block-paragraph">&#8211; the blast radius was high for this PR, with no easy ability to identify what would have caused it given so many changes</p>



<p class="wp-block-paragraph">&#8211; condoning this behavior, human or LLM, sets a precedent that&#8217;s ok to make large PR&#8217;s. It&#8217;s not ok, and I will not condone it.</p>



<p class="wp-block-paragraph">&#8211; would have missed so many wonderful opportunities to teach; I even got a message saying &#8220;Thanks for the review, those are rare nowadays&#8221; which about made my heart sink; happy she appreciated the attention, but this should be the norm to teach, not to be a meat proxy and just &#8220;have the LLM approve it&#8221;</p>



<p class="wp-block-paragraph">&#8211; she now knows of all of this to better drive the LLM; before she wouldn&#8217;t even think to ask, and the code style + lack of rules-in-repo ensured the LLM would never volunteer alternatives</p>



<p class="wp-block-paragraph">I got to help teach, she got setup for success, we both learned how to better drive the LLM&#8217;s. THIS is why I read the code.</p>



<p class="wp-block-paragraph">2nd case is a lot simpler. Junior has a small PR to move a service to a new one with a feature flag. This new service is GraphQL, not REST, but the idea is the data will come back and map to our same domain objects. The issue, however, is despite using Zod in the new code, he&#8217;s still got Shotgun Parsing going on. If Zod safeParse works, he returns void, and continues on vs. using that safe-to-use domain data. There&#8217;s a fundamental understanding of how data validation should work, how TypeScript type narrowing works, and an LLM misunderstanding of how our code base wants you to do things given it&#8217;s brownfield and is lacking repo rules.</p>



<p class="wp-block-paragraph">Again, I get to level him up, and we both learned how we could better articulate to the LLM how to do things, both in prompts and rules, and adding yet another golden data set to give to LLM&#8217;s for the future. THAT again, is why I have to read the code.</p>



<p class="wp-block-paragraph">Yes, LLM&#8217;s are helping me. I&#8217;ve got Claude and Codex running my 3 Domain Driven Design, Unit Test, and Architecture review skills as well as SWE 1.6 in Windsurf. We have an Enterprise LLM code review that I&#8217;ve contributed to as well when I saw a core review was a bit off. So all hands are a deck for this, and helping. None of them, though, know the purpose, or does the Mid-level dev nor Junior know some of these fundamentals in architecture to ASK the LLM&#8217;s for help. Together, we all get smarter, and help the LLM&#8217;s help us more.</p>



<p class="wp-block-paragraph">Yes, there are cases where I&#8217;m not reading the code; libraries that we use, integration points that never change, infra configurations that a multitudes of red tape and cyber checks to ensure they work and are safe. However, I&#8217;m erring on the side of read all of it because I&#8217;m consistently seeing code and architecture I wouldn&#8217;t want to be on call for in production, there are so many wonderful opportunities to teach and learn myself, misunderstandings from both Dev&#8217;s and LLM&#8217;s, and all of these help me refine the LLM&#8217;s to help me, and hopefully others self-teach, in this regard.</p>



<p class="wp-block-paragraph">Finally, the most important part, is to learn. Are these requirements correct? Does this architecture allow future change more easily? Is this safe, or will we get dinged by cyber? I could go on and on; so far, the LLM&#8217;s aren&#8217;t catching all of these things, or are confused on when to apply my rules correct to all situations.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jessewarden.com/2026/09/two-cases-on-why-we-should-read-the-code.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Headfirst into PCI/NPI Redaction</title>
		<link>https://jessewarden.com/2026/08/headfirst-into-pci-npi-redaction.html</link>
					<comments>https://jessewarden.com/2026/08/headfirst-into-pci-npi-redaction.html#respond</comments>
		
		<dc:creator><![CDATA[JesterXL]]></dc:creator>
		<pubDate>Sat, 29 Aug 2026 13:03:58 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://jessewarden.com/?p=7311</guid>

					<description><![CDATA[tl;dr; How can prevent personal data from getting into logs and enable this for development teams without any work beyond npm update? Spending the last 3 weeks side-of-desk looking into redaction, specifically around PCI/NPI (Payment Card Industry / Non Public Information) data (bank account, personal user data, etc) in logs. You break various laws when [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">tl;dr; How can prevent personal data from getting into logs and enable this for development teams without any work beyond <code>npm update</code>?</p>



<p class="wp-block-paragraph">Spending the last 3 weeks side-of-desk looking into redaction, specifically around PCI/NPI (Payment Card Industry / Non Public Information) data (bank account, personal user data, etc) in logs. You break various laws when this happens, and it&#8217;s not a fun thing to clean it up.</p>



<span id="more-7311"></span>



<p class="wp-block-paragraph">This in turn taught me that logs aren&#8217;t the only sinks, e.g. exits of data out of your app that could have PCI/NPI data in them. Streaming data (e.g. Kinesis, Kafka, etc). HOW you get that data is also interesting. Sometimes you parse stuff through JSON.parse from a downstream, but get things you didn&#8217;t mean to. Sometimes a REST call comes in, and things you didn&#8217;t intend to keep around were from the headers. Some of this data can go into the sinks that you didn&#8217;t intentionally mean to log/stream.</p>



<p class="wp-block-paragraph">I looked at how most are solving it. The dynamic language, or &#8220;lol, wat are types&#8221; crews are basically attacking with various Regular Expressions, and string parsing. Any string you log, they either abstract things atop OOP loggers, or write single points of exit sinks like in Pino/Tap. At these points, they&#8217;ll combine multiple RegExp&#8217;s together into a mass string replacer. I&#8217;ve even see a strong arm approach of JSON.stringify&#8217;ing an Object, then redacting the big string that comes out.</p>



<p class="wp-block-paragraph">Some will mark that they redacted something. Some will mark what they redacted. Some will just say &#8220;[REDACTED]&#8221; and you don&#8217;t know if it was a bank account number (BAN), an email, or a number you wrote that was a false positive.</p>



<p class="wp-block-paragraph">The types crew will use&#8230; types. They&#8217;ll either create Branded or Variant/Sum/Union types to designate something as a secret, and ensure logging, streaming, and metrics functions cannot take those types. Some will use type proofs in functions or methods to ensure even nested type records do not contain secrets; ensuring &#8220;if it compiles, it doesn&#8217;t leak PCI data&#8221;.</p>



<p class="wp-block-paragraph">Some, particularly in the TypeScript, Python (gradually typed community) will use both. This is because the type system can, and will often, lie because developers consuming the library can hack their way around it using the 20 billion escape hatches &amp; levers these type systems give you.</p>



<p class="wp-block-paragraph">The amount of Regular Expression and string matchers is vast. I remember back in the video sharing with chat days, there were many string matchers to filter out bad words from chat, and many also included XSS helpers. This ensures that people who find they can&#8217;t type &#8220;badword&#8221; will type &#8220;b a d w o r d&#8221; and find that using spaces like that defeats the string matcher for bad words, so they can type other bad words, or even bad code snippets using spaces. The devs will counter with more aggressive string matchers and regular expressions, and they seem to err on the side of &#8220;false positives are fine because the cost of failure is quite bad&#8221;. While the chat will filter out random words you don&#8217;t think are bad, it gives business piece of mind from legal ramifications of NOT doing it. The User Experience costs here are interesting, both to users and to devs.</p>



<p class="wp-block-paragraph">I&#8217;m finding my in own work, for our existing logger, I&#8217;m having to use that dual approach of &#8220;use types to prevent this from happening&#8221;, but also using a combination of regular expressions when the narrowness of type system breaks down. I&#8217;m also thinking of starting from scratch on a secondary implementation once the first is done that type narrow specifically to ensure we don&#8217;t even need the runtime checks (well, it&#8217;s TypeScript, almost anything can be defeated with an <code>as unknown</code> so I&#8217;ll have to run various tests). But it&#8217;s clear the hybrid approach causes the API to suffer because you&#8217;re constraining what the dev can log, but also have to do a ton of type work to compensate for when they (unknowingly) lie to you.</p>



<p class="wp-block-paragraph">I really like the clean, typed approach as it lessens the attack surface, and I share a lot of this with the streaming and metrics use cases as well as those are less open to the developer so easier to constrain what gets in. It also helps when we attack the problem at the source, and immediately decode into secrets vs. &#8220;I don&#8217;t know man&#8230; they could be anywhere, let&#8217;s just JSON.stringify all the things and run a ball of RegExp on it&#8221;. Having schema libraries like Zod decode immediately to know secrets enables such a better security posture.</p>



<p class="wp-block-paragraph">Before: &#8220;Where are your secrets?&#8221; &#8220;Uh, in this codebase&#8230; I think from a downstream REST call. You&#8217;ll have to go track down their Swagger, it may/may not point them out&#8221;</p>



<p class="wp-block-paragraph">After: &#8220;Find all instances of the Secret class.&#8221;</p>



<p class="wp-block-paragraph">I&#8217;ve found that some secrets aren&#8217;t even secrets. Devs will put credit card number in a secret container, and when you look inside, it&#8217;s actually a null. Having a schema validate it&#8217;s even an actual secret prevents a lot of this from even being a problem.</p>



<p class="wp-block-paragraph">There&#8217;s also some tricky situations that reminds me of the 1989 Batman movie Joker plot. You&#8217;ll have a user&#8217;s last name and the last four digits of their credit card. Both aren&#8217;t necessarily PCI on their own&#8230; but together? Yes. Same with the chemicals Joker was pushing in the movie; isolated they were innocuous, but together, poison. There are various Intersection and Union types you can create to prevent these combinations so you can relax when it compiles.</p>



<p class="wp-block-paragraph">It&#8217;s been interesting to tackle this problem from a Brownfield approach. &#8220;How do we prevent PCI data leakage?&#8221;</p>



<p class="wp-block-paragraph">I think I&#8217;ve settled on improving the logger we have better runtime redaction, with some compile time preventative measures to help move in the right direction over time. A separate, ideal logger for where we&#8217;d like to go. This includes helpers to verify we even have secrets in the first place, and if we do, we use a Parse, Don&#8217;t Validate + Anti-Corruption Layer in the same place via a Zod transform.</p>



<p class="wp-block-paragraph">Brownfield: npm/pip update, you&#8217;ll be safer.</p>



<p class="wp-block-paragraph">Brownfield + migrate: move to this logger, you can offload the problem to the compiler, but log sinks/targets/streaming outputs remain the same.</p>



<p class="wp-block-paragraph">Greenfield: same</p>



<p class="wp-block-paragraph">Auditing: With schema parsing, we can confidently know what secrets we have, where, and what combinations we&#8217;ve forbidden.</p>



<p class="wp-block-paragraph">The escape hatches have been interesting too. Getting at your source logger, whether that&#8217;s AWS Power Tools, or Pino, or Winston or whatever is often needed to configure it, but if it&#8217;s done in more than 1 place, you should get nervous. So we have to provide the ability to do that, but also mark that we&#8217;ve done that. I can solve this with a Linter.</p>



<p class="wp-block-paragraph">For the secrets, you need to provide access to them to do business logic, but sometimes you may have to do that in multiple places unlike log/metric/streaming configurations. I &#8230; don&#8217;t know how to solve this beyond having an LLM track the Branded type that comes out and doing it&#8217;s own audit.</p>



<p class="wp-block-paragraph">Hard problems, lots of ways to approach it. While I&#8217;m having fun, I keep reminding myself why I&#8217;m doing this:</p>



<ol class="wp-block-list">
<li>ensure we&#8217;re following the law</li>



<li>we won&#8217;t have any surprise security work to do</li>



<li>make this easy on developers now in Brownfield, and a &#8220;pit of success&#8221; for those in Greenfield</li>
</ol>



<p class="wp-block-paragraph">Still more to learn, but what a rabbit hole, man.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jessewarden.com/2026/08/headfirst-into-pci-npi-redaction.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
