Sari la conținut
megapromotingHai să discutăm

Expertiză · Mentenanță

Mentenanță înseamnă să știi că formularul livrează astăzi, nu că serverul răspunde 200.

Monitorizare care verifică drumul complet al unei cereri până la un om, actualizări cu poartă înainte de producție și o verificare de acceptare rulată după fiecare publicare. Toate trei rulează pe acest site și se pot deschide din exterior.

Construit dejaTrei implementări proprii, toate în depozitul acestui site și toate verificabile azi: `src/app/api/health/contact/route.ts` (sonda de livrare, răspunde 200 pe live chiar acum), `src/lib/lead-store.ts` (jurnalul append-only cu retenție aplicată la scriere) și `scripts/verify-redesign.ts` (verificarea de acceptare rulată după publicare). Le-am scris pentru că pe 06.09.2026 formularul propriu a căzut tăcut: tokenul botului era revocat, endpointul întorcea 500, iar cererile dispăreau fără urmă. Nu e o poveste de vânzare — e comitul care a produs fișierele de mai sus.

„Site-ul merge” e o afirmație despre pagina de start. Un vizitator care a completat formularul și a primit o eroare nu a fost oprit de o pagină căzută, ci de un canal de livrare care a expirat tăcut. Diferența dintre cele două e tot ce înseamnă mentenanță făcută serios: nu urmărim dacă serverul răspunde, ci dacă o cerere de la un om ajunge la alt om.

Pe 6 septembrie 2026 s-a întâmplat exact asta pe site-ul acesta. Tokenul botului care ducea solicitările din formular către echipă era revocat; interfața Telegram răspundea `401 Unauthorized`, ruta noastră întorcea 500, iar vizitatorul vedea „mesajul nu a putut fi trimis”. Solicitarea nu se scria nicăieri. În jurnalul de erori al procesului erau trei eșecuri reale în cele aproximativ șapte ore scurse de la publicarea precedentă. Nimeni nu se uita.

Ce a ieșit din asta sunt trei piese pe care le montăm acum în fiecare proiect pe care îl întreținem. Un jurnal append-only scris *înainte* de încercarea de livrare, ca un canal stricat să degradeze în „trebuie să ne uităm în fișier” în loc de „cererea n-a existat niciodată”. O sondă de sănătate care răspunde la o singură cerere dacă un lead poate ajunge la un om chiar acum. Și o verificare de acceptare care se rulează după fiecare publicare și cade dacă a dispărut o adresă canonică, o ancoră de întrebări sau dacă în harta de site au apărut adrese care nu se pot deschide.

Restul e disciplină plicticoasă și verificabilă: actualizări cu o poartă de audit înainte de a atinge producția, repornire automată cu prag de memorie și limită de reporniri instabile, retenție aplicată de cod, nu declarată în politică, și adrese IP tăiate la prefix de rețea înainte de a fi scrise undeva.

Ce cuprinde

Lucrarea, pe componente

Sondă care verifică livrarea, nu disponibilitatea

`GET /api/health/contact` răspunde 200 dacă un lead poate ajunge la un om acum și 503 dacă nu. Verifică două lucruri separat: că jetonul canalului de notificare e încă valid (o cerere reală către furnizor, cu timeout de 8 secunde) și că jurnalul de cereri e scriptibil. Răspunsul e alcătuit numai din valori logice — niciodată jetonul, identificatorul de canal sau numele botului. Rezultatul se ține în memorie 60 de secunde, ca o sondă externă apăsată des să nu devină ea însăși trafic. Când furnizorul e inaccesibil, câmpul devine `null`, nu `false`: „nu știu” și „invalid” sunt stări diferite.

Jurnal scris înainte de livrare, nu după

Fiecare cerere primește un identificator și se scrie într-un jurnal append-only, o linie JSON per eveniment, *înainte* de a se încerca notificarea. A doua linie, cu același identificator, spune ce s-a întâmplat efectiv: `delivered` sau `failed`, cu motivul tăiat la 300 de caractere. Directorul se creează cu drepturi `0700`, fișierele cu `0600`, iar calea se pune deliberat în afara directorului de versiune, ca istoricul să supraviețuiască unei publicări.

Verificare de acceptare rulată după publicare

Un script de verificare deschide fiecare pagină de produs, în grupuri de câte trei, și cade dacă lipsește codul 200, ancora de întrebări, ancora de exemplu sau adresa canonică. Verifică apoi harta de site — să nu conțină variante de limbă care nu se pot deschide și să conțină fiecare produs — și `robots.txt`, să nu blocheze resursele necesare randării. Cade și dacă în pagină reapare conținut dintr-un client vechi. E o listă de lucruri care s-au stricat deja o dată.

Actualizări cu poartă, nu cu speranță

Scriptul de publicare refuză să pornească dacă serverul are sub 500 MB memorie liberă, rulează `npm audit --audit-level=high` și se oprește la vulnerabilități de nivel înalt dacă nu confirmi explicit, apoi construiește din curat — `.next` și `node_modules` șterse, instalare din fișierul de blocare. Dacă procesul nu apare `online` după pornire, scriptul afișează ultimele 50 de linii de jurnal și iese cu eroare, în loc să raporteze succes.

Repornire cu praguri, nu la nimereală

Procesul se repornește automat peste 500 MB memorie, cu întârziere de 4 secunde între încercări, creștere exponențială a întârzierii și oprire după 10 reporniri instabile — ca o buclă de cădere să devină vizibilă în loc să consume serverul în tăcere. Timp de grație la oprire: 5 secunde, apoi terminare forțată. Jurnalele au dată și fus orar, într-un singur flux.

Duplicate tratate, nu numărate de două ori

Aceeași persoană, același mesaj, de două ori — un clic dublu, o reîncărcare a paginii — producea două notificări identice pentru o singură cerere. Acum amprenta `sha256` a perechii adresă + mesaj se ține 10 minute în memorie; a doua trimitere primește același identificator de cerere și marcajul `duplicate`, iar notificarea nu se repetă. Se suprimă doar duplicatele unei livrări reușite; una eșuată are voie să treacă din nou.

Coduri de eroare care spun ce s-a rupt

400 pentru date invalide, 405 pe metodă greșită, 500 pentru corp de cerere stricat, 502 când canalul de livrare a răspuns prost, 503 când credențialele lipsesc. Diferența contează la 3 dimineața: 502 înseamnă „furnizorul”, 503 înseamnă „configurația noastră”. Vizitatorului i se spune distinct „am primit cererea, dar nu am putut notifica” — nu un succes fals.

Retenție aplicată de cod, nu promisă în politică

Nota de confidențialitate publicată spune că solicitările din formular se păstrează 24 de luni. Codul aplică exact același număr: `LEAD_RETENTION_DAYS` implicit 730, iar fișierele mai vechi decât pragul se șterg la fiecare scriere, fără planificator care poate fi uitat. Adresa IP se taie la prefixul de rețea — `/24` la IPv4, `/48` la IPv6 — și se citește ultimul hop din antet, nu primul, pentru că primul e trimis de client.

Găsim și ce nu a reclamat nimeni

Aceeași trecere prin cod a scos la iveală două lucruri pe care nu le semnalase niciun utilizator: limita de 10 cereri pe minut se putea ocoli complet, pentru că se citea primul element din antetul de adrese redirecționate — cel controlat de client — iar o rută de inițiere a apelurilor telefonice era deschisă anonim, pe costul și de pe numărul nostru, deși componenta care o folosea nu mai era montată nicăieri. Ambele reparate și verificate pe producție.

Cum arată

Traseul, pas cu pas.

01

Inventarul căilor pe care ajunge o cerere la un om

Prima livrare nu e o unealtă, e o listă: prin ce trece o solicitare de la apăsarea butonului până la cineva care o citește, ce se rupe pe fiecare pas și ce ar trebui să se întâmple când se rupe. La site-ul acesta lista avea trei verigi și una era invizibilă.

02

Sonda și jurnalul, montate înainte de orice altceva

Livrăm o adresă de sănătate care verifică drumul complet, nu procesul, și jurnalul care scrie înainte de livrare. De aici înainte, o cădere e o întrebare cu răspuns, nu o săpătură prin jurnale. Adresa se poate interoga din orice serviciu extern de monitorizare, pentru că nu întoarce nimic sensibil.

03

Verificarea de acceptare, scrisă din defecte reale

Fiecare lucru care s-a stricat o dată intră în scriptul de verificare rulat după publicare. Nu scriem teste pentru cazuri ipotetice; scriem pentru cele care ne-au costat deja. Livrăm scriptul, nu doar rezultatul lui — îl poți rula și tu.

04

Ritmul de actualizare și poarta de dinaintea producției

Stabilim ce se actualizează automat, ce trece prin verificare umană și ce nu se atinge fără fereastră anunțată. Poarta include auditul de securitate al dependențelor și verificarea de resurse a serverului, ambele executate înainte de a atinge producția.

05

Predarea, cu lista de lipsuri

La final predăm procedura de publicare, procedura de revenire, adresele de sănătate și lista scrisă a ce nu e acoperit. La acest site, de exemplu, ramura de expirare a cererii către furnizor e implementată și cade în aceeași tratare ca eroarea de rețea, dar abortul în sine nu a fost provocat în test — scrie așa în jurnalul de execuție, nu într-o notă internă.

1Sonda care verificălivrarea până la unom2jurnalul scrisînainte de încercare3verificarea deacceptare rulată dupăfiecare publicareTrei piese, toate în depozitul acestui site.
Traseul, în 3 pași

Datele

Ce atingem, unde stau și cât rămân

Întrebările pe care le pune oricine are un responsabil cu protecția datelor — puse aici înainte să le pună el.

Jurnalul de solicitări
Nume, adresă de e-mail, telefon, companie, serviciu ales, mesaj, pagina de pe care s-a trimis, gazda paginii de proveniență (numai gazda, nu adresa completă) și prefixul de rețea al vizitatorului. Fișiere JSON pe zi, pe serverul propriu, în afara directorului de versiune. Termen: 24 de luni, aplicat la scriere.
Jurnalele de proces și de server
Ieșirea standard și erorile procesului, cu dată și fus orar, plus jurnalele serverului web. Aici se vede o cădere tăcută: cele trei eșecuri de livrare din incidentul de referință erau în jurnalul de erori, nu în vreo alertă. Rotația și termenul se stabilesc pentru fiecare server; sunt date tehnice, nu conținut de cont.
Ce nu iese niciodată din server
Jetoanele, identificatorii de canal și cheile de furnizor. Sonda de sănătate răspunde exclusiv cu valori logice, tocmai ca să poată fi apelată de un instrument extern fără să divulge nimic. Aceeași regulă în notificare: mesajul conține identificatorul cererii și pagina, nu credențiale.
Statistici de trafic
Măsurarea traficului trece prin instrumentul de analiză configurat pe proiect și se activează după consimțământ. Setarea reală de retenție din contul de analiză este o valoare pe care o citim din cont, nu una pe care o presupunem — registrul de prelucrări al acestui site o are marcată explicit ca element de clarificat, nu ca fapt stabilit.
Registrul de prelucrări
Fiecare tip de date atins de site are o intrare cu scop, temei, categorii și termen, într-un document versionat alături de cod. Când codul schimbă un termen, documentul se schimbă în același comit — altfel politica și programul spun lucruri diferite, iar cel care greșește e de obicei documentul.

Un caz

Un formular care a livrat 500 în loc de leaduri, șapte ore

Situația

Un site de prezentare cu formular de contact, publicat recent. Toate paginile răspund 200, tabloul de bord e verde, nimeni nu reclamă nimic. Singurul canal prin care o solicitare ajungea la echipă era o notificare într-o aplicație de mesagerie.

Ce am construit

Jetonul botului de notificare fusese revocat; interfața furnizorului răspundea `401 Unauthorized`. Ruta de formular întorcea 500 și nu scria nimic. Prima reparație nu a fost jetonul, ci ordinea operațiilor: cererea se scrie acum într-un jurnal append-only, cu identificator propriu, *înainte* de a se încerca livrarea, iar rezultatul livrării se adaugă ca a doua linie. Peste asta s-au montat o sondă publică de sănătate care verifică jetonul și posibilitatea de scriere, coduri de eroare distincte pentru „furnizorul a răspuns prost” și „ne lipsesc credențialele”, un timeout de 10 secunde pe livrare și suprimarea duplicatelor pe o fereastră de 10 minute. Aceeași trecere prin cod a scos și o limită de cereri care se putea ocoli, și o rută de apeluri telefonice rămasă deschisă anonim.

Ce a ieșit

Sonda răspunde acum 200 cu jetonul valid și jurnalul scriptibil; se poate interoga din orice serviciu extern de monitorizare, fără să divulge nimic. Testele pe producție au acoperit fiecare cod de răspuns — 400, 405, 500, 502, 503 — iar două trimiteri identice au întors același identificator de cerere, a doua marcată ca duplicat, cu două linii în jurnal, nu patru. O cădere viitoare a canalului de notificare nu mai șterge cererea: rămâne în jurnal, cu motivul scris.

Ce nu spune cazul

Sonda spune că livrarea e posibilă acum, nu că cineva citește notificările. Cine se uită la ele și în cât timp e o decizie a echipei, nu o funcție a codului. Iar ramura de expirare a cererii către furnizor, deși implementată, nu a fost provocată în test — cade în aceeași tratare ca eroarea de rețea, care a fost testată; o notăm ca neexersată, nu ca verificată.

Întrebări

Ce ne întreabă oamenii înainte să sune

Ce monitorizați, concret?

Drumul unei cereri până la un om, nu disponibilitatea serverului. `GET /api/health/contact` verifică într-o singură cerere două lucruri: că jetonul canalului de notificare e încă valid — printr-un apel real la furnizor, cu timeout de 8 secunde — și că jurnalul de cereri se poate scrie. Răspunde 200 când ambele sunt adevărate și 503 când nu. Poți să o apelezi chiar acum pe acest site: e publică, tocmai pentru că nu întoarce decât valori logice.

De ce ar cădea un formular fără ca nimeni să observe?

Pentru că partea vizibilă continuă să funcționeze. Pagina se încarcă, butonul răspunde, serverul întoarce 200 pe toate paginile — se rupe doar veriga finală, care nu are interfață. Pe site-ul acesta jetonul botului de notificare a fost revocat: furnizorul răspundea `401 Unauthorized`, ruta întorcea 500, iar cererea nu se scria nicăieri. Trei eșecuri reale în aproximativ șapte ore, vizibile numai în jurnalul de erori al procesului. De asta jurnalul se scrie acum înaintea livrării: chiar dacă notificarea cade, cererea există.

Ce se întâmplă dacă notificarea eșuează după ce ați reparat?

Cererea e deja scrisă în jurnal cu un identificator propriu, iar a doua linie din jurnal spune `failed` și motivul. Vizitatorului i se răspunde distinct — „am primit cererea, dar nu am putut notifica” — nu un succes fals. Codul de răspuns diferențiază cauza: 502 înseamnă că furnizorul a răspuns prost, 503 că lipsesc credențialele la noi. La 3 dimineața, diferența dintre cele două decide dacă suni pe cineva sau nu.

Actualizați automat dependențele?

Nu fără poartă. Publicarea rulează `npm audit` la nivel `high` și se oprește la vulnerabilități de acest nivel dacă nu se confirmă explicit continuarea; verifică întâi și memoria disponibilă a serverului, cu prag de 500 MB, pentru că o construire pornită pe un server strâmt lasă aplicația oprită. Construirea se face din curat: directorul de construcție și dependențele se șterg, instalarea se face din fișierul de blocare. Ce se actualizează automat și ce trece prin verificare umană se stabilește pe proiect, nu implicit.

Cum știți că o publicare nu a stricat altceva?

Printr-un script de verificare rulat după publicare, care deschide fiecare pagină de produs și cade dacă lipsește codul 200, ancora de întrebări, ancora de exemplu sau adresa canonică. Verifică apoi harta de site — să conțină fiecare produs și să nu conțină variante de limbă care nu se pot deschide — și `robots.txt`, să nu blocheze resursele de randare. Fiecare verificare din listă corespunde unui lucru care s-a stricat deja o dată. Scriptul se predă odată cu proiectul.

Ce faceți când aplicația se blochează sau consumă memorie?

Procesul se repornește automat peste pragul de 500 MB, cu 4 secunde întârziere între încercări și creștere exponențială, dar se oprește după 10 reporniri instabile într-un interval scurt. Asta e important: o buclă de cădere care se repornește la infinit arată sănătos într-un tablou de bord și consumă serverul în tăcere. Preferăm ca procesul să rămână oprit și vizibil.

Cât timp păstrați datele din formular și cine le poate citi?

24 de luni, aplicate de cod, nu doar declarate: pragul e o variabilă cu valoarea implicită 730 de zile, iar fișierele mai vechi se șterg la fiecare scriere nouă, fără planificator care poate fi uitat. Directorul are drepturi `0700`, fișierele `0600`, iar calea stă în afara directorului de versiune, ca istoricul să supraviețuiască publicării. Adresa IP nu se păstrează întreagă: se taie la `/24` pentru IPv4 și `/48` pentru IPv6, citind ultimul hop din antet, nu primul — primul e trimis de client și nu înseamnă nimic.

Găsiți și probleme pe care nu le-am reclamat?

Se întâmplă, și de obicei alea sunt cele scumpe. Aceeași trecere prin cod care a reparat formularul a scos două lucruri pe care nu le semnalase nimeni: limita de cereri se putea ocoli complet, pentru că se citea primul element din antetul de adrese redirecționate — exact cel pe care îl trimite clientul; și o rută care iniția apeluri telefonice era deschisă anonim, pe costul nostru, deși componenta care o folosea fusese demontată. Ambele au fost reparate și verificate pe producție. Ce nu putem promite e că găsim tot; ce putem promite e că raportăm și ce nu ați cerut.

Ce nu acoperă mentenanța?

Nu e serviciu de securitate cu monitorizare non-stop și nu e centru de operațiuni. Nu garantăm un procent de disponibilitate fără o măsurătoare care să îl susțină — și, ca să fie clar, în acest moment nu publicăm o astfel de cifră pentru site-ul propriu. Nu preluăm responsabilitatea unei platforme terțe la care nu avem acces. Și nu tratăm o pagină care răspunde 200 drept dovadă că totul merge: exact asta a fost problema de la care a pornit tot ce e scris mai sus.

Pe ce se sprijină afirmațiile de mai sus (13 surse)
  1. Sonda de livrare răspunde 200 pe producție: `{"ok":true,"telegram":{"configured":true,"credentialsValid":true},"leadJournal":{"writable":true}}`https://www.megapromoting.com/api/health/contact · 2026-09-06
  2. Antete de securitate active pe producție: HSTS `max-age=63072000; includeSubDomains; preload`, `X-Content-Type-Options: nosniff`, `X-Frame-Options: SAMEORIGIN`, `Referrer-Policy: strict-origin-when-cross-origin`, `Permissions-Policy` cu `microphone=(self)`https://www.megapromoting.com/servicii · 2026-09-06

11 dintre ele sunt cod și fișiere din depozitele noastre. Nu le publicăm numele și nici linia: împreună, pe o singură pagină, ar descrie prea exact cum sunt construite sisteme care nu sunt doar ale noastre. Le parcurgem cu tine, în depozit, la cerere — verificarea rămâne posibilă, doar că se face într-o discuție.

Ce ai vrea să funcționeze mai bine?

Povestește-ne despre procesul tău. Împreună stabilim ce merită construit, ce putem conecta și cum verificăm rezultatul.

Hai să discutăm