SYKII · EXTENSIÓN DE TWITCH 1.0.6

Tus hexes junto al chat de twitch.tv/sykii_: TTS con voz a elegir, los canjes
de la tienda de sykii.gg, las predicciones de Twitch con hexes y el Arcade
entero (HEXBREAK, Plinko, moneda, dado, ruleta y Triple Hex). Chrome, Edge,
Brave y Opera (Chromium 116 o más) y Firefox 140 o más.

Va con el bot 0.31.0, el Control Center 3.48 (con el TTS de la tienda) y la
web 28.9.0, en ese orden. Sin la web 28.9 la extensión no puede vincularse.

1.0.6: quien ve el directo con la extensión cuenta como viewer activo,
como si escribiera en el chat (mismos hexes por tick). Solo en
twitch.tv/sykii_, con el vídeo avanzando, con sonido, la pestaña a la vista y
alguien delante (ha tocado la página o el panel en la última media hora); el
bot, además, solo lo cuenta en directo. Un latido cada 5 min a
bot.sykii.gg/public/presence (no a sykii.gg) con un pase de presencia que da
sykii.gg al renovar el acceso. Se apaga en la ventana del icono («Contar como
activo al ver el directo»). Necesita el bot 0.39.0 y la web 28.23.0; con algo
anterior no cuenta y todo lo demás funciona igual. Firefox declara además
«websiteActivity» en data_collection_permissions.

1.0.5: también para Firefox. Mismo código; Firefox lleva su propio
manifest (firefox/manifest.json: página de fondo en lugar de service worker,
id sykii@sykii.gg y la declaración de datos que pide Mozilla). En Chrome no
cambia nada. Necesita la web 28.22.0, que acepta el origen de Firefox
(moz-extension://<UUID>); sin ella, Firefox no puede vincularse.

1.0.4: diseño propio, lejos del de otras extensiones. En directo, el icono
lleva un hexágono rojo (ya no hay distintivo «LIVE»); la ventana del icono
empieza con una franja de señal oscura y el título del directo; el chip del
chat es una placa en chaflán con el aviso dentro; el inicio del panel es una
consola de filas con iconos en hexágono. Sin cambios de permisos.

1.0.3: Plinko con selector de RIESGO (Normal: ×100 muy raro y más bolas
que devuelven lo apostado; Alto: hasta ×1000) y reglas actualizadas.
Necesita el bot 0.36.0; con uno anterior el selector no sale.

1.0.2: botón «Bonus diario» en el inicio del panel (el mismo !daily del
chat, con su racha). Necesita el bot 0.33.0 y la web 28.16.0; con algo
anterior el botón no sale y todo lo demás funciona igual.

CHROME WEB STORE
  Publicada (id onajmdahgkgbpfbpbdkomladdiclegne; enlace en sykii.gg/extension
  desde la web 28.15). El paquete para la tienda es
  SUBIR-A-CHROME-WEB-STORE-<versión>.zip (manifest en
  la raíz y sin "key": la tienda rechaza ese campo). Textos, permisos e imágenes de la ficha en
  chrome-web-store/FICHA-CHROME-WEB-STORE.txt e imagenes/. La tienda da su
  propio id: hay que añadirlo a la web (DEFAULT_EXTENSION_IDS en
  lib/ext-auth.js o EXT_ALLOWED_ORIGINS en Vercel) ANTES de mandarla a revisar,
  o la vinculación fallará. Desde la tienda Chrome la actualiza sola (el aviso
  de versión nueva solo sale en las instaladas a mano).

FIREFOX ADD-ONS
  El paquete es SUBIR-A-FIREFOX-ADD-ONS-<versión>.zip (lo hace
  empaquetar.py con firefox/manifest.json). Se sube en
  addons.mozilla.org/developers como «En este sitio» (listada); textos en
  firefox/FICHA-FIREFOX-ADD-ONS.txt. Mozilla la firma y Firefox la actualiza
  sola. No hay instalación a mano: Firefox solo instala extensiones firmadas
  (para probar, about:debugging → Este Firefox → Cargar complemento temporal
  → el manifest.json del ZIP descomprimido; se quita al cerrar Firefox).
  En Firefox el origen es moz-extension://<UUID aleatorio por instalación>:
  la web acepta cualquiera bien formado (EXT_ALLOW_FIREFOX=0 en Vercel lo
  corta). Cuando Mozilla la publique, pon su enlace en FIREFOX_URL
  (js/extension-link.js de la web) para que salga «Añadir a Firefox».

INSTALAR (sin tienda de extensiones)
  1. Descomprime sykii-extension.zip.
  2. chrome://extensions (opera://extensions, edge://extensions).
  3. Modo de desarrollador → Cargar descomprimida → carpeta sykii-extension.
  4. Abre sykii.gg/extension, entra con Twitch y pulsa «Vincular».
  El ZIP de instalación a mano (instalacion-manual/, el que descarga
  sykii.gg) lleva el campo "key" y por eso su id es fijo
  (hajeifoeinfehgjdfggnghcnlhaclkjd). La carpeta y el ZIP de la tienda no lo
  llevan. Si se publica en la Chrome Web Store o en Opera Add-ons, la
  tienda da otro id: añádelo en Vercel a EXT_ALLOWED_ORIGINS (separados por
  comas) o la web rechazará esa extensión.

CÓMO FUNCIONA
  - El chip con el saldo va dentro de la barra del chat. Si Twitch cambia su
    HTML y no lo encuentra, sale flotando abajo a la derecha.
  - El panel es una página de la propia extensión en un iframe. HEXBREAK
    agranda el panel sobre el reproductor mientras se juega.
  - El TTS es un canje más de la tienda (id «tts», 1.000 hexes, cooldown de
    2 min, precio y cooldown editables en /admin). El bot lo cobra, el Control
    Center lo filtra y lo lee al instante (1–2 s), también en partida; si lo
    rechaza, se devuelve.
  - Predicciones: las de Twitch, con hexes y pago asegurado (×2 si aciertas).
    El chip enseña un punto dorado cuando hay una abierta.
  - Ventana del icono: aviso de directo (y distintivo LIVE en el icono, cada
    2 min con el estado cacheado de sykii.gg), cuenta y saldo, preferencias
    (chip sí/no, avisos de predicciones, tamaño mini/normal, sonidos y volumen
    del Arcade) y aviso de versión nueva (mira assets/extension/latest.json
    cada 6 h; al publicar una versión, sube ese número).
  - El saldo y las tiradas los da el VPS a través de sykii.gg, igual que en
    /arcade. Una tirada nunca se cobra dos veces aunque se corte la conexión.

SEGURIDAD (resumen; detalle en la release de la web 28.9)
  - Permisos mínimos: «storage», «alarms» (LIVE y versión nueva) y acceso solo
    a sykii.gg y a bot.sykii.gg (el bot de Sykii: estado del directo y
    predicciones públicas, para no gastar el límite de Vercel; 1.0.1). El content script
    solo entra en twitch.tv y en sykii.gg/extension, y solo actúa en el canal
    sykii_. Sin código remoto (Manifest V3, CSP script-src 'self').
  - La extensión no tiene ningún secreto: ni el token del VPS ni la cookie de
    la web. Usa un pase propio: 1 h de acceso firmado (sin coste en Redis) y
    30 días de renovación, anulables desde sykii.gg/extension («Desconectar
    todas»). Los pases solo los ve el service worker.
  - La vinculación usa un código de un solo uso (2 min, en Redis solo su hash)
    que solo puede canjear una extensión con el id permitido.
  - /api/ext no manda cabeceras CORS: ninguna web puede leer sus respuestas,
    ni con un pase robado. Twitch no puede leer el chip (shadow root cerrado)
    ni el panel (otro origen). Nada de lo que viene de la red se pinta como HTML.
  - El VPS no recibe ninguna ruta nueva desde fuera salvo POST
    /api/shop/notify, que solo acepta el token de la web y no lleva datos.

ARCHIVOS
  manifest.json         permisos, id fijo, CSP (Chrome)
  firefox/manifest.json el mismo para Firefox (no va dentro de las copias)
  empaquetar.py         hace los tres ZIP de una versión
  background.js         service worker: pases, llamadas a sykii.gg, quién puede pedir qué
  content/twitch.js     chip y iframe del panel en Twitch
  content/link.js       recoge el código de vinculación en sykii.gg/extension
  panel/                panel (TTS, canjes, Mis canjes, Arcade); arcade/ es copia
                        literal de js/arcade y css de sykii.gg 28.9
  popup/                ventana del icono de la barra

La clave privada del id (clave-privada-extension-NO-COMPARTIR.pem) está FUERA
de esta carpeta a propósito: solo sirve para empaquetar un .crx. No la subas
ni la metas en el ZIP.
