İçeriğe geç
getnextpdf.com

Enterprise sürüm

SaaS — Derinlemesine başvuru

Enterprise SaaS modülü, NextPDF tabanlı bir hizmet için çok kiracılı yapı taşlarını sağlar.

  • TenantContext, yalnızca kimliği doğrulanmış bağlamdan çözümlenen, değişmez bir kimlik değer nesnesidir.
  • ApiKeyGenerator ve ApiKeyAuthenticator, önekli, sağlama toplamlı ve karma olarak saklanan API anahtarlarını üretir ve doğrular.
  • QuotaChecker, istekleri kiracı başına kotalara göre geçitler: %80’de uyarır, %100’de reddeder, kullanım bilinmediğinde fail-closed olarak reddeder.
  • SidecarJwtMinter, bileşenler arası çağrılar için kısa ömürlü HS256 hizmet token’ları üretir.
  • UsageMeter ve StripeMeteringSyncer, kullanım olaylarını çeker ve bunları belirlenimci idempotensi ile faturalama sağlayıcısına eşitler.

Bu yetenek NextPDF Enterprise (nextpdf/enterprise) içinde sevk edilir ve Enterprise katmanı lisans zarfıyla etkinleşir. Bu yetkilendirmeye sahip olmayan bir dağıtım, yeteneğin sınıflarını yüklemez. Sürümleri karşılaştırın ve lisans alın.

SaaS yüzeyi temel bir Enterprise yeteneğidir; özellik başına ayrı bir bayrak yoktur. NextPDF Core (Apache-2.0) ve NextPDF Pro’nun kiracılık, API anahtarı veya kota modeli yoktur; bu yeteneğin daha alt katmanda bir eşdeğeri yoktur.

Terminal window
composer require nextpdf/enterprise:^3

Tüm semboller NextPDF\Enterprise\SaaS altında yer alır.

SembolParametrelerVarsayılan davranışDöndürürFırlatır veya şununla başarısız olurNotlar
TenantContextstring $tenantId, string $source, array $scopes = ['read']Değişmez kimlik değer nesnesideğer nesnesiYokKaynaklar: jwt, mtls, api_key; hasScope() / hasAnyScope() kapsamları test eder
TenantContext::singleTenant()yokread, write, admin ile sabit default kiracıTenantContextYokTek kiracılı dağıtımlar
ApiKeyAuthenticator::authenticate()string $rawKeyAltı adımlı doğrulama, ardından bağlam çözümlemeTenantContextApiKeyAuthenticationException (HTTP 401)Bağlam source değeri api_key’dir; kapsamlar anahtar kaydından kopyalanır
ApiKeyAuthenticator::requireScope()TenantContext $context, ApiKeyScope $requiredScopeAçık kapsam doğrulamasıvoidApiKeyAuthenticationException::insufficientScope() (HTTP 403)Kapsam zorlaması ayrı, açık bir adımdır
ApiKeyGenerator::generateLive() / ::generateTest()yokYeni anahtar: önek, 32 karakterlik base62 gövde (192 bit entropi), 4 karakterlik sağlama toplamıarray{key, hash, prefix}YokÖnekler npf_live_ / npf_test_; hash depolama özetidir
ApiKeyGenerator::validateChecksum()string $keyÖnek, uzunluk ve CRC32 sağlama toplamı biçim denetimiboolYokHerhangi bir veri deposu aramasından önce yazım hatası koruması; bir güvenlik denetimi değil
ApiKeyGenerator::hashKey() (statik)string $keyHam anahtarın SHA-256 onaltılık özetistringYokBir anahtarın saklanan tek gösterimi
ApiKeyGenerator::isLiveKey() / ::isTestKey()string $keyÖnek incelemesiboolYokOrtam, bir arama olmadan görünür
ApiKeykimlik, kiracı, anahtar karması, görüntü öneki, kapsam maskesi, oluşturma/sona erme/iptal anlarıSaklanan anahtar kaydı; düz metin asla kalıcılaştırılmazdeğer nesnesiYokisActive(), isRevoked(), isExpired(), scopeNames()
ApiKeyScopedestekli enum: Read = 1, Write = 2, Admin = 4Bit maskesi kapsam modelienumYokmaskFromNames(), fromName(), fullAccess(); bilinmeyen adlar maske oluşturucu tarafından yok sayılır
ApiKeyRepositoryInterfaceDepolama sözleşmesi; yalnızca karma kalıcılaştırmaUygulama tanımlıfindByHash(), findActiveByTenant(), store(), revoke()
SidecarJwtMinter::__construct()string $secret, issuer, audience, int $ttlSeconds = 300Yapım sırasında 16 bayttan küçük bir imzalama sırrını reddederörnekInvalidArgumentException128 bit anahtar-gücü tabanı; 32 veya daha fazla rastgele bayt önerilir
SidecarJwtMinter::mint()TenantContext $tenantiss, aud, sub, scope, tenant_id, iat, exp, jti içeren HS256 JWTstringTalep kodlama başarısızlığında JsonExceptionBeş dakikalık varsayılan ömür; jti, onaltılık kodlanmış 16 rastgele bayttır
QuotaChecker::check()TenantContext $tenant, TenantQuota $quotaGeçerli kullanımı okur; %80’de uyarır; %100’de reddeder; kullanım bilinmediğinde reddederarray{allowed: bool, warning_percentage: float|null}QuotaExceededException, QuotaUnavailableExceptionUyarı geri çağrısı her iki eşikte de çağrılır
TenantQuotafloat $maxCuPerPeriod, koleksiyonlar, depolama baytları, eşzamanlı işlerDönem başına limitler; %80 yumuşak eşik sabitideğer nesnesiYokfromConfig() varsayılanları: 10,000 CU, 100 koleksiyon, 10 GB, 10 iş
QuotaExceededException::toErrorEnvelope()yokSPEC-QUOTA-001 hata zarfıarrayHTTP 402, yeniden denenebilir değil; geçerli değeri, limiti ve sıfırlama anını taşır
QuotaUnavailableException::toErrorEnvelope()yokSPEC-QUOTA-503 hata zarfıarrayHTTP 503, yeniden denenebilir; neden usage_undeterminable
UsageMeter::pullUsage()array<string, int> $watermarksYapılandırılmış her kullanım-kaynağı ana makinesini imlecinden yoklararray{events, instance_id}Her ana makine erişilemez olduğunda UsageMeterExceptionKısmi kesinti tolere edilir; erişilemeyen ana makineler günlüğe kaydedilir ve atlanır
UsageMeter::getCurrentUsage()string $tenantIdGeçerli dönem hesaplama-birimi kullanımıfloatKullanım belirlenemez olduğunda UsageMeterExceptionAyrıştırılabilir bir sıfır yetkilidir; bilinmeyen kullanım fırlatır
StripeMeteringSyncer::sync()array<string, int> $watermarksBir çekme, dönüştürme, gönderme döngüsüarray{watermarks, sent, failed}Yok; gönderme başarısızlıkları DLQ geri çağrısına yönlendirilirÇekme başarısızlığı, imleci koruyan işlemsiz bir döngü döndürür
StripeAdapter::sendMeterEvent()MeterEvent $eventBir idempotensi başlığıyla sağlayıcıya POSTvoidStripeSyncExceptionHTTP 429 ve 5xx yeniden denenebilir; diğer 4xx yeniden denenebilir değil
StripeAdapter::sendBatch()list<MeterEvent> $eventsHer olayı gönderir; başarısızlıkları toplarlist<StripeSyncException>YokBoş liste, her olayın başarılı olduğu anlamına gelir
MeterEventölçer adı, kiracı, değer, idempotensi anahtarı, zaman damgasıDeğişmez ölçer-olayı değer nesnesideğer nesnesiYoktoStripePayload(), sağlayıcı yükünü serileştirir
final readonly class ApiKeyAuthenticator
{
public function __construct(
private ApiKeyRepositoryInterface $repository,
private ApiKeyGenerator $generator,
private LoggerInterface $logger,
) {}
public function authenticate(string $rawKey): TenantContext {}
public function requireScope(TenantContext $context, ApiKeyScope $requiredScope): void {}
}
final class QuotaChecker
{
public function __construct(
private readonly UsageMeterInterface $usageMeter,
private readonly LoggerInterface $logger,
private readonly Closure $quotaAlertCallback,
) {}
/** @return array{allowed: bool, warning_percentage: float|null} */
public function check(TenantContext $tenant, TenantQuota $quota): array {}
}
interface UsageMeterInterface
{
/** @return array<string, mixed> */
public function pullUsage(array $watermarks): array;
public function getCurrentUsage(string $tenantId): float;
}
final class StripeMeteringSyncer
{
public function __construct(
private readonly UsageMeterInterface $usageMeter,
private readonly StripeAdapterInterface $stripeAdapter,
private readonly LoggerInterface $logger,
private readonly Closure $dlqCallback,
) {}
/** @return array{watermarks: array<string, int>, sent: int, failed: int} */
public function sync(array $watermarks): array {}
}
final readonly class SidecarJwtMinter
{
public function __construct(
private string $secret,
private string $issuer = 'nextpdf-enterprise',
private string $audience = 'nextpdf-spectrum',
private int $ttlSeconds = self::DEFAULT_TTL_SECONDS,
) {}
public function mint(TenantContext $tenant): string {}
}
  • Kiracı kimliği. Bir kiracı bağlamı değişmezdir: kiracı tanımlayıcısı, çözümleme kaynağı, kapsamlar. Kimlik yalnızca kimliği doğrulanmış bağlamdan çözümlenir (jwt, mtls, api_key) — asla istemci tarafından sağlanan bir başlıktan veya sorgu parametresinden değil. Tek kiracılı bir dağıtım, tam kapsamlara sahip sabit default bağlamını kullanır.
  • Kimlik doğrulama sırası. API anahtarı kimlik doğrulaması sabit bir sırayla ilerler: sağlama toplamı, SHA-256 karma, depo araması, iptal denetimi, süre denetimi, bağlam çözümleme. Bilinmeyen, iptal edilmiş ve süresi dolmuş anahtarlar üç farklı sonuçtur, hepsi HTTP 401; yetersiz kapsam ise HTTP 403’tür.
  • Anahtar gizliliği. Ham anahtar asla saklanmaz veya günlüğe kaydedilmez; yalnızca SHA-256 özeti kalıcılaştırılır ve aranır. Kimlik doğrulayıcı, kendisi bayt bazlı bir sır karşılaştırması yapmaz; sabit zamanlı özet araması, depo uygulamasının sözleşmesidir.
  • Kota eşikleri. %80 yumuşak sınırında istek devam eder, uyarı yüzdesi döndürülür ve uyarı geri çağrısı tetiklenir. %100 sert sınırında istek, sıfırlama anını taşıyan SPEC-QUOTA-001 (HTTP 402) ile reddedilir — sonraki ayın ilk günü, gece yarısı UTC.
  • Kota fail-closed. Belirlenemez kullanım, isteği SPEC-QUOTA-503 (HTTP 503, yeniden denenebilir) ile reddeder. Bilinmeyen kullanım asla sıfır olarak değerlendirilmez. Gerçek, ayrıştırılabilir bir sıfır kullanım yetkilidir ve kabul eder.
  • Uyarı yineleme giderme. Denetleyici uyarıları yineleme gidermez; dönem başına yineleme giderme, geri çağrının sorumluluğudur.
  • Ölçümleme eşitleme. Döngü zamanlanmıştır, asla istek yolunda değildir. Kaynak başına imleçlerden devam eder ve her imleci başarıyla gönderilen en yüksek olay kimliğine ilerletir. İdempotensi anahtarı belirlenimcidir — kiracı, dönem, olay kimliği — böylece yeniden gönderilen bir olay, sağlayıcının yineleme gidermesinde birleşir.
  • Çekme başarısızlığı. Başarısız bir çekme, imleçleri koruyan işlemsiz bir döngü (sent 0, failed 0) döndürür; sonraki döngü, pencereyi atlamak yerine aynı pencereyi yeniden dener.
  • Hizmet token’ları. Token’lar, paylaşılan bir sırla HS256’dır ve iss, aud, sub, scope, tenant_id, iat, exp ile benzersiz bir jti taşır. Varsayılan ömür beş dakikadır. Yapım, 16 bayttan küçük bir sırrı fail-closed olarak reddeder.
  • Hatalı biçimli bir anahtar sağlama toplamında başarısız olur ve herhangi bir veri deposu erişiminden önce reddedilir. İyi biçimli ama bilinmeyen bir anahtar, aramadan sonra reddedilir. Her ikisi de geçersiz-anahtar sonucu olarak ortaya çıkar.
  • Bilinmeyen, iptal edilmiş ve süresi dolmuş anahtarlar farklı istisna fabrikaları kullanır; keyExpired bayrağı yalnızca süresi-dolmuş sonucunda true’dur. Bunları farklı istemci yanıtlarına eşleyin.
  • QuotaChecker::check() yalnızca kabulde döner; döndürülen allowed her zaman true’dur. Reddetme ve kullanılamama, istisnai sonuçlardır.
  • TenantQuota::usagePercentage(), pozitif olmayan bir kota için 0.0 döndürür; fromConfig(), eksik değerler için varsayılanları koyar ve tam sayı limitlerini en az 1’e sıkıştırır.
  • İmleçler kaynak başınadır; eksik bir imleç, o kaynağın akışının başından (imleç 0) başlar. Çok kaynaklı bir dağıtım, bağımsız imleçler tutar.
  • Dönüşüm; dizi olmayan olayları, eksik veya boş bir işleme ya da kiracıya sahip olayları, pozitif olmayan bir değere sahip olayları veya eşlenmemiş bir işleme sahip olayları — döngüyü başarısız kılmadan — atlar. Kullanılabilir bir pozitif tam sayı kimliğinden yoksun bir olay, bir uyarıyla reddedilir: rastgele bir yedek anahtar, sağlayıcı tarafındaki yineleme gidermeyi bozar ve kiracıyı iki kez faturalandırabilir.
  • Ardışık on gönderme başarısızlığı, kritik bir günlük kaydına yükselir; sayaç, herhangi bir başarılı göndermede sıfırlanır. Her başarısız olay yine de ölü-mektup geri çağrısına ulaşır.
  • Bir kullanım-kaynağı ana makinesinden gelen hatalı biçimli bir JSON gövdesi, bir döngü başarısızlığı değil, boş bir olay listesi verir. pullUsage() yalnızca yapılandırılmış her ana makine erişilemez olduğunda fırlatır.
  • Özet ve MAC ilkelleri, ana makine PHP kripto sağlayıcısı üzerinden SHA-256 ve HMAC-SHA256’dır. FIPS kısıtlamalı bir derleme, düşürmek yerine onaylanmamış bir algoritmada fail-closed olur; SaaS katmanı kendine ait hiçbir kriptografik politika eklemez.
  • Anahtar gövdeleri ve token tanımlayıcıları CSPRNG’den (random_int(), random_bytes()) gelir.
  • CRC32 sağlama toplamı bir kriptografik denetim değildir ve FIPS modundan etkilenmez.

Aşağıdaki ifadeler, yeteneği atıf yapılan maddelere göre açıklar. Bunlar sertifikasyon iddiaları değildir; NextPDF bu modül için hiçbir sertifikasyona sahip değildir.

DavranışReferans
Hizmet-token exp son-tarih anlambilimiRFC 7519 §4.1.4
Hizmet-token JWS kompakt serileştirmesiRFC 7515 §3.1
16 baytlık HS256 sır tabanı; MAC anahtarı olarak insan-hatırlanabilir parola yokRFC 8725 §3.5 (tehdit: §2.2)
Depo özet-araması sabit-zaman sözleşmesiOWASP ASVS 5.0 §11.2.4
API anahtarı depolama özeti SHA-256FIPS 180-4 (kodda bildirilmiş)

RFC 8725 ve OWASP ASVS 5.0 atıfları RAG-doğrulanmıştır; tam referans tanımlayıcıları bu sayfanın frontmatter’ında kayıtlıdır. FIPS 180-4, FIPS 198-1 ve BSI TR-02102-1 referansları ürün kaynağında kodda bildirilmiştir (hash('sha256', …) ve üretecin belgelenmiş anahtar tabanı); bunlar bu sayfa için RAG bütüncesinden alınmamıştır. ASVS §11.2.4’ün sabit-zaman gereksinimi, kimlik doğrulayıcı sınıfının kendisini değil, operatörün sağladığı depo uygulamasını bağlar.

  • ApiKeyRepositoryInterface ve StripeAdapterInterface için kalıcı uygulamalar sağlayın; paket, kalıcılığı değil, sözleşmeleri ve bir PSR-18 sağlayıcı istemcisini sevk eder.
  • Bağımlılıklar yalnızca PSR soyutlamalarıdır: PSR-3 logger, PSR-18 HTTP istemcisi, PSR-17 istek ve akış fabrikaları. Hiçbir sağlayıcı SDK’sı gerekmez.
  • Ölçümleme eşitlemesini zamanlanmış bir iş olarak çalıştırın. Döndürülen imleçleri her döngüden sonra kalıcı olarak saklayın.
  • Kota uyarı yüzdesini istemcilere gösterin, örneğin bir uyarı başlığı olarak, ve kota uyarılarını geri çağrıda dönem başına yineleme giderin.
  • Token-üreteci sırrını yapılandırmadan yüksek-entropili rastgele bir değer olarak sağlayın; 32 veya daha fazla rastgele bayt önerilir. Bunu asla bir paroladan türetmeyin.
  • Anahtar önekleri, ortamı bir arama olmadan görünür kılar; sandbox ve production anahtarları asla çakışmaz çünkü önek, saklanan özete katılır.
  • Dahilî mekanizma ayrıntısı, kaynak deposunun dahilî belgelerinde kalır ve bu kılavuzun kapsamı dışındadır.

Bu sayfa yalnızca dışarıdan gözlemlenebilir davranışı ve desteklenen genel API yüzeyini belgeler. Dahilî ad alanı yolları, yardımcı sınıflar, mekanizma tabloları, runbook dosya adları ve bilet önekleri kapsam dışıdır.