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.

FrameworkSecurityDavid 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

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.

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.

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

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.

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.

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

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

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

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