<?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: Mustafa Mahmoud Atta</title>
    <description>The latest articles on Forem by Mustafa Mahmoud Atta (@mustafamahmoudatta111).</description>
    <link>https://forem.com/mustafamahmoudatta111</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%2F3876624%2F9f539e53-e263-4c13-8964-e520a2cd07df.png</url>
      <title>Forem: Mustafa Mahmoud Atta</title>
      <link>https://forem.com/mustafamahmoudatta111</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mustafamahmoudatta111"/>
    <language>en</language>
    <item>
      <title>🚀 OathMesh v1.0.0-rc.1: Zero-Trust API Keys That Survive the Real World</title>
      <dc:creator>Mustafa Mahmoud Atta</dc:creator>
      <pubDate>Mon, 27 Apr 2026 10:52:19 +0000</pubDate>
      <link>https://forem.com/mustafamahmoudatta111/oathmesh-v100-rc1-zero-trust-api-keys-that-survive-the-real-world-2hg5</link>
      <guid>https://forem.com/mustafamahmoudatta111/oathmesh-v100-rc1-zero-trust-api-keys-that-survive-the-real-world-2hg5</guid>
      <description>&lt;p&gt;Replacing static API keys with 5-minute, self-destructing Ed25519 tokens sounds great—until your Redis node dies, NTP drifts, or you realize you have to rewrite 50 legacy microservices to verify them. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/mustafamahmoudatta111/we-replaced-api-keys-with-tokens-that-self-destruct-in-5-minutes-p1j"&gt;Last time&lt;/a&gt;, we introduced OathMesh. Since then, we’ve been hardening it for distributed systems. Here is how we solved the hard problems: clock drift, cache failures, and zero-code adoption.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ The Proof: &amp;lt;1ms Overhead
&lt;/h2&gt;

&lt;p&gt;First, the metric that matters. In our Kubernetes &lt;code&gt;k6&lt;/code&gt; benchmarks, the full 14-step verification pipeline (Ed25519 sig check, JWKS resolution, replay defense, policy eval) adds &lt;strong&gt;&amp;lt;1ms latency at p99&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Raw Request]       p50: 2.1ms | p95: 4.5ms | p99: 8.2ms
[+ OathMesh Verify] p50: 2.8ms | p95: 5.1ms | p99: 9.0ms
                                     Delta: &amp;lt;1ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Security shouldn't bottleneck your infra.&lt;/p&gt;




&lt;h2&gt;
  
  
  🕒 1. Clock Drift &amp;amp; Sandboxing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Clock Skew Problem
&lt;/h3&gt;

&lt;p&gt;A strict 5-minute TTL breaks when server clocks desync by even a few seconds. NTP isn't perfect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt; A 30-second &lt;code&gt;ClockSkewLeeway&lt;/code&gt; across all SDKs. Tokens are accepted if &lt;code&gt;exp + 30s &amp;gt; now&lt;/code&gt; and &lt;code&gt;iat - 30s &amp;lt; now&lt;/code&gt;. The token still dies in ≤ 5 minutes; we just don't reject valid tokens because &lt;code&gt;server-b&lt;/code&gt; is slightly behind &lt;code&gt;server-a&lt;/code&gt;.&lt;/p&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%2Fwww.image2url.com%2Fr2%2Fdefault%2Fimages%2F1777286912966-dae03aaf-9605-4a9b-bc86-385190bfd9ff.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%2Fwww.image2url.com%2Fr2%2Fdefault%2Fimages%2F1777286912966-dae03aaf-9605-4a9b-bc86-385190bfd9ff.png" alt="image" width="800" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The SSRF Vector
&lt;/h3&gt;

&lt;p&gt;We use Apple's Pkl for policy-as-code. But what if a malicious policy tries to &lt;code&gt;read("/etc/shadow")&lt;/code&gt; or makes an outbound HTTP request?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt; Strict sandboxing at the execution layer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--allowed-modules="pkl:*"&lt;/code&gt; (no network/package imports)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--allowed-resources="file://&amp;lt;dir&amp;gt;/"&lt;/code&gt; (scoped strictly to the policy directory)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛡️ 2. The Redis Dilemma: Fail-Open vs. Fail-Closed
&lt;/h2&gt;

&lt;p&gt;OathMesh uses Redis to prevent token replays. If Redis drops, you face a classic choice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fail open:&lt;/strong&gt; Accept tokens → Security risk (DDoS your Redis to bypass auth).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fail closed:&lt;/strong&gt; Reject everything → System-wide downtime.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt; We &lt;strong&gt;fail closed for new tokens&lt;/strong&gt;, but use a bounded circuit-breaker to protect in-flight requests.&lt;/p&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%2Flk6bp5j8d6k95edhwgws.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%2Flk6bp5j8d6k95edhwgws.png" alt="image" width="800" height="1278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If Redis drops, the Go engine activates an in-process cache of &lt;strong&gt;known-good tokens verified in the last 60 seconds&lt;/strong&gt;. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New tokens? Rejected (fail closed). &lt;/li&gt;
&lt;li&gt;Legitimate in-flight callers? They survive the blip.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🌐 3. Zero-Code Gateway Integration
&lt;/h2&gt;

&lt;p&gt;You shouldn't rewrite legacy services to adopt zero-trust. We brought OathMesh to the API Gateway layer.&lt;/p&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%2Fwww.image2url.com%2Fr2%2Fdefault%2Fimages%2F1777286977926-d11e0c29-e84e-40be-8352-dfe3fe92a07b.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%2Fwww.image2url.com%2Fr2%2Fdefault%2Fimages%2F1777286977926-d11e0c29-e84e-40be-8352-dfe3fe92a07b.png" alt="image" width="800" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Envoy (&lt;code&gt;ext_authz&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;A standalone Go binary implements Envoy's gRPC &lt;code&gt;ext_authz&lt;/code&gt; interface. It verifies tokens and injects identity headers before traffic hits your app.&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="c1"&gt;# envoy.yaml snippet&lt;/span&gt;
&lt;span class="na"&gt;http_filters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ext_authz&lt;/span&gt;
    &lt;span class="na"&gt;typed_config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@type"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz&lt;/span&gt;
      &lt;span class="s"&gt;grpc_service&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;google_grpc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;target_uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oathmesh:4000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your upstream receives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;X-OathMesh-Subject: agent://ci/deploy-bot
X-OathMesh-Action: deploy
X-OathMesh-Token-ID: &amp;lt;jti-uuid&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zero code changes required.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kong
&lt;/h3&gt;

&lt;p&gt;We built a native Go PDK plugin. It runs our 14-step pipeline directly inside Kong's request lifecycle. No sidecars, no Lua rewrites, no extra network hops.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 4. Observability: Step-Annotated Audit Logs
&lt;/h2&gt;

&lt;p&gt;Every verification emits a structured NDJSON event. No guessing &lt;em&gt;why&lt;/em&gt; a token was rejected.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"ts"&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="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"step"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"jti"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"abc123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"sub"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"agent://ci/deploy-bot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"act"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"deploy"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"ts"&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="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"step"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"jti_replay"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"jti"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"abc123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"src_ip"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"10.0.4.99"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pipe it to &lt;code&gt;jq&lt;/code&gt;, ship it to your SIEM, or grep for &lt;code&gt;step 13&lt;/code&gt; to catch replays instantly.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ Maturity: Where We Actually Are
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capability&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Core engine (Go)&lt;/td&gt;
&lt;td&gt;✅ Production-tested internally&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SDKs (Go, Node.js, Python)&lt;/td&gt;
&lt;td&gt;✅ Stable, cross-SDK conformance-tested&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Envoy + Kong integrations&lt;/td&gt;
&lt;td&gt;✅ Ready for early adopters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Independent security audit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;🔜 Seeking sponsors — &lt;a href="mailto:security@oathmesh.dev"&gt;contact us&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Honest take:&lt;/em&gt; If you're running SPIFFE with full sidecar coverage, keep using it. OathMesh is for teams who want zero-trust machine identity &lt;em&gt;without&lt;/em&gt; the service mesh footprint: CI runners, legacy VMs, and polyglot environments.&lt;/p&gt;




&lt;h2&gt;
  
  
  Ready to kill your static API keys?
&lt;/h2&gt;

&lt;p&gt;The engine is open-source and ready for early adopters. Run the 3-command demo, read the threat model, and tell us what breaks.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://github.com/oathmesh/oathmesh" rel="noopener noreferrer"&gt;GitHub: oathmesh/oathmesh&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
📖 &lt;strong&gt;&lt;a href="https://github.com/oathmesh/oathmesh/blob/main/docs/PERFORMANCE.md" rel="noopener noreferrer"&gt;Performance Benchmarks&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
🔒 &lt;strong&gt;&lt;a href="https://github.com/oathmesh/oathmesh/blob/main/docs/THREAT_MODEL.md" rel="noopener noreferrer"&gt;Threat Model&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built by Moustafa Mahmoud Atta &amp;amp; Abd El-Sabour Ashraf — MIT License&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>microservices</category>
      <category>go</category>
      <category>devops</category>
    </item>
    <item>
      <title>We Replaced API Keys with Tokens That Self-Destruct in 5 Minutes</title>
      <dc:creator>Mustafa Mahmoud Atta</dc:creator>
      <pubDate>Thu, 23 Apr 2026 04:59:05 +0000</pubDate>
      <link>https://forem.com/mustafamahmoudatta111/we-replaced-api-keys-with-tokens-that-self-destruct-in-5-minutes-p1j</link>
      <guid>https://forem.com/mustafamahmoudatta111/we-replaced-api-keys-with-tokens-that-self-destruct-in-5-minutes-p1j</guid>
      <description>&lt;p&gt;Your CI job has a secret. It's been sitting in your environment variables for two years. You don't know exactly who has access to it. Rotating it means coordinating three teams. So you don't.&lt;/p&gt;

&lt;p&gt;That's not a process failure. That's what API keys are &lt;em&gt;designed&lt;/em&gt; to be: long-lived strings that survive forever because they have to.&lt;/p&gt;

&lt;p&gt;We're &lt;strong&gt;Moustafa Mahmoud Atta&lt;/strong&gt; and &lt;strong&gt;Abd El-Sabour Ashraf&lt;/strong&gt;, and we built &lt;a href="https://github.com/oathmesh/oathmesh" rel="noopener noreferrer"&gt;OathMesh&lt;/a&gt; to change that default.&lt;/p&gt;

&lt;p&gt;Every machine call gets a token that's cryptographically signed, scoped to a single action, and dead in &lt;strong&gt;≤ 5 minutes&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The whole idea in two lines of HTTP
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Authorization: Bearer abc123xyz_still_valid_since_2022
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Authorization: OathMesh eyJhbGciOiJFZERTQSIsInR5cCI6Im9tK2p3dCJ9...
                        └── expires in 300 seconds. enforced. not optional.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Leaked? By the time an attacker tries it, it's already dead.&lt;/p&gt;




&lt;h2&gt;
  
  
  Honest comparison
&lt;/h2&gt;

&lt;p&gt;This is the real picture — no spin:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;API Keys&lt;/th&gt;
&lt;th&gt;Typical JWT&lt;/th&gt;
&lt;th&gt;Short-lived JWT + jti&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;OathMesh&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lifetime&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;♾️ Forever&lt;/td&gt;
&lt;td&gt;Hours–Days&lt;/td&gt;
&lt;td&gt;5–15 min (if configured)&lt;/td&gt;
&lt;td&gt;⏱️ &lt;strong&gt;≤ 300s. Enforced.&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cryptography&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Just a string&lt;/td&gt;
&lt;td&gt;HS256 / RS256&lt;/td&gt;
&lt;td&gt;RS256 / ES256&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Ed25519 only&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Replay protection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅ jti blocklist (DIY)&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Built-in, required&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Action scoping&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;⚠️ Custom, optional&lt;/td&gt;
&lt;td&gt;⚠️ Custom, optional&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;&lt;code&gt;act&lt;/code&gt; required&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Policy engine&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Pkl rules, hot-reload&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Audit log&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;⚠️ Roll your own&lt;/td&gt;
&lt;td&gt;⚠️ Roll your own&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Every allow &amp;amp; deny, NDJSON&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Leaked secret blast radius&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;💀 Forever&lt;/td&gt;
&lt;td&gt;🩸 Hours&lt;/td&gt;
&lt;td&gt;🟡 Minutes&lt;/td&gt;
&lt;td&gt;🟢 &lt;strong&gt;≤ 5 min. Max.&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rotation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;😰 Manual + coordination&lt;/td&gt;
&lt;td&gt;⚠️ Varies&lt;/td&gt;
&lt;td&gt;⚠️ Varies&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Auto-expiry by design&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Honest take:&lt;/strong&gt; You &lt;em&gt;can&lt;/em&gt; get close to OathMesh with short-lived JWTs + a jti blocklist. What OathMesh adds is the opinionated wrapper: TTL enforcement you can't disable, &lt;code&gt;act&lt;/code&gt; scoping that's required (not optional), a built-in policy engine, and a full audit trail — out of the box, not DIY.&lt;/p&gt;

&lt;p&gt;Already running SPIFFE/SPIRE or cloud workload identity (AWS IRSA, GCP WI)? Great — those are excellent fits for Kubernetes-native setups. OathMesh is for teams who want this security model without the full service-mesh footprint. And if you want simpler than all of this, keep the API key. If you want safer, read on.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  A real scenario: GitHub Actions → your deploy API
&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%2Fwww.image2url.com%2Fr2%2Fdefault%2Fimages%2F1776920130119-5f0499aa-e0eb-437a-a430-ca1fa3d9e987.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%2Fwww.image2url.com%2Fr2%2Fdefault%2Fimages%2F1776920130119-5f0499aa-e0eb-437a-a430-ca1fa3d9e987.png" alt="image" width="800" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The CI job never stores a secret. It requests a token with a 300-second TTL, uses it, and it's gone. Even if someone captures it from your logs — they get nothing.&lt;/p&gt;




&lt;h2&gt;
  
  
  How verification works — 14 steps, fail-closed
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Fail-closed&lt;/strong&gt; means: if &lt;em&gt;any&lt;/em&gt; single step fails, the request is rejected immediately. No partial-valid state. No fallback. Just 401.&lt;/p&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%2Fwww.image2url.com%2Fr2%2Fdefault%2Fimages%2F1776920196530-bb8c3b78-ffe1-46af-afea-c09162f6ccfc.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%2Fwww.image2url.com%2Fr2%2Fdefault%2Fimages%2F1776920196530-bb8c3b78-ffe1-46af-afea-c09162f6ccfc.png" alt="image" width="800" height="1630"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;What it checks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Valid JWS compact structure (3 segments)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Header: &lt;code&gt;typ = om+jwt&lt;/code&gt;, &lt;code&gt;alg = EdDSA&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Payload decoded, &lt;code&gt;iss&lt;/code&gt; extracted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;iss&lt;/code&gt; in trusted issuer list&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;JWKS loaded (cached in-memory)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;6&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Ed25519 signature verified — no algorithm confusion possible&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;iss&lt;/code&gt; re-verified post-signature&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;exp&lt;/code&gt; is in the future (±10s clock skew tolerance)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;iat&lt;/code&gt; is not in the future&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;aud&lt;/code&gt; matches exactly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;All required claims present: &lt;code&gt;sub&lt;/code&gt;, &lt;code&gt;act&lt;/code&gt;, &lt;code&gt;jti&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;Request hash binding checked (if present)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;13&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;jti&lt;/code&gt; checked against replay cache — seen before → rejected&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;Policy evaluated → audit event emitted&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Steps &lt;strong&gt;6&lt;/strong&gt; and &lt;strong&gt;13&lt;/strong&gt; are the heavy hitters. No algorithm confusion. No replay. No exceptions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Gateway mode — protect services you can't modify
&lt;/h2&gt;

&lt;p&gt;Already have APIs you can't change? Run OathMesh as a reverse proxy in front of them.&lt;/p&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%2Fwww.image2url.com%2Fr2%2Fdefault%2Fimages%2F1776920276079-b24bac9f-b412-400c-a2b2-8628f2edf44b.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%2Fwww.image2url.com%2Fr2%2Fdefault%2Fimages%2F1776920276079-b24bac9f-b412-400c-a2b2-8628f2edf44b.png" alt="image" width="800" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your upstream gets clean, pre-verified identity headers. Zero code changes required.&lt;/p&gt;




&lt;h2&gt;
  
  
  Drop it into your stack in ~5 lines
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Go (chi)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OathMeshMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c"&gt;// Fully typed caller context in your handler:&lt;/span&gt;
&lt;span class="n"&gt;caller&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CallerFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="c"&gt;// caller.Principal.Subject → "agent://ci/deploy-bot"&lt;/span&gt;
&lt;span class="c"&gt;// caller.Action            → "deploy"&lt;/span&gt;
&lt;span class="c"&gt;// caller.TokenID           → unique jti for this call&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Python (FastAPI)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;oathmesh&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;verify_token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OathMeshError&lt;/span&gt;

&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/deploy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;caller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;verify_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;OathMeshError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deployed_by&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;caller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;principal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Next.js (App Router)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;withOathMesh&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@oathmesh/oathmesh/next&lt;/span&gt;&lt;span class="dl"&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;oathmesh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;withOathMesh&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;audience&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;trustedIssuers&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;caller&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;oathmesh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&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;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// typed 401 — missing, invalid, expired, replayed&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;caller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;principal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subject&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;Full examples for Express, Flask, Django, and chi are in the &lt;a href="https://github.com/oathmesh/oathmesh/tree/main/docs/quickstarts" rel="noopener noreferrer"&gt;quickstarts&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try it in 3 commands
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/oathmesh/oathmesh.git &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;oathmesh
docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;

&lt;span class="c"&gt;# Mint a token (300s = the maximum, enforced by the issuer)&lt;/span&gt;
&lt;span class="nv"&gt;TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;docker compose &lt;span class="nb"&gt;exec &lt;/span&gt;oathmesh ./bin/oathmesh mint &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--sub&lt;/span&gt; &lt;span class="s2"&gt;"agent://repo/acme/deploy-bot"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--aud&lt;/span&gt; &lt;span class="s2"&gt;"https://inventory.internal"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--act&lt;/span&gt; &lt;span class="s2"&gt;"deploy"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ttl&lt;/span&gt; 300 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--quiet&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: OathMesh &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; http://localhost:8081/inventory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or run &lt;code&gt;./demo.sh&lt;/code&gt; for the full golden-path demo end to end.&lt;/p&gt;




&lt;h2&gt;
  
  
  Honest pros and cons
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What we got right ✅&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;300s max TTL is enforced in the issuer&lt;/strong&gt; — there's no config flag to make it longer. Intentional, not an oversight.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ed25519 only&lt;/strong&gt; — one algorithm, the correct one. Algorithm confusion attacks aren't possible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fail-closed verification&lt;/strong&gt; — all 14 steps must pass. No partial-valid state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full audit trail&lt;/strong&gt; — every allow and every deny logged as NDJSON. grep-able. Cloud-native.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gateway mode&lt;/strong&gt; — zero changes to your existing APIs.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;MIT license&lt;/strong&gt; — take it, fork it, self-host it.&lt;br&gt;
&lt;strong&gt;What we know needs work ❌&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It's v0.1.0&lt;/strong&gt; — rough edges exist. Read the threat model before running in production.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;You need to run an Issuer service&lt;/strong&gt; — one more thing to deploy and keep alive. Real operational cost.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Horizontal scaling needs Redis&lt;/strong&gt; — the replay cache is in-memory by default. Multiple instances need a shared Redis. We're not hiding this.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pkl for policies&lt;/strong&gt; — powerful, but not everyone knows Apple Pkl. A visual editor is on the roadmap.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Machine-to-machine only&lt;/strong&gt; — user auth is a different problem. Use OAuth2/OIDC for that.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - &lt;strong&gt;Your Ed25519 private key is your trust root&lt;/strong&gt; — unlike an API key (which compromises one service), a leaked signing key compromises &lt;em&gt;every&lt;/em&gt; service on your mesh. &lt;strong&gt;Store it in a secrets manager (Vault, AWS KMS, GCP Secret Manager) — not in an env var.&lt;/strong&gt; This is the one rule that matters most.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Use OathMesh if
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You're running CI/CD pipelines that call internal APIs&lt;/li&gt;
&lt;li&gt;You have service-to-service calls in a zero-trust or service mesh setup&lt;/li&gt;
&lt;li&gt;You're building AI agents that call protected services&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A leaked credential in your environment would cause real damage&lt;/p&gt;
&lt;h2&gt;
  
  
  Don't use OathMesh (yet) if
&lt;/h2&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You need tokens that live longer than 5 minutes by design&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can't add infrastructure — the Issuer service is not optional&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - You need user-facing authentication — this is not the tool
&lt;/h2&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Rust + Java SDKs&lt;/td&gt;
&lt;td&gt;🔜 Next release (v0.2.0)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mTLS + rate limiting in Gateway&lt;/td&gt;
&lt;td&gt;🗓️ Planned&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Visual policy editor (no Pkl required)&lt;/td&gt;
&lt;td&gt;🗓️ Planned&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Audit dashboard&lt;/td&gt;
&lt;td&gt;🗓️ Planned&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitLab CI + GitHub App issuers&lt;/td&gt;
&lt;td&gt;🗓️ Planned&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;We built OathMesh because we kept hitting the same wall: leaked credentials with no expiry and no audit trail. The fix shouldn't require a security team or an enterprise budget.&lt;/p&gt;

&lt;p&gt;It's early. It has rough edges. But the model is sound, the code is open, and the MIT license means you can take it wherever you need it.&lt;/p&gt;

&lt;p&gt;If it solves a problem you have — or if you think we're wrong about something — open an issue or start a discussion. We genuinely want to hear from you.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://github.com/oathmesh/oathmesh" rel="noopener noreferrer"&gt;github.com/oathmesh/oathmesh&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @oathmesh/sdk
pip &lt;span class="nb"&gt;install &lt;/span&gt;oathmesh
go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/oathmesh/oathmesh/cmd/oathmesh@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;em&gt;Built by Moustafa Mahmoud Atta &amp;amp; Abd El-Sabour Ashraf — MIT License&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>devops</category>
      <category>opensource</category>
      <category>zerotrust</category>
    </item>
  </channel>
</rss>
