websub
Model for WebSub resource subscriptions, delivery queues, and automatic imports.
Available model API paths
| Method | Path | Result |
|---|---|---|
get | /subscriptions | Paginated overview; requires use mod_websub. Payload: type (all, export, import), numeric local rsc_id, hostname, status, errors (yes/no/all), and page. |
get | /subscriber_count/+id | Number of unexpired incoming subscriptions; requires resource edit permission. |
get | /status/+id | Latest import subscription status for an editable resource, or undefined when none exists. |
+id is resolved through m_rsc:rid/2. The template equivalent is
m.websub.status[id]; the model checks resource edit permission independently of
the template or controller. Unauthorized reads return eacces. There are no
public model POST or DELETE paths for starting or stopping subscriptions.
The overview includes retained expired/stopped subscriptions and renewal generations,
50 rows per page. Hostname is an exact, case-insensitive match on the incoming
callback host or outgoing source host, ignoring ports and a trailing DNS dot.
Status accepts active, pending, expired, or stopped; empty/all means all
states. The errors filter selects rows with or without the table’s error indicator.
All filters apply before pagination and counting. The overview returns a
search_result record with an exact total, capped at 10,000 pages.
It returns remote hostnames, never callback URLs, tokens, secrets,
or authentication data. Invalid filters return is_invalid without broadening the query.
Status includes desired state (is_enabled), confirmation state
(is_unsubscribed, is_active), pending_mode, lease, last_received,
last_error, and credential_error. During renewal, is_active also accounts
for a still-active predecessor callback. Status never exposes callback tokens,
HMAC secrets, or source OAuth2 tokens.
Erlang API
subscribe/2starts a durable subscription for an editable, non-authoritative resource with a remote URI. It requires a logged-in user and is idempotent for an already-enabled subscription to that source. Discovery and verification run asynchronously;okmeans intent was recorded, not that the hub confirmed it.unsubscribe/2requires edit permission, immediately disables automatic imports, discards queued updates, and schedules remote unsubscription.topic_url/2generates the language-independent JSON topic URL. Usem_rsc:uri/2for the resource's semantic/ididentity instead.
ok = m_websub:subscribe(Id, Context).
ok = m_websub:unsubscribe(Id, Context).
Admin postbacks call these checked functions. The remaining exported queue,
verification, export-registration, schema, and maintenance functions are internal
integration APIs. They are not exposed through model paths. In particular,
update_export/6 and delete_export/3 are called after the hub has verified intent;
callers must not use them to bypass authorization or callback verification.
Delivery and import processing
Publisher queues coalesce resource versions, enforce lease expiry, and recheck current access within the original authentication's group restrictions. Delivery contains the complete JSON topic representation and a signature when a secret was supplied. Exhausted retries discard that notification, allowing later updates to retry delivery for the remaining lease.
Subscriber callbacks identify the subscription by capability token and validate
the signed resource URI. Public imports consume the pushed JSON; credentialed
imports refetch through z_fetch using the subscribing user's source credentials.
Before applying content, the import transaction checks current edit permission,
non-authoritative status, source identity, and version ordering. Saved import
options are reused without allowing automatic updates to restart a stopped
subscription. Resource identity is stored separately from the discovered WebSub
topic_url, so topic migration does not change the semantic resource identifier.
See mod_websub for the two-site protocol flow and z_websub_subscription for
renewal, pending intent, callback rotation, and subscriber state persistence.