<?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: LingFrame · 灵珑</title>
    <description>The latest articles on Forem by LingFrame · 灵珑 (@linglongger).</description>
    <link>https://forem.com/linglongger</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%2F3749856%2Fe6a2660f-a515-4568-8599-35f2352c1110.jpg</url>
      <title>Forem: LingFrame · 灵珑</title>
      <link>https://forem.com/linglongger</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/linglongger"/>
    <language>en</language>
    <item>
      <title>Securing Legacy Java Monoliths with Runtime Zero-Trust: My Open-Source Framework LingFrame</title>
      <dc:creator>LingFrame · 灵珑</dc:creator>
      <pubDate>Tue, 03 Feb 2026 08:46:42 +0000</pubDate>
      <link>https://forem.com/linglongger/securing-legacy-java-monoliths-with-runtime-zero-trust-my-open-source-framework-lingframe-4mdm</link>
      <guid>https://forem.com/linglongger/securing-legacy-java-monoliths-with-runtime-zero-trust-my-open-source-framework-lingframe-4mdm</guid>
      <description>&lt;h2&gt;
  
  
  The Problem No One Wants to Talk About 🦖
&lt;/h2&gt;

&lt;p&gt;Let's be honest.&lt;/p&gt;

&lt;p&gt;You have a giant Java monolith. It's been running for years. It makes money. And it's held together by duct tape and prayers.&lt;/p&gt;

&lt;p&gt;Every time you onboard a new team or integrate a vendor script, you think: &lt;em&gt;"What if this code accidentally calls something it shouldn't? What if a junior dev's DTO leaks sensitive data? What if we need to A/B test this new module without a full restart?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The usual advice is: "Just rewrite it as microservices!" Right. Let me just pause business for 18 months to refactor 500k LOC. 🙃&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This was my frustration.&lt;/strong&gt; I believed there had to be a middle ground—a way to introduce &lt;strong&gt;runtime governance&lt;/strong&gt; into an existing JVM process, without tearing everything down.&lt;/p&gt;

&lt;p&gt;So, I built &lt;strong&gt;&lt;a href="https://github.com/LingFrame/LingFrame" rel="noopener noreferrer"&gt;LingFrame&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is LingFrame? 🛡️
&lt;/h2&gt;

&lt;p&gt;LingFrame is a &lt;strong&gt;JVM runtime governance framework&lt;/strong&gt; for long-running Java applications.&lt;/p&gt;

&lt;p&gt;Think of it as putting guardrails &lt;em&gt;inside&lt;/em&gt; your process. It doesn't replace your architecture; it lets your existing monolith become &lt;em&gt;governable&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Features (The "Why You Should Care" List):
&lt;/h3&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;What it Means for You&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Three-Tier ClassLoader&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Isolated plugins. No more "Jar Hell". Each business module gets its own sandbox.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Capability-Based Security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Plugins must &lt;em&gt;declare&lt;/em&gt; what they need (&lt;code&gt;storage:sql&lt;/code&gt;, &lt;code&gt;cache:local&lt;/code&gt;). Everything else is denied.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;@LingService&lt;/code&gt; &amp;amp; &lt;code&gt;@LingReference&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Expose and consume services across plugin boundaries with simple annotations.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Audit &amp;amp; Trace (&lt;code&gt;@Auditable&lt;/code&gt;)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Every sensitive operation is logged. Who did what, when, and to what resource.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Canary Deployments&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Run a new version of a plugin on a subset of traffic &lt;em&gt;without restarting the JVM&lt;/em&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Show Me The Code (5-Minute Demo) ⏱️
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Add the Starter
&lt;/h3&gt;

&lt;p&gt;In your &lt;strong&gt;Host Application's&lt;/strong&gt; &lt;code&gt;pom.xml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.lingframe&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;lingframe-spring-boot3-starter&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;0.1.0-Preview&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Configure LingFrame
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;application.yaml&lt;/code&gt;:&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;lingframe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;dev-mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;  &lt;span class="c1"&gt;# Logs warnings instead of blocking (for development)&lt;/span&gt;

  &lt;span class="c1"&gt;# Where your plugin JARs live&lt;/span&gt;
  &lt;span class="na"&gt;plugin-home&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;plugins&lt;/span&gt;

  &lt;span class="c1"&gt;# For local development, point directly to source code&lt;/span&gt;
  &lt;span class="na"&gt;plugin-roots&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;../my-user-plugin&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;../my-order-plugin&lt;/span&gt;

  &lt;span class="c1"&gt;# Shared API (interfaces between host and plugins)&lt;/span&gt;
  &lt;span class="na"&gt;preload-api-jars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;shared-api/order-api.jar&lt;/span&gt;

  &lt;span class="c1"&gt;# Enable the visual dashboard&lt;/span&gt;
  &lt;span class="na"&gt;dashboard&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Declare Plugin Capabilities (&lt;code&gt;plugin.yml&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Each plugin must &lt;em&gt;declare&lt;/em&gt; what it intends to access. This is the core of "Zero-Trust".&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;# In your plugin's resources/plugin.yml&lt;/span&gt;
&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user-plugin&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1.0.0&lt;/span&gt;
&lt;span class="na"&gt;mainClass&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;com.example.user.UserPluginApplication&lt;/span&gt;

&lt;span class="na"&gt;governance&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;capabilities&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;capability&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;storage:sql"&lt;/span&gt;
      &lt;span class="na"&gt;accessType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WRITE"&lt;/span&gt;       &lt;span class="c1"&gt;# We need to read/write to DB&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;capability&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cache:local"&lt;/span&gt;
      &lt;span class="na"&gt;accessType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WRITE"&lt;/span&gt;       &lt;span class="c1"&gt;# We need to use the local cache&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;capability&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ipc:order-plugin"&lt;/span&gt;
      &lt;span class="na"&gt;accessType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EXECUTE"&lt;/span&gt;     &lt;span class="c1"&gt;# We want to call the order service&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Annotate Your Services
&lt;/h3&gt;

&lt;p&gt;This is what your plugin code looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="nd"&gt;@RequiredArgsConstructor&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserServiceImpl&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;JdbcTemplate&lt;/span&gt; &lt;span class="n"&gt;jdbcTemplate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@LingService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"query_user"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Query user by ID"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@RequiresPermission&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Capabilities&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;STORAGE_SQL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Declare DB access&lt;/span&gt;
    &lt;span class="nd"&gt;@Cacheable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"users"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"#userId"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;// Also uses cache&lt;/span&gt;
    &lt;span class="nd"&gt;@Auditable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"QUERY_USER"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Audit this&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;queryUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cache miss for user {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;sql&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"SELECT * FROM t_user WHERE id = ?"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;// ... jdbcTemplate query ...&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@LingService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"create_user"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Create a new user"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@RequiresPermission&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Capabilities&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;STORAGE_SQL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@Auditable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"CREATE_USER"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="nf"&gt;createUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ... INSERT SQL ...&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Call Across Plugins with &lt;code&gt;@LingReference&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Need to call &lt;code&gt;user-plugin&lt;/code&gt; from &lt;code&gt;order-plugin&lt;/code&gt;? Don't use &lt;code&gt;@Autowired&lt;/code&gt;. Use &lt;code&gt;@LingReference&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderServiceImpl&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@LingReference&lt;/span&gt; &lt;span class="c1"&gt;// LingFrame routes this to the 'user-plugin'&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;UserQueryService&lt;/span&gt; &lt;span class="n"&gt;userQueryService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@LingService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"get_order"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Get order by ID"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;OrderDTO&lt;/span&gt; &lt;span class="nf"&gt;getOrderById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;orderId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ... get order from DB ...&lt;/span&gt;

        &lt;span class="c1"&gt;// Cross-plugin call (IPC)&lt;/span&gt;
        &lt;span class="n"&gt;userQueryService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;ifPresent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setUserName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  See The Governance in Action 🔥
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Scenario: Unauthorized Write Attempt
&lt;/h3&gt;

&lt;p&gt;Imagine a plugin declares only &lt;code&gt;READ&lt;/code&gt; access to &lt;code&gt;storage:sql&lt;/code&gt;, but then tries to run an &lt;code&gt;INSERT&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"http://localhost:8888/user-plugin/user/createUser?name=Hacker&amp;amp;email=h@ck.er"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; LingFrame blocks it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;c.l.core.exception.PermissionDeniedException: 
Plugin [user-plugin] requires [storage:sql] with [WRITE] access, 
but only allowed: [READ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The plugin fails gracefully. The host app stays alive. The event is audited.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual Dashboard
&lt;/h3&gt;

&lt;p&gt;LingFrame includes a built-in dashboard. You can see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-time plugin status (RUNNING, STOPPED, CANARY)&lt;/li&gt;
&lt;li&gt;Traffic split for Canary deployments&lt;/li&gt;
&lt;li&gt;Live audit logs&lt;/li&gt;
&lt;/ul&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%2Fvx7694ob3htid420787w.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%2Fvx7694ob3htid420787w.png" alt="LingFrame Dashboard" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Not Just Use [OSGi / Spring Cloud / etc.]?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Trade-off&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OSGi&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Very powerful, but has a &lt;em&gt;brutal&lt;/em&gt; learning curve and changes your entire dev lifecycle.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Spring Cloud / K8s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Solves isolation by splitting &lt;em&gt;processes&lt;/em&gt;. This means network hops, serialization, and infrastructure complexity.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;LingFrame&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;In-process isolation. Microservice-like boundaries, but with local method call performance.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;LingFrame is for teams that &lt;strong&gt;can't&lt;/strong&gt; do a full microservices split right now, but &lt;strong&gt;need&lt;/strong&gt; better governance today.&lt;/p&gt;




&lt;h2&gt;
  
  
  Current Status &amp;amp; Roadmap 🗺️
&lt;/h2&gt;

&lt;p&gt;LingFrame is in &lt;strong&gt;v0.1.x Preview&lt;/strong&gt;. The direction is set, but we're still validating the core loop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's Done:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[x] Three-tier ClassLoader isolation&lt;/li&gt;
&lt;li&gt;[x] Capability-based permission model&lt;/li&gt;
&lt;li&gt;[x] Spring Boot 3 integration&lt;/li&gt;
&lt;li&gt;[x] Built-in visual dashboard&lt;/li&gt;
&lt;li&gt;[x] Canary deployment support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What's Next:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] JDK 8 / Spring Boot 2.x compatibility layer&lt;/li&gt;
&lt;li&gt;[ ] Resilience governance (Circuit breaker, Rate limiting, Retry)&lt;/li&gt;
&lt;li&gt;[ ] Observability (Metrics, Distributed tracing export)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Try It Out 🚀
&lt;/h2&gt;

&lt;p&gt;If you're wrestling with an aging monolith and dreaming of better governance, give LingFrame a look.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://github.com/LingFrame/LingFrame" rel="noopener noreferrer"&gt;GitHub: LingFrame/LingFrame&lt;/a&gt;&lt;/strong&gt; ⭐&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to Start:&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;git clone https://github.com/LingFrame/LingFrame.git
&lt;span class="nb"&gt;cd &lt;/span&gt;LingFrame
mvn clean &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-DskipTests&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;lingframe-examples/lingframe-example-host-app
mvn spring-boot:run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then visit &lt;code&gt;http://localhost:8888/dashboard.html&lt;/code&gt; to see the UI.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Star the repo if this resonates with you!&lt;/strong&gt; ⭐&lt;/p&gt;

&lt;p&gt;Drop a comment: What's the messiest legacy system you've had to deal with? How did you handle untrusted code?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(This is Part 1 of my "JVM Runtime Governance" series. Next up: A deep dive into our three-tier ClassLoader architecture!)&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Series: #lingframe-series&lt;br&gt;
 #java #opensource #security #zerotrust #springboot #architecture&lt;/p&gt;

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