SubMan async event streams (SSE) 1.0-149+1ecf439

Every listing endpoint in ldap-subscriber-api.yaml accepts ?subscribe=1, which upgrades the response to text/event-stream and keeps the connection open. This document describes the events delivered on those streams.

Quickstart for an SSE consumer

const es = new EventSource('/realm/example.org/subscriber?subscribe=1');

es.addEventListener('ready', () => {
  // initial state has finished replaying; subsequent `entry`
  // events are live changes
});

es.addEventListener('entry', (e) => {
  const { entryUUID, syncOp, body } = JSON.parse(e.data);
  switch (syncOp) {
    case 'present':                 // existing record (during initial replay)
    case 'add':                     // newly created
    case 'modify':  applyUpsert(body); break;   // full new state in `body`
    case 'delete':  applyDelete(body); break;   // tombstone: only id + _url
  }
});

Two SSE event names are used:

  • ready (fires once) marks the boundary between the initial replay of existing records and the live change stream. Its payload is an empty object.
  • entry (fires repeatedly) carries one record. The JSON payload tells you what kind of change it represents via syncOp, and carries the record itself under body. Records always include a _url field pointing at the matching REST resource.

Deletes

delete events carry only id and _url in body, not the attributes the record had before it was removed. By the time the server emits the event, the record is already gone from the underlying directory and its attributes are unrecoverable; consumers that need the old state must keep their own copy keyed on entryUUID.

Renames

Resources are identified in the URL by their id. When an id changes, that's a rename, and a single underlying rename surfaces on the stream as two events rather than one modify:

  • a delete carrying the old id and _url, followed by
  • an add carrying the new id, _url, and the full object body.

Both events share the same entryUUID, so consumers that want to treat a rename as a single logical operation can correlate by UUID. Consumers that only care about the current URL of a record can treat the pair as an ordinary remove-then-create.

The same shape applies when a record moves between collections (for example, a subscriber re-homed to a different realm): the URL changes, so the stream emits delete against the old URL and add against the new one.

Resuming a dropped stream

Each entry is emitted with an SSE id: line containing an opaque resume cookie. EventSource captures these automatically and sends the most recent one back as Last-Event-ID when it reconnects, so for browser clients no extra code is needed: reconnects pick up where the previous stream left off, without replaying the initial state.

Non-EventSource clients should:

  1. remember the last id: value they received,
  2. on reconnect, set Last-Event-ID: <that value> on the new request.

Cookies are accepted only if they are 1024 bytes or fewer and contain no control characters; otherwise the server returns 400 Bad Request.

Where the events come from

Internally the stream is driven by an LDAP syncrepl persistent search (RFC 4533). The syncOp values (present, add, modify, delete) and the entryUUID field come from that protocol. Consumers do not need to know about LDAP to use the stream: the events describe REST resources, and body contains the same JSON shape returned by the corresponding GET endpoint.

Servers

  • sse://localhost:3000/ssedefault

    The same host that serves the REST API. Streams are reached by appending ?subscribe=1 to the corresponding listing endpoint (and any of the supported filter_* query parameters).

Operations

  • RECEIVE /realm?subscribe=1

    Changes to the set of realms.

    Subscribe to realm changes

    Operation IDreceiveRealmStream

    Available only on servers:

    Accepts one of the following messages:

    • #0Initial replay complete

      Marks the boundary between initial state replay and live change events.

      Message IDready
      object

      Examples

    • #1Realm event
      Message IDentry
      allOf

      Examples

  • RECEIVE /realm/{realmId}/subscriber?subscribe=1

    Changes to the subscribers that belong to a single realm.

    Subscribe to subscriber changes in a realm

    Operation IDreceiveRealmSubscriberStream

    Available only on servers:

    object
    realmIdstring
    required

    Identifier of the parent realm.

    Accepts one of the following messages:

    • #0Initial replay complete

      Marks the boundary between initial state replay and live change events.

      Message IDready
      object

      Examples

    • #1Subscriber event
      Message IDentry
      allOf

      Examples

  • RECEIVE /group?subscribe=1

    Changes to subscriber groups.

    Subscribe to subscriber-group changes

    Operation IDreceiveGroupStream

    Available only on servers:

    Accepts one of the following messages:

    • #0Initial replay complete

      Marks the boundary between initial state replay and live change events.

      Message IDready
      object

      Examples

    • #1Subscriber group event
      Message IDentry
      allOf

      Examples

  • RECEIVE /service?subscribe=1

    Changes to top-level service definitions.

    Subscribe to service changes

    Operation IDreceiveServiceStream

    Available only on servers:

    Accepts one of the following messages:

    • #0Initial replay complete

      Marks the boundary between initial state replay and live change events.

      Message IDready
      object

      Examples

    • #1Service event
      Message IDentry
      allOf

      Examples

  • RECEIVE /service/{serviceId}/profile?subscribe=1

    Changes to service profiles within one service.

    Subscribe to service-profile changes for one service

    Operation IDreceiveServiceProfileStream

    Available only on servers:

    object
    serviceIdstring
    required

    Identifier of the parent service.

    Accepts one of the following messages:

    • #0Initial replay complete

      Marks the boundary between initial state replay and live change events.

      Message IDready
      object

      Examples

    • #1Service profile event
      Message IDentry
      allOf

      Examples

  • RECEIVE /service/{serviceId}/profile/{profileId}/policy?subscribe=1

    Changes to policies attached to a single service profile.

    Subscribe to policy changes for one service profile

    Operation IDreceivePolicyStream

    Available only on servers:

    object
    serviceIdstring
    required

    Identifier of the parent service.

    profileIdstring
    required

    Identifier of the parent service profile.

    Accepts one of the following messages:

    • #0Initial replay complete

      Marks the boundary between initial state replay and live change events.

      Message IDready
      object

      Examples

    • #1Policy event
      Message IDentry
      allOf

      Examples

  • RECEIVE /client?subscribe=1

    Changes to RADIUS clients.

    Subscribe to client changes

    Operation IDreceiveClientStream

    Available only on servers:

    Accepts one of the following messages:

    • #0Initial replay complete

      Marks the boundary between initial state replay and live change events.

      Message IDready
      object

      Examples

    • #1Client event
      Message IDentry
      allOf

      Examples

  • RECEIVE /client/{clientId}/port?subscribe=1

    Changes to the physical ports configured on one client.

    Subscribe to physical-port changes on one client

    Operation IDreceiveClientPortStream

    Available only on servers:

    object
    clientIdstring
    required

    Identifier of the parent client.

    Accepts one of the following messages:

    • #0Initial replay complete

      Marks the boundary between initial state replay and live change events.

      Message IDready
      object

      Examples

    • #1Physical port event
      Message IDentry
      allOf

      Examples

  • RECEIVE /client/{clientId}/port/{portId}/qinq?subscribe=1

    Changes to the QinQ taggings configured on one physical port of a client.

    Subscribe to QinQ tagging changes on one client port

    Operation IDreceiveClientPortQinqStream

    Available only on servers:

    object
    clientIdstring
    required

    Identifier of the parent client.

    portIdstring
    required

    Identifier of the parent physical port.

    Accepts one of the following messages:

    • #0Initial replay complete

      Marks the boundary between initial state replay and live change events.

      Message IDready
      object

      Examples

    • #1QinQ tagging event
      Message IDentry
      allOf

      Examples

  • RECEIVE /client/{clientId}/port/{portId}/stag?subscribe=1

    Changes to the single-tag (S-tag) taggings configured on one physical port of a client.

    Subscribe to S-tag tagging changes on one client port

    Operation IDreceiveClientPortStagStream

    Available only on servers:

    object
    clientIdstring
    required

    Identifier of the parent client.

    portIdstring
    required

    Identifier of the parent physical port.

    Accepts one of the following messages:

    • #0Initial replay complete

      Marks the boundary between initial state replay and live change events.

      Message IDready
      object

      Examples

    • #1S-tag tagging event
      Message IDentry
      allOf

      Examples

  • RECEIVE /clientGroup?subscribe=1

    Changes to client groups.

    Subscribe to client-group changes

    Operation IDreceiveClientGroupStream

    Available only on servers:

    Accepts one of the following messages:

    • #0Initial replay complete

      Marks the boundary between initial state replay and live change events.

      Message IDready
      object

      Examples

    • #1Client group event
      Message IDentry
      allOf

      Examples

  • RECEIVE /accessDevice?subscribe=1

    Changes to access devices.

    Subscribe to access-device changes

    Operation IDreceiveAccessDeviceStream

    Available only on servers:

    Accepts one of the following messages:

    • #0Initial replay complete

      Marks the boundary between initial state replay and live change events.

      Message IDready
      object

      Examples

    • #1Access device event
      Message IDentry
      allOf

      Examples

  • RECEIVE /accessDevice/{accessDeviceId}/port?subscribe=1

    Changes to the physical ports configured on one access device.

    Subscribe to physical-port changes on one access device

    Operation IDreceiveAccessDevicePortStream

    Available only on servers:

    object
    accessDeviceIdstring
    required

    Identifier of the parent access device.

    Accepts one of the following messages:

    • #0Initial replay complete

      Marks the boundary between initial state replay and live change events.

      Message IDready
      object

      Examples

    • #1Physical port event
      Message IDentry
      allOf

      Examples

  • RECEIVE /accessDevice/{accessDeviceId}/port/{portId}/qinq?subscribe=1

    Changes to the QinQ taggings configured on one physical port of an access device.

    Subscribe to QinQ tagging changes on one access device port

    Operation IDreceiveAccessDevicePortQinqStream

    Available only on servers:

    object
    accessDeviceIdstring
    required

    Identifier of the parent access device.

    portIdstring
    required

    Identifier of the parent physical port.

    Accepts one of the following messages:

    • #0Initial replay complete

      Marks the boundary between initial state replay and live change events.

      Message IDready
      object

      Examples

    • #1QinQ tagging event
      Message IDentry
      allOf

      Examples

  • RECEIVE /accessDevice/{accessDeviceId}/port/{portId}/stag?subscribe=1

    Changes to the single-tag (S-tag) taggings configured on one physical port of an access device.

    Subscribe to S-tag tagging changes on one access device port

    Operation IDreceiveAccessDevicePortStagStream

    Available only on servers:

    object
    accessDeviceIdstring
    required

    Identifier of the parent access device.

    portIdstring
    required

    Identifier of the parent physical port.

    Accepts one of the following messages:

    • #0Initial replay complete

      Marks the boundary between initial state replay and live change events.

      Message IDready
      object

      Examples

    • #1S-tag tagging event
      Message IDentry
      allOf

      Examples

Messages

  • #1Initial replay complete

    Marks the boundary between initial state replay and live change events.

    Message IDready
    object
  • #2Realm event
    Message IDrealmEntry
    allOf
  • #3Subscriber event
    Message IDsubscriberEntry
    allOf
  • #4Subscriber group event
    Message IDsubscriberGroupEntry
    allOf
  • #5Service event
    Message IDserviceEntry
    allOf
  • #6Service profile event
    Message IDserviceProfileEntry
    allOf
  • #7Policy event
    Message IDpolicyEntry
    allOf
  • #8Client event
    Message IDclientEntry
    allOf
  • #9Physical port event
    Message IDportPhysicalEntry
    allOf
  • #10QinQ tagging event
    Message IDportQinqEntry
    allOf
  • #11S-tag tagging event
    Message IDportStagEntry
    allOf
  • #12Client group event
    Message IDclientGroupEntry
    allOf
  • #13Access device event
    Message IDaccessDeviceEntry
    allOf

Schemas

  • object
  • object

    Stand-in body for delete events. Only enough information to identify which record went away.

  • object
  • allOf
  • allOf
  • allOf
  • allOf
  • allOf
  • allOf
  • allOf
  • allOf
  • allOf
  • allOf
  • allOf
  • allOf