- Authentik -> edge2 CT 105 (Postgres pg_dump/restore; SECRET_KEY carried verbatim; zero-downtime until ~2s cutover) - Multi-block Caddy cutover: auth.echo6.co + notes.echo6.co outpost/forward_auth -> 100.64.0.36:9000 - runbook: add reboot tailscale-before-docker gotcha; clarify dnsmasq must NOT be repointed (points at Caddy host) - source left stopped + intact on Contabo as cold rollback Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3.1 KiB
3.1 KiB
Hookshot Outbound Webhook Payload Discovery
Generated: 2026-04-09 (Phase 6.0, Question 4)
NOTE: Hookshot is BLOCKED for this use case (E2EE + MAS incompatibility).
This file documents the payload shape for completeness and future reference.
Outbound Webhook Config
Enable in hookshot config.yml:
generic:
outbound: true
HTTP Method and Content-Type
- Method: PUT (default) or POST (configurable per-connection)
- Content-Type: multipart/form-data
- Two parts:
eventfile: Raw Matrix event JSONmediafile (optional): Attached media if the event references it
Headers
| Header | Description |
|---|---|
| X-Matrix-Hookshot-EventId | Matrix event ID |
| X-Matrix-Hookshot-RoomId | Room ID |
| X-Matrix-Hookshot-Token | Per-webhook auth token (for receiver verification) |
Event Type Coverage
ALL events in the room are forwarded. Specifically:
| Event Type | Forwarded? | Notes |
|---|---|---|
| m.room.message | Yes | Normal messages |
| m.room.redaction | Yes | Deletions |
| m.room.message with m.relates_to/m.replace | Yes | Edits (m.new_content present) |
| m.room.message with m.relates_to/m.in_reply_to | Yes | Replies |
| m.reaction | Yes | Reactions |
| m.room.member | Yes | Joins/leaves/invites |
| State events | Yes | All state changes |
The docs state: "All events that occur in the room will be sent to the outbound URL, so be careful to ensure your remote service can filter the traffic appropriately."
Encrypted Room Behavior
IF encryption is working (which it's NOT with MAS — see hookshot_e2ee_discovery.ref):
- The
eventpayload contains DECRYPTED plaintext content - The receiver sees the same JSON as an unencrypted room
IF encryption is NOT working:
- The
eventpayload contains the encrypted blob (m.room.encrypted type) - Content is unusable ciphertext
Sample Payload (from docs/source)
{
"type": "m.room.message",
"sender": "@signal_abc123:echo6.co",
"event_id": "$abc123:echo6.co",
"room_id": "!XUeWZuPdWQQnUYLJBJ:echo6.co",
"origin_server_ts": 1775773462151,
"content": {
"msgtype": "m.text",
"body": "Hello from Signal"
},
"unsigned": {
"age": 42
}
}
Edit event example:
{
"type": "m.room.message",
"sender": "@signal_abc123:echo6.co",
"event_id": "$edit123:echo6.co",
"room_id": "!XUeWZuPdWQQnUYLJBJ:echo6.co",
"origin_server_ts": 1775773462200,
"content": {
"msgtype": "m.text",
"body": "* Hello from Signal (edited)",
"m.new_content": {
"msgtype": "m.text",
"body": "Hello from Signal (edited)"
},
"m.relates_to": {
"rel_type": "m.replace",
"event_id": "$abc123:echo6.co"
}
}
}
Filtering
No built-in filtering. The receiver must filter by type field.
Hookshot sends everything — the receiver decides what to keep.
Retry Behavior
Failed deliveries are retried up to 5 times with increasing delays.