operations tier

operations-dlp-sensor

Host DLP sensors: OS-specific text sources (clipboard, keyboard/evdev, PTY) behind a testable TextSource seam, feeding infrastructure-dlp-detect and emitting masked DlpFindingEnvelopes via infrastructure-dlp. Masked-only by default; the raw-capture path is behind the `raw-capture` feature.

Host DLP sensors: OS-specific text sources (clipboard, keyboard/evdev, PTY) behind a testable TextSource seam, feeding infrastructure-dlp-detect and emitting masked DlpFindingEnvelopes via infrastructure-dlp. Masked-only by default; the raw-capture path is behind the `raw-capture` feature.

Tieroperations
Roleunclassified (baselined)
Pathcrates/operations/dlp-sensor
Edition2021
Targetsclipboard_verify, keyboard_verify, pty_verify, screen_ocr_demo, operations_dlp_sensor, screen_pipeline
Public items31 across 6 modules
Tests12

What it is for

operations-dlp-sensor — host DLP sensors.

OS-specific text sources implement the source::TextSource seam; the pipeline runs each chunk through infrastructure_dlp_detect and emits masked infrastructure_dlp::DlpFindingEnvelopes. Masked-only by default; the raw path is behind the raw-capture feature.

The detector set follows infrastructure-dlp-detect policy defaults — it grew in Sprint 3.6 to include the secret-material classes (api-key, private-key, JWT, email, high-entropy secret) alongside the original PII classes. See pipeline::scan_chunk for how to pin or narrow it.

Sources (feature-gated so a minimal build pulls no OS deps):

Capabilities

ClipboardSource

Clipboard text source (feature clipboard, via arboard; X11/Wayland).

Item
pub struct ClipboardSource
ClipboardSource :: fn new() -> Result <Self, arboard::Error>
ClipboardSource :: fn with_poll_interval(mut self, d : Duration) -> Self
ClipboardSource :: fn read_new(& mut self) -> Option <String>
ClipboardSource :: fn next_chunk(& mut self) -> Option <String>

keyboard (other)

Physical-keyboard text source (feature keyboard, Linux evdev).

Item
pub const MAX_FIELD: usize

KeyboardSource

Physical-keyboard text source (feature keyboard, Linux evdev).

Item
pub struct KeyboardSource
KeyboardSource :: fn from_path <P : AsRef <Path>>(path : P) -> io::Result <Self>
KeyboardSource :: fn first_keyboard() -> io::Result <Self>
KeyboardSource :: fn next_chunk(& mut self) -> Option <String>

SensorCtx

The scan pipeline: text chunk → detector → masked envelopes.

Item
pub struct SensorCtx<'a>
fn scan_chunk(text : & str, ctx : & SensorCtx <'_>, seq : u64, mut mint : impl FnMut() ->(String, i64),) -> Vec <DlpFindingEnvelope>
fn run <S, M, E>(mut source : S, ctx : & SensorCtx <'_>, mut mint : M, mut emit : E) -> u64 where S : TextSource, M : FnMut() ->(String, i64), E : FnMut(DlpFindingEnvelope),
fn run_with_raw <S, M, E, R>(mut source : S, ctx : & SensorCtx <'_>, mut mint : M, mut emit : E, mut emit_raw : R,) -> u64 where S : TextSource, M : FnMut() ->(String, i64), E : FnMut(DlpFindingEnvelope), R : FnMut(infrastructure_dlp::capture::RawCapture),

LineSource

PTY / line-oriented text source (T9).

Item
pub struct LineSource<R : Read>

LineSource<R>

PTY / line-oriented text source (T9).

Item
LineSource<R> :: fn new(reader : R) -> Self
LineSource<R> :: fn next_chunk(& mut self) -> Option <String>

PtySession

PTY / line-oriented text source (T9).

Item
pub struct PtySession
fn run_under_pty(argv : & & str) -> std::io::Result <PtySession>

screen (other)

Screen-capture + OCR text source (feature screen).

Item
pub const DEFAULT_INTERVAL: Duration

ScreenOcrSource

Screen-capture + OCR text source (feature screen).

Item
pub struct ScreenOcrSource<E : LocalOcrEngine>

ScreenOcrSource<E>

Screen-capture + OCR text source (feature screen).

Item
ScreenOcrSource<E> :: fn new(engine : E) -> std::io::Result <Self>
ScreenOcrSource<E> :: fn with_interval(mut self, interval : Duration) -> Self
ScreenOcrSource<E> :: fn with_max_frames(mut self, n : u64) -> Self
ScreenOcrSource<E> :: fn with_capture(mut self, f : impl FnMut() -> Result <SensitiveFrame, CaptureError> + Send + 'static,) -> Self
ScreenOcrSource<E> :: fn next_chunk(& mut self) -> Option <String>

source (other)

The TextSource seam — the single interface every sensor implements so the

Item
fn chunk_hash(s : & str) -> u64

FixtureSource

The TextSource seam — the single interface every sensor implements so the

Item
pub struct FixtureSource
FixtureSource :: fn new(chunks : Vec <String>) -> Self
FixtureSource :: fn next_chunk(& mut self) -> Option <String>

TextSource

The TextSource seam — the single interface every sensor implements so the

Item
pub trait TextSource

How to use it

From `examples/clipboard_verify.rs`:


use infrastructure_dlp::capture::CaptureMode;
use infrastructure_dlp::envelope::Source;
use operations_dlp_sensor::clipboard::ClipboardSource;
use operations_dlp_sensor::pipeline::{scan_chunk, SensorCtx};

fn main() {
    let mut cb = ClipboardSource::new().expect("open clipboard (need DISPLAY)");
    let Some(text) = cb.read_new() else {
        println!("clipboard empty/unchanged — nothing to scan");
        return;
    };

    let ctx = SensorCtx {
        tenant_id: "verify".into(),
        device_id: "host".into(),
        source: Source::Clipboard,
        capture_mode: CaptureMode::MaskedOnly,

From `examples/keyboard_verify.rs`:


use std::thread;
use std::time::Duration;

use evdev::uinput::VirtualDeviceBuilder;
use evdev::{AttributeSet, EventType, InputEvent, Key};

use infrastructure_dlp::capture::CaptureMode;
use infrastructure_dlp::envelope::Source;
use operations_dlp_sensor::keyboard::KeyboardSource;
use operations_dlp_sensor::pipeline::{scan_chunk, SensorCtx};
use operations_dlp_sensor::TextSource;

fn key_for(c: char) -> Key {
    match c {
        '0' => Key::KEY_0,
        '1' => Key::KEY_1,
        '2' => Key::KEY_2,

Module structure

operations_dlp_sensor

flowchart TD
  n_operations_dlp_sensor["operations_dlp_sensor"]
  n_operations_dlp_sensor --> n_clipboard["clipboard"]
  n_operations_dlp_sensor --> n_keyboard["keyboard"]
  n_operations_dlp_sensor --> n_pipeline["pipeline"]
  n_operations_dlp_sensor --> n_pty["pty"]
  n_operations_dlp_sensor --> n_screen["screen"]
  n_operations_dlp_sensor --> n_source["source"]

Public surface

`clipboard`

ItemWhat it is
pub struct ClipboardSourcePolls the OS clipboard and yields newly-observed non-empty text.
ClipboardSource :: fn new() -> Result <Self, arboard::Error>Open the OS clipboard
ClipboardSource :: fn with_poll_interval(mut self, d : Duration) -> SelfOverride the poll interval used by TextSource::next_chunk.
ClipboardSource :: fn read_new(& mut self) -> Option <String>Non-blocking single check: Some(text) if the clipboard holds new, non-empty text since the last observed content, else None
ClipboardSource :: fn next_chunk(& mut self) -> Option <String>

`keyboard`

ItemWhat it is
pub const MAX_FIELD: usizeMax characters buffered for one field before older input is dropped.
pub struct KeyboardSourceReads one keyboard device and yields completed fields as text chunks.
KeyboardSource :: fn from_path <P : AsRef <Path>>(path : P) -> io::Result <Self>Open a specific input device (e.g
KeyboardSource :: fn first_keyboard() -> io::Result <Self>Open the first keyboard-like device (supports KEY_ENTER and KEY_A).
KeyboardSource :: fn next_chunk(& mut self) -> Option <String>

`pipeline`

ItemWhat it is
pub struct SensorCtx<'a>Per-run context supplied by the host
fn scan_chunk(text : & str, ctx : & SensorCtx <'_>, seq : u64, mut mint : impl FnMut() ->(String, i64),) -> Vec <DlpFindingEnvelope>Scan one text chunk and build masked envelopes
fn run <S, M, E>(mut source : S, ctx : & SensorCtx <'_>, mut mint : M, mut emit : E) -> u64 where S : TextSource, M : FnMut() ->(String, i64), E : FnMut(DlpFindingEnvelope),Drive a TextSource to exhaustion, invoking emit for every masked envelope
fn run_with_raw <S, M, E, R>(mut source : S, ctx : & SensorCtx <'_>, mut mint : M, mut emit : E, mut emit_raw : R,) -> u64 where S : TextSource, M : FnMut() ->(String, i64), E : FnMut(DlpFindingEnvelope), R : FnMut(infrastructure_dlp::capture::RawCapture),Like run, but under CaptureMode::Raw it ALSO hands each raw chunk to emit_raw as a infrastructure_dlp::capture::RawCapture (feature raw-capture)

`pty`

ItemWhat it is
pub struct LineSource<R : Read>Yields non-empty, newline-delimited chunks from any reader.
LineSource<R> :: fn new(reader : R) -> SelfWrap a reader (a PTY master, a pipe, or a test cursor).
LineSource<R> :: fn next_chunk(& mut self) -> Option <String>
pub struct PtySessionA running child plus a LineSource over its PTY output (feature pty).
fn run_under_pty(argv : & & str) -> std::io::Result <PtySession>Run argv under a real pseudo-terminal and return a PtySession whose output yields the session's lines for scanning (feature pty).

`screen`

ItemWhat it is
pub const DEFAULT_INTERVAL: DurationDefault interval between screen captures.
pub struct ScreenOcrSource<E : LocalOcrEngine>A screen-capture + local-OCR TextSource.
ScreenOcrSource<E> :: fn new(engine : E) -> std::io::Result <Self>Build a source that captures the primary monitor with the given local engine
ScreenOcrSource<E> :: fn with_interval(mut self, interval : Duration) -> SelfSet the capture interval (0 = capture as fast as possible).
ScreenOcrSource<E> :: fn with_max_frames(mut self, n : u64) -> SelfStop after n captures (unbounded by default)
ScreenOcrSource<E> :: fn with_capture(mut self, f : impl FnMut() -> Result <SensitiveFrame, CaptureError> + Send + 'static,) -> SelfInject a custom capture function (tests, or a non-primary monitor).
ScreenOcrSource<E> :: fn next_chunk(& mut self) -> Option <String>

`source`

ItemWhat it is
pub trait TextSourceA source of scannable text chunks (one clipboard paste, one typed field, one PTY line, …)
pub struct FixtureSourceIn-memory source for unit tests — yields preset chunks, no I/O
FixtureSource :: fn new(chunks : Vec <String>) -> SelfBuild from a list of chunks.
FixtureSource :: fn next_chunk(& mut self) -> Option <String>
fn chunk_hash(s : & str) -> u64Stable non-storing dedup helper: a 64-bit hash of a chunk, so a source can skip re-emitting identical content without retaining the text itself (R5).

Re-exports. Exported here, defined elsewhere.

ExportDefined in
ScreenOcrSourcescreen::ScreenOcrSource
{FixtureSource,TextSource}source::{FixtureSource,TextSource}
{scan_chunk,SensorCtx}pipeline::{scan_chunk,SensorCtx}

Boundary

Reaches into infrastructure.

Shares tier operations with 40 other crates: operations-approval-workflow, operations-assessments, operations-block-imaging, operations-boot-media, operations-browser-agent-worker, operations-camera-discovery, operations-camera-liveview, operations-camera-registry, … (40 total).

_What this crate deliberately does NOT own is a judgment. No committed registry records one for it, so none is stated here._

Where it sits

Tier (ontology)operations
Architectural role (taxonomy)unclassified (baselined)
Locationcrates/operations/dlp-sensor
Vocabulary in force (lexicon)current

Tier flow. Which tiers this crate's own edges cross.

flowchart LR
  n_operations["operations"] --> n_infrastructure["infrastructure"]

Dependencies

Runtime, in this workspace.

CrateTierOptionalOnly on
`infrastructure-dlp`infrastructurenoalways
`infrastructure-dlp-detect`infrastructurenoalways
`infrastructure-ocr-engine`infrastructureyesalways
`infrastructure-screen-capture`infrastructureyesalways

Runtime, from outside the workspace.

CrateRequirementFeaturesOptionalOnly on
arboard^3yesalways
evdev^0.12yesalways
portable-pty^0.8yesalways
tokio^1full, rt, process, io-util, timeyesalways

Development, in this workspace.

CrateTierOptionalOnly on
`infrastructure-dlp-detect`infrastructurenoalways
`infrastructure-ocr-tesseract`infrastructurenoalways

Development, from outside the workspace.

CrateRequirementFeaturesOptionalOnly on
async-trait^0.1noalways
image^0.25pngnoalways
serde_json^1noalways

Build. None.

Depended on by. 1 workspace crate.

Signal flow — what reaches this crate, and what it reaches.

flowchart LR
  n_operations_dlp_agent["operations-dlp-agent"] -->|uses| SELF
  SELF["operations-dlp-sensor"]
  SELF -->|development| n_infrastructure_dlp_detect["infrastructure-dlp-detect"]
  SELF -->|development| n_infrastructure_ocr_tesseract["infrastructure-ocr-tesseract"]
  SELF -->|runtime| n_infrastructure_dlp["infrastructure-dlp"]
  SELF -->|runtime| n_infrastructure_dlp_detect["infrastructure-dlp-detect"]
  SELF -->|runtime| n_infrastructure_ocr_engine["infrastructure-ocr-engine"]
  SELF -->|runtime| n_infrastructure_screen_capture["infrastructure-screen-capture"]
  classDef self fill:#1f883d,stroke:#1f883d,color:#fff;
  class SELF self;

Feature flags

FeatureEnablesOn by default
clipboarddep:arboardyes
defaultclipboardyes
keyboarddep:evdevno
ptydep:portable-ptyno
raw-captureno
screendep:infrastructure-screen-capture, dep:infrastructure-ocr-engine, dep:tokiono
flowchart LR
  n_clipboard["clipboard"] --> n_dep_arboard["dep:arboard"]
  n_default["default"] --> n_clipboard["clipboard"]
  n_keyboard["keyboard"] --> n_dep_evdev["dep:evdev"]
  n_pty["pty"] --> n_dep_portable_pty["dep:portable-pty"]
  n_raw_capture["raw-capture"]
  n_screen["screen"] --> n_dep_infrastructure_screen_capture["dep:infrastructure-screen-capture"]
  n_screen["screen"] --> n_dep_infrastructure_ocr_engine["dep:infrastructure-ocr-engine"]
  n_screen["screen"] --> n_dep_tokio["dep:tokio"]

Targets

KindNameSource
exampleclipboard_verify`examples/clipboard_verify.rs`
examplekeyboard_verify`examples/keyboard_verify.rs`
examplepty_verify`examples/pty_verify.rs`
examplescreen_ocr_demo`examples/screen_ocr_demo.rs`
liboperations_dlp_sensor`src/lib.rs`
testscreen_pipeline`tests/screen_pipeline.rs`

Error model

No public error type was detected: no public item declares a type named *Error, and no public signature returns one.

Operational characteristics

PropertyEvidence
async public surfacenone detected
async runtimeyes
database accessnone detected
network I/Onone detected
unsafe codenone detected
environment variablesnone detected

No unsafe block, unsafe fn, unsafe impl or unsafe trait was found by the parser anywhere in this crate's source.

Configuration

No environment variable is read with a literal name anywhere in this crate. A variable whose key is computed at run time cannot be listed here, and is not claimed to be absent.

1 workspace crate depends on this one: operations-dlp-agent.

Verification

KindCount
Unit tests11
Integration tests1
Examples4
Doctests0

Evidence by module. How often each public module is named by something executable.

ModuleTestsExamplesConsumers
clipboard111
keyboard210
pipeline433
pty310
screen211
source311

What the tests establish, by name:

Documentation coverage

MeasureDocumentedTotal
Public items with rustdoc2631
Public modules with a //! block66
pie showData
    title Public items with rustdoc
    "Documented" : 26
    "No rustdoc detected" : 5

Metrics

MetricValue
Rust source files7
Source lines841
Code lines609
Public API items31
Public modules6
Tests12
Examples4
Cargo features6
Direct runtime dependencies8
Workspace reverse dependencies1
pie showData
    title Public API by kind
    "constant" : 2
    "function" : 5
    "method" : 16
    "struct" : 7
    "trait" : 1
pie showData
    title Rust source composition
    "Code" : 609
    "Blank or comment" : 232

Generation

Rendered by tools-corpus corpus readme from repository evidence alone, renderer schema 2, lexicon current. No model, network service or database was consulted. Regenerate with tools-corpus corpus readme --write; verify with --check.

All operations · Manual