# Метадані

## Що це таке

Метадані — це дані, предметом яких є інші дані: назва, дата, мова, автор, формат
і розмір, що супроводжують документ, аби люди й програми могли його
впорядкувати, довіритися йому й вирішити, що з ним робити, ще до того, як
прочитають сам вміст. У щоденній роботі метадані мають вужчі назви залежно від
того, де вони живуть: поля заголовків у HTTP, властивості в офісному файлі, теги
у фотографії, front matter на початку сторінки Markdown. В англомовних
стандартах старшого покоління трапляється написання meta-data через дефіс.

Метадані зазвичай ділять на три види. Описові кажуть, про що йдеться: назва,
автор, тема, анотація. Структурні пояснюють, як частини складаються в ціле:
розділи, сторінки, порядок читання. Адміністративні фіксують, звідки річ
походить і що з нею можна робити: коли її створено й змінено, ким, за якою
ліцензією і в якому форматі. Найвідоміший спільний перелік описових полів —
Dublin Core: його п'ятнадцять елементів 2003 року стали стандартом ISO 15836, а
назва, автор, дата, мова й права звідти повторюються під іншими іменами майже в
кожному пізнішому форматі.

Вебсторінка несе метадані шарами. Першою надходить відповідь HTTP. За RFC 9110
поле заголовка може змінювати чи розширювати семантику повідомлення, описувати
відправника, визначати вміст або давати додатковий контекст, тож `Content-Type`,
`Content-Language` і `Last-Modified` описують сторінку ще до того, як надійде її
перший байт. Усередині HTML розміщені `<title>`, атрибут `lang` та елементи
`<meta>`, імена яких визначає стандарт HTML, як-от `description`, `author` і
`generator`. Над ними лежать словники, які читають інші сторони: властивості
Open Graph для попереднього перегляду посилань і структуровані дані для
пошукових систем та асистентів.

То що ж відрізняє метадані від даних? Радше читач, ніж самі байти. Каталожний
запис — це метадані про книжку, але для каталогу він і є набором даних; час
зйомки фотографії — дрібниця для того, хто її розглядає, і сировина для того,
хто складає мапу місць, де фотографують. Питання «метадані чи структуровані
дані» вужче, і відповідь на нього така: структуровані дані — це метадані,
записані спільним словником, щоб програма могла прочитати поле, не вгадуючи, що
воно означає.

## Чому це важливо

Кожне поле — маленька обіцянка, і справжнє рішення полягає в тому, звідки кожне
з них бере значення: від людини, яка його вписала, з історії версій, зі стовпця
бази даних чи з того, що випадково повідомила файлова система. Програми діють на
підставі цих обіцянок, не перевіряючи їх. У цьому і сенс метаданих, і їхній
ризик.

Кеші та пошукові роботи розподіляють за ними свої зусилля. Браузер, що має копію
сторінки, надсилає назад отриману дату `Last-Modified` і, якщо сторінка не
змінилася, дістає коротку відповідь `304 Not Modified` замість усієї сторінки.
RFC 9110 просить сервер надсилати цю дату тоді, коли останню зміну можна
визначити обґрунтовано й послідовно, і ця умова працює в обидва боки: де
послідовної дати немає, стандарт її й не вимагає. Дата зміни в карті сайту
виконує ту саму роботу для пошукового робота, який вирішує, що завантажити
знову.

Від метаданих залежать і люди, і допоміжні технології. Атрибут `lang` підказує
екранному читачеві, за якими правилами вимовляти текст, а назву показують
вкладка, закладка й результат пошуку. Права подорожують так само: менеджер
пакетів знає ліцензію залежності лише тому, що залежність сама її оголосила, тож
перевірка ліцензій, побудована на цьому переліку, рівно настільки надійна,
наскільки правдиві оголошення під нею.

Кожне поле треба підтримувати правдивим, тож сторінка із сорока полями має сорок
нагод помилитися. Деякі поля не читає ніхто: стандарт HTML зазначає, що багато
пошукових систем не зважають на ім'я `keywords`, бо його використовували для
спаму в результатах пошуку. До того ж метадані протікають: місце зйомки
фотографії чи історія правок документа можуть сказати більше, ніж сам вміст.
Кілька полів, кожне з яких заповнюється з джерела, що не може розійтися з
дійсністю, зазвичай кращі за багато.

## Як це виглядає на практиці

Метадані трапляються у трьох проєктах на цьому сайті, щоразу в іншому виді
файлу: у карті сайту, у наборі PDF і в графі залежностей.

Одна карта сайту
[стверджувала, що 172 зі 176 сторінок змінилися тієї самої миті](/uk/portfolio/fixed-a-sitemap-with-one-shared-timestamp-140/).
Дати бралися з часу зміни файлів, а експорт вмісту переписує всі файли за
кожного запуску. Тепер дата проходить ланцюжок джерел: спершу явне поле, тоді
історія комітів і лише наостанок файл. У ланцюжку є пастка, яку проєкт записав:
назва поля мусить стояти в переліку, інакше генератор поле взагалі не читає.
База даних за сторінками окремо зберігає, коли запис написано й переглянуто, і
окремо — роки, коли відбувалася сама робота, а якщо дати ніхто не знає, поле
лишається незаповненим: точному хибному числу вірять, відсутньому — ні. Повторна
синхронізація після місяця правок тепер зачіпає 8 файлів зі 186.

Коли
[дев'ять згенерованих PDF-документів перевіряли на відповідність стандарту доступності](/uk/portfolio/established-pdf-ua-1-conformance-across-nine-documents-146/),
для проходження всіх 106 правил знадобилися оголошена мова документа і справжня
назва в метаданих, поряд із тегованою структурою, альтернативним текстом і явним
порядком читання. В архівному профілі ті самі документи не проходять рівно одне
правило зі 146, і сторінка проєкту не видає це за відповідність: 145 пройдених
правил не вбережуть документ від відхилення системою, що застосовує стандарт.

А коли
[ліцензії 644 крейтів Rust перевіряли за кожного збирання](/uk/portfolio/audited-644-rust-crates-for-licence-compatibility-163/),
заявлена межа перевірки виявилася межею метаданих. Перевірка читає оголошену
ліцензію кожного крейта, оголошення бувають хибними або неповними, і про крейт,
що оголошує себе неправдиво, перевірка нічого не доводить. Її двічі навмисно
змусили зупинити збирання, і це показує, що вона працює; а от чесність
оголошень, які вона читає, не здатна показати жодна перевірка.

## Де виникають проблеми

У збоїв нижче одна спільна риса: кожна перевірка, яка їх не шукає, проходить.

**Після кожного розгортання кожна сторінка повідомляє про зміну.** Вебсервер, що
надсилає час зміни статичного файлу як `Last-Modified`, або генератор, що так
само датує карту сайту, повідомляє про мить, коли файл скопіювали, а клонування
репозиторію, експорт чи збирання контейнера копіюють усі файли одразу. Кеші
перевіряють усе заново, а пошукові роботи нічого не дізнаються. Беріть дати з
історії версій або з поля, яке вписала людина, а невідому дату залишайте
відсутньою. У Hugo джерела — це перелік, який читають по черзі, і назва самого
поля мусить у ньому бути:

```toml
enableGitInfo = true

[frontmatter]
date = ["date", ":git", ":fileModTime"]
lastmod = ["lastmod", ":git", ":fileModTime"]
```

**Назва або попередній перегляд посилання показує спотворені символи.**
Кодування символів — це метадані про всі інші байти, і парсер, що натрапляє на
текст раніше за оголошення, мусить вгадувати. Стандарт HTML вимагає, щоб елемент
з оголошенням повністю вміщувався в перші 1 024 байти, а якщо поставити його
першим у `<head>`, вгадувати не доведеться. На цьому сайті інструмент URL
Inspection від Bing якось прочитав назву й обидва рядки Open Graph як Latin-1,
бо довге тире в назві трапилося раніше за оголошення `charset`. Заголовок HTTP
теж називав UTF-8, але інструмент, що читає файл без заголовка, може покладатися
лише на саму сторінку. Тепер `charset` стоїть першим елементом, а перевірка
контролює цей порядок на кожній зібраній сторінці.

**Той самий факт у різних місцях каже різне.** Назва сторінки живе в `<title>`,
в `og:title`, у її структурованих даних, а для PDF — ще й у властивостях
документа; мова живе в `lang`, у `Content-Language` і в `og:locale`. Коли кожне
значення вписують окремо, вони розходяться, і кожен споживач вірить своєму.
Обчислюйте кожне значення один раз, в одному шаблоні чи одній функції, і нехай
кожне місце, що його виводить, читає саме це значення.

**Файл розповідає більше, ніж автор збирався оприлюднити.** Фотографії несуть
модель камери, час і часто координати; офісні документи — імена авторів, історію
правок і шляхи до шаблонів; тег `generator` називає програму, яка зібрала
сторінку. Під час експорту вилучайте все, що ніхто свідомо не вирішив
публікувати, і ставтеся до кожного поля як до тексту, який прочитає незнайомець.

## Що почитати далі

- [RFC 9110, section 6.3: Header Fields](https://www.rfc-editor.org/rfc/rfc9110#section-6.3)
  — як HTTP передає метадані попереду вмісту і що може робити поле заголовка.
- [RFC 9110, section 8.8.2: Last-Modified](https://www.rfc-editor.org/rfc/rfc9110#section-8.8.2)
  — коли сервер має надсилати дату зміни і чому дату з майбутнього замінюють.
- [HTML Standard: the meta element](https://html.spec.whatwg.org/multipage/semantics.html#the-meta-element)
  — стандартні імена метаданих і правила оголошення кодування символів.
- [DCMI Metadata Terms](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/)
  — п'ятнадцять елементів Dublin Core і словник, збудований навколо них.
- [The Open Graph protocol](https://ogp.me/) — чотири властивості, обов'язкові
  для кожної сторінки, і необов'язкові навколо них.

<https://engineer.company/uk/glossary/metadata/>
