Engineering perspectives
Building AI-Ready Enterprise Data: Data Governance, Quality, Lineage, RAG and Secure Access
Why vector search fails without ownership, classification and authorization at retrieval time.
25 June 2026 · 27 min read
Retrieval-augmented generation and enterprise agents fail quietly when data is duplicated, stale, misclassified, or legally fragile. AI-ready data governance connects catalog metadata, quality rules, access control, lineage, and retention to the embeddings and documents your models consume. European organizations face GDPR, sector regulators, and customer audits that ask not only what the model said, but which records informed the answer. This guide defines AI-ready data principles, RAG pipeline architecture, catalog integration, quality checklists, and operating models for data owners and platform teams. It links to enterprise agentic AI architecture and enterprise AI security. Damascode, Digital Agency, Lda assists with data platform design through IT consulting and implementation via nearshore software development.
Table of contents
- What AI-ready data means
- Governance vs enablement
- Data domains and classification
- Reference RAG data architecture
- Catalog, lineage, and ownership
- Ingestion and chunking strategies
- Access control for vectors
- Quality dimensions and SLAs
- PII, special categories, and lawful basis
- Freshness, versioning, and deletion
- Evaluation datasets and golden questions
- Operating model and RACI
- Implementation examples
- Migration checklist
- FAQ
- References
What AI-ready data means
AI-ready data is discoverable, classified, permitted for a stated purpose, technically fit for embedding and retrieval, and removable when retention expires or subjects exercise erasure rights. It is not "dump everything into a vector database."
| Pillar | Question answered |
|---|---|
| Legal | May we use this for AI assistance? |
| Security | Who may retrieve which chunks? |
| Quality | Are facts current and consistent? |
| Operations | How fast do index and deletes propagate? |
| Economics | What does storage and re-embedding cost? (FinOps) |
Without pillars, RAG becomes a shadow copy of production data with weaker controls than the source systems.
Governance vs enablement
Governance teams sometimes fear blocking innovation. Frame governance as guardrails that speed shipping:
- Approved datasets shorten legal review per feature.
- Standard chunking and metadata improve retrieval precision.
- Automated deletion hooks reduce GDPR incident risk.
Platform engineering delivers self-service ingestion pipelines on the internal developer platform; data stewards own definitions and access policies.
Data domains and classification
Map domains before tooling:
| Domain | Examples | Typical classification |
|---|---|---|
| Public marketing | Website, brochures | Public |
| Internal ops | Runbooks, architecture ADRs | Internal |
| Customer | Tickets, contracts | Confidential |
| HR / health | Reviews, medical notes | Restricted / special category |
Classification drives: encryption requirements, whether data may enter shared model APIs, chunk visibility in multi-tenant indexes, and logging verbosity.
+----------------+ +------------------+ +----------------+
| Source systems | --> | Ingestion zone | --> | Curated corpus |
| (CRM, wiki, | | (ETL, PII scan) | | (per domain) |
| data lake) | +------------------+ +-------+--------+
+----------------+ |
v
+--------+---------+
| Vector index + |
| metadata store |
+--------+---------+
|
v
+--------+---------+
| RAG / Agent apps |
+------------------+Reference RAG data architecture
Logical components:
- Connector layer: incremental sync from sources (API, CDC, object storage).
- Normalization: HTML to text, OCR, language detection.
- Enrichment: title, source URL, owner, classification, valid_from/to.
- Chunking: structure-aware splits (headings, tables).
- Embedding job: batch or streaming with model version recorded.
- Index: vector DB plus keyword (hybrid search recommended).
- Serving API: query with user context for ACL filter.
Hybrid retrieval comparison:
| Mode | Strength | Weakness |
|---|---|---|
| Vector only | Semantic match | Misses exact SKUs, IDs |
| Keyword only | Exact tokens | Synonym gap |
| Hybrid + rerank | Best enterprise default | Higher latency/cost |
Catalog, lineage, and ownership
Integrate with catalogs such as OpenMetadata, DataHub, or cloud-native solutions. Minimum metadata per AI dataset:
dataset_id, business name, description- data owner and steward emails
- lawful basis (GDPR Art. 6) and DPIA reference if needed
- retention policy ID
- allowed use cases (
support_bot,engineering_copilot) - embedding model version
- upstream source system IDs
Lineage must show: source table or file -> transformation job -> chunk ID -> vector ID. When a customer deletes a profile, lineage finds all derived chunks.
Example lineage record (YAML):
lineage:
chunk_id: chk_8f2a91
source:
system: confluence
page_id: "4429182"
version: 17
transforms:
- job: normalize_html_v3
at: "2026-10-01T08:00:00Z"
- job: embed_text-embedding-3-large
at: "2026-10-01T08:05:00Z"
vector_ids: [vec_9912, vec_9913]
classification: internal
owner: platform-docs@example.comIngestion and chunking strategies
Poor chunking causes wrong answers more often than weak models.
| Content type | Chunk strategy |
|---|---|
| Policies | Split on H2, keep article title prefix |
| API docs | One endpoint per chunk with method + path |
| Tickets | Thread summary + latest status chunk |
| Tables | Row groups with header row repeated |
Python illustration for structure-aware chunking:
from dataclasses import dataclass
@dataclass
class Chunk:
text: str
metadata: dict
def chunk_markdown_sections(md: str, max_chars: int = 1200) -> list[Chunk]:
sections = md.split("\n## ")
out: list[Chunk] = []
for i, sec in enumerate(sections):
body = sec if i == 0 else "## " + sec
while len(body) > max_chars:
out.append(Chunk(body[:max_chars], {"part": "split"}))
body = body[max_chars:]
out.append(Chunk(body, {"part": "whole"}))
return outStore source_version on every chunk so retrieval can prefer latest version during conflicts.
Access control for vectors
Vectors are not magic security boundaries. Implement filter at query time:
type QueryContext = { userId: string; groups: string[]; clearance: string };
export function buildMetadataFilter(ctx: QueryContext): Record<string, unknown> {
return {
$and: [
{ classification: { $lte: ctx.clearance } },
{ allowed_groups: { $in: ctx.groups } },
{ valid_to: { $gte: new Date().toISOString() } },
],
};
}Synchronize group membership from identity provider on a schedule; fail closed if sync is stale beyond SLA.
For multi-tenant SaaS, physical or logical index isolation per tenant prevents cross-tenant approximate nearest neighbor leaks.
Quality dimensions and SLAs
Define measurable quality for AI corpora:
| Dimension | Metric | Example SLA |
|---|---|---|
| Freshness | Lag source to index | < 4 hours internal wiki |
| Completeness | % docs ingested vs catalog | > 99% approved set |
| Accuracy | Human eval on golden set | > 85% correct attribution |
| Consistency | Duplicate chunk rate | < 2% |
| Safety | PII hits in index | 0 critical findings |
Automate scans: regex and NER for IBAN, email, health terms in wrong domains.
PII, special categories, and lawful basis
GDPR and similar laws require clarity:
- Purpose limitation: do not reuse support transcripts for marketing embeddings without basis.
- Minimization: redact names where not needed for answers.
- Erasure: propagate deletes to vector store within documented timeline.
- Special category data: default deny for general copilots unless explicit legal pathway.
Document decisions in the AI register. Involve DPO early when connecting HR or health sources.
Freshness, versioning, and deletion
Versioning: when Confluence page updates, mark old chunks superseded before new embed job completes; serving layer excludes superseded unless explicitly historical mode.
Deletion API:
def delete_subject_data(subject_id: str, index_client) -> int:
chunk_ids = index_client.find_chunks(metadata={"subject_id": subject_id})
index_client.delete_vectors([c.vector_id for c in chunk_ids])
index_client.delete_metadata(chunk_ids)
return len(chunk_ids)Test erasure quarterly with synthetic subjects.
Evaluation datasets and golden questions
Build a golden Q&A set per domain with:
- question text
- expected answer fragments
- required source document IDs
- negative tests (question should refuse)
Run eval on every embedding model change or major ingestion refactor. Track precision@k and citation accuracy.
| Eval type | Detects |
|---|---|
| Retrieval-only | Wrong chunk selected |
| End-to-end | Model hallucination despite good retrieval |
| Refusal | Over-answering from restricted docs |
Connect eval failures back to stewards, not only to prompt engineers.
Operating model and RACI
| Activity | Data owner | Platform | Security | Legal |
|---|---|---|---|---|
| Approve new source | A | C | C | I |
| Build connector | I | R | C | I |
| Classification | A | I | C | C |
| Incident on leak | I | R | A | C |
R = responsible, A = accountable, C = consulted, I = informed.
Quarterly corpus review: remove obsolete projects, refresh classifications, validate owners still employed.
Implementation examples
Airflow-style DAG fragment (conceptual)
def ingest_wiki_domain(domain: str, **context):
docs = fetch_wiki(domain)
normalized = [normalize(d) for d in docs]
chunks = flatten(chunk_doc(d) for d in normalized)
embed_and_upsert(chunks, model="text-embedding-3-large")dbt test for catalog alignment
-- fail if orphaned chunks exist without catalog entry
select c.chunk_id
from ai_chunks c
left join catalog.datasets d on c.dataset_id = d.id
where d.id is null;HCL for Terraform module tags (illustration)
resource "aws_s3_bucket" "ai_corpus" {
bucket = "corp-ai-corpus-prod"
tags = {
DataClassification = "internal"
DataOwner = "platform-docs"
RetentionDays = "365"
AIUseCase = "engineering_copilot"
}
}Tag cloud objects and index collections consistently for FinOps chargeback.
Contracts with model and SaaS vendors
AI-ready data governance extends to vendor contracts:
- Specify permitted data types (no special category without addendum).
- Define retention and deletion on vendor logs.
- Clarify training use prohibition or opt-out.
- Require breach notification timelines compatible with GDPR Article 33.
Maintain a register mapping each corpus to vendor DPAs. Block ingestion jobs from starting if DPA status is expired.
Multilingual and multimodal corpora
European enterprises serve multiple languages. Governance implications:
| Aspect | Practice |
|---|---|
| Language tags | Store lang on chunks for filtered retrieval |
| Translation | Document if translations are machine-generated |
| OCR quality | Score confidence; exclude low-confidence health scans |
| Audio/video | Transcripts need speaker consent and retention rules |
Use language-specific golden eval sets; do not assume English-only retrieval metrics predict French support quality.
Conflict resolution when sources disagree
RAG systems break trust when wiki and CRM disagree. Implement precedence rules in metadata:
SOURCE_PRECEDENCE = {"crm": 100, "policy_pdf": 90, "wiki": 50, "chat_log": 10}
def rank_chunks(chunks: list[dict]) -> list[dict]:
return sorted(
chunks,
key=lambda c: (SOURCE_PRECEDENCE.get(c["source_type"], 0), c["updated_at"]),
reverse=True,
)Surface citations in UI so users can judge conflicts. Agents should not silently merge contradictory financial figures.
Observability for data pipelines
Monitor ingestion like any critical service:
| Metric | Alert threshold (example) |
|---|---|
| ingest_lag_seconds | > SLA for domain |
| embed_failures_rate | > 1% over 15m |
| acl_filter_empty_results | spike vs baseline |
| delete_job_backlog | > 1000 pending subjects |
Dashboards belong in the platform observability stack; tie alerts to data owner on-call rotation for business context.
Working with external delivery partners
When extending teams through nearshore software development or outsourcing, provide:
- Approved dataset list and forbidden sources
- Classification handling rules in Definition of Done
- Requirement to run golden eval before merge
Partners should not create shadow indexes in personal cloud accounts. All embed jobs run in tenant-controlled infrastructure with the same ACL model as production.
Migration checklist
Discovery
- Inventory sources proposed for RAG
- Classify each source; deny restricted until reviewed
- Map lawful basis and retention
Build
- Catalog entries and lineage jobs
- PII scanning in ingestion path
- ACL filters tested with sample users
- Hybrid retrieval configured
Operate
- Golden eval suite in CI
- Deletion and supersede workflows tested
- Monitoring on lag and error rates
- Runbook for poisoned document (security article)
Scale
- Self-service template on IDP for approved domains
- Cost dashboards for embed jobs
- Partner squads onboarded via software development outsourcing if needed
Questions about corpus design: contact or about us.
FAQ
Can we use production DB replicas directly?
Avoid raw replicas unless row-level security replicates perfectly into filters. Prefer curated exports with minimization.
One big index or many?
Many indexes or namespaces by domain/classification simplify ACL and blast radius.
How often to re-embed everything?
Only when embedding model changes or chunk strategy shifts materially; otherwise incremental updates.
Does GDPR block cloud embedding APIs?
Depends on DPA, region, and data content. Some teams embed on-prem or use EU regions with pseudonymized text.
Who owns wrong answers?
Product owns UX; data owner owns corpus quality; platform owns pipeline SLOs. Document in RACI.
How does governance interact with agents?
Agents multiply retrieval calls; stale or over-broad corpora increase injection risk. Align with agentic architecture.
What is a realistic first corpus for MVP?
Internal engineering docs or approved support macros: high value, manageable classification, clear owners.
How do we handle acquisitions?
Freeze new ingest from acquired systems until classification and DPA status confirmed. Run parallel index namespace during integration.
Should customers opt in to AI training on their tickets?
Default no for training on customer content; contract language must match technical controls (no background fine-tune on tenant data).
Who pays for re-embedding after model change?
Assign cost center to the team that requested model upgrade; FinOps tracks job cost (FinOps guide).
Stewards workshop agenda (half day)
Use this agenda when kicking off AI-ready data for a domain:
- Inventory sources and classify (90 minutes).
- Define lawful basis and retention (60 minutes).
- Sketch chunking and owner RACI (60 minutes).
- Agree golden questions for eval (45 minutes).
- Assign actions for connector MVP (15 minutes).
Facilitators: data steward, platform engineer, security liaison. Output: signed dataset charter in catalog.
Document lifecycle state machine
Model corpus documents explicitly:
DRAFT --> APPROVED --> INDEXED --> ACTIVE
| |
v v
REJECTED SUPERSEDED --> ARCHIVED --> DELETEDTransitions triggered by steward approval, ingestion success, new source version, retention job, or erasure request. Agents should retrieve only ACTIVE unless historical mode enabled for internal audit UI.
Automate transitions in workflow engine; manual spreadsheet tracking fails above ten sources.
Metadata schema reference
Minimum chunk metadata fields:
| Field | Type | Required | Notes |
|---|---|---|---|
| chunk_id | string | yes | Stable identifier |
| dataset_id | string | yes | Catalog foreign key |
| source_type | enum | yes | wiki, crm, pdf, etc. |
| source_version | string | yes | Vendor version id |
| classification | enum | yes | public/internal/confidential |
| allowed_groups | string[] | yes | IAM groups |
| lawful_basis | string | yes | GDPR Art. 6 reference |
| valid_from | datetime | yes | ISO-8601 |
| valid_to | datetime | no | null if open-ended |
| embedding_model | string | yes | Versioned model id |
| language | string | yes | BCP 47 tag |
Validate schema in ingestion pipeline; reject chunks missing required fields rather than defaulting to permissive values.
Board reporting template
Quarterly one-page summary for executives:
- Count of approved AI datasets and owners
- Average ingestion lag vs SLA
- Golden eval score trend
- Open findings from security/privacy reviews
- Planned corpus expansions and cost estimate
Tie metrics to business outcomes: support deflection, engineer self-serve success, not embedding counts alone.
Connector hardening checklist
Before connecting a new source system:
- Service account uses least privilege read scopes
- Credentials stored in vault, rotated on schedule
- Network path documented (VPC peering, private link)
- Rate limits respect source API quotas
- Incremental sync uses change tokens or CDC, not full scrape hourly
- Error handling dead-letters to ops queue with payload redaction
Failed connectors should not partially index corrupt chunks; use transactional batches per document where the vector store supports upsert idempotency.
Sample data handling for non-production
Developers request realistic RAG tests without copying production. Platform provides synthetic corpus packs: generated tickets, fake customer names, and labeled edge cases including indirect injection fixtures for security training. Refresh packs quarterly; never refresh by copying prod without anonymization pipeline sign-off.
Staging indexes must use separate namespaces and credentials from production. CI eval jobs read only synthetic packs unless explicit break-glass approval exists for masked subsets.
When product managers request "just copy prod for better demos," redirect to synthetic packs plus a small manually curated golden set approved by stewards. The incremental quality gain rarely justifies privacy and security risk of bulk prod copies in lower environments.
Index capacity planning
Vector index size drives cost and query latency. Estimate:
- Average chunk size in tokens and embedding dimension.
- Number of documents and expected growth for three years.
- Replica count for high availability.
Hypothetical illustration: One million vectors at 1536 dimensions with metadata might occupy on the order of tens of gigabytes including indexes (vendor-specific; measure in proof of concept). Plan re-sharding before query p95 degrades. FinOps should see index growth alongside embed job costs in the same dashboard.
Schedule annual corpus certification: stewards re-attest classification, lawful basis, and owner employment status for every production dataset. Decertified datasets move to read-only archive until remediated or deleted.
Record certification outcomes in the catalog audit log for regulator requests and internal quality reviews.
Assign an executive sponsor for the top three customer-facing corpora so clear escalation paths exist when stewards and product disagree on scope.
References
- GDPR full text (EUR-Lex): https://eur-lex.europa.eu/eli/reg/2016/679/oj
- ICO guidance on AI and data protection (UK): https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/artificial-intelligence/
- NIST Privacy Framework: https://www.nist.gov/privacy-framework
- DAMA-DMBOK (data management body of knowledge): https://www.dama.org/cpages/body-of-knowledge
- OpenMetadata: https://open-metadata.org/
- DataHub: https://datahubproject.io/
- OWASP LLM Top 10 (data disclosure): https://owasp.org/www-project-top-10-for-large-language-model-applications/
- Related insights: agentic AI, AI security, FinOps, platform engineering
Planning a project in Portugal?
Tell us about your stack, timeline and team setup. We respond on business days.
