A real analysis
Read the output before you install anything
Five artefacts from an actual run of the demonstration project that ships with EVIDENT. Not a mock-up and not a screenshot: the exports, as the product produced them.
Captured from build
2026-09-09 · 86365ef9_run_9152b8cac23440148135b5ea30eeace7
Everything in them is invented. Nébula Shop is a fictional shop written so this product has something real to read, and it contains on purpose the awkward things a real system has — a table whose name does not match its class, a national identifier, a special category hiding in an ordinary-looking column, two log calls that hand a whole customer to a logger, and references pointing at rows that were deleted.
Why does it say that? — one answer, in full
The reports below are worth reading only if their claims can be questioned. This is what the product returns when somebody asks about one field of the demonstration: eight steps, in the order they were reached, across all five kinds of fact. It came out of the same endpoint the interface calls, and it is printed here unedited.
main.customers.dni
WHY?
OBSERVED
Property dni of Customer was read from the repository
maps to dni
OBSERVED
Column dni of customers was read from the database
INFERRED
Customer.dni maps to main.customers.dni.
Confidence 1.00. NAMING_CONVENTION
DECLARED
Lawful basis: Performance of a contract
Marketing consent is held separately and is not what this covers.
DECLARED
Purpose: Account management, order fulfilment and transactional messages
DECLARED
Recipient: The delivery carrier, for the name, the address and the telephone number only
DOCUMENTARY
Retention: 24 months after the account is closed
DECIDED
Confirmed by a reviewer on 2026-09-09.
No reason was recorded.
Read the order. Two things read from systems, one conclusion drawn by a rule from what was read, three facts the organisation states about itself, one carried in a controlled document, and a person’s decision at the end. Nothing in the middle is presented as observation, and the last step is the only one with a name against it.
What each field is, before any report is written
Every column in the demonstration carries two answers, kept apart. What the regulation calls it — personal data, an Article 9 special category, Article 10 conviction data, or not established — and how much attention EVIDENT suggests it needs. The second is this product’s own ordering and says so: the regulation defines no such scale.
Three columns here are worth opening. staff_records.health_notes is a special category, and what establishes it is not the name — "health notes" can be many things — but an employee number, a full name and an email address in the same table. staff_records.criminal_record_check is Article 10, a different regime with a different lawful basis, sitting two rows away at the same sensitivity: the clearest way to see that the level and the category are different questions. devices.device_fingerprint is neither. The name reaches for something Article 9 covers, nothing corroborates it, so the category stays not established and the row asks for a person.
And warehouse_slots.orientation is the direction a shelf faces. It matches the word the regulation uses for sexual orientation, the columns around it argue that reading out, and it appears with no category and no citation — which is the result, not an omission.
The record of processing activities
What personal data the system holds and where, with what the organisation has stated about each activity. Read the purpose column: two of the five activities have one, three do not, and the report says so rather than leaving the cell empty.
Article 30 inventory, drawn from the fields this analysis assessed
| Field | Value |
|---|---|
| System | Assessment |
| Analysis run | 86365ef9_run_9152b8cac23440148135b5ea30eeace7 |
| Exported | 2026-09-09 |
What this report cannot say
- A purpose, a legal basis, a retention period and a recipient are decisions an organisation made, not facts a schema carries. They are read here from what this project has stated, and every stated fact is printed with the class of evidence it is: declared where somebody said so, documented where a controlled document backs it.
- 5 of 7 processing activities have no recorded purpose. They are listed with the purpose not recorded rather than left blank, because a blank in this column reads as nothing to report.
- 41 fields are neither confirmed nor ruled out as personal data, and listed as unknown rather than counted as clean, because an Article 30 record built on a silent assumption is one nobody can defend.
At a glance
| Measure | Value |
|---|---|
| Personal data fields | 16 |
| Special category | 1 |
| With a stated purpose | 2/7 |
| Processing activities | 7 |
| Unclassified | 41 |
Processing activities
One entry per object holding personal data. The purpose, the legal basis and the retention period are decisions an organisation records; this is the inventory they attach to.
Read from the systems, concluded from what was read, stated by the organisation and carried in a controlled document, and some of it never established.
| Object | Severity | Fields | Data subjects | Purpose | Legal basis | Retention |
|---|---|---|---|---|---|---|
| main.customer_addresses | High | postcode, street | CUSTOMER | Delivering an order to the address the customer gave (declared) | Not recorded | Not recorded |
| main.customers | High | birth_date, dietary_preference, dni, email, full_name, phone | CUSTOMER | Account management, order fulfilment and transactional messages (declared) | Performance of a contract (declared) | 24 months after the account is closed (documented) |
| main.devices | High | device_fingerprint | Subject type not recorded | Not recorded | Not recorded | Not recorded |
| main.legacy_subscribers | High | CUSTOMER | Not recorded | Not recorded | Not recorded | |
| main.payments | High | card_last4 | Subject type not recorded | Not recorded | Not recorded | Not recorded |
| main.staff_records | Critical | criminal_record_check, email, full_name, health_notes | CUSTOMER | Not recorded | Not recorded | Not recorded |
| main.support_tickets | High | body | Subject type not recorded | Not recorded | Not recorded | Not recorded |
Fields
Every field not ruled out as personal data, most sensitive first. Unknown is listed rather than counted as clean.
Read from the systems and concluded from what was read.
| Field | Severity | Legal category | Sensitivity | Rests on | Data subjects |
|---|---|---|---|---|---|
| main.staff_records.health_notes | Critical | Special category | High | Context | Not recorded |
| main.customer_addresses.postcode | High | Personal data | Standard | Name only | CUSTOMER |
| main.customer_addresses.street | High | Unknown | Unknown | None | CUSTOMER |
| main.customers.birth_date | High | Personal data | Standard | Name only | CUSTOMER |
| main.customers.dietary_preference | High | Unknown | Unknown | None | Not recorded |
| main.customers.dni | High | Personal data | Elevated | Name only | CUSTOMER |
| main.customers.email | High | Personal data | Standard | Name only | CUSTOMER |
| main.customers.full_name | High | Personal data | Standard | Name only | CUSTOMER |
| main.customers.phone | High | Personal data | Standard | Name only | CUSTOMER |
| main.devices.device_fingerprint | High | Possibly Special category | High | Name only · needs review | Not recorded |
| main.legacy_subscribers.email | High | Personal data | Standard | Name only | CUSTOMER |
| main.payments.card_last4 | High | Unknown | Unknown | None | Not recorded |
| main.staff_records.criminal_record_check | High | Criminal convictions and offences | High | Self corroborating term | Not recorded |
| main.staff_records.email | High | Personal data | Standard | Name only | CUSTOMER |
| main.staff_records.full_name | High | Personal data | Standard | Name only | CUSTOMER |
| main.support_tickets.body | High | Unknown | Elevated | None · needs review | Not recorded |
| main.activity.latitude | Moderate | Personal data | Elevated | Name only | Not recorded |
| main.activity.location | Moderate | Unknown | Unknown | None | Not recorded |
| main.activity.longitude | Moderate | Personal data | Elevated | Name only | Not recorded |
| main.activity.occurred_at | Moderate | Unknown | Unknown | None | Not recorded |
| main.catalogue_items.active | Moderate | Unknown | Unknown | None | Not recorded |
| main.catalogue_items.description | Moderate | Unknown | Elevated | None · needs review | Not recorded |
| main.catalogue_items.name | Moderate | Unknown | Unknown | None | Not recorded |
| main.catalogue_items.price_cents | Moderate | Unknown | Unknown | None | Not recorded |
| main.catalogue_items.stock | Moderate | Unknown | Unknown | None | Not recorded |
| main.customer_addresses.city | Moderate | Unknown | Unknown | None | Not recorded |
| main.customer_addresses.country | Moderate | Unknown | Unknown | None | Not recorded |
| main.customer_addresses.delivery_notes | Moderate | Unknown | Elevated | None · needs review | Not recorded |
| main.customers.created_at | Moderate | Personal data | Standard | Name only | Not recorded |
| main.customers.marketing_opt_in | Moderate | Unknown | Unknown | None | Not recorded |
| main.customers.postal_code | Moderate | Unknown | Unknown | None | Not recorded |
| main.devices.first_seen_at | Moderate | Unknown | Unknown | None | Not recorded |
| main.devices.platform | Moderate | Unknown | Unknown | None | Not recorded |
| main.legacy_subscribers.source | Moderate | Unknown | Unknown | None | Not recorded |
| main.legacy_subscribers.subscribed_at | Moderate | Unknown | Unknown | None | Not recorded |
| main.order_lines.quantity | Moderate | Unknown | Unknown | None | Not recorded |
| main.order_lines.unit_price_cents | Moderate | Unknown | Unknown | None | Not recorded |
| main.orders.placed_at | Moderate | Unknown | Unknown | None | Not recorded |
| main.orders.status | Moderate | Unknown | Unknown | None | Not recorded |
| main.orders.total_cents | Moderate | Unknown | Unknown | None | Not recorded |
| main.payments.authorised_at | Moderate | Not personal | Standard | Name only | Not recorded |
| main.payments.method | Moderate | Unknown | Unknown | None | Not recorded |
| main.payments.status | Moderate | Unknown | Unknown | None | Not recorded |
| main.staff_records.employee_number | Moderate | Unknown | Unknown | None | Not recorded |
| main.staff_records.started_at | Moderate | Unknown | Unknown | None | Not recorded |
| main.support_tickets.created_at | Moderate | Personal data | Standard | Name only | Not recorded |
| main.support_tickets.status | Moderate | Unknown | Unknown | None | Not recorded |
| main.support_tickets.subject | Moderate | Unknown | Unknown | None | Not recorded |
| main.warehouse_slots.aisle | Moderate | Unknown | Unknown | None | Not recorded |
| main.warehouse_slots.capacity | Moderate | Unknown | Unknown | None | Not recorded |
| main.warehouse_slots.depth | Moderate | Unknown | Unknown | None | Not recorded |
| main.warehouse_slots.orientation | Moderate | Unknown | Unknown | None | Not recorded |
| main.warehouse_slots.position_x | Moderate | Unknown | Unknown | None | Not recorded |
| main.warehouse_slots.position_y | Moderate | Unknown | Unknown | None | Not recorded |
| main.warehouse_slots.position_z | Moderate | Unknown | Unknown | None | Not recorded |
| main.warehouse_slots.secret | Moderate | Not personal | Elevated | Name only | Not recorded |
| main.warehouse_slots.updated_at | Moderate | Personal data | Standard | Name only | Not recorded |
The risk register, including the risk that is in no column
A date of birth is moderate on its own and a postcode is low on its own. Together in one table they identify most of the people in it, and no scanner that looks at columns one at a time can say so. Every column named in that entry was classified before the rule was allowed to speak about it.
What was observed, with the evidence that raised it
| Field | Value |
|---|---|
| System | Assessment |
| Analysis run | 86365ef9_run_9152b8cac23440148135b5ea30eeace7 |
| Exported | 2026-09-09 |
What this report cannot say
- Likelihood, impact, an owner and a treatment decision are judgements a person makes. This register is what they are made against: every entry carries the evidence that raised it and nothing that nobody recorded.
- Inherent risk here is a band, not a score. Two entries in the same band are the same finding, and ordering them against each other would be arithmetic on an opinion.
At a glance
| Measure | Value |
|---|---|
| Entries | 1 |
| Critical | 1 |
| Treated | 0 |
Risk from combinations
Risk that is in no column and is in the combination of several. A date of birth is moderate on its own and a postcode is low on its own; together in one table they identify most of the people in it. Every column named here was classified before this rule was allowed to say anything about it.
Read from the systems and concluded from what was read.
| Scenario | Severity | Evidence | Inherent risk | Treatment |
|---|---|---|---|---|
| main.customers holds enough to identify a person without naming one | High | main.customers.birth_date, main.customers.postal_code | HIGH | Not recorded |
| main.devices links a person to where they went | High | main.devices.device_fingerprint, main.activity.latitude, main.activity.longitude, main.activity.location | HIGH | Not recorded |
Register
Ordered by inherent risk. Likelihood, impact, an owner and a treatment are judgements a person makes, and are recorded here as absent until somebody makes them. There is no review queue behind this register yet: its entries are derived each time the report is built, so nothing survives from one run to the next for a decision to attach to.
Read from the systems and concluded from what was read.
| Scenario | Severity | Category | Evidence | Inherent risk | Existing controls | Treatment |
|---|---|---|---|---|---|---|
| main.staff_records.health_notes holds special-category data | Critical | Compliance | Protected in its own right, which changes what the table around it requires. | High | None recorded | Not recorded |
Logging exposure
The findings nothing else in this category produces: the log calls that hand a whole customer to a logger, named down to the file and the line.
Where the application writes personal data, or a credential, into a log
| Field | Value |
|---|---|
| System | Assessment |
| Analysis run | 86365ef9_run_9152b8cac23440148135b5ea30eeace7 |
| Exported | 2026-09-09 |
What this report cannot say
- Nothing here decides what is sensitive. Every finding rests on a classification made elsewhere — by a rule, and in the best case confirmed by a person — and the table below says which. A finding resting on an unconfirmed proposal is worth checking before it is worth acting on.
- This reads the code that writes the logs, not the logs themselves. It establishes that an application would write a field to a log when that line runs; it does not establish that the line has ever run, or what is in any log file today.
- A call this reader did not recognise is a call it says nothing about. It finds a logger by the conventional names — log, logger, logging, console — so an application that wraps its logger in something named otherwise is a gap here rather than a clean result.
- A field named in a log call is retained for as long as the log is, which is almost never the retention this system’s record of processing declares, and it cannot be erased on request because nobody rewrites log archives.
At a glance
| Measure | Value |
|---|---|
| Log calls at risk | 2 |
| Entities logged whole | 2 |
| Credentials in log calls | 0 |
| Fields reaching a log | 6 |
| Resting on a decision | 0/2 |
Credentials named in a log call
A secret written to a log is in every copy of that log, including the ones already shipped to whoever aggregates them. Removing the call is half of the remedy and rotating the value is the other half.
Read from the systems.
| Where | Level | Names | Severity |
|---|---|---|---|
| No log call names a credential |
Entities handed whole to a logger
These write every field the class holds, and will write the next one somebody adds to it without anybody revisiting the line. They are the ones worth changing first.
Read from the systems.
| Where | Severity | Level | Writes to the log | Classification |
|---|---|---|---|---|
| api/src/services/customers.service.ts:34 | Critical | info | Customer.email, Customer.fullName, Customer.phone, Customer.dni, Customer.birthDate, Customer.dietaryPreference | Proposed by a rule |
| api/src/services/orders.service.ts:33 | Critical | info | Customer.email, Customer.fullName, Customer.phone, Customer.dni, Customer.birthDate, Customer.dietaryPreference | Proposed by a rule |
Classified fields written to a log
The call names a field the assessment says holds personal data, and the thing that holds it. A field in a log is retained for as long as the log is.
Read from the systems and concluded from what was read.
| Where | Level | Writes to the log | Classification |
|---|---|---|---|
| No call writes a classified field to a log |
About this check
- 2 calls hand a whole entity to a logger. Those are the ones worth changing first: they write every field the class holds today and every field somebody adds to it next month, without anybody revisiting the line.
- None of these rests on a classification a person has confirmed. They are findings about fields a rule proposed as personal, which is a good reason to look and a poor reason to act before looking.
Coverage, and what could not be seen
The other half of every report. How much of the assessment is settled, how much is waiting for a person, and what the analysis could not reach at all.
What was analysed, what was not, and why
| Field | Value |
|---|---|
| System | Assessment |
| Analysis run | 86365ef9_run_9152b8cac23440148135b5ea30eeace7 |
| Exported | 2026-09-09 |
What this report cannot say
- Coverage is measured against what this analysis could see. A schema the credential cannot read and a repository path nobody configured are both absent from the denominator, which is why the stages that ran are listed beside the figure.
- An element the application declares it does not store is not a gap. Counting those against coverage produces a number that says fifteen per cent about a model that is almost entirely mapped.
At a glance
| Measure | Value |
|---|---|
| Database coverage | 76% |
| Fields assessed | 79 |
| Waiting on a person | 2 |
| Never examined | 0 |
What did not need a person
What this analysis settled on its own, and what it handed to somebody. The question asked of every field is whether it holds personal data: one the classifier answered, either way, reached nobody. One it left open did, and so did a personal field whose special category is still undecided. It says what this analysis did not have to ask, and it is not a claim about how much review this organisation does.
Read from the systems and concluded from what was read.
| Measure | Value |
|---|---|
| Fields analysed | 79 |
| Settled by evidence | 18 |
| Need human judgement | 61 |
| Review avoided | 23% |
What ran
A stage that did not run is a gap in every figure this platform publishes, including the ones that look complete.
Read from the systems.
| Stage | Status | Reported |
|---|
What the evidence reached
The distribution is the shape of the assessment.
| Measure | Count |
|---|---|
| CONFIRMED | 61 |
| NOT_PERSISTED | 11 |
| INSUFFICIENT_EVIDENCE | 19 |
Why elements went unexamined
"We did not look" is only useful if it says what would have to change for the answer to become available.
Concluded from what was read.
| Reason | Elements |
|---|---|
| Nothing went unexamined | 0 |