Every inbound message gets five independent chances to be rejected. Here's why that's a feature — and why you should steal this design.
LLM-based agents are, by default, helpful. Ask them something, they answer. Give them a message, they reason over it. This is great for user experience and terrible for security.
When federation enters the picture, the attack surface explodes. A remote gateway can send your agent:
Instructions disguised as innocent questions to manipulate agent behavior
Requests that consume tokens, API quotas, or compute at scale
Messages designed to extract information your agent has privileged access to
High-volume messages that drown out legitimate requests
Resent old messages to trigger duplicate or unintended actions
Every OGP message carries an Ed25519 signature covering the canonical JSON serialization of all fields except the signature itself. The Doorman's first step is cryptographic verification:
Extract fromGatewayId from the message envelope
Retrieve the stored public key for that peer from the local peer registry
Verify the Ed25519 signature against the message bytes using the stored public key
Verify the message timestamp is within ±5 minutes of current time for replay protection
Ed25519 is fast, has small signatures (64 bytes), and doesn't require randomness during signing — which matters when your daemon is generating signatures under load.
OGP uses Node.js's built-in crypto.sign() with Ed25519 keys — native bindings to OpenSSL/LibreSSL are faster and better maintained than pure-JS alternatives.
The timestamp window (±5 min) is the primary defense. Nonces appear in the envelope but are used for reply correlation, not replay tracking. A seen-nonce cache is a future option for belt-and-suspenders deployments.
HTTPS provides transport encryption, but the Doorman verifies end-to-end message authenticity independent of TLS.
The signature still has to verify against a key you've already approved.
The signature still has to verify against a key you've already approved.
The signature still has to verify against a key you've already approved.
Authentication proves the message was signed by the key. It doesn't prove you want to talk to the owner of that key.
The Doorman maintains a peer registry — every gateway you've federated with, their public key, their current gateway URL, their alias, and their approval status. Before any message proceeds past authentication, the Doorman checks:
Is fromGatewayId in the peer registry?
Is the peer status approved? Not pending, not rejected, not removed.
When a peer is removed, we don't delete their record. We mark it as removed with a timestamp, and the federation state machine transitions the peer to a dedicated tombstoned lifecycle state.
This prevents a subtle attack: if Alice removes Bob, then Bob sends a new federation request from a fresh key, Alice might accidentally re-approve him thinking he's someone new. The tombstone preserves the "I already decided not to trust this person" signal, even across key changes.
Re-federation from a tombstoned peer creates a fresh init-state pending record — it doesn't silently reuse the old one.
This is where most authorization systems stop at "can this user access this endpoint?" OGP goes finer-grained: can this peer invoke this specific intent type?
Human-to-human relay
Agent-to-agent conversation
Request admission to a project
Add to a shared project
Query project state
Check project health
What the peer is allowed right now — checked on every message
What the peer will be granted — set at approval time
What the gateway can support — advertised via /.well-known/ogp
Even a fully trusted, fully scoped peer can misbehave — by accident or malice. A bug in their agent that loops and sends messages. A compromised gateway that gets hijacked. A well-meaning automation that runs too frequently.
Default: 100 requests per 3600 seconds per peer per intent
Configurable: --rate / at approve or grant time
Algorithm: Sliding window — keep a list of request timestamps, drop anything older than the window, count what remains
Response on breach: 429 Too Many Requests with Retry-After header
The rate limiter is stateful but lightweight. It maintains an in-memory Map<string, { timestamps: number[]; windowStart: number }> keyed by {peerId}:{intent}.
On every request, the timestamps array gets filtered to drop entries older than the window. If what's left is at the limit, the request is rejected with 429 and a calculated Retry-After based on when the oldest in-window request will age out.
This is the delegated authority layer. The Doorman doesn't just enforce security — it enforces behavioral policy. After a message passes authentication, trust, scope, and rate checks, the Doorman consults the agent-comms policy to determine delivery mode:
Message is not delivered to the agent at all. Agent never sees it.
Message is summarized before delivery. Reduces injection surface.
Agent handles it autonomously without human review.
Human sees the full raw message for complete transparency.
Putting it all together, the Doorman's checkAccess() method follows six precise steps:
403 unknown-peer or 403 not-approved
403 scope-violation with the offending intent type
429 rate-limited with Retry-After: N
Project-membership checks happen one layer up, in the intent handlers themselves, after checkAccess() returns. That separation matters:
The subtle one. Imagine Alice is federated with Bob for
messageintents. Bob's agent is compromised.
Alice is federated with Bob for message intents only. Bob's agent gets compromised.
Compromised Bob sends a project.query to Alice's gateway, claiming to query on behalf of Carol.
Alice's agent might process this — it trusts Bob, after all. Bob becomes a deputy for an unauthorized operation.
Bob was never granted project.query scope. Rejected at step 4 — before the agent ever sees the request.
The confused deputy problem is one of the oldest in computer security. A trusted entity is tricked or compromised into performing actions on behalf of an unauthorized party — using its own legitimate credentials.
In federated agent systems, this is especially dangerous because:
How does OGP's Doorman stack up against established security patterns?

Mutual TLS authenticates the connection. RBAC checks role permissions. Both are coarse-grained and assume a shared identity provider. OGP replaces the identity provider with Ed25519 keypairs and replaces RBAC roles with per-peer intent scopes — finer-grained, decentralized, no shared CA required.
These require a trusted authorization server. OGP intentionally avoids any third-party issuer. Peers authenticate each other directly using keypairs they control. Slower to bootstrap (bilateral handshake required) but eliminates a central point of compromise.
OGP's scope grants are essentially capabilities — "here is the set of things you are allowed to do." But unlike pure capability systems, OGP capabilities are revocable and auditable. The peer registry shows exactly who has what.
Across 25 test files covering signing canonicalization, agent-comms default-deny, scope grants, federation approval/preflight, peer tombstones, project membership, well-known peer-id authentication, and reply signature verification
Validating rejection paths across a realistic multi-gateway topology
Direct testing of confused deputy scenarios and edge cases
Code review by multiple contributors across all layers
For a personal agent gateway, this is solid. For a financial system processing billions, you'd want formal methods.
OGP is designed for the personal-to-small-team deployment tier, where "well-tested and carefully reviewed" is the right tradeoff against "mathematically proven."
The protocol is extensible — a future deployment could swap in a formally verified Doorman without changing the wire format.
Covering every enforcement layer
Across all Doorman components
Independent rejection chances
The Doorman is OGP's most important component — and the one most people overlook. Five layers of no means five independent chances to catch a mistake before it becomes a breach.
In a world where AI agents are gaining more access to more systems, that paranoia isn't excessive. It's the minimum.
Not because your peers are malicious — most aren't. But because your agent is trusting, your boundaries are personal, and "no" is the most important word in security.
OGP is open source and installable today:
npm install -g @dp-pcs/ogp@latest
ogp setup
ogp whoami # confirm identity & keypair
ogp start --background
ogp status # shows your gateway URLSource, spec, and docs all live at github.com/dp-pcs/ogp. If you install it and it breaks, file an issue. That's how this gets better.
Authentication — Ed25519 signature verification
Peer Trust — bilateral approval registry
Scope Enforcement — per-peer intent grants
Rate Limiting — sliding window per peer/intent
Agent-Comms Policy — behavioral delivery control
Five Layers of No: How OGP's Doorman Actually Works