# Personal data across the project

**Scope and date.** This is a source/data inspection, not a legal opinion or a finding of compliance. Repository snapshots/schema were inspected on 2026-09-29; official source-rights evidence was fetched on 2026-09-29 UTC. Counts for snapshots describe the files then present and can change when snapshots are rebuilt.

## What the sources establish (and do not)

- **Verified: BOAMP reuse licence, with limits.** DILA's official BOAMP [legal notice](https://www.boamp.fr/pages/mentions-legales/) states “Sauf mention contraire, tous les contenus de ce site sont sous licence etalab-2.0.” The official [data.gouv.fr BOAMP dataset record](https://www.data.gouv.fr/datasets/boamp/) and [API BOAMP record](https://www.data.gouv.fr/datasets/api-boamp/) both identify Licence Ouverte (`fr-lo`). This is positive authoritative evidence for reuse of BOAMP-published dataset/site content under Licence Ouverte 2.0 (attribution and licence conditions apply). The BOAMP API catalogue's own metadata still has `license: null` and `license_url: null`; it is incomplete, not proof that no licence exists. **Scope caveat:** this general notice/dataset label does not establish that third-party material included in a notice or attachment is licensed by DILA, nor answer separate privacy/data-protection questions for contact/person information.
- **Cited statutory publication provisions; independently unverified here.** The Code de la commande publique citations for publication of notices ([R. 2183-1 et seq.](https://www.legifrance.gouv.fr/codes/section_lc/LEGITEXT000037701019/LEGISCTA000037703443/)) and essential procurement data ([R. 2196-1 et seq.](https://www.legifrance.gouv.fr/codes/section_lc/LEGITEXT000037701019/LEGISCTA000037703670/)) are relevant references, but Légifrance pages could not be successfully retrieved/read in this investigation. Their exact wording and current status have not been independently verified. Even if confirmed, these publication provisions do not by themselves establish that every personal name, direct contact detail, free-text field, or identifier is legally required to be public; no field-specific legal basis was established here.
- **Verified: API Recherche d’entreprises restrictions and source-data distinction.** Its official [OpenAPI description](https://recherche-entreprises.api.gouv.fr/openapi.json) says non-diffusible businesses and rejected RCS registrations are not accessible; it also says this is not the full Sirene base. The current project selects supplier profiles only when `statut_diffusion = O`. This is an upstream restriction, not proof that identical data in BOAMP/DECP or all derived publication is unrestricted.
- **Verified: limited Annuaire business-data enrichment is under LO 2.0.** OpenAPI `info.license` says MIT, which concerns the API/software description, not business records. The official data.gouv.fr dataset [Données des entreprises utilisées dans l'Annuaire des Entreprises](https://www.data.gouv.fr/datasets/donnees-des-entreprises-utilisees-dans-lannuaire-des-entreprises/) is labelled LO 2.0 (`lov2`), describes data available in the Annuaire and its API, and explicitly lists displayed full name, administrative status, diffusion status, and identifiers. This is positive evidence for this project's limited name/status/identifier enrichment, **not every API field or source**. The project keeps its `statut_diffusion = O` gate. An entity-data licence does not decide personal-data rules where records identify sole traders or individuals.

- **Remaining questions:** DILA should clarify the LO 2.0 scope for third-party notice text/attachments and any applicable exceptions; buyers/publishers should clarify why named contacts/signatories and other person fields are supplied, their correction/removal routes and retention. Further API-owner clarification is about fields beyond the documented name/status/identifier enrichment, if used, and the meaning/coverage of `statut_diffusion = O`—not whether that limited enrichment has dataset-level LO 2.0 evidence. No legal conclusion is made here.

## Repository inventory (no individual values reproduced)

The normalized records largely contain buyer/supplier names and organization identifiers. These are **not necessarily personal data** where they identify a legal entity, but sole traders, named business names, or names of individual suppliers/contacts can identify natural persons. Names were not manually classified person-by-person. String free-text can contain other personal details. Relevant files are publicly served as repository assets, including all raw files listed here; normalization does not remove personal material retained in raw snapshots. Beyond France, the SECOP II normalized and raw extracts include individual/tax identifiers and representative/bank fields; OCDS, Prozorro and TED records may carry party/contact and natural-person details. This inventory describes field/schema risk, not a person-by-person review or jurisdiction-specific legal assessment.

| Files / records at inspection | Relevant fields and types | What the field inspection establishes |
| --- | --- | --- |
| `data/contracts.json` (3,010 rows) | `buyer`, `supplier`: strings; `buyerSiret`: string, 1,858 non-null; `supplierIds`: arrays, 3,002 rows | Buyer/supplier labels can identify people in some cases; identifiers are primarily organizational identifiers, but an identifier/name pairing can still relate to a person. This file combines BOAMP-derived rows and separate audit-dossier records. |
| `data/consultations.json` (10 rows) | `buyer`: string; `consultation`, `deadline`, procedure/notice metadata: objects/strings | Normalized names plus embedded consultation/evidence structures. |
| `data/tours-notices.json` (66 rows) | `buyer`, `supplier`: strings when present; `buyerSiret`: string; `supplierIds`: arrays when present; notice-evidence structures | Normalized record names/identifiers, together with notice/consultation evidence. |
| `data/decp-history.json` (2,594 rows); `data/decp-cities.json` (1,270 rows) | `buyer`, `supplier`: strings; `buyerSiret`: strings; `supplierIds`, `supplierProfiles`: arrays. Profile objects contain `siren`, `name`, `administrativeState`, `diffusionStatus`, `source`, `retrievedAt`, `status` (and may include reason/associated SIRETs in the identity file). | Current supplier profile enrichment is limited by the project's diffusion-status selection. There are 2,594 and 1,270 profile arrays respectively; array contents are not necessarily one profile per row. |
| `data/supplier-identities.json` (1,960 identity objects) | `siren`, `name`, status/diffusion fields, source URL, retrieval time, associated SIRETs | API-derived organization-name lookup records. They contain names and business identifiers, no contact details in the inspected object schema. |
| `data/boamp-raw.json.gz` (8,386 records) | 41 top-level API fields; notably `nomacheteur`, `titulaire`, `donnees` (text), `url_avis`, identifiers, dates and classification fields | Full downloaded API records, not just the normalized sample. The nested notice `donnees` is free text and can contain personal names, roles, email addresses and phone numbers. |
| `data/consultations-raw.json` (14 records) | Same 41-field BOAMP API record shape | Retains initial notices plus linked/correction records. Same free-text/contact risk. |
| `data/tours-notices/raw/` (86 files) | 27 BOAMP API records in `api-records.json`, individual BOAMP record JSON, TED API search JSON, XML notice files and manifests | Publicly hosted raw source notices and XML are not sanitized by normalized-field selection. TED material has separate terms and is not resolved by the BOAMP licence finding. |

**Text-pattern check, not a person count:** scanning only the raw `donnees` text yielded 11,860 distinct email-shaped strings and 12,990 distinct French phone-shaped strings in the 8,386-record BOAMP snapshot; the 14-record consultation snapshot yielded 8 and 11. These are regex matches, include possible organizational/general contacts and false positives, and are not counts of people or confirmed valid contacts. Labels for contact/signatory fields also occur in the notices. No individual values are reproduced here. This demonstrates why treating raw notice text as contact-free would be unsafe.

### Field-level practical actions

1. **Keep the distinctions visible.** In user-facing descriptions and exports distinguish entity names/IDs from personal names/contact details; do not describe all source records as company-only. Do not label API service MIT as a data licence.
2. **Review raw publication separately from the normalized index.** The raw BOAMP files and `data/tours-notices/raw/` are directly fetchable. Before future republishing, establish whether retaining whole notice `donnees`/XML and contact details is necessary and permitted. Consider excluding/minimizing personal direct-contact fields in a future curated export while retaining the source link and notice identifier; retain an auditable source snapshot only if a verified purpose and rights basis supports it. This is a recommendation, not an assertion that the current files are unlawful.
3. **Preserve safeguards on enrichment.** Keep the diffusion-status gate, provenance and retrieval timestamps; do not add non-diffusible API results or treat the availability of an identifier/name in a procurement notice as permission to enrich it from elsewhere.
4. **Targeted upstream follow-up:** ask DILA about third-party notice text/attachments, exceptions, and publication basis for named contacts/representatives; ask the API owner about fields beyond the documented name/status/identifier enrichment (if used) and the meaning/coverage of `statut_diffusion = O`; ask publishing buyers about notice fields that trigger personal disclosures and correction/removal channels.

## Individual suppliers: project-wide rule (2026-10-16)

Owner decision, for every country (Portugal BASE, South Korea and later sources): a supplier that is an individual (sole trader, individual business) keeps its **published name, shown as published** in lists, search, record and profile views, so an investigator finds it at once. No masking, codes or reveal buttons. Two light limits only:

- The importer flags such suppliers in `supplierIndividual` (one boolean per name in `supplierNamesPublished`), from the source identifier: Portugal NIF blank or starting 1, 2, 3 or 45; Korea business registration number with middle digits 01–79 or 90–99. The explorer marks them “individual”; CSV/JSON exports write `individual (name in the explorer)` instead of the name.
- `/data/` is kept out of search engines (`robots.txt`, `X-Robots-Tag: noindex` in `_headers`).

Still dropped at load: personal identifiers (individual tax numbers), representatives' and officials' names, phones, e-mails and street addresses, and unsuccessful bidders' names. This is not anonymisation: the names are public at the source and in the data files.

"Dropped at load" applies only to what is published (the site, the repository, its data files). Private raw downloads and private tables in the cache keep every field as the source returns it, including officials', CEOs', objectors' and other people's names, telephone numbers, e-mails and addresses (owner 2026-11-04). These fields link records for finding connections and support private investigations. If they ever reach the site, it is at most as keyed-HMAC IDs whose secret stays outside the repository. Korea example: `opnstd.sqlite` (it feeds the site) leaves them out, and the private `opnstd-links.sqlite` (tools/korea-opnstd-links.py) holds them.

## Individuals pseudonymised in every country, raw snapshots private (owner 2026-11-09)

Replaces the 2026-10-16 rule: a supplier identified as an individual appears under a keyed pseudonym, `individual #<12 hex>` (HMAC-SHA256 of country and identifier; key `~/.config/contract-signals/pseudonym.key`, outside the repository). `tools/pseudonymise-eu-individuals.py` (`find`, `details`, `apply`) detects them and rewrites `data/` and `research/labels/`; Korea is done by `tools/build-korea-site.py`. Detection: France Sirene category 1000, Czechia ARES forms, Portugal NIF ranges, Colombia/Paraguay/Chile/Ukraine source identifier types, Korea `individual` kind. Limits: UK and Romania have no such identifier, French rows without SIREN only by wording, so a sole trader can still slip through (fix on objection).

The real names, identifiers and addresses are in `data/private/individuals.json` and `data/private/korea-individuals.json` (git-ignored, never deployed). `script.js` reads them on localhost only.

Raw source snapshots (`data/*/raw/`, `data/*-raw.json*`) are no longer in Git or on the site: they held contact details and names of people. They stay locally (git-ignored) for rebuilds and tests; tests that need them skip without them. Older commits still contain them. The site's privacy and legal notice is `privacy.html`.

## Wider inventory by source (schema and field-presence risk)

| Source and checked-in files | Personal-data indicators and scope | Evidence status / limitation |
| --- | --- | --- |
| Colombia · SECOP II (`data/colombia-secop2.json`, `data/colombia-secop2/raw/*.json`; 7,560 normalized records) | Normalized `supplierIds` carries an identifier type/value and may represent a natural-person cédula (source fields `tipodocproveedor` / `documento_proveedor`). Types: Cédula de Ciudadanía 5,817; NIT 1,723; Otro 12; No Definido 4; Cédula de Extranjería 4. `documento_proveedor` is numeric-like in 7,553 rows and a placeholder in 7; payment-official document is a placeholder in 7,241 and numeric-like in 319. The `n_mero_de_cuenta` field occurs in all 7,560 raw rows and all are the placeholder “No Definido”: this is a schema/field-presence and banking-risk indicator, not evidence of actual account numbers in this snapshot. Raw SECOP rows also expose fields for legal representative name, identity type/number, domicile and gender; contract supervisor, payment-ordering official and expenditure authorizer names/ID types/IDs; and bank name/account type. Numeric-like values are not validated identifiers and do not establish that the subject is a natural person. | Verified by inspecting aggregate counts from the checked-in normalized and Socrata-shaped raw snapshots; no values reproduced. Nonempty and meaningful are separate: the latter excludes recognized placeholder labels, not invalid/false data. These counts do not establish identity, validity, legal basis, or field-specific publication authority. |
| Paraguay · DNCP OCDS (`data/paraguay-dncp*.json`, `data/paraguay-dncp*/raw/`) | Normalized buyer/supplier and `supplierIds` may identify sole traders or individuals. Raw OCDS `parties` and related tender/award records can encode party names, identifiers, contact points (name/email/telephone), addresses, and represented persons; attached tender/award documents may contain further data. | Schema-level risk based on OCDS structure and checked-in raw record shape; values/contact populations not manually reviewed. CC BY dataset terms do not determine privacy treatment. |
| Ukraine · Prozorro (`data/prozorro.json`, `data/prozorro/raw/records/*.json.gz`) | Normalized buyer/supplier names and supplier IDs may identify sole traders/natural persons. Raw procedure records can include participant/party identifiers, contact-point or representative details and free-text description/document links. | Checked-in official API record schema/structure, not a complete semantic or field-by-field human review. Prozorro reuse terms are not a privacy-law conclusion. |
| Portugal/Romania · TED (`data/ted-portugal*.json`, `data/ted-romania*.json`, `data/ted-*/raw/notices/*.xml.gz`) | Normalized buyer/supplier names and IDs may identify natural-person economic operators. Raw eForms/XML schema permits organization, person/representative and contact-point details (including person names, contact details, addresses and identifiers, where supplied). | Schema capability is not evidence that each field is populated in these 849 notices. The TED free-reuse notice does not establish a privacy-law basis for every disclosure. |

**Why is it public?** Colombia's official [Ley 1712 de 2014, article 10](https://www.funcionpublica.gov.co/eva/gestornormativo/norma.php?i=56882) directs publication of ongoing state-contracting information and a SECOP link; [Decreto 1082 de 2015, article 2.2.1.1.1.7.1](https://www.funcionpublica.gov.co/eva/gestornormativo/norma.php?i=77653) requires publication in SECOP of process documents and administrative acts, subject to its terms. Colombia Compra Eficiente's [transparency portal](https://www.colombiacompra.gov.co/transparencia) lists contracting and open data. These explain the general publication context, but do not establish that each identity number, contact or bank field must be public.

For France, BOAMP is an official public-notice service; no field-specific requirement to publish every named contact was established here. CNIL guidance on [internet publication and reuse](https://www.cnil.fr/fr/ouverture-et-reutilisation-de-donnees-personnelles-sur-internet-la-cnil-publie-ses-recommandations) and [reuse of disseminated data](https://www.cnil.fr/fr/comment-reutiliser-les-donnees-diffusees) explains that public availability does not remove data-protection obligations. This is French/EU guidance, not a Colombian legal basis or a field-specific BOAMP ruling.

Run `python tools/audit-personal-data.py` from the repository root to produce aggregate text field-name/presence indicators for these non-French datasets. It never prints field values; field-name matching is heuristic and counts occurrences, not people. `nonempty` includes any nonblank value; `meaningful` excludes empty values and recognized placeholder labels (including “No Definido” and “No aplica”), but does not validate content. Outputs are not a substitute for content review and do not scan binary attachments or every XML field.

## Portugal BASE private research inspection (2026-09-30)

The new national BASE archives remain in a private cache outside Git and the website; they are **not** the existing published TED cohorts. A bounded inspection of the first three records/year (nine total, 64 KiB/member) observed buyer, holder and competitor lists containing **NIF/name-shaped strings**. These may identify individuals or sole traders; no person-by-person classification or whole-file population count was performed. No sampled identifiers or names were retained publicly.

The official dataset category is **Other (Public Domain)**, not privacy clearance. BASE explains that contract, modification and execution information is published from reports supplied by buyers/platforms; that general reporting purpose does not establish the necessity of every personal tax ID or unsuccessful bidder name. Some portal explanations are dated 2022 and cite 2018/2019 provisions, so current field-specific legal authority remains unverified.

The implemented candidate importer retains published supplier names as contract-participant names—including individual/sole-trader names where appropriate—without inferring entity type or suspicion. It strips supplier NIF prefixes, omits identified unsuccessful competitors, and requires review of the minimized names/subject text before public redistribution. This is not blanket anonymization of public names. Raw archives remain private with retention review. Schema observations, source statements, official correction/support channels and unanswered questions are in [portugal-base.md](portugal-base.md) and [`../data/portugal-base-rights.json`](../data/portugal-base-rights.json). No source inquiries have been sent.

## Evidence and verification dates

- BOAMP official evidence retrieved 2026-09-29: DILA [mentions légales](https://www.boamp.fr/pages/mentions-legales/) (site contents default to Etalab-2.0); data.gouv.fr official [BOAMP dataset](https://www.data.gouv.fr/datasets/boamp/) and [API BOAMP dataset](https://www.data.gouv.fr/datasets/api-boamp/) records (`fr-lo`); BOAMP [API dataset metadata](https://www.boamp.fr/api/explore/v2.1/catalog/datasets/boamp) and [records endpoint](https://www.boamp.fr/api/explore/v2.1/catalog/datasets/boamp/records) (the API metadata license properties are null). The official data.gouv.fr dataset licences and DILA notice support reuse of BOAMP-published dataset/site content; null API catalogue metadata does not leave the published dataset's licence unresolved. Third-party-content scope remains uncertain.
- API Recherche d’entreprises [OpenAPI document](https://recherche-entreprises.api.gouv.fr/openapi.json) and official data.gouv.fr dataset [Données des entreprises utilisées dans l'Annuaire des Entreprises](https://www.data.gouv.fr/datasets/donnees-des-entreprises-utilisees-dans-lannuaire-des-entreprises/), labelled `lov2`, explicitly describing data in the Annuaire and API. Evidence response retrieved 2026-09-29T22:31:16Z; SHA-256 and selected excerpts are retained in [`source-rights-evidence.json`](source-rights-evidence.json). This supports the limited name/status/identifier enrichment described above, not all API fields.
- Code de la commande publique, official Légifrance: [publication of notices, R. 2183-1 et seq.](https://www.legifrance.gouv.fr/codes/section_lc/LEGITEXT000037701019/LEGISCTA000037703443/), [essential procurement data, R. 2196-1 et seq.](https://www.legifrance.gouv.fr/codes/section_lc/LEGITEXT000037701019/LEGISCTA000037703670/). The links are official references, but successful retrieval and reading of the current provisions were not achieved here; exact wording/currentness remains to verify.
- Colombia publication context checked 2026-09-29: official Colombia Compra Eficiente [transparency portal](https://www.colombiacompra.gov.co/transparencia), [Ley 1712/2014](https://www.funcionpublica.gov.co/eva/gestornormativo/norma.php?i=56882), and [Decreto 1082/2015](https://www.funcionpublica.gov.co/eva/gestornormativo/norma.php?i=77653), article 2.2.1.1.1.7.1. These establish general publication context only; not the necessity or lawful publication of the specific personal/banking fields inventoried.
- CNIL official recommendations read 2026-09-29: [opening and reuse of personal data on the internet](https://www.cnil.fr/fr/ouverture-et-reutilisation-de-donnees-personnelles-sur-internet-la-cnil-publie-ses-recommandations) and [reuse of disseminated data](https://www.cnil.fr/fr/comment-reutiliser-les-donnees-diffusees). Their general French/EU privacy guidance does not decide field-specific BOAMP publication or Colombian processing.
- Project files and raw snapshot schema inspected locally 2026-09-29. Counts describe checked-in snapshots, not upstream totals. No record values identifying individuals are reproduced. Other unresolved evidence includes population/validity of sensitive fields, field-specific legal bases and retention/correction processes across countries, and human review of notice text, attachments and XML.
