For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /reference/docs/decisions/0061-support-context-and-broker-provisioning.md.

0061 — Support context and development broker provisioning

Status: Accepted. Date: 7 October 2026. Broker provisioning superseded by decision 0046 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.

Page source

Source snapshot · Revision f928834c8.