RedactionCore / Swift text-processing package / 2026
Keeping useful context when sensitive text is removed.
RedactionCore gives Omitto a reusable Swift engine that selects sensitive spans, resolves competing matches and replaces them without reconstructing the document.
- ROLE
- Software engineering
- STATE OF THE BUILD
- In progress
- RECORD UPDATED
THE WORK
The project.
RedactionCore is the text-processing package behind Omitto's review workflow. It accepts a string and a redaction policy, then returns redacted text, masked findings and a report. Replacements happen inside the original document, preserving the surrounding indentation, comments, key order and line endings that can make a developer snippet useful to someone else.
Choosing what to replace happens before changing the string. Detectors contribute candidate spans; disabled groups are removed before overlapping matches compete. The selected spans receive placeholders that remain consistent for repeated values within one call, then replacement proceeds from right to left so earlier offsets remain valid.
The package uses Foundation and owns no interface, clipboard, storage or networking. Omitto supplies background scheduling and the review experience. Manual phrases and explicit Keep decisions travel with the current policy, keeping the automatic scan part of a review process rather than a claim that every possible secret has been removed.
IMPLEMENTATION
Design choices.
- Replace spans in the original string instead of rebuilding the document from a parsed representation. This preserves useful surrounding context across text formats, while leaving detection quality as a separate problem to evaluate.
- Filter detector groups before selecting overlap winners. An ineligible high-priority candidate must not discard an enabled fallback and then disappear itself, leaving a value untouched.
- Allocate placeholders within one call instead of keeping a persistent secret-to-label table. Repeated values remain easy to follow inside a result, but their labels do not become stable identities across documents.
- Keep manual phrases active independently of automatic detector groups and make per-finding overrides explicit. These controls let the review address omissions and false positives without presenting automatic detection as complete.
- Leave task scheduling, source-text lifetime and output destinations with the caller. The small package boundary supports reuse; it does not certify the safety of a publication or erase the original bytes.
HOW IT FITS TOGETHER
Architecture.
- Redactor is a synchronous Sendable value API. It receives input and policy and returns text, findings and a report, allowing the same processing logic to be used without an app window or clipboard service.
- CompositeDetector collects and deduplicates candidates. Redactor removes disabled groups before resolving overlaps with priority, confidence and span-length scores, then applies the confidence threshold to the selected candidates.
- Each call creates a new PlaceholderAllocator. Repeated values share a placeholder within that result, different values are numbered by kind, and per-finding Keep choices explicitly leave selected text unchanged.
- Accepted findings use UTF-16 spans and are applied from the end of the string toward the start. This preserves earlier positions and leaves untouched document structure in place instead of parsing and serializing it again.
- Public findings carry ranges, kinds, confidence, fixed reasons and masked previews rather than an original-value field. Omitto uses that metadata for review and remains responsible for scheduling and copying.
Explore the architecture map11 components · 14 connections
RedactionCore's value-based transformation
The library selects spans and returns reviewable values; the calling application owns UI, scheduling, storage and export.
Calling application
RedactionCore library
Returned values
Scroll or drag the background to move. Use the zoom buttons to resize.Arrow keys move between components. Enter selects.
Choose a component to explore
Select a numbered component on the map or use the component menu. Its details and connections will appear here.
No component selected.
All connections (14)
- 01 · Input string → 03 · CompositeDetectorText to inspect · Direct call
- 02 · Options and review policy → 03 · CompositeDetectorManual and mode options · Direct call
- 03 · CompositeDetector → 04 · Detector-group filterCandidate spans · Direct call
- 02 · Options and review policy → 04 · Detector-group filterEnabled detector groups · Direct call
- 04 · Detector-group filter → 05 · Overlap resolverEligible candidates · Direct call
- 05 · Overlap resolver → 06 · Confidence policySelected spans · Direct call
- 02 · Options and review policy → 06 · Confidence policyConfidence policy · Direct call
- 06 · Confidence policy → 07 · Per-call placeholder allocatorAccepted candidates · Direct call
- 07 · Per-call placeholder allocator → 09 · Finding metadataAssigned replacements · Direct call
- 02 · Options and review policy → 09 · Finding metadataPer-finding Keep decisions · Direct call
- 09 · Finding metadata → 08 · Right-to-left span replacementEnabled spans and replacement text · Direct call
- 01 · Input string → 08 · Right-to-left span replacementOriginal string · Direct call
- 08 · Right-to-left span replacement → 10 · Transformed stringReturn transformed text · Response / return
- 09 · Finding metadata → 11 · RedactionReportAggregate finding metadata · Direct call
MADE WITH
Swift · Foundation · Swift Package Manager · XCTest
ACCESS & INPUT
Security controls.
- The package imports Foundation and has no external package dependencies. A repository boundary check rejects UI, pasteboard, persistence, networking and telemetry symbols in the core.
- Public findings omit an original-value field, and custom debug descriptions omit both input and output text. The review metadata can describe a finding without reproducing its detected value.
- The library uses manual phrases for the current call and does not persist them. These phrases remain active even when all automatic detector groups are disabled.
- Placeholder allocation checks whether a proposed replacement equals the original value. If it does, the allocator changes the token so that an accepted redaction does not silently preserve the same text.
- Explicit Keep choices can leave findings in place, and unfamiliar formats can escape heuristic detection. The returned document still needs review before it is shared.
- The caller owns the lifetime of raw input, options, output and any clipboard copy. Nothing in this API promises secure memory erasure.
Explore the security map9 components · 14 connections
Detection policy and caller-owned disclosure
RedactionCore returns selected spans and transformed text; review, raw-value lifetime and clipboard or file export remain outside the library.
Calling application
Foundation-only core
Returned values
Scroll or drag the background to move. Use the zoom buttons to resize.Arrow keys move between components. Enter selects.
Choose a component to explore
Select a numbered component on the map or use the component menu. Its details and connections will appear here.
No component selected.
All connections (14)
- 01 · Caller-owned raw input → 03 · Composite detectionText value to inspect · Direct call
- 02 · Per-call redaction policy → 03 · Composite detectionManual phrases and detection mode · Direct call
- 03 · Composite detection → 04 · Policy and overlap selectionCandidate spans · Direct call
- 02 · Per-call redaction policy → 04 · Policy and overlap selectionEligibility and confidence rules · Direct call
- 04 · Policy and overlap selection → 05 · Reviewable finding metadataSelected spans and placeholders · Direct call
- 02 · Per-call redaction policy → 05 · Reviewable finding metadataPer-finding Keep choices · Direct call
- 05 · Reviewable finding metadata → 06 · Caller review and policy choiceReview metadata · Response / return
- 06 · Caller review and policy choice → 02 · Per-call redaction policyUpdated options for a later call · Response / return
- 05 · Reviewable finding metadata → 07 · Enabled-span replacementApply enabled findings only · Direct call
- 01 · Caller-owned raw input → 07 · Enabled-span replacementOriginal replacement base · Direct call
- 07 · Enabled-span replacement → 08 · Transformed string and reportTransformed value · Response / return
- 05 · Reviewable finding metadata → 08 · Transformed string and reportAggregate report metadata · Response / return
- 08 · Transformed string and report → 06 · Caller review and policy choiceInspect any residual text · Response / return
- 08 · Transformed string and report → 09 · Caller-owned clipboard or file exportCaller controls subsequent disclosure · Response / return
CHECKS & RESULTS
What was checked.
A source review shows what the code does. It is not a fresh test of the running app.
Code and development records reviewedReviewed
The code, tests and available development records were checked. Reported test results keep their original scope. No fresh app or live deployment check was run for this write-up.
- Scope of this check
- Code review, not a fresh run of the app
NEXT
Still to work through.
The July correctness audit records 57 core tests passing, but those tests were not rerun here. A detection-rate claim needs a versioned, independently reviewed benchmark with both sensitive examples and ordinary text that should remain unchanged. The synchronous core also does not poll cancellation; Omitto handles task scheduling and rejects results that no longer belong to the current input.