# Send a hash. Block everything else.

Register operations in your CI/CD pipeline. Clients send a SHA-256 hash instead of the full operation body. The router validates hashes against the CDN-backed registry and rejects anything not on the list.

## The problem

### Production GraphQL without an operation registry

Any valid operation can run. Clients send full query bodies every time. There is no record of what was executed or by whom.

### Full query bodies waste bandwidth

Every request carries the complete operation text. A complex query can run several kilobytes per call, multiplied across every client and every request.

### Any valid GraphQL operation can execute

Without a registration mechanism, clients can run arbitrary operations against your graph—including expensive or malicious ones you never intended to expose.

### No audit trail for client operations

You cannot track which operations each client application sends, what changed between releases, or who registered what. Compliance and debugging both suffer.

## Our solution

### Register once, hash forever

Operations are registered in CI/CD and stored on the Cosmo CDN. Routers fetch them from the CDN at runtime. Clients send only the hash—never the full body again after the first registration.

### How it works end to end

1. Operations are pushed to the control plane with `wgc operations push` during CI/CD. Each operation is identified by its SHA-256 hash.
2. The control plane stores operations and replicates them to the Cosmo CDN.
3. Routers fetch registered operations from the CDN at runtime—per request by default, or all at once into memory at startup when the PQL manifest is enabled. No database connection required.
4. Clients send a hash identifier instead of the full operation body. The router validates the hash and executes the stored operation.
5. Enforcement is configurable: log unknown operations, allow operations matching a registered body (safelist), or block all unregistered hashes.
6. Client-specific namespacing is available via the `graphql-client-name` header, enabling per-app operation sets.

## Before & After

| Before Cosmo | With Cosmo |
| --- | --- |
| Full query body sent with every request | SHA-256 hash transmitted after initial registration |
| Any arbitrary operation can execute in production | Only registered operations allowed when blocking is enabled |
| No record of which operations clients use | Audit trail of registered operations per client application |
| No way to block unauthorized queries at the edge | Router rejects unregistered hashes with a clear error |

### Three modes for incremental rollout

`Log-only`

Log unknown operations without blocking. Observe traffic before enforcing.

`Safelist`

Allow operations whose body matches a registered one, even without the hash.

`Full blocking`

Reject all requests that do not carry a registered hash. Set `security.block_non_persisted_operations.enabled: true`.

## How Persisted Operations work in Cosmo

01

### Register

Run `wgc operations push` in your CI/CD pipeline. The CLI sends operations to the control plane, which assigns each one a SHA-256 hash and stores it.

02

### Replicate

The control plane replicates operations to the Cosmo CDN. Routers fetch operations from the CDN—per request by default, or all at once at startup with the PQL manifest enabled. No runtime database calls.

03

### Validate

The router checks each incoming hash against registered operations. If the hash is found, the stored operation executes. If not, the response depends on the enforcement mode.

04

### Enforce

Three modes: log-only (track unknown operations without blocking), safelist (allow operations whose body matches a registered one), or full blocking (reject all unregistered hashes).

## Capabilities

### Registration, enforcement, and audit

One registry for all clients. Three enforcement modes. Full audit trail.

### CDN-backed operation storage

Registered operations are stored on the Cosmo CDN. Runtime validation requires no database call. Enable the PQL manifest to load all operations into memory at startup and drop per-request CDN fetches.

### Client namespacing

Associate operations with specific client applications using the `graphql-client-name` request header. Each client can have its own operation set.

### Three enforcement modes

Start with log-only to observe traffic, move to safelist to allow matching bodies, then enable full blocking once all clients are migrated.

### CI/CD integration

Push operations during your release pipeline with `wgc operations push`. JSON output is available for custom tooling. Works with GitHub Actions, GitLab CI, and any other pipeline.

## Lock down your production graph

Push operations from CI/CD. Clients send hashes. Block everything else with one config flag.

## FAQ

### Persisted Operations on Cosmo Router

- How do I register operations?
- Can I use persisted operations without blocking unregistered ones?
- How is the operation hash computed?
- Can different clients use different operation sets?
- What happens when a client sends an unregistered hash in blocking mode?
- Can I migrate incrementally without breaking existing clients?

Full details in the [persisted operations documentation](https://cosmo-docs.wundergraph.com/router/persisted-queries/persisted-operations).
