<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: bhagatashisha</title>
    <description>The latest articles on DEV Community by bhagatashisha (@bhagatashisha).</description>
    <link>https://dev.to/bhagatashisha</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4057721%2F3f88c8f6-072a-421a-9129-5ed31a49d912.png</url>
      <title>DEV Community: bhagatashisha</title>
      <link>https://dev.to/bhagatashisha</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bhagatashisha"/>
    <language>en</language>
    <item>
      <title>Sole developer on a national SSO platform for six months, with Claude writing most of the code</title>
      <dc:creator>bhagatashisha</dc:creator>
      <pubDate>Sat, 01 Aug 2026 09:02:59 +0000</pubDate>
      <link>https://dev.to/bhagatashisha/sole-developer-on-a-national-sso-platform-for-six-months-with-claude-writing-most-of-the-code-5bg9</link>
      <guid>https://dev.to/bhagatashisha/sole-developer-on-a-national-sso-platform-for-six-months-with-claude-writing-most-of-the-code-5bg9</guid>
      <description>&lt;p&gt;Solution architect, 17 years in. From roughly March 2026 to July 2026 I was the only hands-on developer on the identity and single-sign-on layer for a Gulf country's national port community system — the platform that fronts its ports and logistics sector. It's live in production.&lt;/p&gt;

&lt;p&gt;I want to be precise about "sole," because it matters: other people committed to both repos — CI, automation tests, a few fixes, downstream integration work. I authored ~80% of backend commits and ~70% of frontend. Nobody else did hands-on feature development on the core system. That's the honest version.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Volume, straight from &lt;code&gt;git log --numstat&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;602 commits, ~184,000 lines changed across 1,423 files&lt;/li&gt;
&lt;li&gt;Backend: 383 Java files / ~21k LOC, 19 controllers, 83 REST endpoints&lt;/li&gt;
&lt;li&gt;Frontend: 152 TS/HTML files / ~15.3k LOC, 62 Angular components&lt;/li&gt;
&lt;li&gt;6 external integrations, each with a real &lt;em&gt;and&lt;/em&gt; a mock adapter&lt;/li&gt;
&lt;li&gt;4 environments, 2 independent penetration tests remediated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My own written estimate to leadership in April, before any of this was contentious: 3–4 engineers over 3 months without AI tooling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;Hexagonal (ports and adapters) + CQRS. The domain package has &lt;strong&gt;zero Spring or JPA imports&lt;/strong&gt; — greppable, returns nothing. That's the actual test of whether hexagonal is a design decision or a buzzword, and most codebases claiming it fail that check.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;domain/         Pure domain — models, value objects, events, ports. No framework imports.
application/    Use cases — Commands (writes) and Queries (reads), DTOs, assemblers.
dataprovider/   Adapters — JPA entities, Spring Data repos, SOAP clients.
web/            Inbound adapter — controllers, DTOs, mappers, JWT filter, SAML handler.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every feature is a paired &lt;code&gt;XxxCommand&lt;/code&gt;/&lt;code&gt;XxxCommandImpl&lt;/code&gt; (transactional writes) and &lt;code&gt;XxxQuery&lt;/code&gt;/&lt;code&gt;XxxQueryImpl&lt;/code&gt; (read-only). Every external dependency sits behind a port with a real and a mock adapter selected by Spring profile — which meant QA and UAT ran full end-to-end flows without depending on government systems being up. They frequently weren't.&lt;/p&gt;

&lt;p&gt;One JPA detail worth stealing: &lt;code&gt;@Version&lt;/code&gt; optimistic locking with a &lt;strong&gt;find-then-update&lt;/strong&gt; save pattern, specifically to dodge Spring Data's null-version-means-new-entity behaviour producing duplicate-key errors. Easy to get wrong, painful to debug.&lt;/p&gt;

&lt;p&gt;User lifecycle is a real state machine (&lt;code&gt;PENDING_VERIFICATION → ACTIVE → LOCKED/INACTIVE&lt;/code&gt;) using the State pattern, so invalid transitions fail at the domain layer rather than being guarded by scattered &lt;code&gt;if&lt;/code&gt; statements in the UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  The four problems worth reading
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Java's X.509 parser rejected the government certificate
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;AVA not a sequence&lt;/code&gt; — a malformed but entirely common real-world encoding that the JDK's strict parser refuses outright. I wrote a manual metadata parser on BouncyCastle's X.509 factory instead.&lt;/p&gt;

&lt;p&gt;Then the ministry rotated their signing certificate in production and it went down anyway. So I made the certificate hot-reloadable with on-failure refresh. It rotated &lt;em&gt;again&lt;/em&gt; twenty days later — that time the system self-healed instead of paging anyone.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Intermittent 500s that everyone blamed on the network
&lt;/h3&gt;

&lt;p&gt;Tester in India, servers in Oman, so "it's latency" was the immediate consensus.&lt;/p&gt;

&lt;p&gt;I checked instead. The configured timeout was 60 seconds. Real India–Oman round-trip latency is 100–250ms — roughly 240× shorter. Even severe degradation can't produce a 60-second delay. And a 500 or 503 is generated &lt;em&gt;by the server&lt;/em&gt;, after it has already accepted the connection, so by definition it isn't a network-path problem.&lt;/p&gt;

&lt;p&gt;The government APIs were simply unstable. That conclusion justified retry-with-backoff instead of weeks chasing a phantom network issue.&lt;/p&gt;

&lt;p&gt;Buried in the same integration: their production API returns &lt;code&gt;"WORKING"&lt;/code&gt; for an active work permit, not &lt;code&gt;"Active"&lt;/code&gt;. One string mismatch silently blocked &lt;strong&gt;every real user&lt;/strong&gt; from registering.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Three clocks that could race through a payment
&lt;/h3&gt;

&lt;p&gt;A 10-minute invoice expiry, a ~2-minute frontend polling window, and a 60-second backend reconciliation job. A slow 3-D Secure confirmation could outlast the frontend's patience &lt;em&gt;even on a successful payment&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The fix was two backend schedulers acting as a safety net independent of whether the browser is still open, plus two independent finalization paths — the bank's own server-to-server callback (authoritative, works even if the user closed the tab) and the SPA's polling (fallback) — both funnelled through a single idempotency guard so downstream sync fires exactly once no matter which path wins.&lt;/p&gt;

&lt;p&gt;Related, and dumber: a direct browser GET to the bank's payment endpoint silently dropped the POST body. Fix was a backend-rendered auto-submit form so the browser never GETs that endpoint at all.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Chrome blocks TLS renegotiation for XHR but not for navigation
&lt;/h3&gt;

&lt;p&gt;Every API call died with &lt;code&gt;net::ERR_FAILED&lt;/code&gt; while SAML redirects worked perfectly.&lt;/p&gt;

&lt;p&gt;That asymmetry is what made it expensive — a system where authentication redirects succeed and every subsequent API call fails looks exactly like a backend auth bug. It was infrastructure config.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rework nobody warns you about
&lt;/h2&gt;

&lt;p&gt;16 distinct revert-and-rebuild cycles across both repos. Two favourites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The downstream token-exchange handshake went through &lt;strong&gt;four different protocols in one afternoon&lt;/strong&gt; — two-step, service-JWT bearer, app_secret bearer, no auth header — then got reverted twice more over the following days before settling on a single-step exchange.&lt;/li&gt;
&lt;li&gt;A business-line normalization rule: four strategies built across four PRs in a single day, all reverted the same day once the counterparty confirmed their API wanted the value exactly as stored, pulled out of &lt;code&gt;main&lt;/code&gt; entirely, then rebuilt a third way two weeks later.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of that was AI's fault or mine. It's what happens when you integrate against teams whose own requirements aren't settled yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Claude actually helped, and where it didn't
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;It wrote most of the code.&lt;/strong&gt; Not just scaffolding — the adapter pairs, the CQRS command and query implementations across dozens of features, the JPA mapping conventions, Angular components, large parts of the integration clients. That compression is the entire reason one person covered a 3–4 person scope.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It found none of the four problems above.&lt;/strong&gt; Every one started with knowing what to suspect. The certificate failure surfaced as a generic SAML error. The 500s were confidently misdiagnosed by everyone in the room. The clock race never appeared in testing. The TLS bug presented as an auth problem.&lt;/p&gt;

&lt;p&gt;You can't prompt your way to a fix for something you haven't correctly identified — you describe symptoms you have already interpreted, and the interpretation is the job.&lt;/p&gt;

&lt;p&gt;There's also a version of this nobody mentions: I hit model usage limits repeatedly across five months. Rate limits were a real schedule constraint, not a footnote.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd do differently
&lt;/h2&gt;

&lt;p&gt;Test coverage is about 23% instruction coverage on the backend. That's low and I'm not going to dress it up. With a second engineer I'd have invested in automated coverage far earlier, and had someone review the downstream integration protocols before implementation rather than discovering the mismatches through four rounds of live rework.&lt;/p&gt;

&lt;p&gt;Happy to go deeper on any of it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>java</category>
      <category>aws</category>
      <category>security</category>
    </item>
  </channel>
</rss>
