Salta al contenuto
Omega Work

Omega Work come modulo

Omega Work dentro il tuo gestionale

Un riquadro sicuro, l’accesso automatico per le tue persone, le persone e le notifiche sincronizzate con la tua piattaforma. Tutto quello che serve per integrarlo, con esempi pronti da copiare.

Avvio rapidoProva Omega Work

Panoramica

Omega Work si mette dentro il tuo gestionale come un modulo: le tue persone lavorano su progetti, attività e bacheche senza uscire dal tuo software, con il tuo colore, e senza un secondo accesso. Si fa a tre livelli, e ognuno aggiunge qualcosa al precedente:

  1. Il riquadro. Incolli un <iframe> nella pagina e le persone entrano con email e password di Omega Work. Non serve scrivere codice sul server.
  2. L’accesso automatico. Il tuo server chiede a Omega Work un biglietto per la persona collegata al tuo gestionale, e il riquadro si apre già dentro, con il suo account. Nessuna password da ricordare.
  3. Il modulo completo. Il tuo gestionale crea e sospende le persone su Omega Work quando abiliti o togli il modulo, riceve le notifiche (per la sua campanella) con un webhook firmato, e può mandare avvisi nella Posta in arrivo di Omega Work.
Entra senza password · GIF
Il colore e la forma del tuo gestionale · GIF
Le notifiche nella tua campanella · GIF

Tutto si configura dal titolare dello spazio di lavoro: Console di amministrazione → Incorpora. Da lì escono la chiave pubblica del riquadro, le chiavi segrete per il server e il segreto del webhook.

Avvio rapido

  1. Nella scheda Incorpora autorizza l’indirizzo del tuo gestionale (per esempio https://gestionale.tuaazienda.it) e accendi il riquadro.
  2. Se il tuo sito ha una Content-Security-Policy, aggiungi frame-src https://work.omegasuite.it (e script-src https://work.omegasuite.it se usi l’SDK).
  3. Incolla il riquadro nella pagina dove vuoi Omega Work:
<iframe
  src="https://work.omegasuite.it/embed/CHIAVE_PUBBLICA_DEL_RIQUADRO"
  title="Omega Work"
  allow="clipboard-read; clipboard-write; fullscreen"
  sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads allow-modals"
  referrerpolicy="strict-origin-when-cross-origin"
  style="display:block;width:100%;height:100%;min-height:640px;border:0"
></iframe>

Il riquadro

L’indirizzo del riquadro è https://work.omegasuite.it/embed/<chiave pubblica>. La chiave pubblica sta nell’HTML di chiunque apra la pagina, e va bene così: da sola non apre niente. Servono le credenziali di una persona dello spazio (o un biglietto del tuo server), e il browser disegna il riquadro solo dentro i siti autorizzati.

  • sandbox: il riquadro non può spostare la tua pagina né aprire finestre senza un clic. Non togliere allow-same-origin (senza, Omega Work non può tenere la sessione) e non aggiungere allow-top-navigation.
  • Dentro il riquadro si lavora: attività, progetti, bacheche, obiettivi, persone. Amministrazione, abbonamento, integrazioni e chiavi si aprono in una scheda di Omega Work.
  • Per aprire una pagina precisa: ?to=/app/my-tasks, ?to=/app/project/42, ?to=/app/task/1234. Vale solo dentro /app.
  • Dagli l’altezza che vuoi: Omega Work riempie il riquadro e scorre al suo interno.

Aspetto

Il titolare sceglie l’aspetto di partenza dalla scheda Incorpora. Se lo permette (è acceso di serie), il tuo gestionale può cambiarlo dall’indirizzo del riquadro, dal biglietto dell’accesso automatico, o al volo con un messaggio.

ParametroValoriEffetto
themelight · dark · systemTema chiaro o scuro forzato, oppure quello del sistema della persona.
accent158063 (esadecimale, senza #)Il colore del tuo marchio su azioni principali, selezione e fuoco. Il testo sopra si scurisce da solo se il colore è chiaro.
hidetopbar,rail,sidebar,create,search,help,logoutToglie le parti elencate: barra in alto, colonna delle sezioni, barra laterale, «Crea», ricerca, aiuto, «Esci».
chromenone · minimalnone: solo il contenuto, senza shell. minimal: via sezioni e barra laterale, resta la barra in alto.
to/app/…La pagina da aprire.
https://work.omegasuite.it/embed/CHIAVE_PUBBLICA_DEL_RIQUADRO?theme=light&accent=158063&hide=help,logout&to=/app/my-tasks

Accesso automatico

Il tuo server, con una chiave segreta (omw_sk_live_…, permesso sso), chiede un biglietto per la persona collegata al tuo gestionale. Il biglietto vale 60 secondi e una volta sola; il riquadro lo scambia con una sessione (8 ore al massimo, poi l’SDK ne chiede un altro senza che nessuno se ne accorga).

Browser→ GET /api/work-ticket →Il tuo server→ POST /tickets →Omega Work← biglietto ←Riquadro
// Il TUO backend. La chiave segreta sta in una variabile d'ambiente, mai nel browser.
app.get('/api/work-ticket', requireLogin, async (req, res) => {
  const r = await fetch('https://work.omegasuite.it/api/embed/v1/tickets', {
    method: 'POST',
    headers: {
      authorization: `Bearer ${process.env.OMEGA_WORK_SECRET}`,
      'content-type': 'application/json',
    },
    body: JSON.stringify({ email: req.user.email }),
    signal: AbortSignal.timeout(10_000),
  });
  if (!r.ok) return res.status(502).json({ error: 'omega_work_unavailable' });
  const { ticket } = await r.json();
  res.set('cache-control', 'no-store').json({ ticket });
});

Il biglietto arriva al riquadro in uno di tre modi, dal migliore:

  1. L’SDK (fetchTicket): chiede il biglietto al tuo server, lo passa con un messaggio e ne chiede un altro quando la sessione scade. Non devi fare altro.
  2. Il frammento: src="…/embed/CHIAVE_PUBBLICA_DEL_RIQUADRO#omw_ticket=omw_tk_…". Il frammento non viaggia nelle richieste, non finisce nei log né nel Referer, e Omega Work lo cancella appena lo legge. Non metterlo mai nella query (?ticket=).
  3. Il messaggio: quando il riquadro manda omega-work:need-ticket, rispondi con iframe.contentWindow.postMessage({ type: 'omega-work:auth', ticket }, 'https://work.omegasuite.it').

Regole: la persona deve essere attiva nello spazio. Il titolare entra sempre con la sua password (si può cambiare dalla scheda), gli amministratori di serie sì. Con «solo accesso automatico» il modulo d’accesso con password sparisce dal riquadro, e ogni apertura chiede un biglietto nuovo: chi usa lo stesso computer dopo un collega non si ritrova nel suo account.

Persone

Con il permesso members:write il tuo gestionale tiene allineate le persone: quando abiliti il modulo a qualcuno, lo crea su Omega Work; quando glielo togli, lo sospende. L’operazione è idempotente: ripeterla non crea doppioni.

curl -X PUT https://work.omegasuite.it/api/embed/v1/members/mario.rossi%40tuaazienda.it \
  -H "Authorization: Bearer $OMEGA_WORK_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"name":"Mario Rossi","role":"member"}'

# 201 { "result": "created" | "added", "member": { … } }
# 200 { "result": "reactivated" | "updated" | "unchanged", "member": { … } }
# 409 { "error": { "code": "seat_limit_reached", "seats_used": 15, "seats_limit": 15, "upgrade_url": "…" } }
  • Ruoli dall’API: member e guest. Titolare e amministratori non si assegnano né si toccano dall’API (403 role_not_modifiable).
  • Una persona creata dall’API non ha una password: entra con l’accesso automatico, o se ne sceglie una con «Password dimenticata?».
  • Gli ospiti non occupano posti del piano; tutti gli altri sì.

Notifiche

Da Omega Work al tuo gestionale (webhook)

Dalla scheda Incorpora imposta l’indirizzo del tuo server e scegli gli eventi. Omega Work manda una POST nel formato Standard Webhooks, firmata con il segreto whsec_…: verificala sempre, e rifiuta le richieste più vecchie di 5 minuti.

// npm i standardwebhooks
import { Webhook } from 'standardwebhooks';
const wh = new Webhook(process.env.OMEGA_WORK_WEBHOOK_SECRET); // "whsec_…"

// Il corpo va letto GREZZO: la firma è sui byte esatti.
app.post('/omega-work/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  let evt;
  try {
    evt = wh.verify(req.body, req.headers); // controlla firma e orario (±5 min)
  } catch {
    return res.sendStatus(401);
  }
  // webhook-id è lo stesso nei nuovi tentativi: usalo per non fare due volte la stessa cosa.
  if (evt.type === 'notification.created') {
    const { recipient, notification, unread } = evt.data;
    notificaNellaCampanella(recipient.email, notification.title ?? 'Nuova notifica su Omega Work', notification.path, unread);
  }
  res.sendStatus(204);
});
EventoQuando
notification.createdUna persona riceve una notifica in Omega Work (assegnazioni, menzioni, commenti, scadenze…). Porta il numero di non lette.
member.provisionedUna persona aggiunta o riattivata dall’API.
member.deactivatedUna persona sospesa dall’API.
session.startedQualcuno entra nel riquadro (con la password o con l’accesso automatico).
webhook.testIl bottone «Manda una prova» della scheda.

Nuovi tentativi se il tuo server non risponde 2xx: dopo 5 s, 5 min, 30 min, 2 h, 5 h, 10 h, 14 h, 20 h e 24 h. Il registro delle ultime consegne, con la risposta ricevuta, è nella scheda Incorpora; da lì si ripete una consegna a mano.

Dal tuo gestionale a Omega Work

curl -X POST https://work.omegasuite.it/api/embed/v1/members/mario.rossi%40tuaazienda.it/notifications \
  -H "Authorization: Bearer $OMEGA_WORK_SECRET" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: ordine-8812-confermato" \
  -d '{"title":"Ordine 8812 confermato","text":"Il cliente ha firmato: puoi pianificare la consegna.","path":"/app/project/42"}'

# 201 { "id": 991, "created_at": "…" }   — compare nella Posta in arrivo di Mario

Nel browser

A riquadro aperto arrivano anche omega-work:unread (il numero) e, se il titolare condivide il testo, omega-work:notification con titolo e frase: per un avviso a comparsa nel tuo gestionale.

Messaggi col riquadro

Omega Work parla con la pagina che lo ospita con postMessage, solo verso le origini autorizzate. Dalla tua parte controlla sempre event.origin === 'https://work.omegasuite.it' e event.source === iframe.contentWindow (l’SDK lo fa per te).

Da Omega WorkDati
omega-work:readyAperto e collegato.
omega-work:navigatepath, title della pagina aperta.
omega-work:unreadcount: notifiche non lette.
omega-work:notificationtitle, text, path (se il titolare condivide il testo).
omega-work:need-ticketServe un biglietto: rispondi con omega-work:auth.
omega-work:session-expiredLa sessione è scaduta.
omega-work:signed-outSi vede l’accesso.
omega-work:errorcode, message (per esempio cookies_blocked).
Verso Omega WorkDati
omega-work:authticket
omega-work:set-themetheme: light · dark · system
omega-work:set-accentaccent: "#rrggbb" o null
omega-work:set-chrometopbar, rail, sidebar: true/false
omega-work:navigate-topath: /app/…

Omega Work non accetta dal riquadro comandi che leggono o scrivono dati: per quello c’è l’API del server.

Riferimento API

Base: https://work.omegasuite.it/api/embed/v1 · autenticazione Authorization: Bearer omw_sk_live_… · corpo JSON · solo dal tuo server (le richieste partite da un browser vengono rifiutate, e non c’è CORS).

Metodo e percorsoPermessoCosa fa
GET /meLo spazio, la chiave, il riquadro, i posti del piano.
GET /membersmembers:readLe persone dello spazio.
GET /members/{email}members:readUna persona.
PUT /members/{email}members:writeAggiunge o riattiva (idempotente).
DELETE /members/{email}members:writeSospende.
POST /ticketsssoBiglietto di accesso automatico (60 s, monouso).
GET /members/{email}/notificationsnotifications:readNon lette e ultime notifiche.
POST /members/{email}/notificationsnotifications:writeUn avviso nella Posta in arrivo.
POST /webhooks/testUn evento di prova al webhook.
  • Idempotency-Key sulle POST e PUT: la stessa richiesta ripetuta entro 24 ore riceve la stessa risposta (Idempotent-Replayed: true) senza rifarla; la stessa chiave con un corpo diverso risponde 422.
  • Ogni risposta porta X-Request-Id e RateLimit-Limit / RateLimit-Remaining / RateLimit-Reset.
  • La versione sta nel percorso (/v1): i cambiamenti che rompono qualcosa arrivano in una /v2, con almeno sei mesi di preavviso.

Errori

{
  "error": {
    "type": "permission_error",
    "code": "missing_scope",
    "message": "Questa chiave non ha il permesso «sso»: …",
    "doc_url": "https://work.omegasuite.it/sviluppatori/incorpora#errori",
    "request_id": "req_…"
  }
}
StatoCodici
400invalid_body, invalid_json, invalid_email, invalid_idempotency_key
401key_missing, key_malformed, key_unknown, key_revoked, key_expired
402read_only — abbonamento fermo: si legge, non si scrive
403missing_scope, key_ip, role_not_modifiable, sso_not_allowed_for_role, browser_not_allowed
404member_not_found, route_not_found
409seat_limit_reached, embed_disabled, webhook_not_configured
422idempotency_key_reused
429rate_limited — rispetta Retry-After

Sicurezza

Cosa fa Omega Work

  • Content-Security-Policy: frame-ancestors con i soli siti autorizzati, su ogni pagina del riquadro: altrove non si disegna.
  • Sessione del riquadro separata da quella di work.omegasuite.it, in un cookie __Host-, Secure, HttpOnly, SameSite=None, Partitioned (CHIPS): vive solo dentro il tuo sito.
  • Nel riquadro non si amministra: console, abbonamento, integrazioni, chiavi e password stanno fuori.
  • Chiavi segrete con prefisso e cifre di controllo (riconoscibili dagli scanner di segreti), salvate solo come impronta, con permessi minimi, IP ammessi, scadenza, ultimo uso, revoca immediata.
  • Biglietti opachi, monouso, da 60 secondi, mai nella query dell’indirizzo.
  • Webhook firmati (Standard Webhooks), solo https, indirizzo controllato a ogni consegna (niente reti interne), redirect non seguiti.
  • Allargare l’accesso chiede la password del titolare; stringerlo è immediato e chiude le sessioni aperte. Ogni cambio finisce nel registro dello spazio.

Cosa fai tu

  • La chiave segreta sta solo sul server, in una variabile d’ambiente: mai nel codice del browser, mai in un repository.
  • L’endpoint che chiede il biglietto controlla la sessione del TUO gestionale e chiede il biglietto solo per la persona collegata.
  • Verifica la firma di ogni webhook e la sua data; usa webhook-id per non elaborare due volte lo stesso evento.
  • Non scrivere nei log biglietti, chiavi e segreti.
  • Una chiave esposta si revoca subito dalla scheda Incorpora, e se ne crea un’altra: due possono restare accese insieme per il cambio senza interruzioni.

Limiti e piano

  • Le persone aggiunte dall’API contano nei posti del piano come quelle invitate a mano (gli ospiti no). A posti finiti l’API risponde 409 seat_limit_reached con i numeri e il collegamento per cambiare piano.
  • Con l’abbonamento fermo lo spazio è in sola lettura: il riquadro si apre e si legge, le scritture dell’API rispondono 402.
  • Richieste al minuto per chiave: 300 in generale, 120 biglietti, 60 persone, 60 notifiche.
  • Fino a 10 siti autorizzati e 5 chiavi segrete attive per spazio di lavoro.

Risoluzione dei problemi

Il riquadro è grigio con «rifiutato di connettersi»
Il sito non è tra quelli autorizzati (controlla schema, www e porta), o il riquadro è spento.
Il riquadro non compare affatto
La Content-Security-Policy del tuo sito non ha frame-src https://work.omegasuite.it. La console del browser lo dice.
«Il tuo browser non conserva l’accesso dentro i riquadri»
Il browser blocca anche i cookie partizionati (alcune versioni di Safari 18, estensioni rigide). Omega Work propone di aprire una scheda; su Safari aggiornato funziona.
401 dall’API
Chiave copiata male (manca un pezzo), revocata o scaduta. Le cifre finali di controllo fanno rispondere key_malformed a una chiave troncata.
403 browser_not_allowed
Stai chiamando l’API dal browser: spostala sul server.
Il biglietto viene rifiutato
È scaduto (60 s), è già stato usato (una volta sola), o la persona è sospesa. Chiedine uno nuovo a ogni apertura.

SDK 1.0.0 · API v1 · Omega Work