<?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: Leo</title>
    <description>The latest articles on DEV Community by Leo (@leobaniak).</description>
    <link>https://dev.to/leobaniak</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%2F3997121%2F061e76e1-0a08-4d9d-827c-24f1e8b9e15b.png</url>
      <title>DEV Community: Leo</title>
      <link>https://dev.to/leobaniak</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/leobaniak"/>
    <language>en</language>
    <item>
      <title>Entire opens preview of regional Git mirrors aimed at AI-agent clone traffic</title>
      <dc:creator>Leo</dc:creator>
      <pubDate>Sun, 12 Jul 2026 16:26:35 +0000</pubDate>
      <link>https://dev.to/leobaniak/entire-opens-preview-of-regional-git-mirrors-aimed-at-ai-agent-clone-traffic-5353</link>
      <guid>https://dev.to/leobaniak/entire-opens-preview-of-regional-git-mirrors-aimed-at-ai-agent-clone-traffic-5353</guid>
      <description>&lt;p&gt;Thomas Dohmke, the former GitHub CEO, opened the preview waitlist this week for Entire, a distributed Git network that mirrors GitHub repositories across regions so AI coding agents can clone from a nearby node instead of hitting the origin. DevOps.com reported the launch on 8 July 2026. The company launched with more than 40 employees across nine countries, and $60 million in seed funding at a $300 million valuation, per the same report.&lt;/p&gt;

&lt;p&gt;The mechanism today is regional read replicas, not a new protocol. Entire keeps a repository on GitHub as the source of truth and stages the objects at mirrors in the United States, Europe and Australia, DevOps.com wrote. Around the mirror layer the company is shipping Entire Blame, Entire Review, and code and semantic search. The roadmap adds native hosting of repositories and, further out, what DevOps.com describes as a fully decentralized network that would let customers meet data-sovereignty requirements.&lt;/p&gt;

&lt;p&gt;The pitch is throughput for agent fleets. DevOps.com cites internal benchmarks of about 570,000 clones per hour, 586 pushes per second, and 470 clone-and-push operations per second on a mixed workload. Those numbers are the vendor's, not an independent measurement, and the report does not disclose the reference repository, the network topology, or how contention was modelled.&lt;/p&gt;

&lt;h2&gt;
  
  
  What CI teams inherit if they adopt a mirror
&lt;/h2&gt;

&lt;p&gt;Mirrors duplicate the fetch layer; they do not replace the identity layer. Pipelines that pin an origin URL, authenticate with a GitHub App or key check runs off a specific host still resolve back to github.com. If a team points its runner-side clone at a nearest-region Entire node, the questions are the ones any read replica introduces to a delivery pipeline. How stale can the mirror be against a just-merged commit before a workflow starts building the wrong SHA? What credential scope does the mirror path require? Where does a &lt;code&gt;git push&lt;/code&gt; from inside a runner actually land, and who signs the resulting ref update?&lt;/p&gt;

&lt;p&gt;The preview is waitlist-only. Entire has not published the wire protocol, the mirror consistency model, or the pricing sheet, per the DevOps.com report. Until it does, the offer to CI/CD owners is a set of vendor throughput numbers and a promise of features next to GitHub, not through it.&lt;/p&gt;

</description>
      <category>githosting</category>
      <category>aiagents</category>
      <category>entire</category>
      <category>developertools</category>
    </item>
    <item>
      <title>AWS puts gray zone failures into the EKS control loop</title>
      <dc:creator>Leo</dc:creator>
      <pubDate>Sun, 12 Jul 2026 08:25:29 +0000</pubDate>
      <link>https://dev.to/leobaniak/aws-puts-gray-zone-failures-into-the-eks-control-loop-1d87</link>
      <guid>https://dev.to/leobaniak/aws-puts-gray-zone-failures-into-the-eks-control-loop-1d87</guid>
      <description>&lt;h2&gt;
  
  
  What AWS is calling out
&lt;/h2&gt;

&lt;p&gt;The New Stack, on July 10, published a walk-through of what running Kubernetes across a very large EKS fleet has taught AWS about availability zone failures. The operational take is one line: the failures that hurt production the most are not the ones that trip the alarms, and EKS now has a primitive that treats that mode as its own category.&lt;/p&gt;

&lt;p&gt;The piece frames gray failures as a class of their own. A zone is slow but not down. Latency climbs on some paths and stays flat on others. Health checks keep answering. Nothing looks broken enough to justify the on-call pushing the button, so traffic keeps landing there, and the partial outage runs longer than it should.&lt;/p&gt;

&lt;p&gt;Per the write-up, EKS zonal shift is the mechanism to redirect traffic away from an impaired zone. AWS now automates that shift on the customer's behalf, so the reordering happens on suspicion rather than on operator confirmation. That is the news underneath the phrase "lessons learned".&lt;/p&gt;

&lt;h2&gt;
  
  
  How zonal shift moves the traffic
&lt;/h2&gt;

&lt;p&gt;The article describes zonal shift as a traffic-level action. It steers new connections away from the affected zone rather than moving pods off of it. Once the signals recover, traffic returns to the zone. That keeps workload placement stable through what is, in the healthy case, a short blip.&lt;/p&gt;

&lt;p&gt;The piece stresses the automation angle: AWS runs its own detection signals across the fleet and can invoke a shift before the customer's dashboards catch up. That trades one step of operator judgement for one step of vendor judgement. It is faster than a human. It is also opinionated about what "degrading" means, and the definition of that word does not live in your repo.&lt;/p&gt;

&lt;p&gt;The New Stack does not detail the exact detection signals, the invocation latency, or the recovery threshold. Those specifics remain on the AWS side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading this from the deploy controller's seat
&lt;/h2&gt;

&lt;p&gt;If you deploy through EKS, the deploy pipeline is no longer the only thing that changes traffic shape during a rollout. A zonal shift can fire mid-canary. It can fire mid-rollout of a stateless service. The deploy job did not cause the swing in error rates the release engineer is watching in the graph, and the rollback decision tree needs to know that before it pulls the wrong lever.&lt;/p&gt;

&lt;p&gt;The read for CI/CD teams is that a regional resilience test needs to cover the slow-but-not-down failure mode as its own scenario. Killing a node is a common chaos drill. So is killing a whole zone. Simulating a zone that keeps answering, only more slowly, is the case most drills skip, and it is the case this feature is designed for.&lt;/p&gt;

&lt;p&gt;Progressive delivery tooling belongs on the same wire. If a shift is active in the zone that hosts a canary, promoting that canary because its own metrics look clean is misreading the picture. The deploy controller and the traffic controller need to be looking at the same view of the world.&lt;/p&gt;

&lt;h2&gt;
  
  
  The knobs the write-up leaves out
&lt;/h2&gt;

&lt;p&gt;The article sits at the pattern level. It does not enumerate the detection thresholds, the propagation delay before traffic actually moves, or how a manual override interacts with the automatic path. Those are the numbers the on-call reaches for at 3am, and they are the numbers the vendor is least eager to publish, because they move.&lt;/p&gt;

&lt;p&gt;The other piece the article leaves for the reader is what your own probes should look like now that AWS has one hand on the wheel. Cloud-side detection is one signal. Synthetics from outside the region are another. Neither replaces the other. If the automatic shift and your dashboards disagree, one of them is wrong for your workload, and you want to know which before the customer emails come in.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>eks</category>
      <category>kubernetes</category>
      <category>sre</category>
    </item>
    <item>
      <title>GitHub lets enterprises pin Copilot's OpenTelemetry endpoint</title>
      <dc:creator>Leo</dc:creator>
      <pubDate>Sun, 12 Jul 2026 00:24:32 +0000</pubDate>
      <link>https://dev.to/leobaniak/github-lets-enterprises-pin-copilots-opentelemetry-endpoint-4pk0</link>
      <guid>https://dev.to/leobaniak/github-lets-enterprises-pin-copilots-opentelemetry-endpoint-4pk0</guid>
      <description>&lt;h2&gt;
  
  
  Where Copilot's telemetry stream lands, decided centrally
&lt;/h2&gt;

&lt;p&gt;GitHub added a control on July 8 that lets an enterprise mandate where the Copilot Chat extension in VS Code and Copilot CLI send OpenTelemetry data, removing the need for individual developers to set &lt;code&gt;OTEL_*&lt;/code&gt; environment variables. Per the GitHub changelog, the setting is delivered through a &lt;code&gt;telemetry&lt;/code&gt; block in the enterprise-managed settings, and a managed value takes precedence over environment variables and user settings.&lt;/p&gt;

&lt;p&gt;Four things are configurable in the block: the OTLP export endpoint and transport (&lt;code&gt;otlp-http&lt;/code&gt; or &lt;code&gt;otlp-grpc&lt;/code&gt;), the OTel service name and resource attributes, exporter headers such as an authentication token for the collector, and whether prompt, response and tool content is captured, with a separate flag for whether developers can change that. Delivery uses the channels documented on the same page: native MDM (Windows Registry or macOS managed preferences), server-managed settings from a signed-in GitHub account, or a file-based &lt;code&gt;managed-settings.json&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this bites
&lt;/h2&gt;

&lt;p&gt;The precedence rule is the point. If a platform team owns the collector and needs traces routed to it, this is exactly the switch they wanted. If a developer had their own OTLP endpoint pointed at a local sink, they will see the session start emitting somewhere else. The changelog does not describe a per-user override once a managed value is set.&lt;/p&gt;

&lt;p&gt;A scoping note is worth reading twice. The changelog states that managed exporter headers apply only to the Copilot Chat extension's OTLP exporter. The endpoint and transport policy still reach the CLI agent host, but the auth-token flow the changelog calls out is bound to the Chat surface. On-call teams standing up the collector should plan for that asymmetry before it lands as a surprise during triage.&lt;/p&gt;

</description>
      <category>opentelemetry</category>
      <category>githubcopilot</category>
      <category>enterprisemanagedsettings</category>
      <category>observability</category>
    </item>
    <item>
      <title>Innersource security advisories go GA: a private channel for private vulns</title>
      <dc:creator>Leo</dc:creator>
      <pubDate>Sat, 11 Jul 2026 16:24:50 +0000</pubDate>
      <link>https://dev.to/leobaniak/innersource-security-advisories-go-ga-a-private-channel-for-private-vulns-og8</link>
      <guid>https://dev.to/leobaniak/innersource-security-advisories-go-ga-a-private-channel-for-private-vulns-og8</guid>
      <description>&lt;p&gt;Your platform team ships an internal package. Half the org pulls it. Someone finds a bug that in the wrong hands is a full RCE. What do you do next: file a public CVE and telegraph the vuln to the internet, or drop it in a Slack channel and hope every downstream repo notices before an exploit does?&lt;/p&gt;

&lt;p&gt;Neither has ever been a good answer. On July 8 GitHub made a third option generally available: innersource security advisories, an internal advisory channel wired into Dependabot, with visibility restricted to repositories owned by the enterprise. You now get the public-advisory workflow without the public part.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually ships
&lt;/h2&gt;

&lt;p&gt;The feature sits inside GitHub Advanced Security for enterprise customers. Per GitHub's changelog, an enterprise can publish an advisory about a component and keep its visibility scoped to enterprise-owned repositories. A new REST API endpoint sits behind it, with the usual create, update and withdraw verbs.&lt;/p&gt;

&lt;p&gt;That last detail matters more than it looks. If the only path were the UI, this would be a nice ticketing surface with a padlock on it. An API makes it a control plane: internal SBOM tooling, vulnerability scanners running on your build fleet, and the security-response playbooks your team already keeps warm can all file advisories the same way they might file JIRA tickets today. The advisory becomes a first-class object your automation can produce.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it reaches a repo
&lt;/h2&gt;

&lt;p&gt;Publishing the advisory is only half the job. The other half is fan-out. GitHub uses Dependabot as the delivery mechanism. Once an advisory exists for a component, Dependabot notifies the repositories inside the enterprise that use that component. Two things fall out of that: security alerts on affected repos, and version-update notifications. Where a fixed version exists, Dependabot will open a pull request to bump the vulnerable dependency.&lt;/p&gt;

&lt;p&gt;Translate that into the developer inbox: the same loop that already lands "please upgrade &lt;code&gt;lodash&lt;/code&gt; to a fixed version" PRs on your repos now lands "please upgrade &lt;code&gt;@yourco/kafka-client&lt;/code&gt; because your platform team said so" PRs on the same repos. From the receiving repo's point of view, nothing has changed. That is the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the trust boundary moved
&lt;/h2&gt;

&lt;p&gt;Before this, "internal CVE" was close to an oxymoron in most orgs. Public advisories were, by definition, public, which made them a bad venue for a vuln in your bespoke auth library. Private issues in a single repo did not federate anywhere. So the actual mechanism most teams used was a Slack message and a shared spreadsheet. That does not scale past two teams and one dependency graph.&lt;/p&gt;

&lt;p&gt;Here is the trust boundary that moved: an advisory is now an enterprise-scoped object, and Dependabot honours that scope. Controlled disclosure inside the walls, without leaking anything outside them. If you own a shared platform monorepo, or a family of internal SDKs used across product teams, this closes a gap that has been open since Dependabot existed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The catch you signed up for
&lt;/h2&gt;

&lt;p&gt;Two limits are worth naming out loud.&lt;/p&gt;

&lt;p&gt;First, the feature is bound to GitHub Advanced Security on the enterprise plan. If your CI/CD stack lives elsewhere, the private-advisory workflow does not follow you. Portability across ecosystems is still your problem.&lt;/p&gt;

&lt;p&gt;Second, this will only ever be as good as the discipline you put into it. No one files internal advisories by accident. If your security team is not empowered to publish them, or the platform group does not know it can, the feature launches with zero entries and stays there. A private CVE feed with nothing in it is worse than useless; it lulls you into thinking a channel exists when nothing has ever come down it.&lt;/p&gt;

&lt;p&gt;Other ecosystems approach the same shape from different angles. GitLab has security policies and its own dependency scanner. Artifact registries such as Nexus and Artifactory expose vulnerability views over hosted internal packages. OSV publishes advisories in a machine-readable schema, though the public/private distinction is not what it is for. This is not the first attempt at broadcasting internal vulns; it is the first one that plugs directly into the PR-creating half of Dependabot, scoped to a single enterprise.&lt;/p&gt;

&lt;p&gt;Ship the plumbing, then ship the culture. Otherwise you have a very expensive announcement board with an audience of zero.&lt;/p&gt;

</description>
      <category>github</category>
      <category>ghas</category>
      <category>dependabot</category>
      <category>supplychain</category>
    </item>
    <item>
      <title>A running cost meter and an MCP tripwire land in Visual Studio's June update</title>
      <dc:creator>Leo</dc:creator>
      <pubDate>Sat, 11 Jul 2026 08:26:32 +0000</pubDate>
      <link>https://dev.to/leobaniak/a-running-cost-meter-and-an-mcp-tripwire-land-in-visual-studios-june-update-4p59</link>
      <guid>https://dev.to/leobaniak/a-running-cost-meter-and-an-mcp-tripwire-land-in-visual-studios-june-update-4p59</guid>
      <description>&lt;h2&gt;
  
  
  The invoice a coworker forwarded me with three exclamation marks
&lt;/h2&gt;

&lt;p&gt;That was the whole message. No context, no question, just the PDF. He is a heavy Copilot user, he had a good June, and the total on the last line was the reason for the exclamation marks. If you have not received one of those yet, I am fairly sure someone on your team has, and Microsoft is reading the same threads. The Visual Studio June Stable Channel update quietly ships two features you can feel on a normal Tuesday: a real-time Copilot usage window with proactive alerts, and a trust check that pauses MCP servers whose configuration has changed between sessions.&lt;/p&gt;

&lt;p&gt;Neither one is glamorous. Both are the kind of change you only notice in the relief of a Slack thread you did not have to open.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually shipped
&lt;/h2&gt;

&lt;p&gt;The cost side is straightforward. Visual Studio now surfaces real-time usage against the token-based model, with proactive alerts as you approach a limit, when you hit it, and when overage billing kicks in. Teams can configure the warning threshold, so the trip wire can sit wherever your team's budget conversation actually happens.&lt;/p&gt;

&lt;p&gt;The MCP side is more mechanical. Trust is checked in two places. At startup, the current MCP server configuration is compared against a previously trusted baseline. After startup, a fingerprint of the server's tools, prompts, resources and instructions is compared to the last trusted version. If anything diverges, Visual Studio stops and asks. You can accept the change and update the baseline, always trust the server going forward, or reject and abort startup. First-time connections are treated as implicitly trusted, and built-in or registry-controlled servers skip the prompt entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why an IDE update matters to a CI/CD reader
&lt;/h2&gt;

&lt;p&gt;Two reasons, and they both land in the same place.&lt;/p&gt;

&lt;p&gt;The first is cost. GitHub shifted every Copilot plan from premium request units to usage-based billing on June 1, with the meter now counting tokens instead of requests. DevOps.com cites reports of monthly bills that jumped from roughly $29 to $750, and from $39 to over $800 for the heaviest agentic users. Whether or not your team's numbers match those, the shape is familiar. A background agent runs a loop, the loop is measured in tokens now, and nobody sees the meter until the invoice arrives. Anything that puts the meter back where the engineer is actually looking pulls that feedback loop closer to the decision.&lt;/p&gt;

&lt;p&gt;The second is drift in agent tooling. MCP servers are the extension port for AI assistants, exposing tools, prompts, resources and instructions the model can call. When those servers get updated on their own schedule, treating a change in the tool list as a security event, not a startup log line, is the right instinct. You would not silently accept a new binary in your CI runner just because it kept the same filename.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using both features on a Tuesday
&lt;/h2&gt;

&lt;p&gt;For cost, the practical move is the threshold. Set it low the first week, high enough not to be noise, and let the alert tell you when a session went agentic without you meaning it to. The window will not stop the spend. It will stop the surprise, which is the useful thing an IDE can actually do.&lt;/p&gt;

&lt;p&gt;For MCP, the trust dialog is a moment of forced attention. The three options are not equivalent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Accept and update the baseline&lt;/strong&gt; is the day-to-day answer, when a server you know has legitimately added a tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Always trust&lt;/strong&gt; is the option you should almost never pick, because it turns the tripwire off permanently for that server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reject and abort&lt;/strong&gt; is the answer whenever the change surprises you. That includes the case where a teammate's server updated overnight and you have not read the release notes yet.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the last option feels harsh, remember that MCP tools can, by design, call things on your behalf.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the update stops short
&lt;/h2&gt;

&lt;p&gt;I like both features. I also want to be honest about where they stop short, because a piece that only celebrates is off-voice.&lt;/p&gt;

&lt;p&gt;The alert fires after tokens are spent. It is a rear-view mirror on the current window, not a pre-flight cap. If you are working with a background agent, the alert can arrive several thousand tokens after the decision that triggered them.&lt;/p&gt;

&lt;p&gt;Trust is per-workstation. In what the article describes, there is no equivalent yet for an org policy that says "these MCP servers are approved, everything else stays cold". A team of ten Visual Studio users still maintains ten independent baselines.&lt;/p&gt;

&lt;p&gt;First-time connections are implicitly trusted. That is a sensible default for a dev tool, but it means the first run is exactly the moment you have to look most carefully at what the server exposes.&lt;/p&gt;

&lt;p&gt;And this is Visual Studio, not VS Code, not JetBrains. If your team splits IDEs, only the Visual Studio users get these two panes this month.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where other tooling stands on the same problems
&lt;/h2&gt;

&lt;p&gt;IDE cost meters are becoming an expected feature, not a differentiator. Most AI coding assistants that meter by tokens now surface a usage view of some kind, whether inline in the sidebar or in the account portal. The interesting question is whether the meter lives where the engineer is actually working. Visual Studio's version at least clears that bar.&lt;/p&gt;

&lt;p&gt;MCP trust is a newer conversation. The MCP specification treats configuration as data a host can consume, and it is up to each host to decide what to do when that data shifts. Some hosts prompt on any new tool. Some log the change and continue. Some do nothing. What Visual Studio is proposing is one specific approach: fingerprint the interface surface, compare it to a stored baseline, and pause when the two diverge. It is a defensible default and I would like to see it copied.&lt;/p&gt;

&lt;p&gt;For a CI/CD team the interesting extension is on the pipeline side. If your agents run in CI too, the trust primitive belongs there as well, not only in the editor. A container that pulls an MCP server from a registry each run should be diffing that server against a locked baseline before it lets the model call anything. Nothing in this Visual Studio update reaches into the pipeline. That part is still on you.&lt;/p&gt;

&lt;h2&gt;
  
  
  The signal I am keeping an eye on
&lt;/h2&gt;

&lt;p&gt;Two things.&lt;/p&gt;

&lt;p&gt;Whether other IDEs pick up the same fingerprint-and-baseline pattern in the next few releases, because that is when a vendor's opinion starts to become a norm. And whether org-scoped MCP allowlists arrive, because a per-user trust dialog is the right primitive, but a team of ten does not have a policy until one central place says so.&lt;/p&gt;

&lt;p&gt;If both land in the second half of the year, we will look back on this June update as the quiet moment the industry started treating MCP configuration as security-relevant. If neither does, we will look back on it as a Visual Studio nicety that saved a few Tuesday invoices, which is not nothing, but not the thing I was hoping for either.&lt;/p&gt;

</description>
      <category>githubcopilot</category>
      <category>mcp</category>
      <category>devrel</category>
      <category>visualstudio</category>
    </item>
    <item>
      <title>After the ingress-NGINX retirement, what your migration plan owes production</title>
      <dc:creator>Leo</dc:creator>
      <pubDate>Sat, 11 Jul 2026 00:24:32 +0000</pubDate>
      <link>https://dev.to/leobaniak/after-the-ingress-nginx-retirement-what-your-migration-plan-owes-production-10de</link>
      <guid>https://dev.to/leobaniak/after-the-ingress-nginx-retirement-what-your-migration-plan-owes-production-10de</guid>
      <description>&lt;h2&gt;
  
  
  The status of the controller
&lt;/h2&gt;

&lt;p&gt;As of March 2026, the Kubernetes SIG Network stopped maintaining ingress-nginx. That is the controller a lot of clusters have been running for years. A CNCF blog post published July 9 walks operators through the state of play. The headline for anyone still on it is short: unpatched CVEs, and no more feature work.&lt;/p&gt;

&lt;p&gt;The post names two operational risks explicitly. New security issues will not receive upstream fixes. Feature updates and community support have stopped. If your ingress plane is a piece of infrastructure you have not touched in a while, this is the reason to pull it up in this quarter's planning doc.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it means at 3am
&lt;/h2&gt;

&lt;p&gt;An ingress controller sits between the internet and your services. When it drops a request, you find out from your users. When it takes a CVE and no one is patching, you find out from a scanner or from a report. Neither is a good discovery path.&lt;/p&gt;

&lt;p&gt;The controller also carries the exact set of annotations, TLS defaults and rewrite rules your workloads rely on. Nothing about a retirement changes the version you have in production today, so the immediate blast radius is zero. The risk is on the calendar, not on the pager. That is the kind of risk teams reliably defer until a scanner flags an unpatched CVE.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two paths CNCF lays out
&lt;/h2&gt;

&lt;p&gt;The post frames the choice as a fork.&lt;/p&gt;

&lt;p&gt;Path A is a lateral swap to another Ingress controller. The example named is Contour, described in the post as Envoy-based. This keeps you on the Ingress API and mostly moves the problem of who is patching.&lt;/p&gt;

&lt;p&gt;Path B is modernization to the Gateway API, described in the post as the upstream-backed successor to Ingress. The CNCF post points at &lt;code&gt;ingress2gateway&lt;/code&gt; to automate the translation, and recommends an incremental rollout: run the new plane in parallel and move non-critical workloads first.&lt;/p&gt;

&lt;p&gt;The stopgap version is a mix. Adopt Contour to buy time on maintained code, then schedule the Gateway API move on your own calendar rather than under duress.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to verify before the cutover
&lt;/h2&gt;

&lt;p&gt;Ingress annotations do not port cleanly between controllers. The affinity, timeout and rewrite rules your services depend on are dialect, and each controller speaks its own. A migration that treats the manifests as one-to-one produces quiet regressions on the traffic paths that carry the most annotations, which is to say the paths that matter most.&lt;/p&gt;

&lt;p&gt;A short list of things to check before you flip DNS or change the IngressClass:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Health-check semantics. Idle timeouts and slow-start behavior vary across implementations.&lt;/li&gt;
&lt;li&gt;TLS behavior. Certificate reload, SNI handling and default cipher policies are all controller-specific.&lt;/li&gt;
&lt;li&gt;Rewrite and canonicalization rules. Trailing slashes and path prefixes are the classic source of a silent 404 after a swap.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rollback path: keep the old controller running in the cluster on a different IngressClass until the new one has held a production week without a page. Cutover by class, not by cluster.&lt;/p&gt;

&lt;h2&gt;
  
  
  The wider shape
&lt;/h2&gt;

&lt;p&gt;The specific news is the retirement. The shape is familiar. A workhorse project ends its maintenance window, and the community points at both a like-for-like replacement and a longer-term API. In this case the CNCF post treats the Gateway API as the destination and Contour as the shorter road to a maintained plane. The reasoning offered is straightforward: the Gateway API is the upstream-backed successor to Ingress, so anything you build against it should still be there when the next controller cycles out.&lt;/p&gt;

&lt;p&gt;None of that changes if you do nothing this week. It changes when the next CVE lands on a controller no one is fixing.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>ingress</category>
      <category>gatewayapi</category>
      <category>migration</category>
    </item>
    <item>
      <title>GitLab shipped a real migration with AI agents and wrote up what actually broke</title>
      <dc:creator>Leo</dc:creator>
      <pubDate>Fri, 10 Jul 2026 16:25:56 +0000</pubDate>
      <link>https://dev.to/leobaniak/gitlab-shipped-a-real-migration-with-ai-agents-and-wrote-up-what-actually-broke-1ce3</link>
      <guid>https://dev.to/leobaniak/gitlab-shipped-a-real-migration-with-ai-agents-and-wrote-up-what-actually-broke-1ce3</guid>
      <description>&lt;p&gt;The last time I watched a team migrate a piece of production plumbing across a hundred call sites, we spent most of the first week just naming everything before anyone typed a real line of code. So when GitLab posted this week about running the same kind of exercise with AI agents doing most of the mechanical fan-out, I was ready to be either annoyed or hooked. The post lands on the honest side of the fence, and that is the reason it is worth reading.&lt;/p&gt;

&lt;p&gt;The setup, per GitLab's write-up: two separate rate-limiting paths in production. One is the application-level &lt;code&gt;Gitlab::ApplicationRateLimiter&lt;/code&gt; with 121 keys. The other is a Rack-level system further out on the edge, which the post says handles roughly four billion requests a day. Both were being unified onto a single implementation in the &lt;code&gt;labkit-ruby&lt;/code&gt; gem, and that meant touching 95 call sites across the monolith and the EE codebase. It is the kind of migration where a missed key does not fail loudly. It just quietly stops working the way you thought.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the agents were actually asked to do
&lt;/h2&gt;

&lt;p&gt;The agents were not turned loose on the codebase. GitLab describes a bounded set of moves they were trusted with, driven from the Duo Agent Platform and paired with Duo Code Review and Duo Developer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read context and draft specifications from the epic.&lt;/li&gt;
&lt;li&gt;Implement bounded code changes, one spec at a time.&lt;/li&gt;
&lt;li&gt;Write test code alongside the change.&lt;/li&gt;
&lt;li&gt;Pre-review the merge requests before a human ever looked at them.&lt;/li&gt;
&lt;li&gt;Fan out mechanical edits across the 95 call sites (83 in the monolith, 12 in EE).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing in that list is "the agent decided the plan". The plan is still an engineering artifact. What moves is the fan-out and the first-draft review, which happen to be the two parts of a migration that eat the most calendar time and cause the most typos at line 4,203.&lt;/p&gt;

&lt;h2&gt;
  
  
  The safety loop they wrapped around it
&lt;/h2&gt;

&lt;p&gt;The interesting bit is the process, not the model. The post describes a structured loop that reads more like a runbook than a prompt. Read the epic, write a spec, adversarially review the spec, implement, verify with explicit evidence in the merge request, adversarially review the MR, human review, merge. Adversarial passes are capped at two rounds of resolution before a human takes over, so an agent cannot argue with itself forever.&lt;/p&gt;

&lt;p&gt;That cap is the sentence I circled twice. If you have ever watched two review bots trade suggestions back and forth in a comment thread, you know why it matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rollout they actually ran
&lt;/h2&gt;

&lt;p&gt;Nothing about this migration was one-shot. The team split the keys into cohorts and rolled them out at 1%, then 10%, then 50%, then 100%, hitting the halfway point on May 4 and the full cutover on May 5, per the post. There were six cohorts in total, because a first audit missed 17 keys and Cohort 6 became the sweep for the ones nobody had noticed.&lt;/p&gt;

&lt;p&gt;The relevant numbers for anyone thinking about this at home, in GitLab's own count: 14 numbered specs, and north of 30 merge requests. This was not one heroic prompt with a green pipeline. It was a long series of small, reviewable steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  The incident they did not hide
&lt;/h2&gt;

&lt;p&gt;The post reports one shadow-mode failure. An adapter quietly dropped an identifier on one unauthenticated code path, and a slice of users started seeing generic failures before the team rolled it back. GitLab names it. That single admission is more useful than a pile of eval numbers, because it points at the exact class of thing an AI agent is bad at catching: the seam between two systems where a value looks harmless in isolation and turns dangerous when it flows across the boundary.&lt;/p&gt;

&lt;p&gt;Shadow mode caught it before it hurt anyone at scale, which is the whole point of shadow mode. Still, if you read the write-up expecting a clean line that says "look, no incidents", you will not find one, and I would trust the post less if you did.&lt;/p&gt;

&lt;h2&gt;
  
  
  What lands for the engineer waiting on the queue
&lt;/h2&gt;

&lt;p&gt;There is nothing in this migration that a careful team could not do by hand. The agents did not invent the plan. They did not choose the cohorts. They did not decide when to flip percentages. What they took off the humans was the mechanical fan-out across 95 call sites and the first pass of spec writing, inside a loop that a human still owned end to end.&lt;/p&gt;

&lt;p&gt;If you have ever run a monotonous migration for a week, you know exactly which minutes those are. They are the ones where you lose your place and the compiler cannot save you.&lt;/p&gt;

&lt;p&gt;The reason this post reads well to me is that it does not claim the agents replaced engineering judgment. It claims they compressed the fan-out and the first-draft review. That is a much more useful claim, and it is one you can copy without buying anyone's roadmap.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I am watching next
&lt;/h2&gt;

&lt;p&gt;Two things. First, whether the "adversarial review, capped at two rounds" pattern shows up in write-ups from other teams. It is a small idea with a lot of leverage, and I want to see it stress-tested against messier codebases than a Ruby monolith with strong review culture. Second, whether the seam-of-two-systems failure mode ends up as a named test category in agent evaluation, the way race conditions eventually got their own bucket in async test suites.&lt;/p&gt;

&lt;p&gt;If your next agent-assisted change touches a boundary between two subsystems, borrow this team's rollout shape before you borrow their tooling. The percentages and the audit cohort are the parts that would have saved them either way.&lt;/p&gt;

</description>
      <category>gitlab</category>
      <category>aiagents</category>
      <category>migrations</category>
      <category>devrel</category>
    </item>
    <item>
      <title>GhostApproval: six AI coding agents shipped a permission dialog that was reading the wrong path</title>
      <dc:creator>Leo</dc:creator>
      <pubDate>Fri, 10 Jul 2026 08:25:29 +0000</pubDate>
      <link>https://dev.to/leobaniak/ghostapproval-six-ai-coding-agents-shipped-a-permission-dialog-that-was-reading-the-wrong-path-10en</link>
      <guid>https://dev.to/leobaniak/ghostapproval-six-ai-coding-agents-shipped-a-permission-dialog-that-was-reading-the-wrong-path-10en</guid>
      <description>&lt;p&gt;You approve a diff. The agent writes the file. The file, it turns out, was not the file. Somewhere between the approval dialog and the disk, a symbolic link redirected the write to a path you never named, and an attacker's public key ended up sitting in your &lt;code&gt;authorized_keys&lt;/code&gt;. This is GhostApproval, disclosed this week by researchers at Google-owned Wiz. Per DevOps.com on July 9, the same primitive hit six AI coding agents at once: Anthropic Claude Code, Amazon Q Developer, Google Antigravity, Augment, Cursor, and Windsurf.&lt;/p&gt;

&lt;p&gt;The trick is a Unix feature that has been in every filesystem you have ever used. A symlink is a file whose contents resolve to a path somewhere else. Write to &lt;code&gt;project_settings.json&lt;/code&gt; and, if that name is actually a symlink pointing at &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt;, you did not write to your project. You wrote to your SSH keyring. Every operating-systems textbook has flagged this for decades. Six of the most-funded coding agents on the market shipped without checking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the dialog stopped telling the truth
&lt;/h2&gt;

&lt;p&gt;Here is the ugly detail. Most of these agents do ask before they touch a file. The problem is what the dialog says. The prompt shows the &lt;em&gt;intended&lt;/em&gt; path, the string the model typed, and not the &lt;em&gt;resolved&lt;/em&gt; path, the file the OS is actually about to open. So you see the friendly project filename, click yes, and the write lands where the attacker aimed it.&lt;/p&gt;

&lt;p&gt;That is a full trust failure at the boundary that was supposed to be the last line of defence. The confirmation dialog was the human check. It is the reason we tolerate agents running with the user's own credentials on the developer's own machine. If the check does not resolve the path before it names it, it is theatre.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is a CI/CD story, not a desktop one
&lt;/h2&gt;

&lt;p&gt;You might read the above and reach for the "well, don't clone hostile repos" reflex. In 2026 that reflex is not available. Coding agents ingest issues, PR descriptions, generated code, docs, and, yes, cloned repositories from anywhere the pipeline touches. The distance between "malicious npm package" and "malicious workspace" is now one &lt;code&gt;git clone&lt;/code&gt; in a container. Any pipeline step that runs an agent over untrusted content is a plausible vector for the same primitive: dependency review bots, PR triage jobs, changelog generation, doc-diffing, security scanners that shell out to an agent.&lt;/p&gt;

&lt;p&gt;Two shifts follow. First, the agent's write path is now part of the pipeline threat model. What identity does it run as? What parts of the filesystem does it reach? What happens when a hostile symlink is on disk before the agent starts? Second, "the user approved it" is no longer a defensible audit line if the approval never named the real target.&lt;/p&gt;

&lt;h2&gt;
  
  
  A short audit list
&lt;/h2&gt;

&lt;p&gt;The immediate mitigations are unglamorous and, mostly, thirty years old:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resolve paths before showing them to a human. If the write target contains a symlink, the dialog names the resolved path or refuses the write.&lt;/li&gt;
&lt;li&gt;Sandbox the agent's write scope to the workspace, with a hard denylist on &lt;code&gt;~/.ssh&lt;/code&gt;, shell rc files, cron files, and the user's config directory.&lt;/li&gt;
&lt;li&gt;Never let a coding agent inherit an SSH agent, a browser cookie jar, or long-lived cloud credentials. Give it short-lived, workspace-scoped tokens or nothing.&lt;/li&gt;
&lt;li&gt;In CI, run agents inside an ephemeral container with the checkout as the only writable mount. Bind everything else read-only, and treat the container as untrusted on exit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The vendor scoreboard, as of Wiz's report
&lt;/h2&gt;

&lt;p&gt;Per DevOps.com's account: AWS, Cursor, and Google shipped fixes. Augment and Windsurf have fixes in progress. Anthropic initially rejected the finding as outside its threat model, then added symlink warnings to Claude Code in a later release. Six vendors, six response curves. The through-line is that none of them caught the class of bug in-house before an external researcher filed the report.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "decades-old feature" is really telling you
&lt;/h2&gt;

&lt;p&gt;The most useful framing in the disclosure is the "decades-old" label. Symlink-following bugs are the oldest privilege-escalation class in Unix. They live in a body of literature every long-running service learned to respect years ago: resolve first, check the resolution, then open with &lt;code&gt;O_NOFOLLOW&lt;/code&gt; where the platform gives it to you. Six agents built in the last two years shipped without any of that. Why? Because agent tooling is written to a "helpful assistant on my laptop" threat model, not a "hostile input, TOCTOU, adversarial filesystem" one. The category is catching up with the deployment. Painfully.&lt;/p&gt;

&lt;p&gt;We keep re-learning that agents are just programs with the developer's keys. Every new capability, tool use, file write, MCP server, is a new place where the OS assumes an adult is watching. GhostApproval is a reminder that the adult was a dialog box, and the dialog box was reading from the wrong side of the symlink. Patch your agents. Then patch the pipeline that runs them. Your &lt;code&gt;authorized_keys&lt;/code&gt; file will thank you.&lt;/p&gt;

</description>
      <category>aiagents</category>
      <category>codingagents</category>
      <category>supplychain</category>
      <category>security</category>
    </item>
    <item>
      <title>Google puts Cloud Run sandboxes into preview for AI-generated code</title>
      <dc:creator>Leo</dc:creator>
      <pubDate>Fri, 10 Jul 2026 00:25:41 +0000</pubDate>
      <link>https://dev.to/leobaniak/google-puts-cloud-run-sandboxes-into-preview-for-ai-generated-code-3anc</link>
      <guid>https://dev.to/leobaniak/google-puts-cloud-run-sandboxes-into-preview-for-ai-generated-code-3anc</guid>
      <description>&lt;p&gt;Now that generative coding tools push draft code into pull requests and pipelines directly, the question of where the resulting artefact actually runs has stopped being a design exercise. On July 9, Google Cloud announced that Cloud Run sandboxes are in public preview, framed on the Google Cloud developers-and-practitioners blog around a single question: how do you run AI-generated code or untrusted binaries without exposing the host application, the data, and the cloud credentials that sit next to them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The change
&lt;/h2&gt;

&lt;p&gt;The pitch, in Google's own framing, is a place to run code that you do not fully trust. The post positions Cloud Run sandboxes as an isolation primitive for AI-written programs and untrusted binaries, distinct from the general-purpose Cloud Run service where you would typically deploy an application you wrote and reviewed yourself. What the announcement commits to publicly is the preview status and the intended use. Anything more specific about limits, quotas, isolation internals, or the exact API surface is out of scope for this article and belongs to the Google Cloud documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this fits in a CI/CD pipeline
&lt;/h2&gt;

&lt;p&gt;The pipeline-side problem is simple. A code-writing agent produces a function, a script, or a container recipe, and something has to execute it to know whether it works. The convenient option is the same runner that already has read access to your registry, your artifact bucket, and often a workload identity that can call into production. Convenient, and exactly the wrong place: if the generated code is buggy, you break the runner; if it is hostile, you have handed a stranger a set of long-lived credentials.&lt;/p&gt;

&lt;p&gt;A dedicated sandbox with no coupling to the host runner turns that from a security-review argument into a routing decision. The generator emits code, a stage ships that code to the sandbox, the sandbox executes and returns results, and only reviewed output ever comes back into the trusted side of the pipeline. The credentials the sandbox holds are the credentials you are willing to lose.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the announcement leaves open
&lt;/h2&gt;

&lt;p&gt;Google's post is a preview note, not a runbook. In the passages the release lede highlights, it does not spell out the isolation technology, the startup latency, the pricing model, or the concurrency ceiling. Those are the numbers that decide whether the service lands in a pipeline or stays on a wish list. Preview also means the API and defaults can move; a wiring diagram drawn this week may need a revision after GA.&lt;/p&gt;

&lt;p&gt;The second-order question the announcement does not address is the one on-call actually cares about. When the sandbox misbehaves, what does the failure look like from the caller's side, and does it degrade gracefully or block the pipeline. Treat that as a load-test item, not an assumption.&lt;/p&gt;

&lt;h2&gt;
  
  
  How other platforms handle untrusted execution
&lt;/h2&gt;

&lt;p&gt;Cloud Run sandboxes join a crowded field of "run this code somewhere it cannot hurt anyone" primitives, and it helps to see the shape of the field before adopting anything.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AWS Lambda / Firecracker microVMs.&lt;/strong&gt; The best-documented approach in the wild. Each invocation gets a fresh microVM. If your workload is short, event-shaped, and you are already an AWS shop, this is the path of least resistance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;E2B.&lt;/strong&gt; A focused product for AI-generated code execution, with SDKs aimed at agent frameworks. If the sandbox is a persistent notebook that an agent is iterating inside, rather than a one-shot pipeline step, E2B is the more targeted option than a generic cloud sandbox.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kata Containers / gVisor.&lt;/strong&gt; Open-source isolation runtimes you can slot under an existing Kubernetes cluster. Higher operational cost, but keeps the compute on infrastructure you already run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker rootless plus user namespaces.&lt;/strong&gt; The cheapest option, and enough for many test workloads. It will not stop a determined attacker, and it does not solve the credential-leakage problem on its own, but it is a reasonable first fence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buddy sandboxes.&lt;/strong&gt; In &lt;a href="https://buddy.works/?utm_source=cicd.deployment.to&amp;amp;utm_medium=article&amp;amp;utm_campaign=cloud-run-sandboxes" rel="noopener noreferrer"&gt;Buddy&lt;/a&gt;, the pipeline itself owns an ephemeral sandbox environment per branch, which some teams point at agent-generated code so it never lands on the shared runner. One option among several; it fits when the code you want to isolate is code the same pipeline just produced, less well when the sandbox is a long-running scratchpad an agent talks to across many turns.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every option here has a real use case, and the honest read is that Cloud Run sandboxes will make sense for teams already routing traffic through Cloud Run, and awkward for teams that are not. The preview label is doing real work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The residual caveat
&lt;/h2&gt;

&lt;p&gt;Preview is preview. The isolation guarantees, the failure modes, and the price of running a lot of untrusted code through the service are the three numbers that turn this into an operational choice, and they are the three numbers a preview blog post does not have to publish. Kick the tires with something disposable before you route production agent output through it.&lt;/p&gt;

</description>
      <category>googlecloud</category>
      <category>cloudrun</category>
      <category>sandbox</category>
      <category>aicode</category>
    </item>
    <item>
      <title>etcd v3.7 adds a streaming range API and drops the legacy v2 store</title>
      <dc:creator>Leo</dc:creator>
      <pubDate>Thu, 09 Jul 2026 16:24:30 +0000</pubDate>
      <link>https://dev.to/leobaniak/etcd-v37-adds-a-streaming-range-api-and-drops-the-legacy-v2-store-4n53</link>
      <guid>https://dev.to/leobaniak/etcd-v37-adds-a-streaming-range-api-and-drops-the-legacy-v2-store-4n53</guid>
      <description>&lt;p&gt;SIG etcd cut v3.7.0 this week, and for teams operating Kubernetes the operational headline is a new streaming range API that stops the server buffering the whole result set before it answers. The release, announced on the Kubernetes blog by the maintainers, adds &lt;code&gt;RangeStream&lt;/code&gt; to the gRPC surface and to &lt;code&gt;etcdctl&lt;/code&gt;, tightens lease behaviour when the cluster is under load, and finally removes the legacy v2 store that etcd has been carrying since the v3 migration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chunked reads instead of a buffered response
&lt;/h2&gt;

&lt;p&gt;The old shape of a &lt;code&gt;Range&lt;/code&gt; call was expensive on a large keyspace. The server read every matching key/value into memory, serialized the response, then answered. Under memory pressure or a slow client the whole response sat on the server heap. &lt;code&gt;RangeStream&lt;/code&gt; chunks that response instead. Per the release notes it is available on both the gRPC API and via &lt;code&gt;etcdctl&lt;/code&gt;. The maintainers describe the payoff two ways: lower latency for callers reading big ranges, and more predictable memory use on both server and client. Kubernetes plans to expose it in v1.37 behind an &lt;code&gt;EtcdRangeStream&lt;/code&gt; feature gate; until then, no default cluster behaviour changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Smaller wins that add up on the pager
&lt;/h2&gt;

&lt;p&gt;A related optimisation lands the same release. When a &lt;code&gt;Range&lt;/code&gt; sets &lt;code&gt;keys_only&lt;/code&gt; (or an operator runs &lt;code&gt;etcdctl get --keys-only&lt;/code&gt;), etcd will read solely from the in-memory index, skipping the bbolt load of serialized values entirely. The one exception the release notes call out is &lt;code&gt;SortTarget=VALUE&lt;/code&gt;, which still needs the values. For anything scanning a wide keyspace to check what exists, the backend read goes away.&lt;/p&gt;

&lt;p&gt;Leases got two changes worth carrying into a runbook. &lt;code&gt;LeaseRevoke&lt;/code&gt; requests are prioritised, per the notes, so leases expire on time when etcd is under load. A &lt;code&gt;FastLeaseKeepAlive&lt;/code&gt; path renews a lease without waiting for the applied index. Both are the sort of change you notice at 3am, when a node still reporting itself alive is really a lease that a controller has been trying to revoke, and the queue in front of the revoke is what is holding the loop open. A separate &lt;code&gt;find()&lt;/code&gt; performance change is aimed at concurrent watches over the same keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bit that matters on upgrade
&lt;/h2&gt;

&lt;p&gt;The removal that jumps out is the v2 store. etcd v3.7.0 boots entirely from v3store; the legacy v2 store, kept around for a long migration tail, is gone. Any tooling, health check or backup path that still leans on the v2 API surface has to move before the upgrade, not during. The release also carries a protobuf overhaul, with the old libraries replaced by supported ones, and pins bbolt at v1.5.0 and raft at v3.7.0.&lt;/p&gt;

&lt;h2&gt;
  
  
  What has not changed
&lt;/h2&gt;

&lt;p&gt;None of this touches the consensus model. etcd is still Raft; the cluster still needs a quorum to write; the familiar failure modes for an on-call, quorum loss on member churn, snapshot restore under time pressure, watch storms after a leader change, are the same failure modes on v3.7. What the release changes is the shape of the reads and the sharpness of the lease timing. On a healthy cluster you may not notice. On the cluster where a controller decides at 2am to enumerate every pod in every namespace, the difference between chunked and buffered is the difference between backpressure and OOM.&lt;/p&gt;

&lt;p&gt;For CI/CD teams the practical read is upstream of the pipeline. Kubernetes v1.37 is the version where the RangeStream benefit reaches the API server, and only if the feature gate is on. Everything else in v3.7 lands the day the cluster runs the new binary.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>etcd</category>
      <category>releases</category>
      <category>sre</category>
    </item>
    <item>
      <title>A primary-nav flyout built on `popover`, not `aria-expanded`</title>
      <dc:creator>Leo</dc:creator>
      <pubDate>Thu, 09 Jul 2026 16:09:00 +0000</pubDate>
      <link>https://dev.to/leobaniak/a-primary-nav-flyout-built-on-popover-not-aria-expanded-do4</link>
      <guid>https://dev.to/leobaniak/a-primary-nav-flyout-built-on-popover-not-aria-expanded-do4</guid>
      <description>&lt;p&gt;The hand-rolled primary-nav flyout is one of the oldest accessibility traps on the web. A button, a hidden list of links, and an &lt;code&gt;aria-expanded&lt;/code&gt; attribute you have to remember to flip every time the state changes. Miss one path through that state machine and a screen-reader user hears the wrong thing about whether the menu is open.&lt;/p&gt;

&lt;p&gt;Adrian Roselli has just published a rebuild of his 2019 disclosure-widget navigation pattern, this time using the native HTML &lt;code&gt;popover&lt;/code&gt; attribute in place of the hand-scripted toggle. The result is worth reading closely, because it clarifies which parts of an accessible flyout the platform now carries for you and which parts you still own.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the pieces sit
&lt;/h2&gt;

&lt;p&gt;Per the source, the pattern uses a link (to the parent page) plus a sibling &lt;code&gt;&amp;lt;button popovertarget&amp;gt;&lt;/code&gt; that opens a &lt;code&gt;&amp;lt;ul popover&amp;gt;&lt;/code&gt;. The list markup is placed immediately after its trigger, so the focus order and the reading order match. That last point is easy to miss and expensive to get wrong: if the popover content sits elsewhere in the DOM, keyboard users can Tab past the item that was supposedly "underneath" the button they just activated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"…"&lt;/span&gt; &lt;span class="na"&gt;aria-current=&lt;/span&gt;&lt;span class="s"&gt;"page"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Products&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;popovertarget=&lt;/span&gt;&lt;span class="s"&gt;"products-menu"&lt;/span&gt;
        &lt;span class="na"&gt;aria-labelledby=&lt;/span&gt;&lt;span class="s"&gt;"…"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;…&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"products-menu"&lt;/span&gt; &lt;span class="na"&gt;popover&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- links --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That link + button + popover triad is the whole shape.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the platform handles now
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;popovertarget&lt;/code&gt; attribute wires the button to the popover, and per the source it also gives you the programmatic &lt;code&gt;aria-expanded&lt;/code&gt; state for free. No script has to toggle it. Two more behaviours come along for the ride: pressing Esc closes the popover, and a click outside closes it. All three used to be script that authors got wrong.&lt;/p&gt;

&lt;p&gt;The only interaction the source still had to write by hand is focusout-to-close, dismissing the popover when focus leaves the whole component. Compared with the old disclosure widget, that is a small residual surface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Naming the button without duplicating the link
&lt;/h2&gt;

&lt;p&gt;Two elements sit side by side in this pattern: the page link and the button that opens the flyout. Naming that button is where accessibility usually goes wrong. An &lt;code&gt;aria-label="Open Products submenu"&lt;/code&gt; on the button duplicates the visible text and, per the source, quietly breaks under auto-translation.&lt;/p&gt;

&lt;p&gt;The source sets &lt;code&gt;aria-labelledby&lt;/code&gt; on the button to reference the preceding link's text. No duplication, no fragile hidden string, and the browser's translation path stays honest. Current-page marking follows the same source-driven rule: &lt;code&gt;aria-current="page"&lt;/code&gt; sits on the current page's link and on the link to its parent page.&lt;/p&gt;

&lt;h2&gt;
  
  
  The condition attached to the top layer
&lt;/h2&gt;

&lt;p&gt;Here is the constraint that decides whether you can adopt this pattern at all. Popovers render in the top layer. Per the source, the pattern is only safe to reach for if every dialog on the site is already using the native &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element. Mix a top-layer popover with an old &lt;code&gt;position: fixed&lt;/code&gt; modal elsewhere and the two will fight over stacking, and users will find the seams.&lt;/p&gt;

&lt;p&gt;That is not a footnote. It is a precondition on the whole approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Small structural wins on top
&lt;/h2&gt;

&lt;p&gt;A few last details from the source, worth noting because they cost nothing extra:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The triggers meet WCAG 2.5.8 Target Size (Minimum). The pattern is not dodging touch reachability.&lt;/li&gt;
&lt;li&gt;Layout uses logical properties and flexbox with no width media queries.&lt;/li&gt;
&lt;li&gt;The demo works out of the box in forced-colors mode / Windows High Contrast Mode.&lt;/li&gt;
&lt;li&gt;The demo relies on cross-browser CSS anchor positioning across Firefox, Chromium and Safari, which the source notes only came about recently. The arrow that visually ties the popover to the button rotates on open via the &lt;code&gt;:popover-open&lt;/code&gt; pseudo-class.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What to take to your next PR
&lt;/h2&gt;

&lt;p&gt;The verdict is straightforward: this is what "use the platform" looks like now that the platform has caught up.&lt;/p&gt;

&lt;p&gt;For your next primary-nav rebuild:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before you start, check that every dialog on the site is already &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt;. If not, fix that first.&lt;/li&gt;
&lt;li&gt;Wire the button with &lt;code&gt;popovertarget&lt;/code&gt; and delete your &lt;code&gt;aria-expanded&lt;/code&gt; toggle script.&lt;/li&gt;
&lt;li&gt;Point &lt;code&gt;aria-labelledby&lt;/code&gt; at the sibling link's text instead of writing a duplicate label.&lt;/li&gt;
&lt;li&gt;Apply &lt;code&gt;aria-current="page"&lt;/code&gt; to both the current page's link and its parent page's link.&lt;/li&gt;
&lt;li&gt;Keep the popover content immediately after its trigger in the DOM.&lt;/li&gt;
&lt;li&gt;Write the focusout-to-close behaviour by hand. The platform does not do that one for you yet.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The old disclosure-widget script is not gone. It is smaller. Take the win.&lt;/p&gt;

</description>
      <category>popover</category>
      <category>a11y</category>
      <category>navigation</category>
      <category>aria</category>
    </item>
    <item>
      <title>setup-java 5.5.0 adds JDK signature verification, if you remember to enable it</title>
      <dc:creator>Leo</dc:creator>
      <pubDate>Thu, 09 Jul 2026 08:25:32 +0000</pubDate>
      <link>https://dev.to/leobaniak/setup-java-550-adds-jdk-signature-verification-if-you-remember-to-enable-it-56f0</link>
      <guid>https://dev.to/leobaniak/setup-java-550-adds-jdk-signature-verification-if-you-remember-to-enable-it-56f0</guid>
      <description>&lt;p&gt;Open the last three months of Java CI logs in your org. Count the JDKs your pipelines pulled from the internet. Now count how many of those downloads were verified against a signature before anything was executed inside them. If the answer to the second question is "we assume the vendor mirror is fine," you have a lot of company. This week the GitHub Blog quietly posted the actions/setup-java v5.5.0 changelog, and the interesting line is not the new distribution.&lt;/p&gt;

&lt;h2&gt;
  
  
  What v5.5.0 actually ships
&lt;/h2&gt;

&lt;p&gt;Three things. First, opt-in cryptographic signature verification for downloaded JDKs, gated behind a new &lt;code&gt;verify-signature&lt;/code&gt; input that performs a detached GPG check before the archive is installed. Second, a new &lt;code&gt;kona&lt;/code&gt; distribution parameter so pipelines targeting Tencent Kona JDK stop needing a hand-rolled download step. Third, a small stack of Maven fixes: &lt;code&gt;--no-transfer-progress&lt;/code&gt; is set automatically in &lt;code&gt;MAVEN_ARGS&lt;/code&gt; for Maven 3.9 and the Maven Wrapper (togglable via &lt;code&gt;show-download-progress: true&lt;/code&gt;); re-running the action no longer appends duplicate JDK entries to &lt;code&gt;toolchains.xml&lt;/code&gt;; and the generated &lt;code&gt;settings.xml&lt;/code&gt; disables interactive mode so a stuck prompt cannot silently hang a runner.&lt;/p&gt;

&lt;p&gt;For context, the prior release v5.4.0 added GraalVM Community support, a &lt;code&gt;javac&lt;/code&gt; problem matcher, and Maven Wrapper caching. Useful. This one is the security release.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the trust boundary actually moved
&lt;/h2&gt;

&lt;p&gt;Here is what &lt;code&gt;actions/setup-java&lt;/code&gt; has been doing quietly on your behalf for years. It fetches a JDK archive from a distribution mirror over TLS, unpacks it onto the runner, and puts it on &lt;code&gt;PATH&lt;/code&gt;. Every subsequent step, your build, your tests, your artifact signer, then runs inside a JVM you pulled from a URL you did not personally audit. TLS gets you the mirror, not the file. That is the exact hand-wave supply-chain attacks feed on.&lt;/p&gt;

&lt;p&gt;v5.5.0 does not solve "we trust the vendor" wholesale. It gives you a smaller, honest thing: the archive is checked against a detached GPG signature before it is installed. Turn on &lt;code&gt;verify-signature: true&lt;/code&gt; and the action pulls the vendor's signature, validates it against a known public key, and refuses to install the JDK if the check fails. Supported distributions in the built-in flow at launch are Temurin and Microsoft. Enable it on a distribution the action does not know how to verify and the action fails fast; it will not silently skip the check. If you run a private mirror with your own signing chain, &lt;code&gt;verify-signature-public-key&lt;/code&gt; lets you pass in your own key.&lt;/p&gt;

&lt;p&gt;Small change. Right end of the funnel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turning it on
&lt;/h2&gt;

&lt;p&gt;The recipe is a single input in the YAML you probably already have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-java@v5.5.0&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;distribution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;temurin&lt;/span&gt;
    &lt;span class="na"&gt;java-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;21'&lt;/span&gt;
    &lt;span class="na"&gt;verify-signature&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you self-host an internal mirror with your own signing chain, feed the action your own public key material:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-java@v5.5.0&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;distribution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;temurin&lt;/span&gt;
    &lt;span class="na"&gt;java-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;21'&lt;/span&gt;
    &lt;span class="na"&gt;verify-signature&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;verify-signature-public-key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.INTERNAL_JDK_PUBKEY }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Placeholder secret name, not a real fingerprint. Use whatever your internal PKI hands you.&lt;/p&gt;

&lt;h2&gt;
  
  
  The catches, in order of how much they will bite
&lt;/h2&gt;

&lt;p&gt;Signed. Verified. Still opt-in. That is the first catch, and it is the one that will decide whether this release matters or not: every existing Java job in your org keeps installing unsigned JDKs by default. The flag will not flip itself. Somebody has to open the pull requests, and the pipeline lint has to fail closed on jobs that do not carry &lt;code&gt;verify-signature: true&lt;/code&gt;. Until that happens, the security release you shipped is just a release note.&lt;/p&gt;

&lt;p&gt;The second catch is scope. Two distributions land with built-in verification: Temurin and Microsoft. If your standard build image is on Corretto, Zulu, Liberica, Oracle or Semeru, you are either bringing your own public key through &lt;code&gt;verify-signature-public-key&lt;/code&gt; or you are living without a signature check for now. Fair, but plan the migration, do not let it sit in the platform backlog until an incident tells you where to file the ticket.&lt;/p&gt;

&lt;p&gt;Third catch, the boring one. &lt;code&gt;verify-signature&lt;/code&gt; covers the JDK. It does not cover Maven itself. It does not cover the dependencies your build resolves afterward. Provenance for the artifacts your pipeline then publishes downstream is still your job, with SLSA-style attestations and a lockfile you actually trust. Read this feature as a lower bound, not a strategy.&lt;/p&gt;

&lt;p&gt;Flip it on. Then keep going.&lt;/p&gt;

</description>
      <category>githubactions</category>
      <category>java</category>
      <category>signing</category>
      <category>supplychain</category>
    </item>
  </channel>
</rss>
