Compliance ยท Advanced Data Privacy

Mask sensitive GraphQL fields by role, without touching subgraphs

Cosmo Router Custom Modules let you intercept and obfuscate GraphQL response fields at the router level. Different users see different data. No subgraph code changes.

Written in Go. Field-level. Applied per request.

Available onProEnterprise

The problem

The same API serves users who should see different data

Field-level access control is real work. Doing it in every subgraph is fragile and expensive to maintain.

Different users need different data visibility

A developer debugging a query should not see real customer names or payment data. A data scientist needs realistic data shapes but not the actual PII. The same API serves both.

Subgraph-level masking requires code changes everywhere

Adding field-level obfuscation in each subgraph means touching every service, syncing release cycles, and maintaining that logic as schemas evolve.

AI systems should not read sensitive fields

When GraphQL APIs are exposed to AI models or third-party systems, fields like SSNs, credit card numbers, and medical data must be protected without duplicating the API.

Our solution

Field-level obfuscation at the router

A Custom Module intercepts GraphQL response data before it reaches the client. The renderer replaces field values based on user role or request context. Subgraphs are unaware of the transformation.

How it works

  1. Implement a `CustomFieldValueRenderer` interface in a Cosmo Router Custom Module, written in Go.

  2. The renderer receives each field value with its GraphQL type (String, Int, Float, or custom) and can transform or replace it.

  3. Use the `RouterOnRequest` hook to select different renderers based on authentication claims, user roles, or request headers.

  4. A developer with the "developer" role gets all String fields replaced with "xxx" and numeric fields with placeholders, preserving the response structure.

  5. An AI system identified by a specific header receives placeholder values for any field marked sensitive, while the rest of the response is unaffected.

  6. No subgraph code changes are required. The obfuscation layer lives entirely at the router.

One renderer per role. Zero subgraph changes.

Advanced data privacy

Before & After

Before CosmoWith Cosmo
Data masking implemented separately in each subgraphCentralized obfuscation at the router, applied to all subgraphs
Complex authorization logic in every resolverRole-based obfuscation via authentication claims and request context
Separate data pipelines for AI and analytics accessSame API with dynamic field filtering per request context
Code changes required to add or change privacy rulesCustom Module update without touching subgraph implementations

Custom renderer

Field value renderer interface

func (c *CustomValueRenderer) RenderFieldValue(
  ctx *resolve.Context,
  value resolve.FieldValue,
  out io.Writer,
) error {
  switch value.Type {
  case "String":
    _, err = out.Write([]byte(`"xxx"`))
  case "Int", "Float":
    _, err = out.Write([]byte(`123`))
  default:
    _, err = out.Write(value.Data)
  }
  return err
}

How field-level obfuscation works in Cosmo Router

01
Before the client sees it.

Intercept

The router processes the GraphQL response from subgraphs before sending it to the client. The Custom Module intercepts each field value at this point.

02
Per-request renderer selection.

Identify

The `RouterOnRequest` hook reads authentication claims, user roles, or request headers to determine which renderer to apply for this request.

03
Field-level, type-aware.

Transform

The `CustomFieldValueRenderer` receives each field with its type information and writes the obfuscated value. String fields become "xxx"; numeric fields become placeholder values.

04
Structure intact. Values masked.

Return

The client receives a structurally complete response. Types, field names, and nesting are preserved. Only the values that match the obfuscation rules are replaced.

Privacy capabilities

Fine-grained control at the gateway

One control point. Every subgraph behind it gets the same protection.

Centralized privacy control

Implement obfuscation once at the router. All subgraphs behind it inherit the protection without any code changes.

Role-based obfuscation

Apply different rendering rules per request based on authentication claims, user roles, or any request context your Custom Module can read.

AI-safe API access

Protect sensitive fields when exposing your GraphQL API to AI models or third-party integrations. The model gets realistic response shapes with placeholders for protected fields.

No subgraph changes

Add, change, or remove privacy rules by updating the Custom Module. Subgraph code and schemas stay untouched.

Add field-level privacy to your GraphQL API

Implement a Custom Module renderer. Apply it at the router. Subgraphs stay unchanged.

FAQ

Advanced data privacy on Cosmo Router

Full implementation guide in the advanced data privacy documentation.