# Session Event Subscriptions

This document describes how Buffaly session event subscriptions are registered, delivered, and inspected.

## Core Concepts

- `sourceSessionKey`: session (or service source) that emits events.
- `subscriberSessionKey`: session that receives callback events.
- `eventTypes`: optional allow-list (`turn.started`, `assistant.message.updated`, `turn.completed`, `heartbeat.tick`, etc.).
- `deliveryMode`:
	- `local`: event is delivered directly to in-process callback handling.
	- `webhook`: event is posted to `callbackUrl`.
- `expiresUtc`: subscription expiry timestamp; `DateTime.MaxValue` means non-expiring.

## Register Subscription

Method: `subscribe-session-events`

Request JSON:

```json
{
	"sourceSessionKey": "source-session",
	"subscriberSessionKey": "watcher-session",
	"eventTypes": ["turn.completed"],
	"ttlSeconds": 3600
}
```

Response shape includes:

- `Subscribed` (`bool`)
- `SourceSessionKey` (`string`)
- `SubscriberSessionKey` (`string`)
- `DeliveryMode` (`string`)
- `CallbackUrl` (`string`)
- `ExpiresUtc` (`ISO-8601 UTC string`)
- `EventTypes` (`string[]`)

## Unregister Subscription

Method: `unsubscribe-session-events`

Request JSON:

```json
{
	"sourceSessionKey": "source-session",
	"subscriberSessionKey": "watcher-session"
}
```

Response includes `Removed` count.

## List Subscriptions

Method: `list-session-event-subscriptions`

Request JSON:

```json
{
	"sourceSessionKey": "source-session"
}
```

Response JSON:

- `SourceSessionKey`
- `Count`
- `Items[]` where each item has:
	- `SourceSessionKey`
	- `SubscriberSessionKey`
	- `DeliveryMode`
	- `CallbackUrl`
	- `CreatedUtc`
	- `ExpiresUtc`
	- `EventTypes[]`

## Receive Events

Method: `session-event-callback`

Request JSON:

```json
{
	"eventEnvelope": {
		"EventId": "evt-123",
		"EventType": "turn.completed",
		"SourceSessionKey": "source-session",
		"TargetSessionKey": "watcher-session",
		"OccurredUtc": "2026-03-25T00:00:00Z",
		"Data": {
			"text": "Optional summary",
			"status": "completed",
			"assistantText": "Done."
		}
	}
}
```

Response includes:

- `Accepted` (`bool`)
- `Duplicate` (`bool`)
- `EventId` (`string`)
- `SourceSessionKey` (`string`)
- `TargetSessionKey` (`string`)
- `SessionKey` (`bucket session key`)
- `SupervisoryDispatchedCount` (`int`)
- `SupervisoryFailedCount` (`int`)

## Heartbeat Service

Heartbeat uses `sourceSessionKey = "heartbeat.service"` and emits `heartbeat.tick` events.

When started, heartbeat registration:

1. Starts a heartbeat job owned by `heartbeat.service` for your target session.
2. Emits callback events at the requested interval when `deliveryMode = session-event-callback`.
3. Stops after `maxCount` emissions.

Inspect heartbeat-specific rows at `/heartbeat-subscriptions`.

