Skip to content

Privacy Guard architecture

Privacy Guard is OpenShell middleware that detects and optionally replaces sensitive entities in provider-bound HTTP request text before OpenShell adds provider credentials.

This architecture is a clean break from the earlier implementation. A processor run receives one UTF-8 text value and invokes an ordered pipeline of entity-processing engines. Structured-body parsing and compatibility with the previous extension and policy APIs are intentionally out of scope.

Privacy Guard can allow the original body, allow a replacement body, or deny the request. It never sends the provider request itself.

Where Privacy Guard runs

Sandbox process
      |
      | provider-bound HTTP request
      v
OpenShell supervisor
      |
      | gRPC: SupervisorMiddleware
      v
Privacy Guard
      |
      | allow original body, allow replacement body, or deny
      v
OpenShell supervisor
      |
      | credentials added only after middleware allows
      v
Provider

Privacy Guard implements the OpenShell-owned SupervisorMiddleware gRPC service and advertises one HTTP-request binding in the pre-credentials phase. The checked-in protocol and generated bindings are canonical copies from OpenShell and must not be edited locally.

Component boundaries

Source paths on these pages are relative to projects/privacy-guard/src/privacy_guard/.

  • service/ owns gRPC, protobuf conversion, UTF-8 decoding and encoding, bounded worker scheduling, active-processor preparation and replacement, and finding serialization. Outside generated bindings/, no other package imports gRPC or generated bindings.
  • cli.py owns command parsing, registry-factory loading, engine discovery, configuration-schema output, logging options, and the adapter that starts the programmatic server. Top-level logging.py provides the shared, standard-library logging configuration used by the CLI and available to programmatic deployments.
  • request_processor.py runs configured stages over one text value, shares one timeout across them, aggregates detections, and applies the user-facing policy action. It does not import gRPC or implement an engine's algorithms.
  • engines/ defines the custom-engine contract, registers engine implementations and operator-owned resources, builds the exact Pydantic discriminated union, and contains the built-in Regex and resource-backed NER implementations. Each engine owns its detection and replacement algorithms.
  • config.py defines ordered stages and the required policy action.
  • top-level base.py defines the package-wide strict immutable domain-model base.
  • string_validators.py defines shared string validators and field types.

The OpenShell policy is the single source of privacy behavior: stage order, each stage's exact engine configuration, entity definitions, replacement recipes, and the final detect, block, or replace action. Deployment configuration registers implementations and injects operational resources such as model profiles, endpoints, clients, and credentials.

Request flow

HttpRequestEvaluation protobuf
        |
        v
PrivacyGuardMiddleware
  validates phase and body size
  validates and normalizes policy configuration
  reuses the matching active RequestProcessor or prepares and activates
  a replacement
  decodes a non-empty body as strict UTF-8
        |
        v
RequestProcessor.process(text)
  derives DETECT or REPLACE engine strategy
  creates one shared Timeout
        |
        v
stage 1 engine.run(current text)
        |
        v
stage 2 engine.run(stage 1 text)
        |
       ...
        |
        v
RequestProcessor
  aggregates stage-qualified detections
  applies detect, block, or replace
        |
        v
RequestProcessingResult
        |
        v
PrivacyGuardMiddleware
  serializes bounded findings
  encodes replacement text only for replace
        |
        v
HttpRequestResult protobuf

The processor passes only EntityProcessingStrategy.DETECT or EntityProcessingStrategy.REPLACE to engines. Blocking is a request disposition and never crosses the engine boundary.

The processor is synchronous. The service runs it in a dedicated thread pool so engine work does not block the gRPC event loop.

Core data types

Type Meaning
PrivacyGuardConfig Ordered entity-processing stages and the required action on detection
EntityProcessingStage One configured engine invocation with an optional diagnostic name
EngineConfig Nominal strict base for an engine's exact policy configuration
EntityProcessingStrategy Per-run engine selection: detect or replace
EntityDetection One occurrence with stage-input offsets and optional confidence
TextProcessingResult One engine's authoritative output text and detections
Timeout One monotonic deadline shared across all stages
EntityDetectionSummary Bounded stage/entity/confidence aggregate for audit output
RequestProcessingResult Allow or deny decision, detection summaries, and replacement text when requested

Pydantic domain models are strict, frozen, reject unknown fields, hide rejected input from validation errors, and suppress sensitive fields from normal representations.

Deliberate omissions

  • Cross-request entity memory is not part of v0.
  • Engines do not receive transport metadata or the user-facing policy action.
  • There is no parallel execution-plan model; preparation constructs a RequestProcessor directly.
  • There is no generic replacement field or replacement-strategy enum. Each engine owns any replacement settings appropriate to its underlying algorithm.
  • Regex catalogs may be supplied inline or as bounded relative YAML paths beneath Privacy Guard's working directory.