API Uç Noktaları İçin AI Metadata
lvntr/api-dock, App\Http\Controllers\Api\* altındaki controller sınıf ve metotlarından altı PHP attribute'unu okuyup üretilen OpenAPI dokümanına vendor extension olarak ekler. Amaçları, bir uç noktayı parametre ve response şeklinin zaten söylediğinin ötesinde bir AI ajanına (ya da /api-dock'ta gezinen bir insana) kendini anlatır hale getirmek: bir alanın neden öyle davrandığı, nerede tuzak olduğu, çalıştırılabilir bir örnek, işlemin MCP tool olarak dışa açılıp açılmadığı ve davranış değişikliklerinin insan tarafından yazılmış geçmişi.
Hiçbiri zorunlu değil. Attribute eklenmemiş bir controller yalnızca Scramble ile de düzgün dokümante olur; attribute'ları yalnızca temel OpenAPI çıktısının söylemediği bir şey varsa ekleyin.
Altı Attribute
Kaynak: vendor/lvntr/api-dock/src/Attributes/.
| Attribute | Hedef | Tekrarlanabilir | Constructor |
|---|---|---|---|
AiHint |
sınıf veya metot | hayır | string $hint |
AiPitfall |
sınıf veya metot | evet | string $text, int $order = 0 |
AiChangelog |
sınıf veya metot | evet | string $date, string $summary, bool $breaking = false |
AiExample |
sınıf veya metot | evet | string $name, array $request = [], array $response = [] |
AiTool |
sınıf veya metot | hayır | bool $enabled = true, ?string $name = null, ?string $description = null |
ApiFeature |
sınıf veya metot | hayır | ?string $auth = null, ?array $scopes = null, ?int $rateLimit = null, ?string $rateLimitPer = null, ?bool $deprecated = null, ?string $stability = null |
AiHint, AiTool ve ApiFeature tekil değerlidir: aynı sınıf veya metoda ikincisini eklemek fazladan olanın okunmadan kalmasına yol açar (yalnızca ilk attribute örneği alınır). AiPitfall, AiChangelog ve AiExample ise IS_REPEATABLE olarak tanımlanmıştır ve üst üste eklenmek üzere tasarlanmıştır.
Birleştirme Sırası
Her işlem için AiMetadataOperationExtension ve FeatureOperationExtension, önce sınıf seviyesindeki attribute'ları, sonra metot seviyesindekileri okur ve şu şekilde birleştirir:
AiHint: metot seviyesinde varsa doğrudan o kazanır, yoksa sınıf seviyesindeki hint kullanılır. Birleştirme yoktur — dokümana yalnızca tek bir hint ulaşır.AiPitfall: sınıf ve metot pitfall'ları art arda eklenir, ardındanorderalanına göre kararlı (stable) biçimde sıralanır (eşitlik durumunda bildirim sırası korunur — sınıf metottan önce).AiChangelog: sınıf ve metot girdileri art arda eklenir, ardından en yeni tarih önce gelecek şekilde sıralanır;datealanı ayrıştırılamayan girdiler en sona düşer, eşitlikte bildirim sırası korunur.AiExample: önce sınıf örnekleri, sonra metot örnekleri, bu sırayla — sıralama veya tekilleştirme yapılmaz.AiTool: metot seviyesinde varsa doğrudan o kazanır, yoksa sınıf attribute'u kullanılır (AiHintile aynı tekil-değer kuralı).ApiFeature: bu attribute tek bir örneği seçmek yerine alan alan birleşir. Sınıf seviyesindekiApiFeature'ınnullolmayan her alanı uygulanır, ardından metot seviyesindekininnullolmayan her alanı bunun üzerine uygulanır — yani metot attribute'u yalnızca kendi belirlediği alanları geçersiz kılar venullbir alan önceki değeri değiştirmeden bırakır.auth,rateLimit/rateLimitPer,deprecatedvestabilityalanları, herhangi birApiFeatureoverride'ı uygulanmadan önce ayrıca route middleware'inden (auth,can/ability/permission/scope*,throttle) ve#[Deprecated]attribute'undan da beslenir.
Üretilen Vendor Extension'lar
Her attribute değeri, üretilen OpenAPI işleminde x- önekli bir anahtar altına yerleşir:
| Extension anahtarı | Kaynak attribute(lar) |
|---|---|
x-ai-hint |
AiHint |
x-ai-pitfalls |
AiPitfall (sıralı dizi) |
x-ai-examples |
AiExample (dizi) |
x-ai-tool |
AiTool ({enabled, name, description}) |
x-api-dock-changelog |
AiChangelog (sıralı dizi) |
x-api-dock-features |
ApiFeature + çıkarımlanan middleware ({auth, scopes, rate_limit, deprecated, stability}) |
Uygulamalı Örnek
Kit'in kendi App\Http\Controllers\Api\UserController sınıfındaki (stubs/app/Http/Controllers/Api/UserController.php) store() metodunu, to_api() ile zaten ApiResponse zarfı üzerinden dönen haliyle, işaretlemek:
use Lvntr\ApiDock\Attributes\AiChangelog;
use Lvntr\ApiDock\Attributes\AiExample;
use Lvntr\ApiDock\Attributes\AiHint;
use Lvntr\ApiDock\Attributes\AiPitfall;
use Lvntr\ApiDock\Attributes\ApiFeature;
#[AiHint('Yönetici tarafından yönetilen bir kullanıcı oluşturur; çağıranın zaten users.create yetkisi olmalı.')]
#[ApiFeature(scopes: ['users.create'])]
class UserController extends Controller
{
#[AiPitfall('email, aktif VE soft-delete edilmiş kullanıcılar arasında benzersiz olmalı — yeniden davet, hata vermek yerine mevcut satırı yeniden kullanır.', order: 1)]
#[AiPitfall('roles oluştururken opsiyoneldir; boş bırakılması kullanıcıyı varsayılan bir rolle değil, rolsüz bırakır.', order: 2)]
#[AiExample(
name: 'Destek personeli oluştur',
request: ['first_name' => 'Ada', 'last_name' => 'Lovelace', 'email' => 'ada@example.com', 'roles' => ['support']],
response: ['success' => true, 'status' => 201, 'message' => 'User created successfully.'],
)]
#[AiChangelog(date: '2026-08-01', summary: 'roles opsiyonel hale geldi; önceden zorunluydu.', breaking: true)]
public function store(StoreUserRequest $request, CreateUserAction $action): ApiResponse
{
// ...
}
}
Sınıf seviyesindeki AiHint ve ApiFeature, bir metot bunları geçersiz kılmadığı sürece controller'daki tüm metotlara (index, show, update, destroy dahil) uygulanır; yukarıdaki pitfall'lar, örnek ve changelog ise yalnızca store()'a özeldir.
Dışa Aktarım Yüzeyi
php artisan api-dock:export, aynı işaretlenmiş OpenAPI dokümanından üretilen AI odaklı çıktıları yazar:
--llms→llms.txt, bir LLM bağlam penceresine yapıştırılmak veya/llms.txtaltında servis edilmek üzere API'nin düz metin özeti.--mcp→mcp-tools.json, MCP (Model Context Protocol) tool tanımları.config/api-dock.phpiçindekiapi-dock.ai.mcp_opt_intrueyapıldığında yalnızcaAiToolattribute'u taşıyan işlemler dışa aktarılır; varsayılanfalseiken her işlem uygundur.--openapi→ extension'lar dahil, düz üretilmişopenapi.json.
Çıktılar config('api-dock.ai.export_path') konumuna yazılır (varsayılan storage_path('api-dock')).
Ayrıca php artisan api-dock:sync, OpenAPI dokümanını yeniden üretir, config('api-dock.snapshot.path') konumundaki saklanan snapshot ile karşılaştırır, breaking / additive / cosmetic değişiklikleri raporlar (makine-okur biçim için api-dock:diff --json) ve snapshot'ı günceller.
AiChangelog ile snapshot diff'i bilinçli olarak birbirinden farklı iki şeydir. AiChangelog, dokümantasyon panelini veya llms.txt'i okuyan bir insan entegratöre yönelik, elle yazılan bir attribute'tur — summary'de ne yazarsanız onu söyler, hatırladığınız her ne sıklıkta yazarsanız o sıklıkta. Snapshot diff'i ise iki OpenAPI dokümanının alan alan karşılaştırılmasından makine tarafından üretilir — kimse yazmasa da her şema kaymasını yakalar. Diff'i bir şeyin değiştiğini tespit etmek için, AiChangelog'u ise neden değiştiğini ve ne yapılması gerektiğini söylemek için kullanın. Hiçbiri diğerinin yerini tutmaz.
Güvenlik
/api-dock panelinin içindeki try-it proxy'si varsayılan olarak açıktır (config('api-dock.try_it.enabled')), ancak try_it.allowed_hosts ve try_it.self_hosts her ikisi de boş gelir — boş oldukları sürece proxy yalnızca bu uygulamanın kendi host'una ulaşabilir, keyfi bir yabancı host'a değil (bir girdi eklemeden önce SSRF-yüzeyi gerekçesi için stubs/config/api-dock.php dosyasına bakın).
/api-dock yüzeyinin tamamı — panel, spec, try-it proxy'si ve kimlik-bilgisi-profili uç noktaları — ['web', 'auth', CheckApiDocsAccess::class] (config('api-dock.middleware')) arkasındadır ve Gate::allows('viewApiDocs') sağlanmadıkça reddeder. Kit bu gate'i, varsayılan olarak developer rolüne verilen, seed edilmiş api-docs.read yetki yeteneğine bağlar (config/permission-resources.php) ve kapalı tarafta hata verir: seed edilmemiş bir yetenek, izin vermek yerine reddeder.