Federation and audiences
An audience answers two questions: what version of an event may leave this
node, and who may receive it? Every new local mutation is projected into each
audience named by federation.default_audiences.
Important
Selected audiences are parallel outputs, not layers of access control. If
publicandneighborsare both selected, the public representation remains public. A restricted representation does not make fields in the public representation private. Evaluate the most permissive selected audience when explaining the policy to flock members.
Public federation
The default configuration selects one public audience:
[federation]
default_audiences = ["public"]
[federation.audiences.public]
transport = "public"
Public events are signed by the flock and readable by anyone with relay access. The public projection uses exact timestamps, includes notes, tags, media, and all extensions, and excludes location.
Restricted federation
Restricted audiences sign a projected inner event and encrypt a separate NIP-59 gift wrap for each recipient.
[federation]
default_audiences = ["public", "neighbors"]
[federation.audiences.public]
transport = "public"
[federation.audiences.neighbors]
transport = "restricted"
recipients = [
"<cerulean-public-key>",
"<sunyshore-public-key>",
]
allowed_senders = [
"<cerulean-public-key>",
"<sunyshore-public-key>",
]
[federation.audiences.neighbors.projection]
observed_at_precision = "day"
publication_delay_seconds = 3600
notes = false
tags = true
location = false
media = false
extensions = ["fyi.birdd.birds/count"]
recipients and allowed_senders are intentionally independent. Recipients
receive your events. Allowed senders may send events into that audience. A
restricted audience can be outbound-only by leaving allowed_senders empty.
These lists do not inherit from the trust database.
What leaves the node
Use this matrix when describing the active policy to operators and flock members. It covers observation content, not all federation protocol metadata:
| Observation data | Public | Restricted |
|---|---|---|
| Subject | Always included | Always included |
| Observation ID | Always included | Always included |
| Event creation time | Exact | Exact |
| Observed time | Exact | Exact, hour, or UTC day |
| Notes | Included | Configurable |
| Tags | Included | Configurable |
| Location | Omitted | Configurable |
| Media references | Included | Configurable |
| Extensions | All envelopes | All or an explicit allowlist |
Timestamp precision changes observed_at, not the exact event creation time.
Publication delay does not hide that creation time after delivery.
Restricted encryption hides projected content from relays, but not all traffic metadata. A relay can see the recipient key on each gift wrap and when encrypted messages are published. After decryption, a recipient learns the sender key, audience name, sequence, policy epoch, and revision identity in addition to the projected observation.
A media reference identifies an object but does not make the media bytes public. Fetching media requires a signed request from a flock directly trusted by the media’s origin. Restricted media access additionally requires a published representation that disclosed the reference to that recipient.
Extension allowlists include the complete envelope for each selected extension ID. Review the extension’s schema and actual values; an innocent-looking column name does not guarantee that the envelope contains no other sensitive keys. A local extension manifest is not a projection filter; see Extensions.
Corrections and deletions follow the selected audiences too. A deletion updates the current state on conforming nodes but cannot force relays or prior recipients to erase copies. Recipients can also retain or redistribute decrypted restricted data.
Projection controls
A restricted projection can:
- Reduce observation timestamps to the start of an hour or UTC day
- Delay publication for up to one year
- Remove notes, tags, location, or media
- Include all extensions or an explicit allowlist of extension IDs
The subject and observation identity are always included. Public audiences use the default projection and cannot customize these controls.
An enabled field is preserved only when present on an observation. In particular, current local create and correction commands do not accept location, even though restricted projection policy has a location control.
Preview the current projection of a locally owned observation without publishing it:
birdd --config birdd.toml federation-preview <observation-id>
Preview representative observations containing notes, tags, location, media, and every installed extension. Do not preview only an empty test observation.
Choose a privacy posture
Open public sharing
Use the default public audience only when members understand that observation subjects, exact times, notes, tags, media references, and every extension are publicly readable:
[federation]
default_audiences = ["public"]
[federation.audiences.public]
transport = "public"
Public projections cannot be reduced. If any of those fields should be limited
to named flocks, remove public from default_audiences and use a restricted
audience instead.
Named recipients with full detail
Select only a restricted audience to preserve the normal observation detail while limiting relay-readable content and delivery to named recipient keys:
[federation]
default_audiences = ["neighbors"]
[federation.audiences.neighbors]
transport = "restricted"
recipients = [
"<cerulean-public-key>",
"<sunyshore-public-key>",
]
allowed_senders = []
The default restricted projection still sends exact observed times, notes, tags, media references, and every extension. It omits location. Encryption limits delivery but does not minimize what recipients learn.
Leaving allowed_senders empty makes this audience outbound-only. Add keys only
for flocks whose restricted events this node should accept; this does not happen
automatically when a key is a recipient or is directly trusted.
Minimized and delayed sharing
For sensitive observations, reduce the data before encryption and delay its release:
[federation]
default_audiences = ["regional-summary"]
[federation.audiences.regional-summary]
transport = "restricted"
recipients = ["<regional-coordinator-public-key>"]
allowed_senders = []
[federation.audiences.regional-summary.projection]
observed_at_precision = "day"
publication_delay_seconds = 86400
notes = false
tags = false
location = false
media = false
extensions = ["fyi.birdd.birds/count"]
This sends the subject, observation ID, exact event creation time, day-level observed time, and the count envelope when present. It does not provide full anonymity: subjects and creation times can still be identifying.
The extension projection must be ["*"] or a non-empty allowlist. There is no
explicit deny-all setting. An allowlist containing a reserved namespaced ID that
the node never writes, such as invalid.example/not-installed, effectively
omits current extensions, but would disclose that ID if it were ever added to an
observation. Treat this as a workaround and audit it when installing extensions.
Different policies for different recipients
Define multiple restricted audiences when recipient groups should receive
different projections, then select all of them in default_audiences. A
recipient key can belong to only one restricted audience, so groups cannot
overlap.
Every local observation and later correction or deletion goes to every selected audience. Users cannot select an audience per observation. There is no local-only audience transport. Leaving the relay list empty only postpones delivery: selected representations remain stored and can publish if relays are configured later. A durable “never federate” policy therefore requires a separate operationally isolated deployment and is not enforced by the current audience model.
Changing policy
Projection, transport, and recipient changes create a new stream policy epoch.
Pending deliveries made obsolete by the new policy are marked suppressed;
already published events cannot be recalled.
Warning
Adding an audience does not backfill existing history. An older observation without a representation for every currently selected audience cannot be corrected or deleted.
birddreports that explicit backfill is required, but this MVP does not yet include a backfill command.
Inspect stream positions, missing sequences, conflicts, manifests, and restricted delivery queues with:
birdd --config birdd.toml federation-status --json
Restricted delivery states are delayed, due, wrapped, published, and
suppressed. See Node configuration for every audience option.