Seilide, la nube
La parte de la app que vive en internet (#253): lo que tiene que funcionar aunque la casa esté
apagada, y a mano desde fuera. La casa (jellycartoon, en la carpeta de arriba) se queda con la
media; Seilide habla con ella por sus APIs (/rest, /api/v1), a través del túnel rathole.
El túnel es de cada casa: cada familia pone su rathole en el servidor que quiera (Las APIs desde fuera, con rathole) y da en Ajustes su dirección de fuera y su clave. Seilide no tiene servidor de rathole ni hace de puente para nadie: solo llama a la dirección que cada familia le dio. El de quien la mantiene es solo para su casa.
Varias familias en una sola app, cada una aislada por la seguridad por filas de Postgres.
Cómo está hecha
Sección titulada «Cómo está hecha»- El mismo stack que jellycartoon: SvelteKit 3, Svelte 5, Bun, Drizzle, Postgres y Better Auth (con verificación en dos pasos).
- Familias: todas sus tablas llevan
family_idy una política de Postgres que solo deja ver y tocar las filas de la familia de quien pregunta (src/lib/server/db/family.schema.ts). La app entra comonube_app, un rol que no es el dueño de las tablas, ywithFamily(src/lib/server/family-scope.ts) le dice a Postgres, para una transacción, quién pregunta y de qué familia. Una consulta que lo olvide no ve nada. Los tests (family-scope.test.ts) lo comprueban contra un Postgres real en memoria (PGlite). - Quién entra: solo con invitación, un enlace
/invitacion/<token>que caduca a los 7 días (como las de svelte-thinking), mandado por correo; allí se crea la cuenta, o se entra con ella, y se acepta (src/lib/server/invitation-scope.ts). Una familia pide acceso desde la portada, yADMIN_EMAILse lo da en Lista de espera (/admin/lista-de-espera, en su menú): le llega un enlace para crear su familia, de la que es administrador. El administrador de cada familia invita a los suyos en Ajustes → Familia → Invitaciones, y ve el enlace de cada una por si el correo no llega.bun run familia "Casa García" ana@example.comcrea una familia a mano e imprime el enlace. - Una sola cuenta (#279): Seilide es proveedor OpenID Connect de las casas
(
@better-auth/oauth-provider+jwt,src/lib/server/auth.ts); discovery enhttps://nube…/api/auth/.well-known/openid-configuration. Cada casa es un cliente de su familia, que crea su administrador en Ajustes → Familia → «Entrar en casa con Seilide» con la direcciónhttps://de la casa: salenNUBE_URL,NUBE_CLIENT_IDyNUBE_CLIENT_SECRETpara el.envde la casa (el secreto, una vez). Sin pantalla de consentimiento; tras la contraseña y el segundo paso,/loginvuelve a la casa (src/lib/server/oauth-return.ts). Solo los de la familia: a otro no se le da el token (src/lib/server/oidc.ts), y el token lleva la familia enhttps://nube.scholio.review/family. La casa vuelve ahttps://casa…/api/auth/callback/nube(genericOAuthde Better Auth, en Producción de la casa). - Las apps con la misma cuenta (#284): Langua, Librarian… son también clientes del proveedor,
pero de ninguna familia: los crea
ADMIN_EMAILen Apps (/admin/apps, en su menú), con su dirección de vuelta, y salenSEILIDE_URL,SEILIDE_CLIENT_IDySEILIDE_CLIENT_SECRETpara su.env. Entra cualquiera con cuenta, sin consentimiento. La familia solo va en el token con el scopefamily, que solo se permite a las apps «para familias» (Langua sí, Librarian no); a alguien sin familia no se le da (src/lib/server/oidc-claims.ts). Las de las casas siguen llevándola siempre. Las apps piden tambiénoffline_access, para tener refresh token. - La IA de las apps (#284):
POST /api/ia/v1/chat/completions, con la forma de OpenAI (la de OpenRouter): la app apunta su cliente compatible con OpenAI ahttps://nube…/api/ia/v1, con el access token de la persona como clave y su nombre enX-Title. Seilide comprueba el token con su propio userinfo, que solo da la familia con el scopefamily, y llama a OpenRouter con la clave de esa familia, que no sale de Seilide. Con stream o sin él, y cada gasto va a Gastos → IA (src/lib/server/app-ai.ts,forwardChatenopenrouter.ts). - La casa: en Ajustes, la dirección de fuera de jellycartoon (su
MEDIA_HOST) y la clave de su Ajustes → Casa → «Seilide». La clave se guarda cifrada y no sale del servidor; cada petición a casa va en nombre de la persona, por su email (el mismo en las dos apps).