Plataforma Synsema (syn)
synsema.com corre programas Synsema por vos: subís una carpeta y recibís una URL. Es una forma de desplegar — el mismo programa corre en tu propio servidor con synsema serve (Deploy); nada del lenguaje depende de la plataforma.
Lo que agrega la plataforma: contenedores, una URL con HTTPS (y dominios propios), secretos fuera de tu repositorio, logs, la auditoría de cada chequeo de capacidades, programaciones para los jobs, los gates humanos de tu programa (approve, confirm, ask) contestados desde un panel o una API, y túneles que ponen un puerto de tu propia computadora en una dirección HTTPS fija.
Instalar syn§
syn es a su vez un programa Synsema, así que primero va el motor (Inicio rápido):
curl -fsSL https://synsema.com/cli/install.sh | sh # macOS, Linux → ~/.local/bin/syn
irm https://synsema.com/cli/install.ps1 | iex # Windows → %LOCALAPPDATA%\Synsema\syn
Cuenta y login§
syn signup # si todavía no tenés cuenta
syn login # si ya tenés
Los dos muestran una página y un código corto. Abrí la página, creá la cuenta ahí si hace falta y aprobá el código: la terminal queda logueada, una vez para toda la computadora. Ninguna contraseña pasa por la terminal. El token queda en ~/.synsema/syn.json, con el nombre de la computadora (--name, o su nombre de host). Cada carpeta de proyecto guarda sólo el id de su proyecto en .synsema/syn.json — agregá .synsema/ a tu .gitignore.
En CI, o en un servidor sin navegador, sin login: definí SYN_TOKEN (o SYNSEMA_TOKEN) con un token de API de Ajustes en synsema.com y, si usás otro sitio, SYN_SITE.
Desplegar§
Desde la carpeta de tu proyecto:
syn deploy
La primera vez crea el proyecto, con el nombre de la carpeta (--name elige otro; un syn.toml también puede nombrarlo); después manda una versión nueva. Imprime el techo — cada línea require de tu programa, concedida como se declaró en todos los planes — y los secretos que el programa todavía necesita. Lo que el programa no declaró, el runtime lo niega en cada llamada. Lo que puede frenar un deploy es un recurso que el plan no sostiene (memoria por servicio, servicios a la vez): la plataforma lo dice antes de que corra, en vez de dejarlo fallar después.
Qué viaja: cada archivo de la carpeta salvo lo que nombra .gitignore, más .git, .env, .synsema, node_modules y target, que siempre quedan afuera. Un archivo de más de 1 MB se saltea con un aviso; el paquete entero tiene que quedar por debajo de 8 MB. syn files muestra la lista sin subir nada.
El archivo de entrada es el que nombra syn.toml; sin él, el único .syn de la raíz con un bloque serve on, o --entry.
Sin terminal, Nuevo proyecto en el panel toma la misma carpeta desde el navegador (arrastrala o elegila; el .env nunca se sube), un repositorio público de GitHub o una receta.
Comandos§
| Comando | Qué hace |
|---|---|
syn signup / syn login | Loguea esta computadora desde el navegador (arriba) |
syn whoami | El sitio, la cuenta y la computadora que usa syn acá, y de dónde sale el token |
syn deploy [--name N] [--entry E] [--kind web|worker] | Sube la carpeta y encola un deploy |
syn status | Estado, paquete, techo y deploys del proyecto de esta carpeta |
syn logs [--follow] | Lo que escribieron la plataforma y el runner |
syn secrets [set NOMBRE=valor …] | Lista los secretos definidos y los que faltan, o los define (sólo escritura) |
syn env [set NOMBRE=valor … [--secret]] [rm NOMBRE …] | El entorno: listarlo como .env, definir, borrar |
syn projects | Todos los proyectos de la cuenta |
syn open | La URL de este proyecto |
syn files | Lo que viajaría, sin subir |
syn stop | Baja el servicio; los archivos, secretos y volumen quedan |
syn delete --yes | Borra el proyecto y todo lo que el runner tiene de él |
syn tunnel <puerto> [--name N] [--subdomain S] [--json] | Un puerto de esta computadora en una dirección HTTPS fija (Túneles, abajo) |
syn tunnel list · syn tunnel release <nombre> | Los túneles de la cuenta; liberar una dirección |
syn tunnel <puerto> --name N --service · syn tunnel service list|remove <nombre> | Mantener un túnel corriendo con la computadora, sin una terminal abierta |
syn agent … | Agentes que se hablan (REDSYN) |
syn update | Esta CLI otra vez, desde el sitio en el que está logueada (el motor se actualiza aparte: synsema update) |
Un comando que falla termina con código de salida 1, así un script o un agente se entera.
Qué es un proyecto§
Una carpeta de archivos Synsema con un archivo de entrada. Su bloque require es el manifiesto: la plataforma concede cada línea como se declaró, en todos los planes, y el runtime niega lo que el programa no declaró. Un deploy corre el programa en un contenedor bajo ese techo con la auditoría encendida, así que cada chequeo de capacidades queda en la auditoría del proyecto.
| Tipo | Corre | URL |
|---|---|---|
web | synsema serve <entrada> | <slug>.synsema.app, nombres extra <slug>-<etiqueta>.synsema.app, tu propio dominio en Pro. El programa los recibe como SYNSEMA_HOST, SYNSEMA_HOSTS, SYNSEMA_HOST_<ETIQUETA> |
worker | synsema run <entrada>, siempre encendido | ninguna (un bloque serve on se sirve en un puerto local, así sus gates humanos funcionan) |
job | synsema run <entrada> en un contenedor nuevo por ejecución, según una programación o a pedido | ninguna |
syn.toml§
Opcional, en la raíz de la carpeta. Dice lo que el código no puede decir de sí mismo; el bloque require sigue siendo el manifiesto.
name = "Invoice agent"
slug = "invoices" # el nombre de la URL; se puede cambiar después
entry = "app.syn"
kind = "web" # web | worker | job
memory = "512m" # opcional; el plan tiene un valor por defecto y un techo
[schedule] # sólo jobs, UTC: cinco campos cron o @hourly, @daily, …
cron = "0 * * * *"
[secrets] # lo que el programa necesita definido, y una línea para quien lo define
LLM_API_KEY = "la clave"
[env] # variables con valor por defecto, visibles, editables
LLM_PROVIDER = "anthropic"
[hosts] # sólo web: nombres extra; etiqueta = para qué es
api = "la API JSON"
[volumes] # carpetas donde escribe el programa, que se conservan entre deploys
data = "./data"
[provision] # una URL que la plataforma consulta una vez, al crear; su env siembra el entorno
env_url = "https://example.com/token"
Dominios§
Un proyecto web responde en <slug>.synsema.app. El slug lo elegís y lo podés renombrar después; los nombres extra son etiquetas, <slug>-<etiqueta>.synsema.app. En Pro y Enterprise también puede responder en un dominio tuyo: agregalo en la página del proyecto y apuntá tu DNS a la plataforma:
| Tu nombre | Registro DNS |
|---|---|
un subdominio, app.example.com | CNAME a <slug>.synsema.app |
la raíz, example.com | A a la dirección IP que muestra la página del proyecto (la raíz de un dominio no admite CNAME; un proveedor de DNS con CNAME flattening o ALIAS también sirve) |
Agregá www.example.com como otro nombre si también lo querés. El certificado HTTPS se emite la primera vez que se visita el nombre. Todos los nombres llegan al mismo programa, que los distingue por host; un nombre agregado o quitado rige desde el próximo deploy.
Gates humanos§
Un programa que llega a approve "¿Pagar 800 USDC al proveedor?" within 2h (o confirm, o ask … with [...]) se detiene en esa línea bajo serve. La pregunta aparece en Approvals en synsema.com y en GET /api/v1/approvals; contestala ahí o con POST /api/v1/approvals/{id} y el pedido que esperaba sigue. Pasado el within sin respuesta, cuenta como un no. Sólo espera el pedido que llegó al gate; el resto del servicio sigue respondiendo. En un job, o un worker sin serve on, nadie puede contestar, así que approve responde no de inmediato — un programa desatendido no puede concederse el umbral a sí mismo.
En Pro y Enterprise, la página de Aprobaciones activa notificaciones push en cada navegador que uses: la pregunta llega a tu computadora o tu teléfono en el momento en que el programa la hace, aunque la pestaña esté cerrada (en iPhone, una vez que el sitio está agregado a la pantalla de inicio).
Jobs, programaciones y reposo§
- Un job corre según su programación (
[schedule]oPUT /api/v1/projects/{id}/schedule), con
POST /api/v1/projects/{id}/run, o desde el panel. Una ejecución nunca se superpone con la anterior y se abandona a las dos horas; cada una guarda su código de salida y el final de su salida.
- Un servicio web que nadie llama por un rato entra en reposo y despierta con el siguiente pedido
en alrededor de un segundo (el pedido espera). En el plan Free se duerme a los 10 minutos sin uso; Pro y Enterprise eligen, y un servicio siempre activo igual se duerme tras 7 días sin un solo pedido. Un worker nunca duerme.
- Lo que nadie usa se va. En Free, un proyecto sin pedidos, deploys ni ejecuciones durante 7 días
queda en pausa (se detiene; su código y sus datos se conservan) y se borra 30 días después salvo que se vuelva a desplegar. En un plan pago nada se borra por falta de uso; cuando una cuenta deja de pagar, lo que el plan Free no sostiene se borra 30 días después. Cada fecha de borrado se avisa por correo una semana y un día antes.
La auditoría§
Cada chequeo de capacidades de un programa en marcha — qué pidió, si se concedió o se negó y por qué — queda en la auditoría del proyecto; nunca lo que pasó por él. Cuánto tiempo depende del plan: los últimos 7 días en Free, 90 días en Pro, sin límite en Enterprise. En Pro y Enterprise la auditoría se exporta en CSV o JSON Lines, desde la pestaña Auditoría del proyecto o desde la API:
curl "https://synsema.com/api/v1/projects/<id>/audit/export?format=csv" \
-H "Authorization: Bearer $SYN_TOKEN" -o audit.csv
format es csv o jsonl; only=granted|denied y q=<texto> filtran como el panel.
Túneles (syn tunnel)§
syn tunnel <puerto> pone 127.0.0.1:<puerto> de tu computadora en una dirección fija https://<id>-tunnel.synsema.app, sin abrir puertos ni tocar DNS: la computadora abre una conexión saliente y cada pedido llega por ella — HTTP con bodies de cualquier tamaño, Server-Sent Events a medida que se emiten, WebSocket en los dos sentidos. Sólo reenvía a ese puerto de esa computadora.
syn tunnel <puerto> # https://<id>-tunnel.synsema.app → 127.0.0.1:<puerto>
syn tunnel <puerto> --name <nombre> # otro túnel en la misma computadora, con su dirección
syn tunnel <puerto> --name <nombre> --subdomain <sub> # Pro: además https://<sub>.synsema.app
- La dirección es fija para la computadora y el
--name(por defectodefault): la misma cada
vez, guardada en la cuenta. syn tunnel release <nombre> la libera.
--subdomain(Pro y Enterprise) le da al túnel un nombre propio bajo synsema.app, en el mismo
espacio que los nombres de URL de los proyectos. El nombre se verifica antes de crear nada: las mismas reglas que el slug de un proyecto, no reservado, que no termine en -tunnel, y libre — un nombre es de un proyecto o de un túnel. Un nombre que no se puede tener se rechaza con el motivo (… is already in use, that name is reserved) y no cambia nada; en Free se rechaza con code: plan. Se cambia corriendo otra vez con otro --subdomain, o desde Túneles en el panel, que también lo quita. La dirección <id>-tunnel sigue respondiendo.
- Qué recibe el servicio local: el
Hostpúblico, y siempreX-Forwarded-For(la IP de quien
visita), X-Forwarded-Proto: https y X-Forwarded-Host. Un servicio Synsema los ve sólo si confía en el túnel, que le llega por loopback: trust proxy ["127.0.0.1"] en su bloque serve, o --trust-proxy 127.0.0.1 (Servidor).
- Cuando la computadora no está conectada, la dirección responde
503con
X-Synsema-Tunnel: offline.
- Límites por plan: Free 3 direcciones y 5 GB por mes, con una página de aviso la primera vez que
un navegador abre un túnel (las llamadas de API, fetch y WebSocket nunca la ven); Pro 20 direcciones y 100 GB, sin página de aviso; Enterprise 100 direcciones y 1 TB.
- Siempre corriendo:
syn tunnelvive mientras vive su terminal. Con--servicelo mantiene la
computadora: arranca con ella y no necesita una terminal abierta — una unit de systemd en Linux (de usuario si no sos root), un LaunchAgent en macOS, la carpeta Inicio en Windows. syn tunnel service list los muestra con su último estado; syn tunnel service remove <nombre> detiene uno (la dirección sigue siendo tuya). Su log es ~/.synsema/tunnels/<nombre>.log.
``sh syn tunnel <puerto> --name <nombre> --service ``
- Para programas que arrancan un túnel:
--jsonimprime una línea JSON por evento —
{"event":"connected","id":…,"id_url":…,"name":…,"port":…,"url":…}, reconnecting con retry_in, y error con fatal, code y message (un error fatal es la última línea, y el comando termina con 1). Se reconecta solo con espera creciente; Ctrl-C lo detiene.
Agentes que se hablan§
La plataforma también transporta mensajes entre agentes, entre máquinas y entre empresas: syn agent listen y syn agent send. El protocolo, con su API HTTP, firmas y cifrado de extremo a extremo, es REDSYN.
La API§
Todo lo que hacen syn y el panel es una API HTTPS con token bearer: synsema.com/docs y el openapi.json legible por máquinas.