|
Download docs/anonymization-qualification.md from Leon4gr45/agent-0: direct link, hf CLI and curl.
- Browser
- Download file 15.4 kB
-
https://huggingface.co/spaces/Leon4gr45/agent-0/resolve/main/docs/anonymization-qualification.md
- Command line
-
hf download hf://spaces/Leon4gr45/agent-0/docs/anonymization-qualification.md
-
curl -L -o anonymization-qualification.md https://huggingface.co/spaces/Leon4gr45/agent-0/resolve/main/docs/anonymization-qualification.md
15.4 kB
| > Current development result: [Gate03e taxonomy and review readiness](anonymization-gate03e.md). | |
| > Three returned religion-status canaries improve; one organization partial mask | |
| > and five safe abstentions remain. No new independent holdout; model qualification, | |
| > private deployment, sensitive processing and automatic release remain NO-GO. | |
| > Historical first independent result: [Gate03d religious terminology qualification](anonymization-gate03d.md) | |
| > preserves the failed Gate03c result, compares limited fixes, and records a FAILED | |
| > new independent 160-case first holdout. Model recognition, real sensitive processing, | |
| > private deployment and automated release remain NO-GO. Earlier sections are history. | |
| # Anonymization Qualification Report | |
| Current staging/sensitive-processing decision: **NO-GO**. The fresh 120-case | |
| [Gate 03c holdout](anonymization-gate03c.md) has two unmasked religious-reference | |
| canaries; real identity integration remains BLOCKED. Earlier findings below are | |
| preserved as historical evidence. | |
| ## Mission Objective | |
| Investigate and test the existing anonymization implementation before integrating it into the OCR workflow. | |
| ## 1. Implementation Audit | |
| - **Recognizers Available:** Presidio (Analyzer/Anonymizer) is supported but optional. The code defaults to `nltk` (using `word_tokenize`, `pos_tag`, `ne_chunk`). | |
| - **Entity Categories Supported:** Only `PERSON` and `LOCATION` are supported explicitly by both NLTK and Presidio configurations in `anonymize_text`. Organizations, Emails, Phone Numbers, and Religious Affiliations are **not** supported. | |
| - **Languages:** English (`en`) is hardcoded in Presidio. German support is virtually non-existent, leading to substantial classification errors (e.g., mislabeling German words as English entities or completely missing them). | |
| - **Span Replacement:** When it does detect an entity, the span replacement works reasonably well, but the NLTK logic sometimes joins punctuation incorrectly or misses multi-word entities. | |
| - **Fail-Open Security Flaw (Baseline Defect):** If an exception occurs in `anonymize_text_nltk` (e.g., during tokenization or chunking), it catches the exception and returns the *original, unredacted text*. This means a recognition failure leaks the original sensitive content. | |
| - **Integration with OCR:** The `ocr/handoff.py` script provides a secure bridge (`anonymization_handoff`) that properly returns the result as `release_review_required=True` and `anonymous=False`. | |
| ## 2. Evaluation Metrics (Document-Level Exact-Match Scoring) | |
| A synthetic dataset of 40 text cases was tested. Because the current `anonymize_text` implementation does not yield character offsets (spans), entity-level Precision, Recall, and F1 metrics are explicitly marked as **UNAVAILABLE**. | |
| *Note: The following metrics are published benchmark observations derived from local test runs using the baseline NLTK implementation. They are historical/unverified in standard CI, as the real model evaluation is marked as an opt-in test (`RUN_OPTIONAL_OCR_INTEGRATION=1`) to avoid arbitrary heavy ML dependencies in the default GitHub Actions run.* | |
| ```text | |
| --- Benchmark Observations --- | |
| PERSON: {'precision': 'UNAVAILABLE', 'recall': 'UNAVAILABLE', 'f1': 'UNAVAILABLE', 'unredacted_canaries': 5} | |
| CITY: {'precision': 'UNAVAILABLE', 'recall': 'UNAVAILABLE', 'f1': 'UNAVAILABLE', 'unredacted_canaries': 3} | |
| RELIGION: {'precision': 'UNAVAILABLE', 'recall': 'UNAVAILABLE', 'f1': 'UNAVAILABLE', 'unredacted_canaries': 5} | |
| EMAIL: {'precision': 'UNAVAILABLE', 'recall': 'UNAVAILABLE', 'f1': 'UNAVAILABLE', 'unredacted_canaries': 2} | |
| PHONE: {'precision': 'UNAVAILABLE', 'recall': 'UNAVAILABLE', 'f1': 'UNAVAILABLE', 'unredacted_canaries': 1} | |
| ORGANIZATION: {'precision': 'UNAVAILABLE', 'recall': 'UNAVAILABLE', 'f1': 'UNAVAILABLE', 'unredacted_canaries': 2} | |
| document_exact_match_rate: 0.175 | |
| avg_runtime_ms: ~840.0 | |
| ``` | |
| - **Document Exact Match Rate**: Only 17.5% of the test documents were redacted exactly as specified in the gold standard. | |
| - **Canary Leakage**: Every required entity category saw significant canary leakage. | |
| - **Unsupported Categories**: `RELIGION`, `EMAIL`, `PHONE`, and `ORGANIZATION` are unhandled by the NLTK/Presidio implementations. This leads to large numbers of unredacted canary leaks. | |
| ## 3. Testing Context and Integration | |
| The independent verification tests executing globally in CI cover: | |
| - Validation of all 40 synthetic gold-standard entity spans. | |
| - Acceptance tests proving `anonymization_handoff` handles malformed outputs securely (`SafeError`) and correctly bounds metadata (`release_review_required=True`, `anonymous=False`). | |
| - Baseline demonstration of the NLTK fail-open security flaw. | |
| An opt-in integration test (`test_ocr_to_anonymization_integration`) simulates the OCR-to-anonymizer integration boundary. It demonstrates that the legacy baseline **fails to fully redact** required canaries like "Lina", "Wolkenstein", "Berlin", and "evangelisch". | |
| ## 4. Final Decision | |
| **Decision:** `NO-GO` | |
| **Reasons:** | |
| 1. **Fail-Open Behavior:** The existing NLTK baseline implementation returns the original text on failure. This is a critical security vulnerability. | |
| 2. **Missing Entity Support:** Essential categories (`[RELIGION]`, `[EMAIL]`, `[PHONE]`, `[ORGANIZATION]`) are completely unhandled, immediately leading to compliance failures (canary leakage). | |
| 3. **Missing Multilingual Support:** The hardcoded English Presidio configuration and NLTK fallback severely underperform on German text. | |
| **Recommendation:** | |
| The next implementation gate needs to: | |
| - Introduce a multilingual GLiNER-based recognizer (or similar robust multilingual model) to properly handle German and custom entity tags like `RELIGION` without downloading arbitrary corpora. | |
| - The recognizer must return explicit spans to calculate accurate P/R/F1. | |
| - Implement explicit catch blocks inside the tagger wrappers that fail closed (throw `Exception`) ensuring `ocr/handoff.py` correctly converts it to a `SafeError`. | |
| --- | |
| ## New span engine qualification — 2026-10-18 | |
| This section qualifies the new explicit implementation. All preceding legacy | |
| findings and characterization tests are preserved unchanged; their NO-GO decision | |
| still applies to the legacy engine. A test demonstrating its fail-open behavior | |
| is not a passing acceptance test for security. | |
| **Decision: PARTIAL for reviewed private integration; NO-GO for automated release.** | |
| The boundary/replacement implementation passes its offline acceptance tests. The | |
| actual pinned recognizer still leaves one required synthetic CITY canary unmasked. | |
| The opt-in canary acceptance test fails deliberately without xfail or altered gold | |
| labels. Every candidate remains ineligible for automatic release. | |
| ### Synchronization evidence | |
| - Original checkout: `work`, `9fc91e6f92b4ae9cc902359fd56ef0011a10f9f1`. | |
| - Prior review worktree: `review/pr-1-fixes`, `a8f5d7b22c6c5787621973aa5207311d2cc75dca`; uncommitted corrections preserved untouched. | |
| - No pre-existing local anonymization implementation branch or commits existed. | |
| - Fetched/verified integration branch: `jules-agent-0-deployment-9610133099829518547`, `281c84172281a2294227f15287a4aded8a7ea948`. GitHub confirms PR #2 merged at that SHA. | |
| - Feature branch: `feat/ocr-anonymization-failclosed`, initial local HEAD `281c84172281a2294227f15287a4aded8a7ea948`. No rebase/conflicts were necessary; shared integration branch was not changed. | |
| - Worktree: `/workspace/augmentoolkit-anonymization`. Final delivery SHA/PR/CI are in the delivery report; `git merge-base --is-ancestor origin/jules-agent-0-deployment-9610133099829518547 HEAD` verifies ancestry. | |
| ### Actual-model evaluation | |
| Selected `VAGOsolutions/SauerkrautLM-GLiNER` revision | |
| `ba967ee030b7e679dd5422cb16fcd1b379da38e1`, native local CPU runtime, threshold | |
| 0.5, two inference threads. Linux container CPU quota: four CPUs; memory ceiling | |
| 32 GiB. No GPU, external model endpoint, public worker or real private documents | |
| were used. The actual recognition tests start from synthetic mocked OCRResult | |
| objects; this task did not rerun image/PDF OCR benchmarks. | |
| Raw reproducible aggregate evidence: [cpu-pinned.json](anonymization-evaluation/cpu-pinned.json). | |
| Installation/runtime pins and exact commands: [integration](anonymization-integration.md). | |
| The 40-case corpus is a faithful copy of merged qualification cases, with language | |
| and noise annotations added. A separate 10-case validation set was written before | |
| model evaluation and is not read by the runtime. No test entity names are hardcoded | |
| in recognizers/detectors. Generic line-wrap handling was developed after the initial | |
| evaluation; this is development feedback, not independent external validation. | |
| Further held-out real-world evaluation is required to assess overfitting/domain shift. | |
| Metrics below match exact **(start, end, label)** tuples. Wrong boundaries or labels | |
| count as both a false positive and a false negative. NER-only metrics and combined | |
| NER + deterministic detector metrics are separately recorded in JSON; their final | |
| counts match on these small corpora. A canary fails if any original alphanumeric | |
| character in its gold span remains uncovered, even if partial masking removed the | |
| full literal string. Literal-string checks are also recorded separately. | |
| #### Merged qualification corpus (40 cases) | |
| | Entity | Precision | Recall | F1 | FP | FN | Unredacted canaries | | |
| | --- | ---: | ---: | ---: | ---: | ---: | ---: | | |
| | PERSON | 0.818 | 0.900 | 0.857 | 4 | 2 | 0 | | |
| | CITY | 1.000 | 0.824 | 0.903 | 0 | 3 | 1 | | |
| | RELIGION | 1.000 | 1.000 | 1.000 | 0 | 0 | 0 | | |
| | EMAIL | 1.000 | 1.000 | 1.000 | 0 | 0 | 0 | | |
| | PHONE | 1.000 | 1.000 | 1.000 | 0 | 0 | 0 | | |
| | ORGANIZATION | 0.250 | 0.500 | 0.333 | 3 | 1 | 0 | | |
| Document exact-match rate: **82.5%**; blocked documents: 0. | |
| | Group | Documents | Exact matches | Entity FN | | |
| | --- | ---: | ---: | ---: | | |
| | de | 10 | 8 | 1 | | |
| | en | 29 | 24 | 5 | | |
| | mixed | 1 | 1 | 0 | | |
| | ocr_noise | 4 | 2 | 2 | | |
| Warm latency median 89.4 ms, maximum 335.5 ms. | |
| #### Separate validation corpus (10 cases) | |
| | Entity | Precision | Recall | F1 | FP | FN | Unredacted canaries | | |
| | --- | ---: | ---: | ---: | ---: | ---: | ---: | | |
| | PERSON | 1.000 | 1.000 | 1.000 | 0 | 0 | 0 | | |
| | CITY | 1.000 | 0.800 | 0.889 | 0 | 1 | 0 | | |
| | RELIGION | 0.667 | 1.000 | 0.800 | 1 | 0 | 0 | | |
| | EMAIL | 1.000 | 1.000 | 1.000 | 0 | 0 | 0 | | |
| | PHONE | 1.000 | 1.000 | 1.000 | 0 | 0 | 0 | | |
| | ORGANIZATION | 0.500 | 1.000 | 0.667 | 2 | 0 | 0 | | |
| Document exact-match rate: **70.0%**; blocked documents: 0. | |
| | Group | Documents | Exact matches | Entity FN | | |
| | --- | ---: | ---: | ---: | | |
| | de | 5 | 3 | 1 | | |
| | en | 5 | 4 | 0 | | |
| | ocr_noise | 2 | 2 | 0 | | |
| Warm latency median 96.3 ms, maximum 121.7 ms. | |
| Model loading (including artifact integrity verification and runtime import): | |
| **12.42 seconds**. Process peak RSS: **3061.2 MiB**. | |
| These are local observations, not a throughput SLA or HF CPU Basic sizing claim. | |
| Gold limitations are retained rather than silently repaired: the historical | |
| organization fixture includes its terminal period inside a gold span but expects | |
| the period after replacement. Replacement correctly follows source spans; the | |
| replacement unit test documents that inconsistency separately. Some historical | |
| CITY annotations describe states/rivers, which differs from the prompt's strict | |
| city meaning. Aggregate strict scores are still reported against the unchanged | |
| gold labels. Remaining category/boundary errors and one canary preclude acceptance | |
| of autonomous release. No recognition threshold or name dictionary was tuned to | |
| make the suite green. | |
| ### Tests and security qualification matrix | |
| Baseline before implementation: **64 passed, 6 skipped**. Final default suite: | |
| **114 passed, 8 skipped**, one existing Starlette TestClient deprecation warning. | |
| Ruff check and format check pass. Two skips are explicit real-model tests, three | |
| are legacy NLTK/optional characterization cases (NLTK not installed), and three | |
| are existing opt-in OCR/backend tests. The historical tests were not edited. | |
| Separate actual-model pytest run: **1 passed, 1 failed**. Real local recognition | |
| and two-page OCR handoff passed; the zero-canary release qualification failed. | |
| The aggregate evaluator completed successfully and records | |
| `recognition_qualification_passed=false`. Its successful execution does not | |
| change that failed gate. Default CI intentionally does not download a NER model. | |
| | Boundary | Evidence | Result | | |
| | --- | --- | --- | | |
| | Missing/corrupt/pin-mismatched model artifacts | Offline cache and manifest tests | PASS: constant error, no candidate | | |
| | Model initialization/inference exception | Injected failures, no raw exception/document logging | PASS | | |
| | Malformed spans, scores, labels, extra fields, forged copies | Offline strict-schema tests | PASS | | |
| | Untrusted tagger text/metadata | New path accepts validated model spans; historical dictionaries cannot enter release | PASS | | |
| | Overlap/repeat/umlaut/line wrap/spacing | Gold replacement tests and source-offset mapping tests | PASS for replacement; recognition remains imperfect | | |
| | Incomplete/missing/duplicate pages or classification mismatch | Multi-page failures and second-page inference exception | PASS: all-or-nothing | | |
| | Raw Markdown/blocks/alternatives/engine/IDs | Canary-rich mocked OCR evidence and immutable snapshot test | PASS: omitted from candidate/export | | |
| | D1/D2 local handling | Classification-retention and remote-recognizer rejection tests; no remote adapter | PASS within trusted application boundary | | |
| | Empty predictions | Review reason, approval false, automated eligibility false | PASS | | |
| | Unauthorized/unreviewed/expired/forged/mismatched approval | Identity callback, digest/HMAC, expiry tests | PASS | | |
| | Unsupported exports and D1/D2 bare text export | Export policy tests | PASS: blocked | | |
| | Legacy pipeline implicit anonymization | Real chunking entry function rejects anonymize=True | PASS: migration required | | |
| | Model detects every required canary | Actual pinned CPU model, 40 + 10 synthetic cases | **FAIL: one CITY canary** | | |
| | Original OCR runtime/public worker packaging | Existing OCR tests; no worker/API/Docker/runtime dependency edits | PASS regression; no production deployment performed | | |
| Review authorization is a host application integration contract, not a mocked | |
| claim of deployed SSO/ACL enforcement. Tests use synthetic actors/signing keys. | |
| Production approval storage, identity integration, CUDA, live Debian-Devil execution | |
| and a reviewed destination for D1/D2 export remain operator integration work. No | |
| public Debian port was opened, HF deployment changed, production service restarted, | |
| or PR automatically merged. | |
| --- | |
| ## PR #3 follow-up — recognition and private release hardening | |
| The [follow-up report](anonymization-pr3-hardening.md) supersedes the initial new-engine | |
| results above while retaining them as historical evidence. The actual final model | |
| tests now both pass; zero canaries remain in 40 qualification + 10 validation cases | |
| after the general CITY `location` prompt fix. Strict per-category errors are still | |
| reported; no gold corpus changes were made. Approval exports now require verified | |
| review evidence, destination binding and durable single-use replay protection. | |
| Automated release and deployment remain **NO-GO**. See the linked report for all | |
| comparison metrics, security regressions and four separate readiness decisions. | |