dec-0130

Vista generada de dec-0130: Modo público y Styx como plataforma: registro abierto o con aprobación, roles atados al registro, entrega por biblioteca, moderación y retirada, superficie pública publicable y frontend plantilla

ImplementadoSin versión del tren todavía· generada desde docs/decisions/dec-0130-modo-publico-y-styx-como-plataforma.md
track/docsdec-0124track/docs:DC10

Vista generada desde docs/decisions/dec-0130-modo-publico-y-styx-como-plataforma.md. No se edita a mano: bun run docs:gen la regenera y bun run docs:check falla si difiere. El estado aquí es el del model: si discrepa con otra página, manda el model.

CampoValor
EstadoPROPOSED
Fecha2026-10-01
Ficherodocs/decisions/dec-0130-modo-publico-y-styx-como-plataforma.md

Por qué importa (del frontmatter del ADR):

Fija dos cosas que waxin pidió juntas el 2026-10-01 (N8). (1) El modo público: un perfil de despliegue aditivo sobre las capas de cuentas (dec-0125), autorización (dec-0118), catálogo, ingesta (dec-0121) y entrega, con política de registro (cerrado, invitación, aprobación, abierto), principal anónimo opcional, roles de ver, descargar, subir, editar y moderar como niveles de concesión de biblioteca atados a la vía de registro, entrega por biblioteca (stream, descarga o ambos), moderación, aviso y retirada (DMCA, DSA, TCO) y cuotas para un servidor con usuarios no confiables. (2) Styx como plataforma: qué paquetes y componentes se publican, con qué etiquetas de estabilidad y con qué reglas de versionado (sobre dec-0123), docs (dec-0124) y un frontend plantilla que sólo consume la superficie pública. Sin este ADR cada pieza pública nacería con su propia idea de estabilidad, el SDK público heredaría la excepción r52 (tipos importados de un servicio) y el primer despliegue abierto llegaría sin cuotas para anónimos, sin moderación y sin canal de retirada.

Nodos del roadmap que lo citan en refs: ninguno.

Páginas de la documentación que lo citan: Modo público y Styx como plataforma (especificado)

Texto del ADR

Leído de docs/decisions/dec-0130-modo-publico-y-styx-como-plataforma.md, el fichero canónico.

dec-0130 — Modo público y Styx como plataforma: registro abierto o con aprobación, roles atados al registro, entrega por biblioteca, moderación y retirada, superficie pública publicable y frontend plantilla

  • Fecha: 2026-10-01
  • Estado: PROPOSED. No es un lock. waxin lo lockea vía AskUserQuestion, con las preguntas de §15 resueltas o diferidas de forma explícita. Mientras no se lockee no se implementa nada: este ADR describe el sistema objetivo para que la doc (dec-0124 §6) lo especifique y los contratos se diseñen antes que el código.
  • Dirección de waxin (2026-10-02, punto 16 de sus decisiones; no lockea el ADR): tras el MVP (release alpha.1, dec-0133) el modo público se valora bien y el ADR se re-lockea (diferido d19). Si hace falta algo de contratos antes, se hace. El modo público queda fuera de los alfas (excludes de alpha.1).
  • Propone: workflow de visión (rama w10/adr-publico, desde w10/vision). Nodos track/platform y track/public-mode: alta propuesta queued en el model, pendiente de ratificar en P10 (§15).
  • Ledger de visión que cubre (docs/overview/vision-ledger.yml): V-N08 (modo público), V-BIZ-01 (base para construir encima), V-BIZ-02 (aditivo sobre capas existentes), V-BIZ-03 (motivación: mercado nuevo a coste bajo), V-BIZ-04 (stream, descarga o ambos; frontend como plantilla; sólo la API). Toca de lado V-N02 (el player como componente público) y V-N07 (descargas, cuyo diseño es de dec-0129).
  • Dirección de waxin que cumple (2026-10-01, sesion:resp#9, literal con sus erratas):
    • «esto seria un modo "publico" en el que sea abierto o semi abierto, ya sea con registros abiettos, registros con approval de admin, o sin registro. modo aparte del modelo q teniamos pensado. orientado a web publica.»
    • «con roles para quien puede subir ver editar etc atadas a los registros.»
    • «que pueda ser de stram o descaga o ambas , que puedas usar el frontend como plantilla por como esya compuesto styx y el sdk y el frontend los paquetes el player todo lo asi reusable o usar solo la api y construir como quieras sobre styx»
    • «por como montamos styx solo cambiamos capas creadas ya o planeadas»
    • «ofrecer styx como base para consttruir envcima con su sdk, plugins, api y componentes publicos de la app como el player o alguna pieza que de por si sea buena como no se, conduit o lo que acabe quedando chulo. esto nos hara escribir un codigo mejor ya que dejamos de ser los unicos consumidores y auditores»
  • Cita:
    • r16: frontier salvo blocker. Y su «Productización diferida: "si sale bien"» (línea 31), con el que este ADR choca a medias (§11.2).
    • r17: un contenedor por authority. El modo público no añade servicios (§11).
    • r20 §2.3 / dec-0116: contract-first TypeBox. El SDK público sale del contrato, no de los tipos de un servicio (§8.3).
    • r28: cada pieza termina en un consumidor real. El frontend plantilla es el consumidor de la superficie pública (§9).
    • r48: track/plugins-sdk = SDK público de plugins post-F1, trust levels y manifest versionado. Este ADR lo enmarca dentro de la superficie pública, no lo redecide.
    • r52: @styx/clients importa el tipo App de catalog-svc. Válido dentro del monorepo; no publicable (§8.3).
    • r53 / dec-0063: player web propio. N2 ordena: primero los vendorizados, luego el propio.
    • dec-0112 §1: ningún claim comparativo contra Jellyfin sin la suite WC-JF12, tampoco en la doc pública ni en el README de un paquete.
    • dec-0117: data plane Zig, escritura fd-relativa (las subidas públicas no cambian eso).
    • dec-0118 (LOCKED): BFF sin tokens en el navegador, roles owner/admin/member/restricted, can(), audit, rate-limit por unidad de cliente. Se respeta entero; una enmienda acotada (§11.1, principal anónimo).
    • dec-0119 / dec-0120: los eventos nuevos van por spire (BUS_ROUTES).
    • dec-0121: ingesta con conduit, SCT ingest, cuotas por fichero, por actor y de raíz. El modo público las reutiliza y las escalona por nivel (§7.3).
    • dec-0123 (PROPOSED, w7/release-eng): tren + SemVer por componente, detectores de interfaz, canales. En su tabla de descartes dice «Publicar packages/* en npm — Son internos (private). Si algún día se publica plugin-sdk o source-sdk, se promueve a componente con su tag.» Este ADR es ese «algún día» y fija cómo (§8.4).
    • dec-0124 (PROPOSED): doc como contrato, registro de operaciones (§6.1), estados especificado|implementado|verificado. La superficie pública es la parte que se documenta para terceros.
    • dec-0125 (PROPOSED): cuentas, identidades, hogares, perfiles, concesiones de biblioteca, invitaciones, API keys, device grant. El modo público es configuración de ese modelo más tres añadidos (§4).
    • dec-0126 (PROPOSED): metadatos en el fichero. Lo que se descarga de un servidor público lleva sus metadatos y nada del usuario.
    • Del mismo workflow, también PROPOSED: dec-0127 (modelo de datos), dec-0128 (dispositivos), dec-0129 (transferencias: descarga reanudable y generación al vuelo) y dec-0131 (federación). Este ADR depende de dec-0129 para el detalle de la descarga y no lo redecide.

1. Contexto: qué existe hoy y qué es nuevo

Verificado sobre el árbol de w10/vision (base w9/docs).

PiezaEstadoDónde
Roles de instalación restricted < member < admin < owner, permisos <recurso>:<acción> con alcance own/shared/anyexistepackages/authz/src/policy.ts (dec-0118 §4, TS4-P2-02)
Permisos que hoy existen: asset:play, asset:scan, ingest-session:*, playback-session:close, sesiones y actorexisteRESOURCE_ACTIONS en policy.ts
Rate-limit y agregación de audit por unidad de cliente (IPv6 por su /64)existe@styx/observability/client-unit (TS10-P2-01), dec-0118 §9
Ingesta con SCT ingest, tope por fichero, cuota por actor (STYX_INGEST_QUOTA_PER_ACTOR_MIB), tope de raíz, sesiones por actorexistedec-0121, daemon IngestSink, playback-svc IngestHandler
SCT por sesión de reproducción, deny-by-default en el daemonexistedec-0117, spire.cap
Cuentas, hogares, perfiles, concesiones de biblioteca, invitaciones, API keys, device grantPROPOSEDdec-0125
Registro de operaciones, SDK por operación, CLI styx, MCPPROPOSEDdec-0124 §6.1
SemVer por componente, detectores de interfaz, manifiesto firmadoPROPOSEDdec-0123 (w7/release-eng)
Todos los package.json de packages/* y apps/*: private: true, versión 0.0.1/0.1.0existeárbol
Licencia del repo: MPL-2.0existeLICENSE
spire y conduit: SDKs en sus propios repos, fijados por URL publicada y hashexistenative/zig/build.zig.zon, @spire/bus en los package.json
Player: vidstack (dependencia) y limeplay (vendorizado en apps/web/src/engines/limeplay/)existeapps/web
UI: TIER 2 compositional en @styx/ui (packages/ui/src/composite/)existeapps/web/CLAUDE.md §TIER
Principal anónimo, política de registro, nivel de concesión, visibilidad y entrega por biblioteca, moderación, aviso y retiradanuevoeste ADR
Etiquetas de estabilidad de API pública, informe de API, publicación de paquetes, frontend plantillanuevoeste ADR

Hoy Styx asume que todo usuario es de confianza: alguien que el owner metió a mano. El modo público rompe esa suposición, y por eso lo que falta no es una pantalla sino tres cosas que un servidor privado no necesita: un principal sin cuenta, una forma de dar permisos por la vía de entrada, y moderación.

2. Referencias externas estudiadas y qué se toma

ReferenciaQué haceQué se toma / qué no
PeerTube (vídeo público federado)Registro cerrado, abierto o con aprobación (el solicitante escribe un motivo, admin y moderadores aceptan o rechazan). Cuota diaria y total por usuario. Cualquiera, local o remoto, puede denunciar un vídeo; cola de denuncias con aceptar/rechazar y aviso al denunciante. Recomienda cuota baja o cuarentena automática de lo nuevo.Las tres políticas de registro con motivo (§5), cuota diaria + total (§7.3), cuarentena de lo subido por cuentas nuevas (§7.2), cola de denuncias con resolución notificada (§7.4). La federación es de dec-0131.
Mastodon (registro de instancia)Registro «cualquiera», «con aprobación» o «nadie», más enlaces de invitación que saltan la aprobación.Misma tabla, y que una invitación (dec-0125 §7) siempre salta la política de registro.
JellyfinServidor privado. Sin registro público, sin subida de ficheros, sin moderación.Nada que tomar: es el hueco. No se escribe como claim comparativo en la doc pública sin WC-JF12 (dec-0112).
DSA (Reglamento UE 2022/2065)Arts. 16–18 aplican a todo servicio de alojamiento, también a las pequeñas empresas: mecanismo de aviso y acción, exposición de motivos de cada restricción, aviso de sospecha de delito. Los arts. 19–28 (plataformas) no aplican a micro y pequeñas empresas salvo el 24(3).Canal de aviso estructurado, exposición de motivos por cada acción de moderación y registro de ambos (§7.4). Styx da el mecanismo; el cumplimiento es del operador.
TCO / TERREG (Reglamento UE 2021/784)Una orden de retirada de contenido terrorista se cumple en una hora en toda la UE. Lo retirado se conserva un tiempo.La retirada tiene que ser una operación de un paso, alcanzable por API y CLI, que corte también las sesiones en curso, y con retención configurable de lo retirado (§7.4).
DMCA §512 (EE. UU.)Puerto seguro si hay agente designado (registro en la Copyright Office, se renueva cada tres años), aviso y retirada, contraaviso, y política de reincidentes aplicada.Plantilla de aviso, contraaviso y contador de reincidencia por cuenta, con umbral configurable (§7.4). El agente designado es del operador; Styx sólo muestra el contacto.
npm trusted publishing (GA 2025-07-31)Publicar desde GitHub Actions con OIDC, sin token de larga vida, con atestación de procedencia por defecto (npm CLI ≥ 11.5.1).Canal de publicación de los paquetes públicos (§8.5), coherente con cosign keyless de dec-0123 D3.
API Extractor (etiquetas de release de TSDoc)@public = contrato soportado, no cambia sin MAJOR; @beta = vista previa; @alpha = temprano, no usar; @internal = sólo paquetes del mismo mantenedor. Informe de API versionado en el repo.Las cuatro etiquetas y el informe de API por paquete como detector de interfaz (§8.4). La herramienta concreta la elige el ticket (TypeDoc ya está en dec-0124).

Fuentes al final del documento.

3. Decisión (resumen)

  1. Modo = configuración, no código aparte. STYX_MODE=private|public es un preset de valores por defecto sobre cinco ajustes independientes (registro, anónimo, visibilidad y entrega por biblioteca, moderación). private es lo de hoy y sigue siendo el default (§4).
  2. Registro: closed | invite | approval | open. Una invitación de dec-0125 salta siempre la política. Sin registro ≠ sin acceso: el acceso sin cuenta es el principal anónimo, aparte (§5).
  3. Principal anónimo opcional (anonymous: off | browse | play | download), nunca un actor en la base: no tiene sesión de identity, sus límites cuelgan de la unidad de cliente y sólo ve bibliotecas concedidas a @anyone (§5.3).
  4. Roles atados al registro = niveles de concesión de biblioteca: view < download < upload < edit < moderate, sobre las concesiones de dec-0125. La política de registro dice qué concesión recibe la cuenta al nacer. Los roles de servidor de dec-0118 no cambian (§6).
  5. Entrega por biblioteca: delivery: stream | download | both y visibility: private | unlisted | public, aplicados por playback-svc al emitir la SCT (§6.4).
  6. Moderación y retirada first-class en modo público: cuarentena, denuncias, acciones con exposición de motivos, retirada en un paso que corta sesiones, aviso/contraaviso, reincidencia y retención (§7).
  7. Superficie pública publicable: lista cerrada de paquetes y binarios, cada uno con etiquetas @public/@beta/@alpha/@internal, informe de API, SemVer de componente (dec-0123) y referencia generada (dec-0124). Lo demás sigue private (§8).
  8. Frontend plantilla templates/public-catalog: una app que sólo puede importar la superficie pública. Es su consumidor real y el test de que se puede construir encima sin fricción (§9).
  9. Aditivo: ningún contrato existente cambia de forma incompatible; las tres enmiendas que hacen falta son acotadas y se listan (§11).

4. El modo como preset

4.1 Los ajustes

AjusteValoresDónde viveprivate (default)public (preset)
registrationclosed, invite, approval, openidentity-svc, config de servidorinviteapproval
anonymousoff, browse, play, downloadidentity-svc + @styx/authzoffbrowse
library.visibilityprivate, unlisted, publiccatalog-svc, por bibliotecaprivateprivate (el owner publica a mano)
library.deliverystream, download, bothcatalog-svc, por bibliotecabothstream
moderationoff, oncatalog-svc + identity-svcoffon (no se puede apagar en público)
registration.defaultGrantnivel de concesión por vía (§6.2)identity-svc—tabla de §6.2
  • El preset sólo fija defaults: cada ajuste se puede cambiar por config, API y CLI, con dos restricciones duras que valida el arranque:
    • registration: open o anonymous ≠ off exigen moderation: on, un contacto de abuso configurado (STYX_ABUSE_CONTACT) y las cuotas de §7.3. Sin ellos el servicio no arranca (fail-closed, como el resto de dec-0118).
    • anonymous: download exige que la biblioteca tenga delivery con descarga y que el servidor tenga STYX_ANON_EGRESS_* (§7.3).
  • STYX_MODE no es un modo de compilación ni de imagen: es el mismo artefacto (dec-0123).

4.2 Lo que el modo público NO es

  • No es multi-tenant en el sentido de hosting: sigue habiendo una instalación, un owner y un catálogo. Varias comunidades = varias instalaciones, unidas, si se quiere, por la federación de dec-0131.
  • No cambia el modelo Work → Edition → MediaAsset → SourceBinding (r08) ni el de cuentas (dec-0125). Añade estado de moderación y dos campos de biblioteca.
  • No es otra web: la web de Styx sigue siendo la web de Styx. El frontend sencillo es la plantilla (§9).

5. Registro y principal anónimo

5.1 Políticas de registro

PolíticaQuién puede crear cuentaQué pasa al pedirla
closedSólo el owner/admin, a mano.No hay formulario.
inviteQuien tenga una invitación (dec-0125 §7).Lo de dec-0125.
approvalCualquiera pide; un admin o moderador aprueba.Se crea una solicitud (identidad OIDC ya verificada + motivo + aceptación de normas). Sin cuenta hasta aprobarla.
openCualquiera.La cuenta nace al volver del OP, con la concesión de la vía open (§6.2) y en periodo de prueba (§7.2).
  • La identidad sigue siendo OIDC con passkeys (dec-0125 §8). En open y approval el OP tiene que permitir alta pública (Pocket ID ALLOW_USER_SIGNUPS=open) o Styx le pide un token de registro de un uso por solicitud, el mismo port de aprovisionamiento de dec-0125 §8.2. El password local opt-in de dec-0125 §8.3 no cambia y no se recomienda en público.
  • La solicitud de approval guarda lo mínimo (sujeto OIDC, email si el OP lo da, motivo, fecha) y caduca (STYX_REGISTRATION_REQUEST_TTL). Rechazarla la borra; aprobarla crea la cuenta con la concesión de la vía approval. Las dos acciones se auditan.
  • Anti-bots: en open y en el formulario de approval, un reto de prueba de trabajo sin terceros ni cookies de rastreo (ALTCHA, MIT, o uno propio sobre el mismo esquema) más el rate-limit por unidad de cliente. CAPTCHAs de terceros no: ponen a un tercero delante del registro y filtran datos (P5).
  • Una invitación de dec-0125 salta cualquier política, incluso closed. Es la forma de dar upload o edit a gente concreta en un servidor abierto.

5.2 Por qué "sin registro" no es una cuarta política de cuentas

waxin pidió «registros abiettos, registros con approval de admin, o sin registro». "Sin registro" se lee de dos formas y las dos caben:

  • Nadie se registra = registration: closed.
  • Se usa sin registrarse = anonymous ≠ off, combinable con cualquier política. Un catálogo público de sólo lectura es registration: closed + anonymous: play. Uno con comunidad es approval + anonymous: browse.

Separarlos evita la trampa de PeerTube y Mastodon, donde "abierto" mezcla quién entra con qué ve el que no ha entrado.

5.3 El principal anónimo

  • @styx/authz gana un tipo de principal anonymous además del actor. No tiene id persistente, ni sesión de identity, ni perfil, ni historial: el estado por perfil de dec-0125 no existe para él. Si se quiere «seguir viendo» sin cuenta, vive en el navegador (localStorage), nunca en el servidor.
  • Sus permisos salen de anonymous (§4.1) intersecado con las bibliotecas concedidas al grantee especial @anyone (§6.3). Nunca recibe upload, edit ni moderate, ni ningún permiso de los recursos de sesión o actor.
  • Sus límites cuelgan de la unidad de cliente (clientUnitKey, IPv6 por su /64), la misma clave del rate-limit y del audit (TS10-P2-01).
  • La web sigue sin tokens (dec-0118 §2.1): el BFF emite la SCT de reproducción o descarga para el anónimo con TTL corto y ligada a la unidad de cliente. En el daemon no cambia nada: una SCT es una SCT.
  • Denunciar (§7.4) es lo único que un anónimo puede escribir, y siempre con reto de prueba de trabajo.

6. Roles atados al registro: niveles de concesión

6.1 Por qué niveles de concesión y no roles nuevos

dec-0118 fija cuatro roles de servidor y está LOCKED. Lo que waxin pide («quien puede subir ver editar») no es un rango sobre todo el servidor: es qué hace cada uno con cada biblioteca. dec-0125 ya tiene la pieza, la concesión de biblioteca a una cuenta o un hogar. Se le añade un nivel:

NivelPermitePermisos nuevos en RESOURCE_ACTIONS
viewVer el catálogo y reproducir (si delivery lo permite).library:browse (asset:play ya existe)
downloadLo anterior + descargar (si delivery lo permite; el cómo es de dec-0129).asset:download
uploadLo anterior + subir a esa biblioteca (sesión de ingesta con destino = la biblioteca).ingest-session:create con alcance de biblioteca
editLo anterior + editar metadatos y artwork de lo que hay en ella.metadata:edit
moderateLo anterior + resolver denuncias, ocultar, retirar y suspender en esa biblioteca.report:resolve, asset:moderate, registration:approve
  • Cada nivel incluye los anteriores. Permiso efectivo = rol de servidor ∩ perfil ∩ credencial ∩ nivel de la concesión de la biblioteca del recurso (extiende la regla de intersección de dec-0125 §5.1; no la cambia).
  • En un servidor privado todas las concesiones existentes migran como download (equivale a lo de hoy: member ve y reproduce lo shared) y la subida sigue saliendo del rol, como en dec-0121. Nadie pierde ni gana nada al migrar.
  • upload por concesión acota la subida: hoy member sube con alcance own a la raíz de ingesta; con niveles, sube a la biblioteca concedida y sólo a ella.
  • edit cubre la edición manual de metadatos. Cómo se reescribe el fichero cuando el metadato vive en él (N1, dec-0127/dec-0126) no es de este ADR; aquí sólo quién puede pedirlo.

6.2 La vía de registro decide la concesión inicial

VíaConcesión inicial (recomendada; configurable)Estado inicial
anónimo@anyone: según anonymous (browse = view sin asset:play)—
open@registered (§6.3) a viewprueba (§7.2)
approval@registered a view; el que aprueba puede subir el nivelnormal
invitación (dec-0125 §7)la que diga la invitación (puede ser upload, edit, moderate)normal
creada por adminla que fije el adminnormal

Ninguna vía automática da upload o más: subir, editar y moderar en un servidor abierto se concede a personas concretas (invitación o admin). Si waxin quiere un servidor de subida abierta («cualquiera sube»), es @registered a upload con cuarentena obligatoria (P3).

6.3 Grantees especiales

dec-0125 concede a cuenta u hogar. Se añaden dos grantees sin fila propia:

  • @anyone: cualquier principal, incluido el anónimo. Una biblioteca concedida a @anyone es visibility: public.
  • @registered: cualquier cuenta activa del servidor.

visibility es una vista de las concesiones, no un segundo sistema: public ⇔ hay concesión a @anyone; unlisted ⇔ concesión a @anyone sólo por enlace directo (no aparece en listados ni en búsqueda, el id no es adivinable); private ⇔ ninguna. Así sólo hay una fuente de verdad del acceso.

6.4 Entrega por biblioteca

  • delivery: stream | download | both es un campo de la biblioteca. playback-svc lo comprueba al emitir la SCT: no emite scope de descarga si la biblioteca es stream, ni de reproducción si es download.
  • Descarga «en un formato o códec que el fichero no tiene» se genera al vuelo como el stream (N7). En público eso es CPU que puede pedir cualquiera, así que:
    • anónimo: sólo variantes ya presentes o en caché (STYX_ANON_ONTHEFLY=off por defecto);
    • registrado: generación al vuelo dentro de su cuota de cómputo (§7.3). El mecanismo de la descarga (reanudable, conduit, offline) es de dec-0129.

7. Moderación, abuso y retirada

7.1 Amenazas propias de un servidor abierto

AmenazaMitigación
Altas masivas de botsapproval por defecto; prueba de trabajo; rate-limit por unidad de cliente; solicitudes con TTL y tope global.
Subida de contenido ilegal o ajenoNadie sube sin concesión explícita (§6.2); cuarentena de lo nuevo (§7.2); denuncias y retirada (§7.4); lista de bloqueo por huella (§7.5).
Agotar discoCuotas de dec-0121 (fichero, actor, raíz) más cuota diaria (§7.3).
Agotar CPU con generación al vueloAnónimo sin generación al vuelo; cuota de cómputo por cuenta; cola con prioridad a reproducción sobre descarga.
Agotar ancho de banda (hotlinking, descargas en bucle)SCT corta ligada a unidad de cliente; tope de egress por unidad de cliente y global para anónimos; sin URLs de media estables.
Enumeración y scraping del catálogoListados paginados con tope; unlisted con ids no adivinables; rate-limit de library:browse anónimo.
Abuso del canal de denuncias (denuncias falsas masivas)Prueba de trabajo; rate-limit; denuncias agregadas por objeto; una denuncia no oculta nada por sí sola salvo umbral configurable (P6).
Moderador que abusamoderate sólo por biblioteca; toda acción con motivo y en el audit append-only; el owner revierte; el afectado ve la exposición de motivos.
Datos personales en lo subido (metadatos del fichero)La ingesta no publica los tags originales sin revisar; dec-0126 ya prohíbe datos de usuario en lo que Styx escribe.

7.2 Cuarentena y periodo de prueba

  • Lo que sube una cuenta en periodo de prueba, o en una biblioteca con moderation.quarantineUploads: true, entra con estado quarantined: existe, lo ve quien lo subió y los moderadores, no aparece para nadie más. Un moderador lo publica.
  • El periodo de prueba de una cuenta open termina por tiempo o por aprobación manual (configurable); mientras dura, cuotas reducidas.

7.3 Cuotas

Se reutiliza el ledger por actor de dec-0121 (TS5-P2-01) y se añade:

  • Cuota diaria de subida por cuenta además de la total (PeerTube hace las dos), y cuotas por nivel de confianza (prueba, normal, de confianza).
  • Cuota de cómputo por cuenta para generación al vuelo (segundos de CPU/GPU por día).
  • Egress anónimo: tope por unidad de cliente y global (STYX_ANON_EGRESS_*), medido en el daemon, que es quien sirve los bytes.
  • El daemon sigue siendo el último tope (raíz de ingesta, sesiones). Las cuotas de política viven en catalog-svc/playback-svc; el daemon no conoce niveles.

7.4 Denuncias, acciones y retirada

  • Denuncia (report:create): cualquiera, anónimo incluido, contra un asset, una obra, un comentario futuro o una cuenta. Categoría (derechos de autor, ilegal, spam, otro), texto, contacto opcional. Para derechos de autor, los campos del aviso DMCA/DSA (titular, obra original, declaración de buena fe) para que el aviso esté completo.
  • Acciones (asset:moderate): ocultar, retirar (el objeto deja de servirse), restaurar, suspender cuenta, bloquear unidad de cliente. Cada acción lleva exposición de motivos (DSA art. 17: qué, por qué, base, cómo recurrir) que el afectado ve, y va al audit.
  • Retirada en un paso: asset.takedown deja de servir el objeto en todos los caminos (catálogo, reproducción, descarga, federación), revoca las SCT vivas de ese asset (la revocación de flujos largos ya existe) y avisa al owner. Por API, por CLI (styx moderation takedown <id> --reason …) y desde la web. Es lo que hace posible cumplir una orden de una hora (TCO).
  • Retención: lo retirado no se borra en el acto; pasa a un área sin servir durante STYX_TAKEDOWN_RETENTION (TCO pide conservarlo), y después se purga. El operador decide el plazo.
  • Contraaviso y recurso: el afectado puede responder; un moderador restaura o confirma.
  • Reincidencia: contador de retiradas confirmadas por cuenta y umbral de suspensión configurable (la política de reincidentes de DMCA la decide y publica el operador).
  • Contacto: STYX_ABUSE_CONTACT obligatorio en público, mostrado en el pie y en una ruta de aviso legal (no en security.txt, que es para vulnerabilidades). El agente designado, las normas de la comunidad y el texto legal son del operador; Styx da el hueco y una plantilla.

7.5 Detección automática (plugin, no núcleo)

  • Lista de bloqueo por huella de contenido (la de dec-0114 SC1): si lo subido coincide con algo retirado antes, entra en cuarentena con la denuncia previa enlazada.
  • Clasificadores, hash perceptual o listas de terceros (por ejemplo para material de abuso infantil) van como plugin de un kind nuevo moderation (r48 trust levels), porque dependen de servicios y licencias externas (PhotoDNA no es abierto). El núcleo no lleva ninguno (P7).

8. Styx como plataforma: la superficie pública

8.1 Qué se publica

PiezaFormaDe dónde sale hoyEstabilidad inicial
API HTTP pública + OpenAPIrutas del registro de operaciones marcadas publicdec-0124 §6.1, @styx/api-contracts@beta
@styx/sdk (TS)cliente tipado por operación, generado del contratoevolución de @styx/clients (§8.3)@beta
@styx/plugin-sdk + @styx/source-sdkmanifest, kinds, contexto, trust levelspackages/plugin-sdk, packages/source-sdk, r48@alpha
@styx/player (web)adaptadores para players de terceros + luego el motor propioapps/web/src/engines/*, r53, N2@alpha
@styx/uicomponentes TIER 2 sin dominiopackages/ui/src/composite/@alpha
CLI styxbinario, --json y exit codes establesdec-0123 D6, dec-0124 §6.1@beta
conduit (cliente de subida/descarga)SDK propio en su reporepo conduit, dec-0121lo fija su repo
spireSDK propio en su reporepo spire, dec-0119/dec-0120lo fija su repo
MCPherramientas = operaciones agentSafedec-0124 §6.1 (propuesta)@alpha
  • No se publica: los servicios (apps/*-svc), el daemon y sus protocolos internos (session-ipc), @styx/bus, @styx/authz, @styx/service-http, @styx/observability, @styx/domain entero. Lo que un tercero necesite de @styx/domain sale por los tipos del contrato.
  • conduit y spire ya son SDKs con repo y versión propios. Styx no los re-publica ni los envuelve en público: la doc de Styx enlaza su versión fijada. Así «conduit como pieza buena por sí misma» no depende de Styx.
  • El player público empieza por lo que N2 pone primero: el motor de Styx sirve HLS/fMP4 estándar que cualquier player de terceros consume, y @styx/player publica los adaptadores (sesión de Styx → vidstack/limeplay/<video>). El motor propio entra en el mismo paquete cuando exista, como otro adaptador, sin romper la API de sesión.

8.2 Etiquetas de estabilidad

Cada símbolo exportado por un paquete público lleva una etiqueta TSDoc:

  • @public: contrato. No cambia de forma incompatible sin subir MAJOR (o MINOR en 0.x, dec-0123 D1). Documentado al completo.
  • @beta: estable en intención, puede cambiar con aviso en el changelog del componente.
  • @alpha: se puede usar para probar; cambia sin aviso.
  • @internal: sólo para paquetes de Styx; no aparece en la doc pública.

Las operaciones HTTP llevan la misma etiqueta en el registro de operaciones, que pasa a la OpenAPI (x-styx-stability). La doc de referencia pinta la etiqueta.

8.3 El SDK público no puede heredar r52

@styx/clients toma el tipo App de @styx/catalog-svc (excepción r52, type-only). Dentro del monorepo vale; publicado, arrastraría los tipos internos de un servicio y su dependencia de Elysia a cada consumidor, y cualquier refactor del servicio sería un breaking change público. Por eso:

  • @styx/sdk se genera del registro de operaciones y de los esquemas TypeBox de @styx/api-contracts (contract-first, r20 §2.3, dec-0116), no de App.
  • La web puede seguir con Eden internamente mientras r52 viva. Cuando el SDK exista, la web lo consume desde sus server functions (lo que dec-0124 §6.1 ya prevé) y r52 queda sin consumidores: entonces se borra la excepción (DELETE > @deprecated). Eso lo decide waxin (P8); este ADR sólo fija que lo publicado no depende de App.

8.4 Versionado y compatibilidad (sobre dec-0123)

  • Cada paquete de §8.1 pasa a ser componente en release/components.yml con su SemVer, como dec-0123 prevé para plugin-sdk/source-sdk. Se quita private: true sólo en esos.
  • Detector de interfaz nuevo: informe de API por paquete público (la firma de lo @public y @beta), versionado en el repo. Un cambio en el informe sin bump es rojo; un cambio incompatible en @public sin MAJOR (MINOR en 0.x) es rojo. Se engancha a check:interfaces de dec-0123 D2, que ya trata los detectores como no bajables.
  • API HTTP: el diff de OpenAPI entre la versión publicada y la nueva clasifica los cambios (añadir campo opcional = compatible; quitar o volver obligatorio = incompatible). Misma regla que el informe de API.
  • Deprecación: un símbolo @public se marca @deprecated con el reemplazo y vive al menos una versión MINOR (0.x) o una MAJOR (≥1) antes de borrarse. Una operación HTTP deprecada responde con la cabecera Deprecation (RFC 9745) y Sunset (RFC 8594).
  • 1.0 de cada paquete lo declara waxin, igual que el 1.0.0 del tren.

8.5 Publicación

  • Registro: npm (P9 decide el nombre del scope: @styx puede no estar libre) con trusted publishing por OIDC desde el workflow de release de dec-0123 y procedencia por defecto. Nunca desde una máquina local.
  • Se publica en el canal stable de dec-0123 D5 y con dist-tag next desde nightly.
  • Cada paquete publicado pasa publint y la comprobación de tipos para ESM y Node/Bun (lo concreto lo fija el ticket).
  • Licencia: MPL-2.0 del repo. Es copyleft por fichero: quien construye encima puede tener su app con la licencia que quiera y sólo comparte cambios a ficheros de Styx. Encaja con «construir encima sin fricción». Ninguna dependencia GPL en lo publicado (regla de casa).

8.6 Docs de la superficie pública (dec-0124)

  • Todo @public y @beta tiene doc; TypeDoc con notDocumented como error (dec-0124 §7) se aplica a estos paquetes primero.
  • Sección de docs «construir sobre Styx»: tutorial con la plantilla, guía del SDK, guía de plugins, referencia generada, política de estabilidad. Audiencia desarrollador.
  • Ningún claim comparativo contra Jellyfin sin WC-JF12 (dec-0112), tampoco en READMEs de paquete.

9. El frontend plantilla

  • templates/public-catalog/: app TanStack Start (el stack de apps/web) que sólo puede importar paquetes de §8.1, por su nombre publicado. Un guard (extensión de test/no-apps-imports.test.ts) prohíbe importar apps/*, @internal o paquetes no públicos. Si la plantilla necesita algo que no está en la superficie pública, falta en la superficie, no se importa por la puerta de atrás.
  • Hace lo que waxin describió: catálogo público, ficha, reproducción y/o descarga según delivery, registro según la política, subida para quien tenga upload, cola de moderación para quien tenga moderate. Más sencilla que la web de Styx; mismo BFF (dec-0118), mismas cookies, sin tokens en el navegador.
  • Es la prueba mecánica de V-BIZ-01: si la plantilla compila y su e2e pasa contra un servidor en STYX_MODE=public usando sólo paquetes públicos, se puede construir encima.
  • «Usar sólo la API» es el caso degenerado: el SDK, o la OpenAPI con cualquier generador.
  • Nombre y ubicación (templates/ es un top-level nuevo) son pregunta (P4).

10. Paridad headless (dec-0124 §6.1)

Operaciones nuevas (ids estables, sin implementar), cada una con ruta, permiso, método de SDK, comando de CLI y marca agentSafe:

OperaciónPermisoCLIagentSafe
server.mode.get / .setserver:configurestyx server mode [public|private]get sí, set no
registration.request.create(anónimo con reto)—no
registration.request.listregistration:approvestyx registration listsí
registration.request.approve / .rejectregistration:approvestyx registration approve|reject <id>no (--yes)
library.access.setlibrary:configurestyx library access <id> --visibility … --delivery …no
library.grant.setlibrary:configurestyx library grant <id> <grantee> <nivel>no
report.createreport:createstyx report createsí
report.list / .resolvereport:resolvestyx moderation reports / resolvelist sí, resolve no
asset.moderate (ocultar, restaurar)asset:moderatestyx moderation hide|restore <id>no
asset.takedownasset:moderatestyx moderation takedown <id> --reason …no (--yes)
account.suspend / .reinstateaccount:moderatestyx moderation suspend|reinstate <cuenta>no

Los nombres finales los fija el registro de operaciones.

11. Por qué es aditivo (y dónde no lo es del todo)

11.1 Capa por capa

CapaQué cambia¿Rompe un contrato?
Modelo de catálogo (r08)Nada en Work/Edition/MediaAsset/SourceBinding. Estado de moderación como proyección sobre el asset.No.
Cuentas (dec-0125)Nivel en la concesión, grantees @anyone/@registered, solicitudes de registro, periodo de prueba.No: campos y filas nuevas; las concesiones existentes migran a download.
@styx/authzPermisos nuevos en RESOURCE_ACTIONS; principal anonymous.Enmienda acotada a dec-0118 §4: un tipo de principal sin actor. Los cuatro roles no cambian.
identity-svcPolítica de registro, reto, solicitudes.No.
catalog-svcvisibility/delivery como vista y campo de biblioteca, denuncias, acciones, cuarentena, retención.No.
playback-svcComprueba delivery y nivel al emitir SCT; SCT para anónimo; cuota de cómputo.No: la SCT y el daemon no cambian.
Daemon ZigContador de egress por unidad de cliente si se exige en el daemon.No: métrica y tope nuevos.
Busevt.moderation.*, evt.identity.registration*, qry.catalog.libraryAccess en BUS_ROUTES.No: subjects nuevos.
Web de StyxPantallas de moderación y de solicitudes.No.
Release (dec-0123)Paquetes públicos como componentes, detector de informe de API.Enmienda a su tabla de descartes: «Publicar packages/*» pasa a «se publican los de dec-0130 §8.1».
@styx/clients (r52)@styx/sdk generado del contrato.No publica r52; retirar la excepción es una decisión aparte (P8).

Ningún servicio nuevo (r17): todo cae en identity, catalog y playback. Un nodo de producto nuevo sí (P10).

11.2 Choques con lo escrito

  • r16 «Productización diferida» y product-horizon §8 «Productización para terceros» fuera hasta Personal Alpha. El modo público y la superficie pública son productización para terceros. waxin lo pide ahora; el choque se resuelve en el lock (P1), no aquí. Lo que este ADR propone para no adelantar trabajo: diseñar ya los contratos (para no cerrar puertas) y construir después de outcome/first-vertical.
  • dec-0126 P1 recomienda catálogo autoritativo contra N1; no afecta a este ADR más que en que la descarga pública lleva el metadato del fichero (lo que N1 quiere).

12. Contratos a añadir (sin implementar)

  • @styx/api-contracts: ServerModeConfig, RegistrationPolicy, RegistrationRequest, LibraryAccess { visibility, delivery }, LibraryGrant { grantee, level } (extiende dec-0125), Report, ModerationAction { kind, reason, basis, appeal }, TakedownNotice, ModerationState del asset. Errores IDENTITY_REGISTRATION_*, CATALOG_MODERATION_*, PLAYBACK_DELIVERY_NOT_ALLOWED.
  • BUS_ROUTES: los subjects de §11.1 con su contrato versionado.
  • Config: STYX_MODE, STYX_REGISTRATION, STYX_ANONYMOUS, STYX_ABUSE_CONTACT, STYX_ANON_EGRESS_*, STYX_ANON_ONTHEFLY, STYX_TAKEDOWN_RETENTION, STYX_REGISTRATION_REQUEST_TTL, en el esquema único de config (dec-0124 §7).
  • Registro de operaciones: §10, con stability por operación.

13. Consumidor real de cada pieza (r28)

PiezaConsumidor
Política de registro, principal anónimoLa plantilla en STYX_MODE=public y su e2e.
Niveles de concesiónLa plantilla (subida, edición) y la web de Styx (migración download).
Moderación y retiradaCola de moderación de la plantilla y de la web; CLI.
@styx/sdk y el resto de §8.1La plantilla (sólo paquetes públicos) y la web (server functions).
Informe de API y estabilidadcheck:interfaces de dec-0123.

Nada de esto se construye sin la plantilla o sin un despliegue público real detrás (P2).

14. Riesgos

  • Coste de mantener una API pública: cada @public es una promesa. Mitigación: empezar todo en @alpha/@beta y promover sólo lo que la plantilla usa de verdad.
  • Responsabilidad legal: Styx da mecanismos; el operador es responsable del cumplimiento (DSA, TCO, DMCA, protección de datos). La doc lo dice en la primera línea de la guía de operación pública.
  • Superficie de ataque: un anónimo es un atacante por defecto. Todo lo de §7.1 es obligatorio en public, y el arranque falla sin ello.
  • Deriva hacia "otro producto": si la plantilla empieza a necesitar cosas que la web de Styx no tiene, se están metiendo features en la plantilla. Regla: la plantilla no tiene lógica de dominio propia, sólo composición.

15. Preguntas para waxin (bloquean el lock)

  • P1 — Cuándo: diseñar contratos ya y construir tras outcome/first-vertical (recomendado), o meter el modo público antes. Y si esto enmienda r16/product-horizon §8 («productización diferida») o convive con ellos como excepción.
  • P2 — Primer despliegue público real: ¿hay uno en mente (qué catálogo, quién sube)? Sin él, el consumidor de r28 es sólo la plantilla y su e2e.
  • P3 — Subida abierta: ¿un servidor público puede dar upload a cualquier registrado (con cuarentena obligatoria), o la subida en público es siempre por invitación o admin (recomendado)?
  • P4 — Plantilla: templates/public-catalog como top-level nuevo (recomendado, deja claro que no es apps/web), o apps/public-web. ¿Se publica también como plantilla de create-…?
  • P5 — Anti-bots: prueba de trabajo propia o ALTCHA (MIT) (recomendado), y confirmar que no se quiere CAPTCHA de terceros.
  • P6 — Umbral de denuncias: ¿N denuncias distintas ocultan algo de forma provisional hasta revisión, o nada se oculta sin un moderador (recomendado)?
  • P7 — Detección automática: plugin moderation fuera del núcleo (recomendado), o algo dentro (lista por huella ya está en §7.5).
  • P8 — r52: cuando exista @styx/sdk, ¿la web pasa a usarlo y se borra la excepción r52 (recomendado), o conviven?
  • P9 — Registro de paquetes y nombre: npm con scope (¿@styx está libre? si no, cuál), o JSR, o GitHub Packages. Y si los paquetes públicos pasan a un repo propio o se publican desde este monorepo (recomendado: desde aquí, como componentes de dec-0123).
  • P10 — Nodos (los dos primeros ya son alta propuesta queued en el model, sin gate, pendiente de tu OK; si eliges la alternativa, se borran):
    • track/platform — superficie pública: etiquetas, informes de API, @styx/sdk generado, publicación, docs «construir sobre Styx», plantilla. Depende de track/docs y de track/release-engineering (w7).
    • track/public-mode — registro, anónimo, niveles de concesión, entrega por biblioteca, moderación y retirada. Depende de los milestones de cuentas de dec-0125 P9.
    • O ambos como milestones de track/identity y track/plugins-sdk. Los gate items los redacta el ticket, con author ≠ verifier y mutantes.
  • P11 — Defaults de public: ¿approval + anonymous: browse + delivery: stream (recomendado, lo más conservador), u otro?

16. Qué fija el lock y qué queda reversible

  • Fija el lock: que el modo es configuración sobre el mismo artefacto; que registro y anónimo son ejes separados; que los roles de subir/ver/editar/moderar son niveles de concesión por biblioteca y los roles de servidor de dec-0118 no cambian; que visibility es una vista de las concesiones; que moderation: on y el contacto de abuso son obligatorios en público y el arranque falla sin ellos; que la retirada es de un paso y revoca sesiones; que lo publicado lleva etiqueta de estabilidad, informe de API y SemVer de componente, y no depende de tipos de un servicio; que la plantilla sólo importa la superficie pública.
  • Reversible sin lock: defaults del preset, TTLs, cuotas, umbrales, la lista exacta de paquetes de §8.1, nombres de operaciones y de variables, el reto anti-bots concreto, la herramienta del informe de API, el registro de paquetes.

17. Consecuencias

  • identity-svc y catalog-svc crecen; playback-svc gana una comprobación. Ningún servicio nuevo.
  • @styx/authz deja de suponer que todo principal es un actor. Toda función que reciba un principal tiene que tratar el anónimo (el tipo lo obliga).
  • dec-0123 gana componentes publicados y un detector; su canal stable pasa a publicar en un registro público además de OCI.
  • dec-0124 gana una audiencia externa real: la referencia de los paquetes públicos deja de ser «para nosotros».
  • La excepción r52 queda con fecha de caducidad ligada a @styx/sdk (P8).
  • Lo que no decide: el mecanismo de descarga y generación al vuelo (dec-0129), la federación entre servidores (dec-0131), dónde vive el metadato (dec-0127/dec-0126), dispositivos y cast (dec-0128), el diseño del motor de player propio (N2, posterior).

Back-refs

  • Ledger de visión: V-N08, V-BIZ-01, V-BIZ-02, V-BIZ-03, V-BIZ-04 pasan a mapear este ADR (sus GAPs siguen abiertos por nodo y lock).
  • dec-0118 y dec-0123 recibirán un banner de enmienda en el lock, no antes.
  • dec-0125 §5.1 (permiso efectivo) y §4.1 (concesión) son los puntos que este ADR extiende.

Fuentes externas

Texto del ADR
dec-0130 — Modo público y Styx como plataforma: registro abierto o con aprobación, roles atados al registro, entrega por biblioteca, moderación y retirada, superficie pública publicable y frontend plantilla
1. Contexto: qué existe hoy y qué es nuevo
2. Referencias externas estudiadas y qué se toma
3. Decisión (resumen)
4. El modo como preset
4.1 Los ajustes
4.2 Lo que el modo público NO es
5. Registro y principal anónimo
5.1 Políticas de registro
5.2 Por qué "sin registro" no es una cuarta política de cuentas
5.3 El principal anónimo
6. Roles atados al registro: niveles de concesión
6.1 Por qué niveles de concesión y no roles nuevos
6.2 La vía de registro decide la concesión inicial
6.3 Grantees especiales
6.4 Entrega por biblioteca
7. Moderación, abuso y retirada
7.1 Amenazas propias de un servidor abierto
7.2 Cuarentena y periodo de prueba
7.3 Cuotas
7.4 Denuncias, acciones y retirada
7.5 Detección automática (plugin, no núcleo)
8. Styx como plataforma: la superficie pública
8.1 Qué se publica
8.2 Etiquetas de estabilidad
8.3 El SDK público no puede heredar r52
8.4 Versionado y compatibilidad (sobre dec-0123)
8.5 Publicación
8.6 Docs de la superficie pública (dec-0124)
9. El frontend plantilla
10. Paridad headless (dec-0124 §6.1)
11. Por qué es aditivo (y dónde no lo es del todo)
11.1 Capa por capa
11.2 Choques con lo escrito
12. Contratos a añadir (sin implementar)
13. Consumidor real de cada pieza (r28)
14. Riesgos
15. Preguntas para waxin (bloquean el lock)
16. Qué fija el lock y qué queda reversible
17. Consecuencias
Back-refs
Fuentes externas