Teknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor Haberleri
Yazı Tipi BoyutlandırıcıAa
  • Anasayfa
  • Teknoloji
    • Siber Güvenlik
    • Yapay Zeka
    • Donanım
    • Bilim
  • Yazılım
  • Savunma & İstihbarat
  • Oyun
  • Yaşam
    • Finans
    • Sinema
    • Dünyadan Haberler
  • İş Birliği
Okuma: Yapay Zeka Ajanına Anahtarları Vermek, Ancak Bina Vermemek: Laravel’de RBAC ve Organizasyona Özgü MCP Araçları
Paylaş
Yazı Tipi BoyutlandırıcıAa
Teknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor Haberleri
Ara
Bizi Takip Et
  • Hakkımızda
  • Gizlilik politikası
  • Tanıtım Yazısı ve Backlink Hizmeti
© 2026 Teknomers. All Rights Reserved.

Anasayfa » Yapay Zeka Ajanına Anahtarları Vermek, Ancak Bina Vermemek: Laravel’de RBAC ve Organizasyona Özgü MCP Araçları

Yazılım

Yapay Zeka Ajanına Anahtarları Vermek, Ancak Bina Vermemek: Laravel’de RBAC ve Organizasyona Özgü MCP Araçları

teknomers
Son güncelleme: 25 Haziran 2026 05:09
teknomers
Paylaş
Paylaş
<p>Uygulamanızı bir AI ajanına MCAP üzerinden açmak, kelime anlamıyla bir anahtar kısmını eline verip, sadece açması gereken kapıları açacağını ummaktır. Bu güven, bir hata olma potansiyelidir. Bu hafta, çok kiracılı bir Laravel uygulaması üzerinde bir grup MCP aracını yapılandırdım ve süreç esasen şu soruya odaklandı: <em>Bir ajana uygulamayı sürdürmesine nasıl izin veririm, ama başka birinin verilerine erişmesine nasıl engel olurum?</em></p>

<p>Burada MCP araçları hakkında önemli bir detay var: her biri bir uç noktadır. Bir ajan <code>list_events</code>, <code>publish_event</code>, <code>check_in_participant</code> gibi çağrılar yapar ve sunucunuz, çağrıyı yapanın adına kod çalıştırır. Birden fazla kiracı olduğunda, her bir aracın öncelikle iki soruya cevap vermesi gerekir: <strong>bunu yapmaya yetkin misin</strong> ve <strong>bunu *burada* yapmaya yetkin misin</strong>. Yetkilendirme ve kapsam. Biri atlanırsa, karmaşık bir durum yaratmış olursunuz.</p>

<h2>
    <a name="the-trap-ambient-scope-doesnt-exist-under-token-auth" href="#the-trap-ambient-scope-doesnt-exist-under-token-auth"></a>
    Tuzak: Token auth altında çevresel kapsam mevcut değildir
</h2>

<p>Normal bir web isteğinde, çok kiracılık rahattır. Giriş yapmış bir kullanıcınız, model üzerinde <code>where organization_id = ?</code> kümesiyle global bir kapsam vardır ve çoğunlukla varlığını unuturuz. Her şey düzgün çalışır çünkü oturumda bir "mevcut organizasyon" bulunur.</p>

<p>Ancak MCP araçlarında bu yoktur. Çağıran bir token ile kimlik doğrulaması yapar, oturum yoktur, "mevcut kiracı" bağlamını oluşturan herhangi bir middleware yığına sahip değildir. Eğer bir global <code>OrganizationScope</code>'a dayanıyorsanız ve "mevcut organizasyon" bir yerden okuyorsa, <em>hiçbir şey</em> okur ve varsaydığınız bir sorgu, her kiracının satırını döner. Bu tür bir hata, bir hata fırlatmaz; sessizce sızıntı yapar.</p>

<p>Bu yüzden, benimsediğim kural: <strong>token auth altında, çevresel kapsamdan asla yararlanmayın. Her zaman, kesin olarak filtreleyin, tek bir yerde.</strong></p>

<p>Bu "tek yer", her etkinlik kapsamlı aracın içe aktardığı küçük bir trait'tir:<br/></p>

<div class="highlight js-code-highlight">
    <pre class="highlight php"><code><span class="kd">trait</span> <span class="nc">ResolvesOrgEvents</span>

{
protected function resolveOrgEvent(Authenticatable $user, string $uuid): ?Event
{
if (empty($user->organization_id)) {
return null;
}

    <span class="k">return</span> <span class="nc">Event</span><span class="o">::</span><span class="nf">query</span><span class="p">()</span>
        <span class="o">-&gt;</span><span class="nf">withOrganization</span><span class="p">(</span><span class="nv">$user</span><span class="o">-&gt;</span><span class="n">organization_id</span><span class="p">)</span>
        <span class="o">-&gt;</span><span class="nf">where</span><span class="p">(</span><span class="s1">'uuid'</span><span class="p">,</span> <span class="nv">$uuid</span><span class="p">)</span>
        <span class="o">-&gt;</span><span class="nf">first</span><span class="p">();</span>
<span class="p">}</span>

}

<p>Hiçbir zeka içermeyen bir çözüm — ve bu nokta. Organizasyon filtresi, aktif olmasını umudu içinde beklediğiniz küresel bir kapsam değil; elle uygulanan ve tam olarak bir trait içinde yaşayan bir adlandırılmış sorgu alanı (<code>withOrganization</code>). UUID ile bir etkinlik belirlemek için her ayrıntılı araç bu yoldan geçer. Eğer belirleme <code>null</code> dönerse, araç "organizasyonunuzda bulunamadı" yanıtını verir ve durur. Başka bir kiracıdan gelen bir UUID sorgulayan bir ajan, var olmayan UUID ile aynı yanıtı alır — orak yok, sızıntı yok.</p>

<p>Unutmayın, arama <strong>UUID ile istemektedir, artan otomatik kimlik ile değil</strong>. Kamusal tanıtıcıların tahmin edilemez olması gerekir. Bir ajan (ya da prompt enjekte edilen bir) <code>event/1</code>, <code>event/2</code>, <code>event/3</code> şeklinde sıralamaya girememelidir. Dahili sayısal anahtar, veritabanının dışına çıkmaz.</p>

<h2>
    <a name="authorization-one-ability-per-tool-checked-the-same-way-as-the-web-app" href="#authorization-one-ability-per-tool-checked-the-same-way-as-the-web-app"></a>
    Yetkilendirme: her araç için tek bir yetenek, web uygulamasıyla aynı şekilde kontrol edildi
</h2>

<p>Kapsam sizi kiracınızda tutar. Yetkilendirme, içinde ne yapabileceğinizi belirler. Her araca tek bir beyan edilmiş yetenek verdim:<br/></p>

<div class="highlight js-code-highlight">
    <pre class="highlight php"><code><span class="na">#[Name('event_readiness_check')]</span>

#[Description(‘Check whether an event is ready to publish. Returns ready=true/false and blocking issues.’)]
#[IsReadOnly]
class EventReadinessCheckTool extends McpKitTool
{
use ResolvesOrgEvents;

<span class="k">protected</span> <span class="k">function</span> <span class="n">ability</span><span class="p">():</span> <span class="kt">string</span>
<span class="p">{</span>
    <span class="k">return</span> <span class="s1>'events.view.details'</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">public</span> <span class="k">function</span> <span class="n">handle</span><span class="p">(</span><span class="kt">Request</span> <span class="nv">$request</span><span class="p">):</span> <span class="kt">Response</span>
<span class="p">{</span>
    <span class="nv">$user</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">authorizedUser</span><span class="p">(</span><span class="nv">$request</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="nv">$user</span> <span class="o">===</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">unauthorized</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="nv">$validated</span> <span class="o">=</span> <span class="nv">$request</span><span class="o">-&gt;</span><span class="nf">validate</span><span class="p">([</span>
        <span class="s1>'event'</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="s1>'required'</span><span class="p">,</span> <span class="s1>'string'</span><span class="p">,</span> <span class="s1>'max:36'</span><span class="p">],</span>
    <span class="p">]);</span>

    <span class="nv">$event</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">resolveOrgEvent</span><span class="p">(</span><span class="nv">$user</span><span class="p">,</span> <span class="nv">$validated</span><span class="p">[</span><span class="s1>'event'</span><span class="p">]);</span>

    <span class="k">if</span> <span class="p">(</span><span class="nv">$event</span> <span class="o">===</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nc">Response</span><span class="o">::</span><span class="nf">error</span><span class="p">(</span><span class="s1>'Event not found in your organization.'</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// ... read-only work</span>
<span class="p">}</span>

}

<p>Burada birkaç kasti tercih var.</p>

<p><code>ability()</code> metodu aracın sözleşmesidir — bir satırda "bana çağırmak için bu izne ihtiyaç var" der. Ana <code>McpKitTool</code>, <code>authorizedUser()</code> metodunda kapı kontrolünü yapar, bu yüzden yetki mantığı her <code>handle()</code> içinde kopyalanmaz. Ve kritik olan, <strong>bu yetenek dizesinin web uygulaması ve arka planda mevcut olan eylemle zaten kullanılan aynı dize olmasıdır</strong>. Hazırlık kontrolü <code>events.view.details</code>'a dayanıyor; yayın akışı, yaşam döngüsü eyleminin uyguladığı aynı kapıya dayanıyor. Tek bir izin modeli, üç giriş noktası (web, eylem, MCP). İkincil, paralel bir "ajan ne yapabilir" matrisini sürdürmüyorum; bu ayrım, bir ajanın arkasındaki insandan daha ayrıcalıklı hale gelmesinin tam sebebidir.</p>

<p><code>#[IsReadOnly]</code> anotasyonu, küçük bir dürüstlük sinyalidir. Okuma araçları ve yazma araçları farklı biçimlerde işaretlenir, böylece bir istemci hangi çağrıların yan etkileri olduğunu anlayabilir. <code>list_events</code> ve <code>event_readiness_check</code> yalnızca okuma yapar; <code>publish_event</code> ise bu değildir. İşaretleme, ucuz bir eylemdir ve yıkıcı yüzeyi açık hale getirir.</p>

<p>Ve giriş yine de <code>$request-&gt;validate()</code> üzerinden geçer. Ajan, diğer bir güvenilmeyen istemcidir — <code>max:36</code> UUID alanındaki bir temkinlilik değil, kamuya açık bir form talebine uygulayacağınız aynı hijyendir.</p>

<h2>
    <a name="the-shape-that-emerged" href="#the-shape-that-emerged"></a>
    Ortaya Çıkan Şekil
</h2>

<p>Birkaç araç var oldukça, bu model netleşti ve geri kalanlar neredeyse mekanik hale geldi:</p>

<ul>
    <li>
        <strong>Önce listele.</strong> <code>list_events</code>, giriş noktasıdır — UUID almamanın tek yolu, çünkü ajanın UUID'leri <em>almasına</em> yol açar. Aynı açık filtreleme ile kiracı filtresidir, böylece ajanın dünyası ilk çağrıdan itibaren kendi kiracısıdır.</li>
    <li>
        <strong>Trait üzerinden çöz.</strong> Her etkinlik kapsamlı aracın çözümü, <code>resolveOrgEvent</code> aracılığıyla gerçekleştirilir. Çit, tek bir dosyada yaşamaktadır.</li>
    <li>
        <strong>Gerçek bir yetenek üzerinde gate.</strong> Uygulamanızın izin dizgelerini yeniden kullanın, ajan-açık olarak yeni dizeler oluşturmayın.</li>
    <li>
        <strong>Yan etkileri işaretleyin.</strong> Okuma ve yazma beyan edilmelidir, ima edilmemelidir.</li>
</ul>

<p>Bu eşitlik, herhangi bir tek araçtan daha önemlidir. On beş araç aynı dört kuralı izlediğinde, kuralları <em>denetleyebilirsiniz</em>; on beş ayrı <code>handle()</code> yöntemini denetlemek zorunda kalmazsınız.</p>

<h2>
    <a name="worth-a-test" href="#worth-a-test"></a>
    Test Değeri
</h2>

<p>Organizasyon sınırı, bugün doğru bir şekilde yapılması kolay ancak altı ay sonra birinin "sorguyu optimize etmesi"yle sessizce bozulma potansiyeli olan bir şeydir. Dolayısıyla doğrudan sınırı doğrulayan bir Pest testi alıyor — "mutlu yol çalışıyor mu değil" değil ama "yanlış kiracı hiçbir şey alıyor mu":<br/></p>

<div class="highlight js-code-highlight">
    <pre class="highlight php"><code><span class="nf">it</span><span class="p">(</span><span class="s1>'never resolves an event from another organization'</span><span class="p">,</span> <span class="k">function</span> <span class="p">()</span> <span class="p">{</span>
        <span class="nv">$mine</span> <span class="o">=</span> <span class="nc">Event</span><span class="o">::</span><span class="nf">factory</span><span class="p">()</span><span class="o">-&gt;</span><span class="k">for</span><span class="p">(</span><span class="nv">$orgA</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">create</span><span class="p">();</span>
        <span class="nv">$theirs</span> <span class="o">=</span> <span class="nc">Event</span><span class="o">::</span><span class="nf">factory</span><span class="p">()</span><span class="o">-&gt;</span><span class="k">for</span><span class="p">(</span><span class="nv">$orgB</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">create</span><span class="p">();</span>

        <span class="nv">$user</span> <span class="o">=</span> <span class="nc">User</span><span class="o">::</span><span class="nf">factory</span><span class="p">()</span><span class="o">-&gt;</span><span class="k">for</span><span class="p">(</span><span class="nv">$orgA</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">create</span><span class="p">();</span>

        <span class="nf">expect</span><span class="p">(</span><span class="nf">resolveOrgEvent</span><span class="p">(</span><span class="nv">$user</span><span class="p">,</span> <span class="nv">$mine</span><span class="o">-&gt;</span><span class="n">uuid</span><span class="p">))</span><span class="o">-&gt;</span><span class="n">not</span><span class="o">-&gt;</span><span class="nf">toBeNull</span><span class="p">()</span>
            <span class="o">-&gt;</span><span class="k">and</span><span class="p">(</span><span class="nf">resolveOrgEvent</span><span class="p">(</span><span class="nv">$user</span><span class="p">,</span> <span class="nv">$theirs</span><span class="o">-&gt;</span><span class="n">uuid</span><span class="p">))</span><span class="o">-&gt;</span><span class="nf">toBeNull</span><span class="p">();</span>
    <span class="p">});</span>

    <span class="nf">it</span><span class="p">(</span><span class="s1>'returns null when the user has no organization'</span><span class="p">,</span> <span class="k">function</span> <span class="p">()</span> <span class="p">{</span>
        <span class="nv">$user</span> <span class="o">=</span> <span class="nc">User</span><span class="o">::</span><span class="nf">factory</span><span class="p">()</span><span class="o">-&gt;</span><span class="nf">create</span><span class="p">([</span><span class="s1>'organization_id'</span> <span class="o">=&gt;</span> <span class="kc">null</span><span class="p">]);</span>

        <span class="nf">expect</span><span class="p">(</span><span class="nf">resolveOrgEvent</span><span class="p">(</span><span class="nv">$user</span><span class="p">,</span> <span class="nc">Event</span><span class="o">::</span><span class="nf">factory</span><span class="p">()</span><span class="o">-&gt;</span><span class="nf">create</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">uuid</span><span class="p">))</span>
            <span class="o">-&gt;</span><span class="nf">toBeNull</span><span class="p">();</span>
    <span class="p">});</span>
</code></pre>
</div>

<p>İkinci durum — hiçbir organizasyon bağlamına sahip olmayan bir kullanıcı — unutulan durumdur. Token auth altında, kesinlikle kiracı ile ilişkilendirilmemiş bir yetkilendirilmiş varlık elde edebilirsiniz ve "hiçbir org" bu durumda erek olarak "tüm erişimi" değil, "hiçbir erişimi" temsil etmelidir.</p>

<h2>
    <a name="takeaway" href="#takeaway"></a>
    Özet
</h2>

<p>MCP, uygulamanızı bir ajana açmayı gerçekten kolay hale getiriyor — belki de biraz <em>çok</em> kolay. Bir aracın kaydedilmesi mekanikleri basittir; disiplin tamamen sınırlar içindedir. Her aracı güvenilmeyen bir uç nokta olarak değerlendirin: açık kiracı kapsamı (asla çevresel, token auth altında), her araç için yeniden kullanılan mevcut izin modelini baz alarak tek bir beyan edilmiş yetenek, tahmin edilemeyen UUID'ler ve okuma/yazma dürüstlüğü. Çiti tek bir trait içinde yerleştirin, böylece doğru yapabileceğiniz tek bir yer olacak — ve kontrol edebileceğiniz tek bir yer.</p>

<p>Bir ajan, arkasındaki insanın yapabileceği her şeyi yapabilmeli; tam olarak ait olduğu kiracıda ve hiçbir fazlasında. Bu AI sorunu değil. Her zaman ihtiyaç duyduğumuz çok kiracılık ve yetkilendirme disiplinidir — MCP, dikkatsiz olmayı kolaylaştıran tüm bahaneleri ortadan kaldırıyor.</p>

Kaynak: Orijinal Makale

Harici API’leri Koruma: Laravel’de Redis Token Bucket Kullanımı
Yakınlaştırma güncellemesi, daha verimli toplantılar için hızlı bir hack sağlar
Neden “Soft Delete” Uygulamalarından Vazgeçip S3’ü Tercih Ettim: Fiziksel Temizleme İş Akışı Oluşturma
Ücretsiz 5 Bölümlük Laravel Giriş Serisi
SaaS altyapıma bir denetim günlükü çıkardım ve inceleme yanlış bir şeyi kaydettiğini tespit etti.
Bu Makaleyi Paylaş
Facebook Bağlantıyı Kopyala Yazdır
Paylaş
Önceki Makale GTA 6 ön siparişleri bu gece başlıyor; hemen al, garajda bekliyor!
Sonraki Makale Google Arama’nın Yeni AI Veri Eğitim Özelliğinden Nasıl Çıkılır?

Sanal Medya

FacebookBeğen
452Takip Et
PinterestSabitle
237Takip Et

Son Eklenenler

Amazon Prime Günü’nde en iyi PC donanım fırsatları 3. günde
Donanım
Kritik: Cisco Catalyst SD-WAN Sıfır Günü Açığı ile Kök Erişimi!
Siber Güvenlik
Valve’ın Steam Machine fiyat artışı, RAMpocalypse öncesi PS5 Pro ile rekabetçi fiyatlandırıldı
Donanım
2026 Prime Günü’nde Yüzde 50 İndirimli En İyi Sahte Noel Ağaçları!
Genel
Bant Genişliğini Kayıp Etmeyin: ETag ile API Ön Belleklemesini Ustaca Yapın ⚡
Yazılım
Bambu Lab Prime Day İndirimleri: 3D Yazıcılarda %52’ye Varan İndirimler
Donanım
//

Siber güvenlik, yapay zeka ve savunma sanayiinden; finans ve sinema dünyasına uzanan geniş bir yelpaze. Teknomers; teknoloji, strateji ve yazılım dünyasını sade bir dille sizlerle buluşturuyor.

Kurumsal

  • Hakkımızda
  • Gizlilik politikası
  • Tanıtım Yazısı ve Backlink Hizmeti

Kategoriler

  • Teknoloji
  • Oyun
  • Sinema
  • Siber Güvenlik
  • Bilim
  • Finans
  • Dünyadan Güncel Haberler

Populer

  • TV'de Ücretsiz İzlenebilen Şifresiz Erotik Kanallar (2025 Güncel Frekans Listesi)

  • The Last of Us PC Kontrolleri: Hızlı Silah Değiştirme ve Tüm Tuşlar (2025)

  • Hogwarts Legacy'de Odaklanma İksiri Nasıl Yapılır?

Teknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor Haberleri
Bizi Takip Et
© 2026 Teknomers. All Rights Reserved.
Welcome Back!

Sign in to your account

Kullanıcı Adı veya E-posta Adresi
Şifre

Şifrenizi mi unuttunuz?