# REV Spain

# Technical Architecture

See the [Diagrams page](https://docs.emb.digital/books/rev-spain/page/diagrams) for the deployment diagram. See the [Functional Overview](https://docs.emb.digital/books/rev-spain/page/functional-overview) for goals, context, and users.

## 1. Building Block View

REV Spain is a monolith. Main internal modules:

- **Intake module** — claimant onboarding and document/data submission entry point
- **Extraction engine** — parses ITA and RNT documents (fixed-structure official Spanish government PDFs) using direct PDF text extraction (no OCR, since layout is standardized)
- **Unified.to adapter** — alternative ingestion path fetching employee/salary data directly from client HR/payroll systems
- **Project &amp; employee allocation module** — gathers project information and maps employees to projects
- **Eligibility rules engine** — evaluates R&amp;D tax credit eligibility criteria
- **Report generator** — produces both financial and technical claim reports
- **Access control** — role-based access for claimants, reviewers, and admins

## 2. Deployment View

### Stack

- Frontend: Vue.js 3 SPA
- Backend: Node.js / Express API
- Data &amp; document storage: MongoDB, including GridFS for document storage (no separate object storage service)

### Topology

- **VM 1** — runs the full application stack via Docker Compose (frontend, API, MongoDB)
- **VM 2** — reverse proxy handling the domain name and TLS termination, forwarding to VM 1

This is a single-server deployment: no horizontal scaling or failover across app instances currently exists.

## 3. Risks &amp; Technical Debt

- **Single point of failure** — the entire application stack (including the database) runs on one VM; no redundancy or failover.
- **No documented scaling path** — current architecture sits in tension with quality goals like fast data gathering and claims centralization at higher volume.
- **Shared storage engine** — MongoDB serves both transactional data and GridFS document storage; document I/O could contend with regular query load as usage grows.
- **External dependency** — the Unified.to ingestion path introduces availability dependency on a third party for one of the two data-gathering flows.
- **PII handling** — sensitive employee/salary data is processed directly by the core system in both ingestion paths; encryption, access control, and retention policies should be explicitly reviewed and documented.

# Diagrams

## Workflow — Claim Generation Flow

<svg id="bkmrk-upload-ita%2Frntor-con" style="width: 100%; height: auto; font-family: sans-serif;" viewbox="0 0 900 200" xmlns="http://www.w3.org/2000/svg"><defs><marker id="bkmrk-" markerheight="10" markerunits="strokeWidth" markerwidth="10" orient="auto" refx="8" refy="3"><path d="M0,0 L0,6 L9,3 z" fill="#4472c4"></path></marker></defs><g fill="#1f3864" font-size="12"><rect fill="#eef3fb" height="80" rx="6" stroke="#4472c4" width="130" x="10" y="60"></rect><text text-anchor="middle" x="75" y="90">Upload ITA/RNT</text><text text-anchor="middle" x="75" y="106">or connect</text><text text-anchor="middle" x="75" y="122">Unified.to</text><line marker-end="url(#arrow1)" stroke="#4472c4" stroke-width="2" x1="140" x2="170" y1="100" y2="100"></line><rect fill="#eef3fb" height="80" rx="6" stroke="#4472c4" width="130" x="170" y="60"></rect><text text-anchor="middle" x="235" y="96">Extraction /</text><text text-anchor="middle" x="235" y="112">Normalization</text><line marker-end="url(#arrow1)" stroke="#4472c4" stroke-width="2" x1="300" x2="330" y1="100" y2="100"></line><rect fill="#eef3fb" height="80" rx="6" stroke="#4472c4" width="140" x="330" y="60"></rect><text text-anchor="middle" x="400" y="90">Project Info +</text><text text-anchor="middle" x="400" y="106">Employee</text><text text-anchor="middle" x="400" y="122">Allocation</text><line marker-end="url(#arrow1)" stroke="#4472c4" stroke-width="2" x1="470" x2="500" y1="100" y2="100"></line><rect fill="#eef3fb" height="80" rx="6" stroke="#4472c4" width="130" x="500" y="60"></rect><text text-anchor="middle" x="565" y="96">Eligibility</text><text text-anchor="middle" x="565" y="112">Evaluation</text><line marker-end="url(#arrow1)" stroke="#4472c4" stroke-width="2" x1="630" x2="660" y1="100" y2="100"></line><rect fill="#eef3fb" height="80" rx="6" stroke="#4472c4" width="130" x="660" y="60"></rect><text text-anchor="middle" x="725" y="90">Report</text><text text-anchor="middle" x="725" y="106">Generation</text><text text-anchor="middle" x="725" y="122">(Fin. + Tech.)</text></g></svg>## Technical Architecture — Deployment

<svg id="bkmrk-internetvm-2-%E2%80%94-rever" style="width: 100%; height: auto; font-family: sans-serif;" viewbox="0 0 700 380" xmlns="http://www.w3.org/2000/svg"><defs><marker id="bkmrk--1" markerheight="10" markerunits="strokeWidth" markerwidth="10" orient="auto" refx="8" refy="3"><path d="M0,0 L0,6 L9,3 z" fill="#548235"></path></marker></defs><g fill="#375623" font-size="12"><text font-size="13" text-anchor="middle" x="350" y="20">Internet</text><line marker-end="url(#arrow2)" stroke="#548235" stroke-width="2" x1="350" x2="350" y1="28" y2="55"></line><rect fill="#e2efda" height="55" rx="6" stroke="#548235" width="200" x="250" y="55"></rect><text text-anchor="middle" x="350" y="78">VM 2 — Reverse Proxy</text><text font-size="11" text-anchor="middle" x="350" y="94">(domain name, TLS)</text><line marker-end="url(#arrow2)" stroke="#548235" stroke-width="2" x1="350" x2="350" y1="110" y2="140"></line><rect fill="none" height="210" rx="6" stroke="#548235" stroke-dasharray="4,3" width="620" x="40" y="140"></rect><text font-size="13" x="60" y="160">VM 1 — Docker Compose Host</text><rect fill="#e2efda" height="70" rx="6" stroke="#548235" width="170" x="70" y="180"></rect><text text-anchor="middle" x="155" y="210">Vue.js 3 SPA</text><text font-size="11" text-anchor="middle" x="155" y="226">(frontend)</text><line marker-end="url(#arrow2)" stroke="#548235" stroke-width="2" x1="240" x2="280" y1="215" y2="215"></line><rect fill="#e2efda" height="70" rx="6" stroke="#548235" width="170" x="280" y="180"></rect><text text-anchor="middle" x="365" y="210">Node/Express API</text><text font-size="11" text-anchor="middle" x="365" y="226">(backend)</text><line marker-end="url(#arrow2)" stroke="#548235" stroke-width="2" x1="450" x2="490" y1="215" y2="215"></line><rect fill="#e2efda" height="70" rx="6" stroke="#548235" width="150" x="490" y="180"></rect><text text-anchor="middle" x="565" y="205">MongoDB</text><text font-size="11" text-anchor="middle" x="565" y="221">+ GridFS</text><text font-size="11" text-anchor="middle" x="565" y="237">(documents)</text></g></svg>

# Functional Overview

See the [Diagrams page](https://docs.emb.digital/books/rev-spain/page/diagrams) for the visual workflow.

## 1. Introduction &amp; Goals

REV Spain lets companies self-manage the process of claiming Spanish R&amp;D tax credits end to end: intake, eligibility check, extraction of employee/salary data from official documents, project information gathering, employee-to-project allocation, and generation of both financial and technical claim reports.

### Quality Goals

- Self-service — minimal need for manual handling by internal teams
- Ease of use for non-technical claimants
- Fast data gathering (short time-to-claim)
- Centralization of claims across the organization

### Stakeholders

- Top Management
- Head of Business Unit
- R&amp;D Consultants

## 2. System Scope &amp; Context

### User Types

- Self-service claimants
- Internal reviewers
- Admins

### External Systems

- **Unified.to** — third-party integration used as an alternative ingestion path when a client does not want to upload sensitive employee/salary data directly (e.g. pulls HR/payroll data from the client's own systems).

### Sensitive Data Boundary

REV Spain handles sensitive employee and salary data directly in both ingestion paths: either after extraction from uploaded ITA/RNT documents, or via the Unified.to integration. There is no path that avoids the core system processing PII — this should be treated as a compliance-relevant boundary (encryption at rest/in transit, access control, retention policy).

## 3. Claim Generation Flow (Functional)

1. Claimant submits ITA/RNT documents, or connects via Unified.to
2. Employee &amp; salary data is normalized
3. Claimant/reviewer provides project information
4. Employees are mapped to projects
5. Eligibility criteria are evaluated
6. Financial and technical reports are generated
7. Internal reviewer validates the claim before export/submission