ZCore LogoZCore
How to

How to mask sensitive fields dynamically

Use Zchema to automatically prune fields from API responses, sanitize inputs, and mask OpenAPI schemas.

Instead of maintaining separate Pydantic models for public, user, and admin views (e.g., TaskPublic, TaskAdmin), ZCore provides dynamic, role-aware projection via Zchema.

1. Bind Schema to a Domain

Inherit from Zchema and set the __model__ class attribute to your domain identifier:

# schemas.py
import uuid
from zcore import Zchema
from pydantic import ConfigDict

class TaskResponse(Zchema):
    __model__ = "tasks"  # Binds this schema to the 'tasks' domain
    
    id: uuid.UUID
    title: str
    salary: float        # Sensitive field!
    
    model_config = ConfigDict(from_attributes=True)

2. Guest-Level Masking with __private__

If certain fields must never be exposed to unauthenticated public visitors (guests), declare them directly in the __private__ class variable:

# schemas.py
import uuid
from zcore import Zchema
from pydantic import ConfigDict

class TaskResponse(Zchema):
    __model__ = "tasks"
    __private__ = {"internal_notes", "cost_price"}  # Stripped for unauthenticated visitors

    id: uuid.UUID
    title: str
    salary: float
    cost_price: float = 0.0
    internal_notes: str | None = None

    model_config = ConfigDict(from_attributes=True)

When an unauthenticated request hits the endpoint (ctx.user_id is None), ZCore automatically purges these fields from response serialization, input validation, and dynamic OpenAPI schema generation without requiring active context lookups.

3. Set Restrictions in Context

During your authentication flow (or inside BaseAuth), load the active user's restricted paths into ctx.restricted_fields:

from zcore import ctx

# Mask 'salary' specifically on view/GET requests for the 'tasks' domain
ctx.restricted_fields = ["tasks.view.salary"]

4. Automatic Response Pruning

When your endpoint returns a TaskResponse model or dictionary, Zchema intercepts serialization and removes restricted keys:

// Normal Output (Admin)
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "title": "Build Architecture",
  "salary": 120000.0
}

// Filtered Output (Restricted User)
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "title": "Build Architecture"
  // 'salary' is pruned automatically!
}

Restriction Path Syntax

PatternExampleEffect
<domain>.<action>.<field>tasks.view.salaryPrunes salary only on view (GET) actions.
<domain>.<field>tasks.salaryGlobally prunes salary across all actions (create, update, view).
<domain>.<action>.<nested.path>tasks.view.author.emailRecursively traverses dicts/lists to prune email.
<domain>.<action>tasks.viewMasks the entire model representation (*).

Bidirectional Protection & CDN Safety:

  • Input Sanitization (Mass Assignment): Zchema also filters incoming input payloads, silently dropping restricted fields before they reach your database services.
  • Cache Protection (Vary Header): When fields are pruned, ZCore automatically appends Vary: Authorization, Cookie to HTTP response headers to prevent intermediate proxies or CDN caches from serving masked data to authorized users.

On this page