GNL 0.17: erken aşamada ve hızlı ilerliyor — API'ler sürümden sürüme değişebilirBize katıl

GNL
Dokümanlar menüsü
Core · Ücretsiz@gnldev/server

Çok organizasyonluluk (organizasyon izolasyonu)

Açık çekirdekte ücretsiz: her isteği bir organizasyonun izole journal'ına indirir (withOrg); run'lar, memory ve exactly-once garantileri organizasyon başına ayrışır, kimliğe bağlı organizasyon header'ı ezer (uyuşmazlıkta 403).

Ne işe yarar / ne zaman kullanılır#

Tek bir GNL dağıtımıyla birden çok müşteriye (organizasyona) hizmet vermek istediğinde — ör. bir SaaS ürününde her müşterinin run geçmişi, memory'si ve kullanım/bütçe sayaçları diğerlerinden tamamen ayrı olmalı. org opsiyonu açıldığında her istek, withOrg ile kapsamlanmış ayrı bir journal'a iner; organizasyonlar birbirinin anahtarlarını göremez, aynı runId farklı organizasyonlarda bağımsızdır.

Token'ın hangi organizasyona ait olduğu token'ın kendisinde yazar: Principal.orgId, roleAuth'taki Cred.orgId'den gelir. Bu bağ x-gnl-org header'ını her zaman ezer: kimlik başka bir organizasyon isterse 403 alır. Yani bir token kendi organizasyonunun dışına çıkamaz.

org ayarlıysa, hiçbir organizasyona bağlı olmayan kimlik tüm organizasyonları gören bir operatör sayılmaz, reddedilir (403). Her organizasyona erişmek açıkça verilen bir yetkidir: superAdmin sınıfı. Böylece unutulan bir orgId kapıları açmaz, tek bir kapıyı kapatır.

Kurulum / import#

org ve OrgOptions, @gnldev/server'ın createRestApi seçenekleridir; withOrg alttan @gnldev/durable'dan gelir; organizasyon bağı (Cred.orgId) @gnldev/auth'taki ücretsiz roleAuth'tan. Lisans gerekmez.

npm install
npm install @gnldev/server @gnldev/durable @gnldev/auth
config + auth
import { SqliteStorage } from '@gnldev/durable/sqlite';
import { createRestApi } from '@gnldev/server';
import { roleAuth } from '@gnldev/auth';

const storage = new SqliteStorage('runs.db');
const config = { storage, agents: { starwars: { model, system: SYSTEM, tools } } };

// `superAdmin`, not a bare admin: with the `org` option configured, an identity bound to no
// organization is refused (403). The cross-organization scope is an EXPLICIT grant, never
// inferred from a missing orgId. The 'acme' viewer only ever sees acme's data.
const auth = roleAuth({
  superAdmin: { token: ADMIN_TOKEN },
  viewer: { token: ACME_TOKEN, orgId: 'acme' },
});

Adım adım kullanım#

createRestApi'ye org: {} vermek yeterli — organizasyon varsayılan olarak x-gnl-org header'ından çözülür (OrgOptions.resolve ile özelleştirilebilir). Organizasyon başına registry lazy kurulur ve önbelleklenir.

org izolasyonunu aç
app.mount('/api', createRestApi(config, {
  title: 'SWAPI Pro',
  auth,
  org: {},       // opt-in: every request lands in its organization's journal (withOrg)
  budgets: {},   // optional — per-organization budget/quota (separate doc: budget-quota)
}));

Platform operatörü (superAdmin; tasarım gereği hiçbir organizasyona bağlı değil) header'da adını verdiği organizasyonda çalışabilir:

superAdmin: x-gnl-org ile organizasyon seç
# superAdmin: acts in any organization via the x-gnl-org header
curl -s -X POST http://localhost:3002/api/agents/starwars/run \
  -H 'content-type: application/json' -H 'authorization: Bearer ${ADMIN_TOKEN}' -H 'x-gnl-org: acme' \
  -d '{"runId":"demo-1","prompt":"Who is Darth Vader?"}'

Organizasyona bağlı bir kimlik (viewer) header vermese bile kendi organizasyonuna düşer; farklı bir organizasyon istemeye çalışırsa 403 alır:

organizasyona bağlı viewer + uyuşmazlık 403
# organization-BOUND viewer: scoped to acme even without the header
curl -s http://localhost:3002/api/usage -H 'authorization: Bearer ${ACME_TOKEN}'

# the same viewer asking for another organization (x-gnl-org: globex) → 403 org mismatch
curl -s http://localhost:3002/api/runs -H 'authorization: Bearer ${ACME_TOKEN}' -H 'x-gnl-org: globex'
# -> 403 "organization mismatch: identity is bound to organization 'acme'"

Altta yatan izolasyon mekanizması doğrudan da kullanılabilir — journal'ı elle bir organizasyona kapsamla:

withOrg — doğrudan kullanım
import { withOrg } from '@gnldev/durable';

// createRestApi does this AUTOMATICALLY with opt-in org, but you can also use it directly:
// EVERY key in the journal is written/read under an `org:<orgId>:` prefix — runs, memory,
// queue and cache included, so EVERYTHING is isolated (same Journal interface; exactly-once
// is inherited for free).
const scoped = withOrg(baseJournal, 'acme');
// scoped.listRuns() returns ONLY acme's runs (with the prefix stripped).

API referansı#

fnwithOrg

Bir journal'ı organizasyona kapsamlar (@gnldev/durable): dönen journal aynı arayüzü uygular (get/put/putIfAbsent/listKeys/deletePrefix/readRun/listRuns varsa köprülenir), tüm anahtarlar `org:<orgId>:` önekiyle taşınır ve okurken önek soyulur. Zaten kapsamlanmış bir journal'ı yeniden kapsamlamak hata fırlatır.

typeRestApiOptions.org

createRestApi seçeneği (@gnldev/server): opt-in çok organizasyonluluk — verilirse her istek withOrg ile kapsamlanmış journal görür, çözülen organizasyon requestContext'e enjekte edilir. Auth sağlayıcısı varken hiçbir organizasyona bağlı olmayan ve platform-admin yetkisi taşımayan kimlik 403 alır.

typeOrgOptions

{ resolve?, required?, requireRegistration?, maxInstances? } — resolve web Request'i alır (varsayılan: x-gnl-org header'ı); required: true → organizasyonsuz istek 400 alır (varsayılan false: paylaşılan alanda çalışır); requireRegistration: true → yalnızca kayıtlı organizasyonlar çalışabilir (ör. Studio'nun POST /organizations ile oluşturduğu); maxInstances bellekte tutulan organizasyon registry sayısını sınırlar (varsayılan 512).

fnprincipalOf

@gnldev/auth: doğrulanmış Principal'ı web Request'inden okur; Principal.orgId buradan gelir ve scope() içinde bağlı organizasyonu belirler.

typeCred.orgId

roleAuth (@gnldev/auth) kimlik bilgisinde (Cred) opsiyonel alan: verilirse o sınıfın kimliği bir organizasyona bağlanır — istek header'ından bağımsız olarak her zaman o organizasyona kapsamlanır, farklı organizasyon istenirse 403.

Açık çekirdekte ücretsiz
Organizasyon izolasyonu lisans istemez: org seçeneği, Principal.orgId ve kapalı-varsayılan kuralı @gnldev/server, @gnldev/auth ve @gnldev/durable içinde gelir. Ücretli @gnldev/auth-ee yönetimi satar — SSO, kullanıcı dizini, RBAC, FGA ve audit. Kimin neyi göreceğini asla satmaz.
İpucu
Organizasyon başına registry (model-fallback, memory dahil) lazy kurulur ve önbelleklenir — her istek yeni bir createGnl çağrısı yapmaz. Bütçe/kota da organizasyon bazında ayrışır; ayrıntı için Bütçe & kota dokümanına bakın.