Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/site-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ jobs:
node --check tests/consent-coc.cjs
- name: Check consent persistence and Code of Conduct version
run: |
node --test tests/consent-coc.cjs
node --test tests/voluntariado-page.cjs
node --test tests/*.cjs
- name: Check whitespace errors
run: git diff --check HEAD^ HEAD
2 changes: 1 addition & 1 deletion 2026/about.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha384-iw3OoTErCYJJB9mCa8LNS2hbsQ7M3C0EpIsO/H5+EGAkPGc6rk+V8i04oW/K5xq0" crossorigin="anonymous">
<link href="css/variables.css" rel="stylesheet">
<link href="css/base.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
Expand Down
2 changes: 1 addition & 1 deletion 2026/agenda.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha384-iw3OoTErCYJJB9mCa8LNS2hbsQ7M3C0EpIsO/H5+EGAkPGc6rk+V8i04oW/K5xq0" crossorigin="anonymous">
<link href="css/variables.css" rel="stylesheet">
<link href="css/base.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
Expand Down
2 changes: 1 addition & 1 deletion 2026/codigo_conducta.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha384-iw3OoTErCYJJB9mCa8LNS2hbsQ7M3C0EpIsO/H5+EGAkPGc6rk+V8i04oW/K5xq0" crossorigin="anonymous">
<link href="css/variables.css" rel="stylesheet">
<link href="css/base.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
Expand Down
2 changes: 1 addition & 1 deletion 2026/convence-a-tu-jefe.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha384-iw3OoTErCYJJB9mCa8LNS2hbsQ7M3C0EpIsO/H5+EGAkPGc6rk+V8i04oW/K5xq0" crossorigin="anonymous">
<link href="css/variables.css" rel="stylesheet">
<link href="css/base.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
Expand Down
2 changes: 1 addition & 1 deletion 2026/faq.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha384-iw3OoTErCYJJB9mCa8LNS2hbsQ7M3C0EpIsO/H5+EGAkPGc6rk+V8i04oW/K5xq0" crossorigin="anonymous">
<link href="css/variables.css" rel="stylesheet">
<link href="css/base.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
Expand Down
2 changes: 1 addition & 1 deletion 2026/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha384-iw3OoTErCYJJB9mCa8LNS2hbsQ7M3C0EpIsO/H5+EGAkPGc6rk+V8i04oW/K5xq0" crossorigin="anonymous">
<link href="css/variables.css" rel="stylesheet">
<link href="css/base.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
Expand Down
2 changes: 1 addition & 1 deletion 2026/patrocinadores.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha384-iw3OoTErCYJJB9mCa8LNS2hbsQ7M3C0EpIsO/H5+EGAkPGc6rk+V8i04oW/K5xq0" crossorigin="anonymous">
<link href="css/variables.css" rel="stylesheet">
<link href="css/base.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
Expand Down
4 changes: 2 additions & 2 deletions 2026/ponentes.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha384-iw3OoTErCYJJB9mCa8LNS2hbsQ7M3C0EpIsO/H5+EGAkPGc6rk+V8i04oW/K5xq0" crossorigin="anonymous">
<link href="css/variables.css" rel="stylesheet">
<link href="css/base.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
Expand Down Expand Up @@ -332,7 +332,7 @@ <h2>¿Por qué presentar en PyCon?</h2>
</footer>

<!-- Supabase CDN Client Library & Config -->
<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>
<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2.117.2/dist/umd/supabase.js" integrity="sha384-Rj26LVGvoeRVR6+mwQmFfcR3QOBEwT+ZmuCWpuiqeTzJpCs0ER4ITAWGb4Hiy3Ok" crossorigin="anonymous"></script>
<script src="js/env.js"></script>
<script src="js/supabase-config.js?v=5427c37ebf46"></script>
<script src="js/main.js"></script>
Expand Down
2 changes: 1 addition & 1 deletion 2026/privacidad.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha384-iw3OoTErCYJJB9mCa8LNS2hbsQ7M3C0EpIsO/H5+EGAkPGc6rk+V8i04oW/K5xq0" crossorigin="anonymous">
<link href="css/variables.css" rel="stylesheet">
<link href="css/base.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
Expand Down
4 changes: 2 additions & 2 deletions 2026/registro.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha384-iw3OoTErCYJJB9mCa8LNS2hbsQ7M3C0EpIsO/H5+EGAkPGc6rk+V8i04oW/K5xq0" crossorigin="anonymous">
<link href="css/variables.css" rel="stylesheet">
<link href="css/base.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
Expand Down Expand Up @@ -338,7 +338,7 @@ <h2>PyCon Panamá 2026</h2>
</footer>

<!-- Supabase CDN Client Library & Config -->
<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>
<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2.117.2/dist/umd/supabase.js" integrity="sha384-Rj26LVGvoeRVR6+mwQmFfcR3QOBEwT+ZmuCWpuiqeTzJpCs0ER4ITAWGb4Hiy3Ok" crossorigin="anonymous"></script>
<script src="js/env.js"></script>
<script src="js/supabase-config.js?v=5427c37ebf46"></script>
<script src="js/main.js"></script>
Expand Down
2 changes: 1 addition & 1 deletion 2026/sedes.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha384-iw3OoTErCYJJB9mCa8LNS2hbsQ7M3C0EpIsO/H5+EGAkPGc6rk+V8i04oW/K5xq0" crossorigin="anonymous">
<link href="css/variables.css" rel="stylesheet">
<link href="css/base.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
Expand Down
4 changes: 2 additions & 2 deletions 2026/voluntariado/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha384-iw3OoTErCYJJB9mCa8LNS2hbsQ7M3C0EpIsO/H5+EGAkPGc6rk+V8i04oW/K5xq0" crossorigin="anonymous">
<link href="../css/variables.css" rel="stylesheet">
<link href="../css/base.css" rel="stylesheet">
<link href="../css/style.css" rel="stylesheet">
Expand Down Expand Up @@ -221,7 +221,7 @@ <h2>Construyamos PyCon juntos</h2>
</div>
</footer>

<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>
<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2.117.2/dist/umd/supabase.js" integrity="sha384-Rj26LVGvoeRVR6+mwQmFfcR3QOBEwT+ZmuCWpuiqeTzJpCs0ER4ITAWGb4Hiy3Ok" crossorigin="anonymous"></script>
<script src="../js/env.js"></script>
<script src="../js/supabase-config.js?v=5427c37ebf46"></script>
<script src="../js/main.js"></script>
Expand Down
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Este repositorio contiene el sitio público de [PyCon Panamá](https://pycon.pa/
- [Estructura y alcance](#estructura-y-alcance)
- [Cambiar el sitio](#cambiar-el-sitio)
- [Validar antes de proponer cambios](#validar-antes-de-proponer-cambios)
- [Actualizar recursos CDN e integridad](#actualizar-recursos-cdn-e-integridad)
- [Despliegue](#despliegue)
- [Contribuir](#contribuir)
- [Documentación y contacto](#documentación-y-contacto)
Expand Down Expand Up @@ -107,6 +108,33 @@ git diff --check
git diff -- 2026/ netlify.toml sitemap.xml robots.txt
```

## Actualizar recursos CDN e integridad

Última actualización: 27 de septiembre de 2026.

La edición 2026 fija Supabase JS en `2.117.2` (`dist/umd/supabase.js`) y Font Awesome en `6.4.0` (`css/all.min.css`). Sus etiquetas llevan `integrity="sha384-…"` y `crossorigin="anonymous"`. La versión de Supabase corresponde a la que resolvía `@2` al realizar este cambio; el archivo UMD coincide con el distribuido en npm.

Para actualizar cualquiera de estos recursos:

1. Revisa las notas de la versión y elige una versión exacta; no uses `@2`, `latest` ni rangos.
2. Descarga la URL exacta en un archivo temporal fuera del repositorio y calcula SHA-384 sobre sus bytes. Por ejemplo, para la versión actual de Supabase:

```bash
cdn_file=$(mktemp)
curl --fail --location --silent --show-error --compressed \
'https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2.117.2/dist/umd/supabase.js' \
--output "$cdn_file" &&
openssl dgst -sha384 -binary "$cdn_file" | openssl base64 -A
rm -f "$cdn_file"
```

3. Anteponer `sha384-` al resultado da el valor de `integrity`. Para Font Awesome usa su URL exacta de cdnjs y el mismo procedimiento. Verifica el archivo contra la distribución oficial y comprueba que el CDN devuelve `Access-Control-Allow-Origin: *`.
4. Actualiza URL e integridad juntas en las tres páginas con Supabase (`registro.html`, `ponentes.html`, `voluntariado/index.html`) o en las doce páginas de 2026 con Font Awesome. Conserva `crossorigin="anonymous"`. No cambies las ediciones archivadas.
5. Ejecuta `node --test tests/*.cjs`, `python3 scripts/validate_site.py` y `git diff --check`. La prueba de CDN detecta versiones flotantes, atributos ausentes e inconsistencias entre páginas; verifica también el hash descargando los recursos, ya que esa prueba local no consulta la red.
6. Revisa el preview de Netlify: SDK e iconos deben cargar sin errores de SRI/CORS. Antes de probar envíos, confirma que el preview utiliza una base de pruebas aislada. Comprueba los flujos abiertos con datos sintéticos y conserva cerrado el formulario de ponencias mientras la convocatoria siga cerrada; su ruta de integración puede probarse con respuestas simuladas.

Si el navegador rechaza un recurso, compara los bytes y la versión con el hash esperado; no retires `integrity` para sortear el fallo. SRI verifica el JS y la hoja CSS enlazados, no los archivos de fuentes que esa hoja descarga. Consulta [Subresource Integrity en MDN](https://developer.mozilla.org/en-US/docs/Web/Security/Defenses/Subresource_Integrity).

## Despliegue

Netlify publica la raíz del repositorio (`publish = "."`) según [`netlify.toml`](netlify.toml). La configuración redirige `/` a `/2026/` y define cabeceras de seguridad para el sitio.
Expand Down
39 changes: 39 additions & 0 deletions tests/cdn-integrity.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');

function htmlFiles(directory) {
return fs.readdirSync(directory, { withFileTypes: true }).flatMap(entry => {
const file = path.join(directory, entry.name);
return entry.isDirectory() ? htmlFiles(file) : file.endsWith('.html') ? [file] : [];
});
}

test('los recursos CDN usan versiones exactas, SRI y CORS coherentes', () => {
const hashes = new Map();
const sdkPages = [];
for (const file of htmlFiles('2026')) {
const html = fs.readFileSync(file, 'utf8');
let fontAwesome = 0;
for (const [tag] of html.matchAll(/<(?:script|link)\b[^>]*>/g)) {
const attrs = Object.fromEntries([...tag.matchAll(/([\w-]+)="([^"]*)"/g)].map(m => [m[1], m[2]]));
const url = attrs.src || attrs.href || '';
if (!url.includes('cdn.jsdelivr.net/npm/@supabase/') && !url.includes('cdnjs.cloudflare.com/ajax/libs/font-awesome/')) continue;
assert.equal(attrs.crossorigin, 'anonymous', file);
assert.match(attrs.integrity || '', /^sha384-[A-Za-z0-9+/]{64}$/, file);
if (url.includes('@supabase/')) {
assert.match(url, /^https:\/\/cdn\.jsdelivr\.net\/npm\/@supabase\/supabase-js@\d+\.\d+\.\d+\/dist\/umd\/supabase(?:\.min)?\.js$/, file);
sdkPages.push(file);
} else {
assert.match(url, /^https:\/\/cdnjs\.cloudflare\.com\/ajax\/libs\/font-awesome\/\d+\.\d+\.\d+\/css\/all\.min\.css$/, file);
fontAwesome++;
}
if (hashes.has(url)) assert.equal(attrs.integrity, hashes.get(url), file);
hashes.set(url, attrs.integrity);
}
assert.equal(fontAwesome, 1, file);
}
assert.deepEqual(sdkPages.sort(), ['2026/ponentes.html', '2026/registro.html', '2026/voluntariado/index.html']);
assert.equal(hashes.size, 2, 'Todas las páginas deben usar la misma versión de cada recurso');
});
Loading