Saltar al contenido
Tornar a l'inici

00 / Arquitectura

Com està construït aquest web

Treballo en un SOC, així que aquest web és també una declaració d'intencions: si no fos capaç d'assegurar el meu propi lloc, poc tindria a aportar assegurant el de ningú. A sota hi ha les decisions que hi ha al darrere i el motiu de cadascuna, no una llista de tecnologies.

Resum del stack

Frontend
Astro 7 (SSG) · Tailwind CSS · TypeScript
Backend
PHP 8 (PDO) · MySQL / MariaDB · sin framework
Infraestructura
CDMON · Apache · Cloudflare · TLS
Idiomes
Español · English · Català

01 / Superficie d'atac del frontend

El lloc es compila a HTML pla, de manera que la major part del risc classic de servidor desapareix. El que queda es tanca per capcalera.

  • CSP amb hash recalculats a cada compilacio

    script-src porta el SHA-256 de cada script del lloc i no inclou ‘unsafe-inline’. Un <script> injectat no s'executa: no pot portar un hash que la politica no conegui. Els hash es generen sols en compilar, no es mantenen a ma.

    astro.config.mjs

  • HSTS a un any, deliberadament sense preload

    includeSubDomains actiu. Es deixa fora de la llista de precarrega expressament: entrar-hi es facil i sortir-ne triga mesos, i per a un portfolio aquest compromis no compensa.

    server/.htaccess

  • Aillament del document

    X-Frame-Options DENY contra el clickjacking, Cross-Origin-Opener-Policy i Cross-Origin-Resource-Policy en same-origin, i Permissions-Policy que apaga geolocalitzacio, microfon i camera encara que res no les demani.

    server/.htaccess

  • Res de tercers

    Sense CDN, sense Google Fonts, sense etiquetes d'analitica externa. Les tipografies van autoallotjades amb subset llati. Cada domini que es treu es un tercer menys que pot caure, canviar el fitxer que serveix o registrar la IP del visitant.

02 / Consola d'administracio

La part amb acces a la base de dades i a les pujades. Aqui es on el detall importa de debo.

  • Consultes preparades reals, no emulades

    PDO amb ATTR_EMULATE_PREPARES a false. Amb l'emulacio activada el driver interpola els valors al client abans d'enviar-los, i aquesta interpolacio es justament on han viscut historicament els salts d'entrecometat en certs jocs de caracters.

    server/db.php

  • Login que no revela si l’usuari existeix

    Contra un usuari inexistent es verifica igualment un hash fictici. Sense aquest pas, la resposta torna abans quan l'usuari no existeix i el temps permet enumerar comptes validos. Les contrasenyes van amb bcrypt i es rehashegen soles si puja el cost.

    server/admin/auth.php

  • CSRF en temps constant, amb el cas buit cobert

    El token es compara amb hash_equals. A mes s'exigeix que el de la sessio existeixi i no estigui buit: sense aquesta condicio, una peticio sense galeta creava una sessio nova amb el token a cadena buida i la comparacio de dues cadenes buides retornava cert, deixant passar la peticio.

    server/admin/auth.php

  • Sessions endurides i amb caducitat doble

    Regeneracio de l'identificador despres del login (fixacio de sessio), galetes HttpOnly, Secure i SameSite=Lax, use_strict_mode perque ningu no imposi un identificador propi, i tancament tant per inactivitat com per durada maxima absoluta.

    server/admin/auth.php

  • Bloqueig de forca bruta per IP

    Els intents fallits es compten en una finestra temporal i bloquegen la IP en superar el llindar. La IP es pren de REMOTE_ADDR llevat que es declari explicitament un proxy de confianca: fiar-se de X-Forwarded-For sense proxy al davant permet falsejar la IP i saltar-se el limit sencer.

    server/lib/http.php

03 / Contingut que no em pertany

Imatges pujades a la consola i missatges escrits per desconeguts: tot el que entra de fora es tracta com a hostil fins que es demostri el contrari.

  • Les imatges es validen per contingut, no per extensio

    Primer el tipus MIME real amb finfo, i despres getimagesize(), que nomes reconeix imatges de debo. Un polyglot amb capcalera GIF falsificada passa el primer filtre pero no el segon. Hi ha a mes un topall de dimensions perque ningu no tombi el servidor amb una imatge de 30000 px de costat.

    server/lib/upload.php

  • La carpeta de pujades no executa codi

    Defensa en profunditat: encara que la validacio fallés i s'hi colés un .php, el .htaccess d'aquella carpeta retira els handlers i apaga el motor, de manera que es serviria com a text pla. Els fitxers es desen amb nom aleatori, mai amb el que envia el client.

    server/uploads/.htaccess

  • El formulari no pot convertir-se en un relay de spam

    S'eliminen salts de linia i caracters de control abans que cap valor toqui una capcalera de correu. Sense aquest sanejament, un nom amb CRLF permet injectar capcaleres (un Bcc:, per exemple) i fer servir el formulari per enviar correu a tercers.

    server/api/contact.php

  • Exportacions CSV sense injeccio de formules

    Excel i LibreOffice executen com a formula qualsevol cel·la que comenci per =, +, - o @. Com que la safata exporta text escrit per desconeguts, aquestes cel·les es prefixen perque es tractin com a text i no com a codi en obrir el fitxer.

    server/admin/partials/layout.php

04 / Analitica propia i privacitat

Saber quanta gent hi entra no exigeix muntar el perfil de ningu. L'analitica es propia i desa el minim.

  • L'adreca IP no s'emmagatzema

    Es desa un SHA-256 de la IP amb una sal del servidor. Serveix per comptar visitants unics aproximats i per frenar floods, pero no permet reconstruir l'adreca ni creuar-la amb cap altra base de dades.

    server/api/visit.php

  • Sense galetes de seguiment i amb Do Not Track respectat

    No hi ha bàner de consentiment perque no hi ha res a consentir. Si el navegador envia el senyal Do Not Track, la visita ni tan sols es registra.

  • Del referrer es descarta la query

    Nomes es conserva esquema, host i ruta. Els parametres d'una URL aliena solen portar identificadors de sessio o de campanya, i no hi ha cap rao perque acabin a la meva base de dades.

    server/api/visit.php

  • Retencio acotada i purga automatica

    Les visites s'esborren als 400 dies, els intents de login als 90 i el registre d'auditoria a l'any. La purga va incorporada al mateix flux, sense dependre d'un cron que ningu no recorda revisar.

    server/api/visit.php

05 / SEO tecnic

Un portfolio que no apareix no serveix de res. El posicionament aqui es una questio d'estructura, no de repetir paraules clau.

  • Un unic graf de dades estructurades

    Person, WebSite, ProfilePage, BreadcrumbList i FAQPage viatgen en un sol bloc JSON-LD enllacat per @id, en comptes de blocs solts que poden contradir-se entre ells. Cada article del blog hi afegeix el seu propi BlogPosting.

    src/components/Seo.astro

  • 410 Gone en lloc de 404 per al que s’ha retirat

    Dos projectes es van retirar del lloc amb les URL ja indexades. Un 404 diu al cercador que la pagina podria tornar, i la reintenta durant setmanes; un 410 li diu que la retirada es deliberada i definitiva, i la treu de l'index forca abans.

    server/.htaccess

  • hreflang reciproc, i nomes on hi ha traduccio

    Cada pagina traduida declara totes les seves germanes i un x-default. Les que existeixen en un sol idioma no en declaren cap: anunciar un alternatiu que no existeix trenca el grup sencer, i Google llavors el descarta del tot.

    src/pages/sitemap.xml.ts

  • SEO local amb senyals coherents

    Badalona i Barcelona apareixen al titol, a la descripcio, a les etiquetes geo i dins del bloc Person amb address, homeLocation i areaServed. El senyal importa quan es el mateix a tot arreu, no quan es repeteix en un sol lloc.

    src/config.ts

06 / Llegible per a models de llenguatge

Cada cop es pregunta mes a un assistent i menys a un cercador. Si la resposta sobre mi l'ha de donar una IA, prefereixo que llegeixi dades ordenades i no que improvisi.

  • llms.txt generat a cada compilacio

    Un resum en text pla seguint la convencio de llmstxt.org, sense HTML ni soroll. Surt de les mateixes fonts que alimenten el web, aixi que no pot quedar desfasat respecte del que es veu a la pantalla.

    src/pages/llms.txt.ts

  • Politica explicita per a rastrejadors d’IA

    GPTBot, ClaudeBot, PerplexityBot, Google-Extended i Applebot tenen permis escrit. Els rastrejadors de SEO comercial, que nomes consumeixen amplada de banda de l'allotjament compartit, estan bloquejats. Es una decisio presa, no el resultat de no haver tocat el fitxer.

    public/robots.txt

  • Divulgacio de vulnerabilitats per RFC 9116

    Un /.well-known/security.txt amb contacte, idiomes i data de caducitat. Es el primer que busca qui troba una fallada i la vol reportar be; no tenir-lo es la rao habitual que un avis acabi en un formulari generic o enlloc.

    public/.well-known/security.txt

  • Analisi estatica a cada push

    CodeQL cobreix el frontend en TypeScript i JavaScript. Com que CodeQL no analitza PHP, el backend el revisa Semgrep amb regles d'injeccio, XSS i secrets, i tots dos resultats arriben en format SARIF a la mateixa pestanya. Dependabot vigila les dependencies cada setmana.

    .github/workflows/codeql.yml

Cada punt d'aquesta pàgina correspon a codi que pots obrir al repositori. Si trobes res que no quadri, el canal per avisar-me és a /.well-known/security.txt

Mètriques de rendiment (PageSpeed Insights)

100
Rendiment
100
Accessibilitat
100
Bones pràctiques
100
SEO

* Mesura sobre el servidor de producció de CDMON amb HTTPS i TLS actius. És una foto d'un moment concret, no una garantia permanent: comprova-ho tu mateix si t'interessa.