> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# 0061 — Support context and development broker provisioning

Status: Accepted. Date: 7 October 2026. Broker provisioning superseded by
[decision 0046](/reference/docs/decisions/0046-service-communication-and-composition.md) on 21 October 2026.

> **21 October 2026.** The Support context and its link rules stand. Its broker
> provisioning below does not: Support now follows decision 0046. Its broker roles,
> queues and permissions are generated from `contracts/support/messaging/broker.json`
> and `services/beto/contracts/subscriptions.json` into
> `services/beto/services/topology/permissions.generated.json`, and the
> administration process provisions them; `contracts/events/topology/beto.json`,
> the Go `amqp.Plan` and the `import_definitions` step are gone. The `.dead`
> retention policy is not carried over; dead letters are replayed with main's
> replay tool. The text below is kept as the record of the original decision.

Beto owns the Support context. Its `SupportCustomer` aggregate, keyed by the
Pharos user ID, links each Pharos user to a customer in the support service
(today Zammad, whose user ID stays an opaque binding). The flow follows the Miro
frame "Final create user in support service flow simple method": a link is
`pending`, `linked`, `failed` (support service unreachable, retried) or `conflict`
(email owned by another Pharos user, or HTTP 422; a person resolves it and the
retry after 24 hours picks the fix up). A `support-retry` CronJob retries links
with no attempt limit; `unresolvedSince` feeds an age alert instead.

Support is the first context with broker delivery inside a cluster. Beto's
composition root therefore lists contexts, delivery contexts and realtime contexts
separately, as Metallo does. Support has delivery and no realtime projection.

Runtime broker users have no topology or administration rights. Each delivery
context gets a `pharos_<owner>` user: configure `^$`; write only its delivery
exchange and `pharos.events`; read only `ref.<owner>.*`; topic permissions to
publish only `domain|integration.<owner>.*` and read its own private events plus
public ones. Development provisioning imports these users as salted SHA-256
hashes, their permissions, the topology and Support's `.dead` retention policy
(7 days, 10,000 messages, oldest dropped) with one `rabbitmqctl import_definitions`
read from stdin into a private broker-local file. This reuses the mechanism of
the hello-world decision on `feat/metallo-hello-world` (its 0002, not yet merged);
the two scripts should merge, and this record renumbered, when that branch lands.

The broker topology is declared once, in Beto's Go `amqp.Plan`. `Declare` uses it
and `topology -definitions` prints it; `pnpm generate:contracts` writes
`contracts/events/topology/beto.json`, which provisioning imports. A Go test fails
when the committed file or the Go catalogue drifts from the code and the shared
`contracts/events/catalogue.json`.

Only `support.customer_link_requested` is published: mandatory routing would
block the outbox for an event without a consumer. Linked, conflict and failure
outcomes are aggregate state until something consumes them. No `UserCreated`
event exists yet, so a development-only Beto endpoint stands in for it.

<details class="page-source"><summary>Page source</summary>

<a href="/source/docs/decisions/0061-support-context-and-broker-provisioning.md.txt">Source snapshot</a> · Revision `f928834c8`.

</details>
