Canales y permisos
Los tres niveles de canales privados, y el permiso de corta duración que obtiene un miembro para unirse a ellos.
- Disponibilidad: Planificado
- Evidencia: Leído del código fuente
- Referencia
Canales
| Canal | Nombre | Transporta |
|---|---|---|
| Trabajo | job:<job> |
Todo lo relativo a un trabajo: estados, posición en la cola, turnos, etapas, paquetes, módulos, aciertos de caché, reintentos, registros, consumo |
| Aplicación | app:<application> |
Cambios de estado de trabajos, grafos fijados, inventarios guardados, releases, dominios, avisos y cambios de la aplicación |
| Organización | org:<organization> |
Cambios de plan, crédito, consumo y cambios de aplicaciones |
Un nombre cumple ^(org|app|job):[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$. Cada evento pertenece exactamente a un canal, el más específico que corresponda: el trabajo cuando lo hay, si no la aplicación, y si no la organización. Un resumen que también aparece en un canal más amplio es allí un evento aparte, con su propio id y su propia sequence.
Obtener un permiso
| Operación | Solicitud | Capacidad | Reintento |
|---|---|---|---|
realtime.grant |
POST /v1/realtime/grants |
events.subscribe |
natural |
El cuerpo enumera de 1 a 20 canales distintos:
{ "channels": ["app:app_Shop0001x", "job:job_Prep0001x"] }// Ask for a short-lived grant to join private channels. The service checks your
// access to the resource behind every channel; the name alone proves nothing.
const api = process.env.CDN_API_ORIGIN;
const token = process.env.CDN_TOKEN;
const response = await fetch(new URL('/v1/realtime/grants', api), {
method: 'POST',
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ channels: [`app:${process.env.CDN_APPLICATION}`, `job:${process.env.CDN_JOB}`] })
});
const grant = await response.json();
if (!response.ok) {
console.log(`${response.status} ${grant.error.code} — ${grant.error.message}`);
process.exit(1);
}
console.log(`granted: ${grant.channels.join(', ')}`);
console.log(`denied or unknown: ${(grant.denied ?? []).join(', ') || 'none'}`);
console.log(`expires: ${grant.expires} — renew before then`);
console.log(`transport: ${grant.transport.kind}, event name ${grant.transport.event}`);| Miembro del permiso | Significado |
|---|---|
token |
Permiso de corta duración para unirse exactamente a los canales indicados. Su ámbito es quien llama, y nunca es una clave de servicio. |
channels |
Los canales concedidos |
denied |
Canales pedidos a los que quien llama no puede unirse. No se distinguen de canales que no existen. |
expires |
Cuándo termina el permiso. Renuévalo antes. |
transport.kind |
supabase-broadcast, o local para el desarrollo local |
transport.url, transport.key |
Dónde conectarse, y la clave publicable de cliente del transporte cuando la necesita. Nunca una clave de rol de servicio. |
transport.event |
beyond-cdn-events/1: el nombre del evento de difusión que transporta un microlote. El mismo canal también puede transportar el evento de difusión beyond-cdn-pointer/1, un puntero. |
Cuando ningún canal pedido es visible para quien llama, la respuesta es 404 NOT_FOUND. Emitir un permiso no tiene efectos duraderos, así que un reintento simplemente emite otro. Demasiadas solicitudes responden 429 RATE_LIMITED; respeta Retry-After.
Lo que un navegador nunca recibe
El estado de los trabajos lo publican solo servicios autorizados. Los navegadores reciben un permiso cuyo ámbito es quien llama y, si el transporte la necesita, una clave publicable. Las claves de rol de servicio, las credenciales de registros y los datos de otras organizaciones nunca llegan a un cliente, y nunca aparecen en eventos ni en registros.