245 lines
14 KiB
HTML
245 lines
14 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
|
|
|
|
<meta charset="utf-8">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
|
|
<link rel="canonical" href="https://git.tylconsulting.it/thothii-docs/operations/sensitivity-analysis/">
|
|
<link rel="shortcut icon" href="../../img/favicon.ico">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
|
|
<title>Sensitive columns - ThothII Docs</title>
|
|
<link href="../../css/bootstrap-3.3.7.min.css" rel="stylesheet">
|
|
<link href="../../css/font-awesome-4.7.0.css" rel="stylesheet">
|
|
<link href="../../css/base.css" rel="stylesheet">
|
|
<link rel="stylesheet" href="../../css/highlight.css">
|
|
<link href="../../stylesheets/extra.css" rel="stylesheet">
|
|
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
|
<!--[if lt IE 9]>
|
|
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
|
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
|
|
<![endif]-->
|
|
|
|
<script src="../../js/jquery-3.2.1.min.js"></script>
|
|
<script src="../../js/bootstrap-3.3.7.min.js"></script>
|
|
<script src="../../js/highlight.pack.js"></script>
|
|
|
|
<base target="_top">
|
|
<script>
|
|
var base_url = '../..';
|
|
var is_top_frame = false;
|
|
|
|
var pageToc = [
|
|
{title: "Local sensitivity analysis", url: "#_top", children: [
|
|
{title: "Default policy", url: "#default-policy" },
|
|
{title: "Optional CPU-only GLiNER2 evidence", url: "#optional-cpu-only-gliner2-evidence" },
|
|
{title: "Prepare and enable the optional profile", url: "#prepare-and-enable-the-optional-profile" },
|
|
{title: "Acceptance on a real database", url: "#acceptance-on-a-real-database" },
|
|
]},
|
|
];
|
|
|
|
</script>
|
|
<script src="../../js/base.js"></script>
|
|
<script src="../../javascripts/layout-init.js"></script>
|
|
</head>
|
|
|
|
<body>
|
|
<script>
|
|
if (is_top_frame) { $('body').addClass('wm-top-page'); }
|
|
</script>
|
|
|
|
|
|
|
|
<div class="container-fluid wm-page-content">
|
|
<a name="_top"></a>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="row wm-article-nav-buttons" role="navigation" aria-label="navigation">
|
|
|
|
<div class="wm-article-nav pull-right">
|
|
<a href="../../evidence/" class="btn btn-xs btn-default pull-right">
|
|
Next
|
|
<i class="fa fa-chevron-right" aria-hidden="true"></i>
|
|
</a>
|
|
<a href="../../evidence/" class="btn btn-xs btn-link">
|
|
Evidence
|
|
</a>
|
|
</div>
|
|
|
|
<div class="wm-article-nav">
|
|
<a href="../database-management/" class="btn btn-xs btn-default pull-left">
|
|
<i class="fa fa-chevron-left" aria-hidden="true"></i>
|
|
Previous</a><a href="../database-management/" class="btn btn-xs btn-link">
|
|
Databases and descriptions
|
|
</a>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<h1 id="local-sensitivity-analysis">Local sensitivity analysis<a class="headerlink" href="#local-sensitivity-analysis" title="Permanent link">¶</a></h1>
|
|
<p>Database Management can assess selected columns without sending their metadata or contents to a
|
|
generative model. The feature is advisory: it creates a transient review draft, while the catalog's
|
|
Sensitive Data Flag changes only when an administrator explicitly saves a choice. The administrator
|
|
may set either value, including overriding a <code>sensitive</code> proposal.</p>
|
|
<h2 id="default-policy">Default policy<a class="headerlink" href="#default-policy" title="Permanent link">¶</a></h2>
|
|
<p><code>SensitivityClassifier</code> is the only column-level decision point. The versioned <code>sensitivity-v4</code>
|
|
policy combines:</p>
|
|
<ul>
|
|
<li>a structural exclusion for declared <code>bigint</code> primary-key columns and undeclared <code>bigint</code>
|
|
columns following the exact <code>pk</code> naming convention; their values are non-informative identifiers
|
|
and are therefore not inspected as possible sensitive content. The evidence distinguishes
|
|
declared constraints from convention-based inference;</li>
|
|
<li>normalized column-name rules for direct identifiers, credentials, and health data;</li>
|
|
<li>validated content rules for email, Italian fiscal code and VAT, passport, identity-card and
|
|
driving-licence identifiers, phone numbers, IBAN/BIC, payment-card checksums, IP/MAC addresses,
|
|
URLs, UUIDs, access keys, private-key markers, sensitive keys inside bounded recursive JSON, and
|
|
a reviewed Italian clinical-term dictionary;</li>
|
|
<li>a conservative length rule: any observed textual value longer than 500 characters makes the
|
|
entire column sensitive.</li>
|
|
</ul>
|
|
<p>One decisive value is enough to classify the column as <code>sensitive</code> and removes it from subsequent
|
|
passes. Binary or otherwise uninspectable column types are also proposed as <code>sensitive</code>, because
|
|
their contents cannot be cleared by the textual rules. A completed analysis has only two draft
|
|
outcomes: <code>sensitive</code> and <code>non_sensitive</code>. Empty or all-null columns are <code>non_sensitive</code> with
|
|
<code>no_values</code> coverage; a sampled column with no match is <code>non_sensitive</code> with explicit sampled
|
|
coverage. The administrator remains free to reverse either proposal before saving it.</p>
|
|
<p>Source reads are database-specific, but decisions are database-independent. PostgreSQL direct and
|
|
REST <code>run_query</code> adapters project at most 501 characters per value, use only <code>SELECT</code>, and never
|
|
persist source values. Tables proven to contain at most 1,000 rows are fully scanned. Larger tables
|
|
are processed breadth-first so every table gets the cheapest pass before any table gets a deeper
|
|
one:</p>
|
|
<ol>
|
|
<li>inspect up to 300 non-null values per unresolved column;</li>
|
|
<li>inspect up to 700 additional values, reaching a 1,000-value target;</li>
|
|
<li>for unresolved text, JSON, and XML columns only, inspect up to 2,000 additional values, reaching
|
|
a 3,000-value target.</li>
|
|
</ol>
|
|
<p>At most two tables are scanned concurrently, and the database adapter groups at most 25 columns in
|
|
one source query. Each probe or value query has a five-second statement timeout; PostgreSQL-wire
|
|
reads run in a read-only transaction and always end with rollback. Sampling is bounded and
|
|
repeatable for a policy version. If a randomized sample is empty or reaches its query timeout, the
|
|
adapter tries one sequential bounded sample; if that also times out, the source error fails the run
|
|
and returns no review instead of manufacturing <code>unknown</code> decisions.</p>
|
|
<p>There is no global sixty-second analysis deadline. Work is bounded by sample counts, per-query
|
|
timeouts, and early column exits. The operation is interrupted only when its request connection is
|
|
aborted or the backend restarts. Historical or interrupted run counters named <code>unknown</code> represent
|
|
columns that were not processed; <code>unknown</code> is not a <code>sensitivity-v4</code> column assessment.</p>
|
|
<p>History stores only the policy version, aggregate outcomes, timestamps, and fixed operational
|
|
events. Sanitized rule IDs are returned in the transient review and shadow report, not persisted.
|
|
Neither path stores values, matched spans, prompts, or free-form model output.</p>
|
|
<h2 id="optional-cpu-only-gliner2-evidence">Optional CPU-only GLiNER2 evidence<a class="headerlink" href="#optional-cpu-only-gliner2-evidence" title="Permanent link">¶</a></h2>
|
|
<p>The deterministic engine works without Python NER. An installation may opt into
|
|
<code>fastino/gliner2-privacy-filter-PII-multi</code> for unresolved short text. It runs in a persistent local
|
|
Python worker, adds sanitized evidence, and never becomes a second decision point. The worker:</p>
|
|
<ul>
|
|
<li>loads a local model directory only and forces Hugging Face/Transformers offline mode;</li>
|
|
<li>starts warming in the background when the backend starts; an analysis never waits for warm-up
|
|
and skips NER until the worker is ready, so loading cannot consume the run's NER allowance;</li>
|
|
<li>hides CUDA and HIP devices and loads weights with <code>map_location="cpu"</code>;</li>
|
|
<li>starts with a scrubbed environment, then installs a fail-closed seccomp filter that denies
|
|
network syscalls before accepting source text (the Python socket API is disabled as defense in depth);</li>
|
|
<li>receives at most two 500-character candidates per table by default, selected breadth-first
|
|
across unresolved columns, and shares a ten-second NER allowance across the whole run;</li>
|
|
<li>returns only column ID, normalized label, and confidence; source text and entity spans are not
|
|
returned or stored;</li>
|
|
<li>is skipped on timeout, startup failure, invalid output, or absent configuration. No LLM fallback
|
|
is selected.</li>
|
|
</ul>
|
|
<p>The pinned model revision is <code>c153999da5f4c509df4322b0c6a1baf3d2c284d7</code>. GLiNER2 and the model
|
|
are Apache-2.0; the published mDeBERTa base is MIT. The optional runtime pins
|
|
<code>gliner2[local]==2.0.0</code>, <code>transformers==4.57.6</code>, and the CPU-only PyTorch wheel
|
|
<code>torch==2.14.0+cpu</code>. It lives in <code>/opt/sensitivity-ner</code>, is not installed in the default core image,
|
|
and does not install CUDA packages.</p>
|
|
<p>The current upstream checkpoint was saved by Transformers 5.8 even though GLiNER2 2.0.0 officially
|
|
requires Transformers <code><5</code>; the resulting tokenizer error is independently reported in
|
|
<a href="https://github.com/fastino-ai/GLiNER2/issues/145">GLiNER2 issue 145</a>. At startup ThothII leaves the
|
|
pinned model directory unchanged and creates a temporary symlink view that maps the checkpoint's
|
|
<code>extra_special_tokens</code> list to the Transformers 4 name <code>additional_special_tokens</code>. Any other or
|
|
ambiguous shape fails closed and leaves the optional NER unavailable. The offline CPU smoke test
|
|
must remain part of every dependency or model revision update.</p>
|
|
<h2 id="prepare-and-enable-the-optional-profile">Prepare and enable the optional profile<a class="headerlink" href="#prepare-and-enable-the-optional-profile" title="Permanent link">¶</a></h2>
|
|
<p>Download happens during explicit installation, never during inference:</p>
|
|
<pre class="highlight"><code class="language-bash">./scripts/fetch-sensitivity-ner-model.sh /absolute/path/to/gliner2-pii</code></pre>
|
|
<p>The script builds the separate <code>thothii-core:sensitivity-ner</code> image, downloads the exact revision, and writes
|
|
<code>MODEL_SHA256SUMS</code>. Keep the model directory outside the repository. Then set:</p>
|
|
<pre class="highlight"><code class="language-bash">export THOTH_ENABLE_SENSITIVITY_NER=1
|
|
export THT_SENSITIVITY_NER_MODEL_DIR=/absolute/path/to/gliner2-pii
|
|
export THT_SENSITIVITY_NER_THREADS=2
|
|
./scripts/run-stack.sh</code></pre>
|
|
<p>For an operator-managed Compose invocation, include <code>deploy/compose.sensitivity-ner.yaml</code> after the
|
|
base and installation overlays. The core build argument <code>INSTALL_SENSITIVITY_NER=true</code> installs the
|
|
optional Python dependencies into their isolated virtualenv. The model mount is read-only. Values
|
|
above eight threads are rejected; start with two so classification cannot contend heavily with
|
|
other CPU workloads.</p>
|
|
<h2 id="acceptance-on-a-real-database">Acceptance on a real database<a class="headerlink" href="#acceptance-on-a-real-database" title="Permanent link">¶</a></h2>
|
|
<p>Run the first evaluation in shadow mode: read the source with its existing read-only role, do not
|
|
save proposed flags, and report only aggregate counts, rule IDs, coverage, and timings. Never copy
|
|
matched values into test output. Use a separately approved, labeled Italian corpus to calculate
|
|
precision and recall; source values must remain inside the authorized environment.</p>
|
|
<p>Inside the configured core runtime, the non-mutating command is:</p>
|
|
<pre class="highlight"><code class="language-bash">npm run sensitivity:shadow -- <workspace-id></code></pre>
|
|
<p>It reads catalog metadata and source values but emits one aggregate JSON object with no database,
|
|
table, column, or source-value detail. It neither creates an analysis run nor updates a flag.</p>
|
|
<p>Enabling NER by default requires all of these gates:</p>
|
|
<ol>
|
|
<li>the pinned artifact and <code>MODEL_SHA256SUMS</code> are archived with the installation inventory;</li>
|
|
<li>the Python dependency/license inventory contains only redistribution-compatible licenses;</li>
|
|
<li>the CPU benchmark stays within the configured NER allowance and does not use a GPU;</li>
|
|
<li>the labeled Italian evaluation meets thresholds approved by the product owner.</li>
|
|
</ol>
|
|
<p>If a gate fails, leave NER disabled. The deterministic policy remains available and produces the
|
|
binary draft from its scan coverage; no content is sent to an internal or external LLM.</p>
|
|
<p>Benchmarks from a particular installation are not a guarantee for another database or machine.
|
|
NER remains opt-in until an approved evaluation establishes that additional findings justify
|
|
their false-positive rate and operational cost. Keep benchmark and release records with the
|
|
installation's technical evidence, separate from this operator procedure.</p>
|
|
|
|
<br>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="row wm-article-nav-buttons" role="navigation" aria-label="navigation">
|
|
|
|
<div class="wm-article-nav pull-right">
|
|
<a href="../../evidence/" class="btn btn-xs btn-default pull-right">
|
|
Next
|
|
<i class="fa fa-chevron-right" aria-hidden="true"></i>
|
|
</a>
|
|
<a href="../../evidence/" class="btn btn-xs btn-link">
|
|
Evidence
|
|
</a>
|
|
</div>
|
|
|
|
<div class="wm-article-nav">
|
|
<a href="../database-management/" class="btn btn-xs btn-default pull-left">
|
|
<i class="fa fa-chevron-left" aria-hidden="true"></i>
|
|
Previous</a><a href="../database-management/" class="btn btn-xs btn-link">
|
|
Databases and descriptions
|
|
</a>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<br>
|
|
</div>
|
|
|
|
<footer class="container-fluid wm-page-content">
|
|
<p>Documentation built with <a href="https://www.mkdocs.org/">MkDocs</a> using <a href="https://github.com/gristlabs/mkdocs-windmill">Windmill</a> theme by Grist Labs.</p>
|
|
</footer>
|
|
|
|
</body>
|
|
</html> |