Skip to content

Documentation

How DataAnchor works

A precise description of the prototype — every rule the demo applies, the schemas it produces, and what is planned but not yet built.

Overview

DataAnchor is a proposed data layer that sits between unstructured business information — documents, emails, support tickets, messages — and the AI applications, APIs and databases that consume it. Its job is to turn text into clean, validated, structured JSON while keeping sensitive identifiers out of downstream systems.

Today, DataAnchor exists as this website and a working browser-based prototype of the pipeline. The prototype is intentionally rule-based: it shows the shape of the product — the stages, the output contract, the validation behaviour — without depending on a model or a backend.

Prototype status

CapabilityStatusNotes
Input normalisationPrototypePasted text up to 20,000 characters.
Identifier detection & redactionPrototypeEight detector types; replace, mask and off modes.
Classification & extractionPrototypeRule-based, three document types plus a generic fallback.
Schema validationPrototypeBuilt-in schemas only.
HTTP API & SDKsIn designInterface shown on the home page is illustrative.
Custom schemasIn designPlanned to use JSON Schema.
Model-assisted extraction, files & OCRPlannedNot implemented.
Routing & deliveryPlannedNot implemented.

Pipeline

The planned product processes every input through six stages. The prototype implements the first five.

  1. Input — normalise line endings and whitespace, enforce limits.
  2. Detect — find identifiers and classify the document.
  3. Redact — replace identifiers with consistent, typed placeholders.
  4. Extract — map text to schema fields, normalising dates, amounts and enums.
  5. Validate — check types, formats and required fields; set processed or needs_review.
  6. Route — deliver the record to its destination (planned).

In the planned service, extraction operates on redacted text so that no later stage sees raw identifiers. In the browser prototype, rules read the original text locally and only redacted values are written to the output.

Demo engine

Working in prototype

The engine is about 1,500 lines of dependency-free TypeScript in src/lib/engine. It is deterministic — the same input and mode always yield the same output — and it performs no network I/O. It is covered by automated tests in tests/engine.test.ts.

Detectors

When two detections overlap, the higher-priority kind wins (secret, email, IBAN, card, SSN, IP, phone, name), so an email address is never partially redacted as a name.

KindPlaceholderMethodRule
Email address[EMAIL_n]Patternlocal@domain.tld with a 2+ letter top-level domain.
Phone number[PHONE_n]Pattern + shape7–15 digits; needs “+”, parentheses or two separators — or nearby words such as “call” or “phone”. Date-shaped numbers are rejected.
Payment card[CARD_n]Pattern + Luhn13–19 digits with optional spaces or dashes, accepted only if the Luhn checksum passes.
IBAN[IBAN_n]Pattern + mod-97Country code, check digits and account groups, verified with the ISO 7064 mod 97-10 checksum.
US SSN[SSN_n]Pattern + rangesAAA-GG-SSSS, excluding the 000, 666 and 9xx areas and zero groups.
IPv4 address[IP_n]PatternFour octets in the 0–255 range.
API key / secret[SECRET_n]Known formatsCommon key prefixes (for example sk_live_, AKIA, ghp_, xoxb-), JWTs, and values assigned to api_key=, token: or password=.
Person name[NAME_n]ContextCapitalised names after “this is”, “my name is”, “From:”, “Reported by:”, greetings or on the line after a sign-off. Later mentions of the same name are linked.

Classification

Each matching rule adds its weight to one document type. The highest total wins if it reaches 3; otherwise the input is reported as unknown and validated against the generic schema with status needs_review.

TypeSignalWeight
invoice“invoice” keyword+3
invoiceINV- identifier+3
invoicedue-date phrase+2
invoiceremittance terms+1
invoicebilling language+1
support_ticket“ticket” keyword+3
support_ticketticket identifier+3
support_ticketpriority field+2
support_ticketfailure language+2
support_ticketHTTP / error status+1
support_ticketreproduction details+1
customer_emailemail headers+3
customer_emailgreeting+1
customer_emailsign-off+1
customer_emailorder / purchase language+2
customer_emailrefund / cancellation request+2

Normalisation

  • Dates — ISO dates, “October 30, 2026”, “30 Oct 2026”, DD.MM.YYYY and MM/DD/YYYY become YYYY-MM-DD. Impossible dates are rejected. Dates without a year are kept as written and fail validation rather than receiving an invented year. Ambiguous slash dates are read as MM/DD/YYYY and noted.
  • Amounts — US (1,250.00) and European (1.250,00) formats become numbers. A labelled total is preferred, then an amount introduced by words such as “for” or “charged”, then the largest value.
  • Currencies — explicit ISO 4217 codes are used as-is. Symbols are mapped (€ → EUR, £ → GBP); “$” is assumed to be USD and that assumption is reported.
  • Enums — priority, ticket category, email intent and payment method come from keyword scoring and are only set when a keyword matches.

Schemas

Each document type has a versioned schema. Fields marked required must validate for the result to be processed; PII fields are redacted or masked in the output according to the selected mode.

invoice@v1

Invoices and payment requests, including remittance details.

FieldTypeRuleDescription
document_typeenumrequiredAlways invoice.
invoice_idstringrequiredInvoice reference such as INV-2048 or Invoice #4471.
po_numberstringPurchase-order reference, if present.
organizationstringrecommendedIssuing or requesting organisation.
contact_namestringPIIPerson named as the contact (context heuristic).
contact_emailemailPIIFirst email address in the document.
contact_phonephonePIIFirst phone number in the document.
amountnumberrequiredPrimary amount — a labelled total first, otherwise the best candidate.
currencycurrencyrequiredISO 4217 code, from an explicit code or a currency symbol.
issue_datedateDate introduced by “dated”, “issued” or similar.
due_datedaterecommendedDate introduced by “due”, “by”, “before” or similar.
payment_methodenumPayment method mentioned in the text.
bank_accountstringPIIIBAN, validated with the ISO 7064 mod-97 checksum.
statusenumprocessed when every required field validated, otherwise needs_review.

support_ticket@v1

Bug reports, incidents and help-desk requests.

FieldTypeRuleDescription
document_typeenumrequiredAlways support_ticket.
ticket_idstringrecommendedTicket reference such as TKT-4821 or Case #5512.
priorityenumrecommendedExplicit priority, or urgent when urgency keywords appear.
categoryenumrequiredKeyword-scored category of the issue.
organizationstringCustomer organisation.
reporter_namestringPIIPerson who reported the issue (context heuristic).
reporter_emailemailPIIFirst email address in the ticket.
contact_phonephonePIIFirst phone number in the ticket.
account_idstringCustomer or account identifier such as ACC-77120.
error_codestringHTTP status or application error code.
incident_datedateFirst fully specified date in the ticket.
subjectstringValue of a Subject: line, if present.
statusenumprocessed when every required field validated, otherwise needs_review.

customer_email@v1

Inbound customer correspondence.

FieldTypeRuleDescription
document_typeenumrequiredAlways customer_email.
subjectstringValue of a Subject: line, if present.
intentenumrequiredKeyword-scored request intent.
order_idstringOrder reference such as #BW-55821.
organizationstringSender's organisation.
sender_namestringPIISender's name (context heuristic).
sender_emailemailrecommended · PIIFirst email address in the message.
contact_phonephonePIIFirst phone number in the message.
amountnumberPrimary amount mentioned.
currencycurrencyISO 4217 code for amount.
dates_mentioneddate[]All fully specified dates, normalised to ISO 8601.
statusenumprocessed when every required field validated, otherwise needs_review.

generic@v1

Fallback when no document type has enough matching signals.

FieldTypeRuleDescription
document_typeenumrequiredAlways unknown.
organizationstringOrganisation name, if one is recognisable.
contact_namestringPIIPerson name (context heuristic).
contact_emailemailPIIFirst email address.
contact_phonephonePIIFirst phone number.
amountnumberPrimary amount mentioned.
currencycurrencyISO 4217 code for amount.
dates_mentioneddate[]All fully specified dates, normalised to ISO 8601.
reference_idsstring[]Identifier-shaped tokens such as ABC-1234.
statusenumprocessed when every required field validated, otherwise needs_review.

Redaction modes

ModeIn textIn JSON
redact[EMAIL_1]"[REDACTED]"
masks•••@example.com"s•••@example.com"
offunchangedunchanged

Placeholders are consistent within one document: repeated values share a number, and a first or last name on its own is linked to the full name detected earlier. Free-text fields such as subject keep their wording, with any identifiers inside them replaced.

Illustrative API

In design

No API or SDK has been published. The examples below describe the intended interface so that the output contract can be discussed; names, parameters and endpoints are placeholders.

from dataanchor import DataAnchor   # placeholder package name client = DataAnchor(api_key="YOUR_API_KEY")result = client.extract(input=text, schema="invoice@v1", redact_pii=True) result.status       # "processed" | "needs_review"result.data         # dict matching invoice@v1result.redactions   # list of {type, token}result.warnings     # assumptions such as "$ assumed USD"

Privacy model

  • The demo runs entirely in the browser tab. Submitted text is never sent to a server.
  • Nothing is written to cookies, local storage or IndexedDB; text disappears on reload.
  • In production the site sends a Content-Security-Policy with connect-src 'self', so the browser itself blocks scripts from contacting other origins.
  • The console measures requests to other origins during each run using the Resource Timing API and shows the count.
  • No analytics, trackers or third-party scripts are loaded. Fonts are self-hosted.

Limitations

  • English-language text only; three document types plus a generic fallback.
  • Person names are found only in the contexts listed above. Names elsewhere are not redacted.
  • Postal addresses, dates of birth and most national ID formats are not detected.
  • Organisation names rely on labels, common suffixes (Inc., Labs, GmbH…) or phrases such as “from …”.
  • Pasted text only — no PDFs, images or attachments.
  • The prototype is a demonstration. It must not be used as a compliance control or relied on to remove all sensitive information.

See also the privacy notice and legal disclaimer below.