← Entangle

Připojení libovolného webu do sítě Entangle (bez WordPressu)

Jak napojit web postavený na čemkoli (Drupal, Django, Next.js, statický web + serverless, vlastní CMS) do sítě Entangle. Kontrakt hub↔web je CMS-neutrální — WordPress plugin je jen referenční klient. Detailní referenci endpointů má API.md; tohle je integrační průvodce.

Kanonická base všech endpointů hubu je /entangle/v1/…. Cesty /wp-json/entangle/v1/… jsou jen alias, který si přidává WordPress přes rest_url()ignorujte je. V příkladech níže je {hub} = základ hubu (např. https://entangle.cz) a {web} = váš web.

Integrace má tři nezávislé části; vezměte si jen ty, které potřebujete:

  1. Publikace obsahu (novinky, události, participace) → push přes podepsané webhooky. Nutné pro feed a notifikace.
  2. Profil + feed projektů → hub si je sám stahuje z vašeho webu. Nutné pro mapu a galerii.
  3. Přihlášení přes Entangle (OAuth 2.0 / OIDC). Volitelné.

1. Kanonická identita webu

Váš web má jednu stabilní kanonickou URL ve tvaru scheme://host[:port][/cesta] (malými písmeny host i schéma, bez koncového lomítka, bez query a fragmentu).

Tuto URL musíte posílat bajtově stejnou:

Hub obě strany normalizuje a pak je porovná; posílejte URL v jednom stabilním kanonickém tvaru, ať se shoda nerozjede. Nesedící web → 401 (neznámý web). Cesta se zachovává, takže různé podadresáře jsou různé weby (https://mesto.cz/spolek-a a https://mesto.cz/spolek-b jsou dva nezávislé weby; WP multisite je jen jeden příklad tohoto vzoru).


2. Registrace a získání secretu

POST {hub}/entangle/v1/hub/register-site
Content-Type: application/json

{ "site_url": "https://spolek.cz", "name": "Spolek Zelené Údolí" }

Odpověď 201 obsahuje secret (48 znaků) — vydá se právě jednou:

{ "message": "Web zaregistrován.", "secret": "AbC…48znaků…xyz" }

3. HMAC podpis požadavků

Každá publikace (a retract/withdraw) se podepisuje sdíleným secretem. Tři hlavičky:

Hlavička Hodnota
X-Entangle-Site vaše kanonická site_url
X-Entangle-Timestamp unixový čas odeslání (tolerance ±300 s)
X-Entangle-Signature sha256= + hex z HMAC_SHA256(secret, timestamp + "." + raw_body)

Recept (jazykově neutrální):

ts        = aktuální unixový čas (celé sekundy)
raw_body  = PŘESNÉ bajty JSON těla, které odešlete
signature = "sha256=" + hex( HMAC_SHA256( secret, ts + "." + raw_body ) )

⚠️ Podepisují se přesně ty bajty, které pošlete. Serializujte JSON jednou do proměnné, tu podepište i odešlete — nepřegenerovávejte JSON mezi podpisem a odesláním (jiné pořadí klíčů/mezer = jiný podpis = 403).


4. Publikace obsahu

POST {hub}/entangle/v1/hub/publish        (podepsané dle §3)

Společná pole těla:

Pole Význam
type post (výchozí) · event · update · participation
title titulek (povinný, když chybí content)
content text; je bráno jako HTML-source — entity (&, …) se dekódují, tagy se u titulků notifikací mohou strhnout. Posílejte HTML (jako WP), nebo prostý text bez doslovných entit.
url kanonický permalink (váš, pod site_url). Same-origin je striktně vynuceno u retract/withdraw a u feedu projektů; u publish se URL uloží tak, jak přijde — posílejte vlastní permalinky.
image reprezentativní/hero obrázek (absolutní http(s) URL). Když chybí, hub sám zkusí og:image z url. (Není to nutně „featured image" — to je jen WP název.)

Odpověď 202 {status: delivered, notified: n}. Chyby: 400 chybí site · 401 neznámý web · 403 špatný podpis/čas · 422 validace.

Události (type: event) navíc: starts_at (ISO, povinné), url (povinné, dedupe klíč), ends_at?, location?, is_online?. Hub událost uloží a vystaví ji jako strukturovaný community.lexicon.calendar.event do atproto (viz API.md §2).

Participace (type: participation, např. anketa/hlasování): url povinné, kind? (druh, max 30 znaků), starts_at? (smí být v budoucnu — spuštění naplánuje scheduler), ends_at?.

Backfill historie: položce lze přidat published_at (ISO, původní datum) a silent: true (uloží bez notifikací). Pro hromadný import je POST {hub}/entangle/v1/hub/publish-batch s { items: [...] } (max 100, jen post/update, vždy tiché, idempotentní podle source_url + url).

Re-publikace stejného permalinku = update na místě (drží původní datum).


5. Stažení obsahu


6. Profil pro mapu (murmurations.json)

Aby se web objevil na mapě a v adresáři, hostujte profil ve formátu Murmurations organizations_schema-v1.0.0:

GET {web}/murmurations.json
{
  "linked_schemas": ["organizations_schema-v1.0.0"],
  "name": "Spolek Zelené Údolí",
  "primary_url": "https://spolek.cz",
  "description": "Komunitní spolek v Zeleném Údolí.",
  "full_address": "Náves 1, Zelené Údolí",
  "geolocation": { "lat": 49.5, "lon": 15.3 },
  "tags": ["entangle", "entangle:actor:community", "entangle:oblast:bezpecnost"],
  "image": "https://spolek.cz/logo.png",
  "projects_url": "https://spolek.cz/api/projekty.json"
}

7. Feed projektů

Jednotlivé projekty (s vlastními piny a filtrací) hostujte jako JSON feed. Hub jeho umístění zjistí v tomto pořadí:

  1. projects_url deklarované ve vašem murmurations.json (absolutní, same-origin) — doporučeno, umístíte feed kam chcete;
  2. jinak neutrální GET {web}/entangle/projects.json;
  3. jinak legacy GET {web}/wp-json/entangle/v1/projects (WP plugin).
{
  "projects": [
    {
      "id": 1,
      "title": "Revitalizace hřiště",
      "url": "https://spolek.cz/projekty/hriste",
      "excerpt": "Krátké shrnutí projektu.",
      "thumbnail": "https://spolek.cz/img/hriste.jpg",
      "geolocation": { "lat": 49.6, "lon": 15.4 },
      "areas": [{ "slug": "verejny-prostor-a-zelen-priroda-v-intravilanu", "name": "Veřejný prostor a zeleň" }],
      "tags": ["entangle:oblast:verejny-prostor-a-zelen-priroda-v-intravilanu"],
      "status": "v-realizaci"
    }
  ]
}

8. Řízený slovník (kategorie)

Slugy areas[] a status nelze odvozovat — zkopírujte je verbatim z hubu:

GET {hub}/entangle/v1/taxonomy

Vrací typy aktérů (entangle:actor:<typ>), oblasti (entangle:oblast:<slug> / areas) a stavy projektu. status musí být síťový slug: v-priprave · v-realizaci · dokonceny.


9. (Volitelné) Přihlášení přes Entangle — OAuth 2.0 / OIDC

Standardní OAuth 2.0 authorization-code flow; funguje s jakoukoli OAuth knihovnou.

GET  {hub}/entangle/v1/hub/oauth/authorize?redirect_uri=…&scope=…&state=…   (v prohlížeči)
POST {hub}/entangle/v1/hub/oauth/token       { code, client_id, client_secret }
GET  {hub}/entangle/v1/hub/oauth/userinfo    Authorization: Bearer …

10. Ověření vlastnictví webu (TOFU)

Registrace je dnes trust-on-first-use: kdo si kanonickou URL zaregistruje první, dostane secret; vlastnictví se zatím neověřuje (stejně pro WP i ne-WP weby). → Zaregistrujte si svou URL dřív, než to za vás udělá někdo jiný.

Do budoucna je plánovaný CMS-neutrální challenge: hub vydá nonce a stáhne ho z {site_url}/.well-known/entangle-challenge. Až bude, přibude sem postup.


11. Rychlý checklist + minimální end-to-end příklad

Checklist připojení:

Publikace novinky (ilustrační bash + openssl):

HUB="https://entangle.cz"
SITE="https://spolek.cz"
SECRET="…secret z registrace…"

BODY='{"type":"post","title":"Zahajujeme sběr podnětů","url":"https://spolek.cz/aktuality/podnety"}'
TS=$(date +%s)
SIG="sha256=$(printf '%s' "$TS.$BODY" | openssl dgst -sha256 -hmac "$SECRET" | sed 's/^.* //')"

curl -X POST "$HUB/entangle/v1/hub/publish" \
  -H "Content-Type: application/json" \
  -H "X-Entangle-Site: $SITE" \
  -H "X-Entangle-Timestamp: $TS" \
  -H "X-Entangle-Signature: $SIG" \
  --data "$BODY"
# → 202 {"status":"delivered","notified":N}

Po tomto: novinka je ve feedu sítě a odběratelé webu dostanou notifikaci; jakmile hub stáhne váš murmurations.json + feed projektů, objeví se web na mapě a projekty v galerii.