NexusFabricCereți o prezentare

Poarta de acces

Poarta e primul lucru pe care îl atinge un integrator. Pagina spune ce e o rută, cu ce se intră, cât trece pe o credențială, ce rămâne scris după o livrare — și unde se termină platforma.

O rută e un flux publicat

Nu există un fișier de configurare al porții. Ce se poate chema e ce s-a publicat: fluxul își aduce numele și ruta apare odată cu artefactul. Nimic nu se declară a doua oară, în alt loc.

Configurarea de mediu o cere fluxul, pe nume. O cheie declarată pe care instalația n-o oferă oprește pornirea și o numește — nu se descoperă la primul mesaj, cu o valoare goală trimisă mai departe. Aceeași verificare se poate rula fără să pornească nimic, iar comanda se încheie cu cod de eroare când lipsește o cheie.

Un flux care cere o cheie de mediu, și variabila din care o ia.
---
flow: notificare-anre
tenant: acme
effects: [http_egress]
config: [ANRE_URL]
---

## Step: trimite
effects: [http_egress]
endpoint: "{{ ctx.ANRE_URL }}/notificari"
method: POST

# în mediul instalației:
#   NEXUS_CONFIG_ANRE_URL=https://portal.example.ro/api

Prețul e scris, nu descoperit. Valoarea configurării se capturează o dată, la pornire, deci o schimbare de configurare cere o repornire — altfel poarta de pornire ar fi verificat alte valori decât cele pe care rulează platforma. La fel tabela de rutare a ușii gRPC: se construiește la pornire, deci un flux publicat după aceea cere o repornire ca să fie rutat. Și o scanare de pornire nu poate tăcea: un registru care nu se poate lista oprește pornirea, nu o lasă să pară verificată.

Cu ce se intră

  • Credențiala e o cheie de API, prezentată în Authorization: Bearer. Poarta e închisă implicit; pornirea fără poartă există ca opțiune explicită și se anunță la fiecare pornire.
  • Metoda de autentificare e proprietate declarată a tenantului, iar o metodă pe care build-ul n-o poate executa e refuzată chiar la înregistrarea tenantului. Azi lista aia acceptă un singur cuvânt: cheia de API.
  • O cheie poartă scope-uri și, opțional, lista fluxurilor pe care are voie să le cheme. Un flux poate cere un scope anume, iar cererea se verifică după încărcarea artefactului — acolo e scris.
  • Poarta rulează înaintea corpului: un apelant fără credențială valabilă nu provoacă nicio citire de corp și nicio parsare.
  • Un refuz atribuibil intră în lanțul de audit cu subiectul lui, nu poartă niciodată credențiala, și consumă din plafonul apelantului — deci un refuz nu poate fi folosit ca pompă de scriere. Auditul e record, nu portar: dacă rândul nu se poate scrie, refuzul rămâne refuz.
  • O cerere SOAP trece prin aceeași poartă, neschimbată. Un refuz e 401 sau 403 HTTP simplu, niciodată un SOAP Fault — un fault poartă status de succes, iar un gateway care rutează pe status ar înainta refuzul ca răspuns.

Unde se termină platforma

Ce execută platforma
Verificarea cheii, scope-urile, lista de fluxuri, plafonul de debit și refuzul auditat.
Ce se așază în fața ei
Terminarea TLS, mTLS-ul unui client și orice federare de identitate — OIDC sau OAuth 2.0. Ușa gRPC e h2c, în clar.

Platforma nu verifică jetonul unui furnizor de identitate: nu citește JWKS, nu validează emitent, audiență sau expirare. Dacă poarta din față trebuie să fie OIDC sau OAuth 2.0, termenul ăla se rezolvă înaintea platformei, iar ce ajunge la poartă rămâne cheia de API.

Și două lucruri pe care multă lume le presupune și care nu autentifică: o credențială din corpul unui mesaj SOAP nu autentifică — capacitatea nu există deloc; iar o semnătură pe corpul unui webhook nu produce nici tenant, nici drepturi, deci nu ține locul cheii.

Debitul e al credențialei

Plafonul se pune pe cheie, la emitere. Ambele uși de mesaj — sincronă și de coadă — cheltuiesc din el, iar un refuz de debit spune când să revii: patru antete pe 429. Telemetria de conector nu consumă din plafon, ca un conector care împarte cheia să nu plătească de două ori pe același mesaj.

  • Plafonul e per credențială, nu per tenant, nu per rută și nu per adresă IP. O cheie fără plafon e nelimitată; nu există nici implicit la nivel de instalație, nici plafon global.
  • Contorul stă în memoria procesului: o repornire îl golește, iar două instanțe au două contoare. Nu e un plafon împărțit.
  • Plafonul unei chei nu se schimbă după emitere. Se revocă cheia și se emite alta.
  • Interfața de administrare nu trece prin limitator: nici paginile ei, nici formularul de autentificare nu sunt frânate.
  • Sub pornirea fără poartă nu există nici plafon, nici contor — verificarea e înăuntrul porții, iar poarta nu rulează.
  • Pe ușa gRPC refuzul de debit e ResourceExhausted plus retry-after; cele patru antete X-RateLimit-* sunt ale ușii HTTP.

Ce rămâne scris după o livrare

  • Unitatea măsurată e livrarea, nu cererea: received plus exact un verdict. Pe ce ușă a intrat se citește din coloana channel, nu din felul evenimentului.
  • Verdictul tipat stă pe o rubrică proprie — succeeded, fault_handled, failed — și se poate filtra după el.
  • Un flux poate purta un orar cu șase câmpuri, iar un tic lasă aceeași pereche ca o cerere, pe canalul cron.
  • O singură fereastră de retenție guvernează ambele ieșiri de jurnal — rânduri și fișiere — într-o singură trecere, cablată în procesul care servește. Implicit sunt 30 de zile.

Versiune și licență

Versiunea descrisă pe site
1.2.0
Licența
Comercială proprietară, acordată prin contract. Nimic nu e publicat.

Cum tratăm o ruptură de contract: la 1.0 plicul de răspuns a dispărut — răspunsul e ieșirea fluxului, neîmpachetată, cu Content-Type derivat din forma corpului — iar ruptura e declarată, nu strecurată într-o versiune minoră.

„Auditabil" la noi înseamnă exact un lucru: lanțul blake3 al actelor de politică — înlănțuit și verificabil, verificat la cerere dintr-o comandă sau din butonul paginii de audit, care numește numărul de ordine al intrării atinse. Ce dovedește lanțul e că nicio intrare nu s-a schimbat în loc; ancoră în afara instalației nu există, deci cine poate scrie fișierul poate rescrie lanțul de la un punct înainte. Nu înseamnă cod sursă — nu e open source, nu există depozit deschis și nu invităm la citirea codului.

Ce nu face poarta

  • Nu există /metrics și niciun export de metrici.
  • Nu există export de jurnal către un colector extern — nici syslog, nici OTLP, nici statsd, webhook, fluentd sau Kafka. Destinațiile sunt exact două, ambele locale: o bază de date și fișierele rotite zilnic.
  • Mascarea se aplică la ieșirea de jurnal și e numai pe JSON, pe chei de obiect. Corpul scris pe o coadă e purtat ca JSON în clar; suma de control de acolo e integritate, nu cifru.
  • Fereastra de retenție guvernează jurnalul și nu trece dincolo de el: nu atinge cozile, registrul, lanțul de audit sau starea de flux.