LearnNewsExamplesServices
Frontmatter
id16054
titleIntra-deployment A2A trust: a private deployment''s members should be able to message each other without pairwise grants
stateClosed
labels
enhancementai
assigneesneo-opus-vega
createdAtJul 27, 2026, 9:28 PM
updatedAtJul 28, 2026, 2:54 AM
githubUrlhttps://github.com/neomjs/neo/issues/16054
authorneo-opus-vega
commentsCount2
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 28, 2026, 2:54 AM

Intra-deployment A2A trust: a private deployment's members should be able to message each other without pairwise grants

Closed Backlog/active-chunk-10 enhancementai
neo-opus-vega
neo-opus-vega commented on Jul 27, 2026, 9:28 PM

Context

Observed on a fresh self-hosted private deployment during post-redeploy verification. The identity roster was healthy — 19 AgentIdentity nodes present, auto-provisioned from auth provenance — but every attempt to initiate a message failed:

Unauthorized: Cannot send to @<recipient>. Requires CAN_REPLY_TO permission or prior message history.

The gate is behaving exactly as written. The problem is that it has no bootstrap.

The Problem

add_message admits a send when the sender holds CAN_REPLY_TO or there is prior message history. On a newly provisioned plane there is neither, and there is no way to obtain the second without the first. So the mailbox is installed, correctly fail-closed, and unusable: no member can initiate to any other member until someone grants permissions out of band.

For a deployment with ~15 members that is up to 210 pairwise grants to make a fundamental capability work at all — and every new member re-opens the problem. The result is that A2A reads as broken to the deployment's users even though identity, transport, and storage are all healthy.

This capability never existed — it is not a regression. There is currently no notion of "members of the same private deployment are mutually reachable by default."

The Architectural Reality

The current model is per-pair permission with a history escape hatch. That is the right default for a multi-tenant plane, where two callers who share a server share nothing else. It is the wrong default for a single-organisation private deployment, where every authenticated member is already inside one trust boundary — the auth provider decided that at login.

So the missing concept is deployment-scoped trust: the admission decision belongs to the deployment's posture, not to each pair of members inside it. autoProvisionIdentitySources already encodes exactly this reasoning for identity creation — GitLab PAT auto-provisions because a self-hosted GitLab is a scoped caller set, while public GitHub does not. Mailbox admission needs the same distinction and does not have it.

The Fix (one PR)

Add an AiConfig leaf governing default intra-deployment mailbox reachability, with an env binding, registered in the config-leaf parity manifest:

  • Members authenticated by the same deployment may initiate to one another without a prior grant when the posture is private/self-hosted.
  • Multi-tenant and public-identity postures keep today's pairwise behaviour.
  • Explicit grants and revocations continue to work and continue to win; this changes the default, not the mechanism.
  • Cross-deployment sends are unaffected — this is strictly intra-plane.

Acceptance Criteria

  • A new AiConfig leaf with an env binding controls default intra-deployment mailbox admission, registered in ai/scripts/lint/config-leaf-parity.json in the same commit.
  • With the private/self-hosted posture, a member with no grant and no history can add_message to another member of the same deployment.
  • With the multi-tenant posture the current refusal is unchanged, asserted by a test — the permissive path must not be reachable by posture drift.
  • An explicit revoke_permission still blocks a send that the default would otherwise allow; the default is a floor, not an override.
  • Cross-deployment / unknown-identity sends still refuse, asserted.
  • The refusal message names the posture when it blocks, so an operator can tell "you need a grant" from "this deployment does not permit intra-plane initiation."

Out of Scope

  • Broadcast semantics (AGENT:*) — unchanged.
  • Wake/subscription authorization — separate surface.
  • Any change to identity auto-provisioning.

Related

  • autoProvisionIdentitySources — the existing precedent for posture-scoped admission
  • #15798 (Local Runtime Parity) — the epic this deployment posture belongs to