Five Layers of No: How OGP's Doorman Actually Works
Every inbound message gets five independent chances to be rejected. Here's why that's a feature — and why you should steal this design.
Framework
Security
David Proctor · Apr 28, 2026
The Problem: Your Agent Is a Trusting Beast
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:
🎭 Disguised Instructions
Instructions disguised as innocent questions to manipulate agent behavior
💸 Resource Drain
Requests that consume tokens, API quotas, or compute at scale
🕵️ Data Extraction
Messages designed to extract information your agent has privileged access to
🌊 Flood Traffic
High-volume messages that drown out legitimate requests
🔁 Replay Attacks
Resent old messages to trigger duplicate or unintended actions

The agent will handle all of these helpfully unless something stops it. That something is the Doorman.
Layer 1: Authentication
Layer 1 of 5
Question: Did this message actually come from who it claims to come from?
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:
01
Parse Gateway ID
Extract fromGatewayId from the message envelope
02
Key Lookup
Retrieve the stored public key for that peer from the local peer registry
03
Signature Verify
Verify the Ed25519 signature against the message bytes using the stored public key
04
Timestamp Check
Verify the message timestamp is within ±5 minutes of current time for replay protection
Why Ed25519?
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.

Replay Protection
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.
The Key Insight: Authentication Doesn't Trust the Network
HTTPS provides transport encryption, but the Doorman verifies end-to-end message authenticity independent of TLS.
If nginx misconfigures a proxy header…
The signature still has to verify against a key you've already approved.
If a load balancer strips a token…
The signature still has to verify against a key you've already approved.
If a man-in-the-middle compromises the TLS session…
The signature still has to verify against a key you've already approved.

Transport can fail. Application-layer authentication must not.
Layer 2: Peer Trust
Layer 2 of 5
Question: Do I even talk to this gateway?
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:
1
Registry Check
Is fromGatewayId in the peer registry?
2
Status Check
Is the peer status approved? Not pending, not rejected, not removed.

Even a cryptographically valid message from an unknown or unapproved peer gets a hard 403.
Tombstones Matter
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.
Layer 3: Scope Enforcement
Layer 3 of 5
Question: Even if I trust this peer, did they ask for something I said they could ask for?
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?
Default Scope Bundle
message
Human-to-human relay
agent-comms
Agent-to-agent conversation
project.join
Request admission to a project
project.contribute
Add to a shared project
project.query
Query project state
project.status
Check project health
Three-Layer Scope Model
1
2
3
1
Runtime Enforcement
What the peer is allowed right now — checked on every message
2
Peer Negotiation
What the peer will be granted — set at approval time
3
Gateway Capabilities
What the gateway can support — advertised via /.well-known/ogp

The Doorman always enforces the most restrictive applicable layer. Capabilities can be broader than grants. Grants can be broader than runtime enforcement.
Layer 4: Rate Limiting
Layer 4 of 5
Question: Is this peer being polite?
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.
Rate Limiter Specs
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
Implementation Details
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.

On daemon restart, limits reset — a deliberate tradeoff for simplicity. For production deployments, the store could be backed by Redis, but the default is designed for personal gateways where "restart and reset" is acceptable.
Layer 5: Agent-Comms Policy
Layer 5 of 5
Question: Even if the message passes all security checks, how should my agent handle it?
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:
off
Message is not delivered to the agent at all. Agent never sees it.
summary
Message is summarized before delivery. Reduces injection surface.
escalate
Agent handles it autonomously without human review.
full
Human sees the full raw message for complete transparency.

If the policy says off, the agent literally never sees the message — and can't be prompt-injected, socially engineered, or otherwise manipulated by it.
The 6-Step Validation Algorithm
Putting it all together, the Doorman's checkAccess() method follows six precise steps:
Rejection Codes
Steps 1–2 fail
403 unknown-peer or 403 not-approved
Steps 3–5 fail
403 scope-violation with the offending intent type
Step 6 fails
429 rate-limited with Retry-After: N
Separation of Concerns
Project-membership checks happen one layer up, in the intent handlers themselves, after checkAccess() returns. That separation matters:
  • The Doorman is responsible for whether you can speak this intent at all
  • The handler is responsible for whether the specific resource you're asking about exists and includes you
  • Different questions → different answers → different return codes

All rejections are cryptographically signed, so the sending gateway can verify the rejection is authentic and surface actionable feedback to its human.
Why Six Steps? Each Catches a Different Threat
Steps 1–2: Peer Trust
  • Unknown actors sending forged or unsolicited messages
  • Replay attacks using old captured requests
  • Removed peers attempting to reconnect with fresh credentials
Steps 3–5: Scope Enforcement
  • Overreach by approved peers exceeding their granted permissions
  • Project membership leakage across federation boundaries
  • Confused deputy attacks where a trusted peer is compromised and used as a proxy
Step 6: Rate Limiting
  • Accidental loops in peer agents generating runaway traffic
  • Compromised trusted peers being weaponized
  • DDoS from otherwise legitimate, approved sources
The Confused Deputy Attack
The subtle one. Imagine Alice is federated with Bob for message intents. Bob's agent is compromised.
The Attack Scenario
01
Bob is Compromised
Alice is federated with Bob for message intents only. Bob's agent gets compromised.
02
Unauthorized Request
Compromised Bob sends a project.query to Alice's gateway, claiming to query on behalf of Carol.
03
Without Scope Enforcement
Alice's agent might process this — it trusts Bob, after all. Bob becomes a deputy for an unauthorized operation.
04
With the Doorman
Bob was never granted project.query scope. Rejected at step 4 — before the agent ever sees the request.
Why This Matters
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:
  • Agents are designed to be helpful and act on requests
  • Trust relationships are transitive in naive implementations
  • The compromised peer has real, valid credentials
  • The attack looks like legitimate traffic from a trusted source

Scope enforcement at the intent level — not just the peer level — is the only reliable defense against confused deputy attacks in federated systems.
Comparison to Alternatives
How does OGP's Doorman stack up against established security patterns?
mTLS + RBAC
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.
OAuth 2.0 / OIDC
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.
Capability-Based Security
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.
The Honest Limitation

The Doorman is not formally verified. There is no TLA+ model or Coq proof that checkAccess() is correct.
What We Have Instead
198-Test Suite
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
Three-Node Mesh Test
Validating rejection paths across a realistic multi-gateway topology
Empirical Testing
Direct testing of confused deputy scenarios and edge cases
Multi-Contributor Review
Code review by multiple contributors across all layers
The Right Tradeoff
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.

198
Tests
Covering every enforcement layer
25
Test Files
Across all Doorman components
5
Layers
Independent rejection chances
Bottom Line
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.
If you're building federated agent infrastructure, you need something like the Doorman.
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.

How to Try It
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 URL
Source, 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.
Layer 1
Authentication — Ed25519 signature verification
Layer 2
Peer Trust — bilateral approval registry
Layer 3
Scope Enforcement — per-peer intent grants
Layer 4
Rate Limiting — sliding window per peer/intent
Layer 5
Agent-Comms Policy — behavioral delivery control

David Proctor is VP of AI at Trilogy. The Doorman ships with every OGP installation. Read the source in src/daemon/doorman.ts or install it: npm install -g @dp-pcs/ogp