header.kobets.info

Единая шапка для проектов kobets.info: текущий пользователь, его реалмы и часы-индикатор живости. Авторизацию шапка выясняет сама при загрузке страницы.

Версия шапки: 1.0.086 · файлы: embed.js, embed.css, loader.js

Копий кода шапки не существует. Шапка подключается только по абсолютному адресу https://header.kobets.info/embed.js. Не копировать embed.js / embed.css к себе в проект, не класть рядом «свою версию», не форкать. Любая копия молча отстаёт: у неё остаётся старый вид и старое поведение, а чинят потом там, где копии нет. Один адрес — одна шапка на всех проектах.

1. Как подключить — одна строка

В конце <body>, после контента:

<script src="https://header.kobets.info/embed.js"
        id="kobets-header-script"
        defer
        data-realm="ваш_реалм"></script>

Всё. Контейнер создавать не нужно — виджет сам вставит <div id="kobets-header"> в начало <body> (если хотите другое место — положите этот div сами). Стили виджет подгружает сам, отдельный <link> не нужен. defer обязателен: без него скрипт блокирует разбор страницы.

Параметры тега

АтрибутОбязателенЗачем
id="kobets-header-script"дапо нему страница и диагностика находят тег шапки
data-realmдаидентификатор реалма проекта в Key (net, home, tracker…)
data-auth-urlнетэндпоинт вашего сервиса, который знает сессию: шапка сама спросит его при загрузке (см. п. 3)
data-key-authнетразрешить шапке спрашивать ключник напрямую — только если Key отдаёт CORS для вашего origin
data-shell="off"нетне строить каркас (полоса + контейнер во всю высоту), оставить полосу просто первой в body
data-log-endpointнетURL, куда виджет шлёт свои клиентские логи (init_ok / init_fail)

Вариант с резервным сервером

Если проект не должен падать без header.kobets.info — подключайте loader.js: он грузит embed.js с первого адреса, а при недоступности — со второго. Код шапки при этом всё равно один, просто раздаётся с двух хостов.

<script src="https://header.kobets.info/loader.js"
        id="kobets-header-script"
        defer
        data-realm="ваш_реалм"
        data-base-url="https://header.kobets.info"
        data-base-url-fallback="https://второй-хост/header"></script>

2. Что показывает шапка

В полосе — только имя пользователя, в правом углу (или «Войти», если сессии нет), рядом крестик «выйти». Всё остальное убрано с глаз и открывается окошком при наведении на имя (на тач-экранах — по тапу). Окошко не захлопывается сразу: после ухода курсора оно висит ещё 0,9 с, чтобы успеть дойти до крестика реалма:

ГдеЧтоДействие
Полосаимя авторизованного либо «Войти»крестик — выйти
Окошкочасы — индикатор того, что шапка живазамирают, если скрипт шапки повис
Окошкореалм(ы): чип на каждый, имя — ссылкакрестик — выйти из реалма

Названия и версии проекта в шапке нет: проект и так знает, как он называется, а место это занимало у всех. Ссылок в админку ключника и прочего «полезного одному человеку» — тоже нет.

Каркас страницы

Шапка задаёт каркас окна: полоса всегда сверху и во всю ширину браузера, а всё содержимое страницы живёт в контейнере #kobets-page под ней. Контейнер занимает всю оставшуюся высоту окна и скроллится сам — полоса при этом остаётся на месте, ничего не перекрывает и padding-top не требует.

Виджет делает это сам при загрузке: переносит содержимое <body> в контейнер и ставит на <html> класс kobets-shell. Отступы body переезжают на контейнер, чтобы вёрстка не поехала.

Что учесть. Скролл теперь у контейнера, а не у окна: если ваш код слушает window.onscroll или читает window.scrollY, переключите его на document.getElementById('kobets-page'). Каркас можно отключить — data-shell="off" у тега шапки (или shell: false в конфиге), тогда полоса просто стоит первой в body, как раньше.

Цвет полоса берёт от окна браузера (системные Canvas / CanvasText): в светлой теме она светлая с тёмным текстом, в тёмной — наоборот, переключается сама вместе с браузером и ОС. Полупрозрачность оставлена, так что фон сервиса сквозь неё просвечивает. Нужен свой цвет — задайте переменные на своей странице:

:root {
  --kobets-header-bg: rgba(20, 30, 60, .35);
  --kobets-header-fg: #eef;
}

3. Авторизация: шапка спрашивает сама

При загрузке страницы шапка сама идёт за состоянием авторизации — хосту ничего вызывать не нужно. Пока ответа нет, блок пользователя пустой (чтобы не мигало «Войти»); есть права — сразу появляется имя; прав нет или ответа не дождались — появляется кнопка «Войти». Надписей «Не авторизован» и «Нет доступа» в шапке нет: пользователю нужно действие, а не диагноз.

Куда шапка идёт, по порядку:

ИсточникКогда
состояние от хоста (__KOBETS_HEADER_AUTH__, SET_AUTH)если хост его дал — оно главнее всего
data-auth-url — эндпоинт хостаесли задан: свой origin, работает всегда
ключник напрямуютолько с data-key-auth — и только там, где Key отдаёт CORS для вашего origin
<script src="https://header.kobets.info/embed.js"
        id="kobets-header-script" defer
        data-realm="net"
        data-auth-url="/api/auth/header-state"></script>

Эндпоинт по data-auth-url отдаёт тот же объект auth, что описан ниже (как минимум status и name); запрос идёт с credentials: same-origin, то есть с вашей сессионной cookie. Если он не ответил за 4 секунды — шапка показывает «Войти».

4. Что можно передать шапке со страницы

Если хост хочет управлять состоянием сам (или дополнить его), после загрузки виджета доступны три глобальные функции.

Кто авторизован — __KOBETS_HEADER_SET_AUTH__(auth)

window.__KOBETS_HEADER_SET_AUTH__({
  status: "allowed",              // allowed | need_login | pending | revoked | invalid
  name:   "Иван Петров",         // имя для показа; GUID в шапку не выводится
  realm:  "net",                  // либо realms: [...] — см. ниже
  loginUrl:  "https://key.kobets.info/auth/login?service_id=net&…",
  logoutUrl: "/auth/logout"
});

Если сервису нужно сразу несколько реалмов — передавайте realms; каждый станет отдельным чипом. Имя реалма — ссылка: адрес берётся из url самого реалма, затем из шаблона realmUrl с {realm}, а если ничего не задано — из projectUrl (см. SET_PROJECT) или текущего origin. Крестик «Выйти из реалма» появляется только там, где хост дал адрес выхода (logoutUrl/logoutApi у реалма, шаблон realmLogoutUrl, либо общий logoutUrl — если реалм единственный).

window.__KOBETS_HEADER_SET_AUTH__({
  status: "allowed",
  name: "Иван Петров",
  realms: [
    { realm: "tracker", status: "allowed", url: "/tracker/", logoutUrl: "/auth/logout?realm=tracker" },
    { realm: "net",     status: "allowed", url: "/net/",     logoutUrl: "/auth/logout?realm=net" },
    { realm: "key",     status: "pending" }
  ],
  realmUrl: "/r/{realm}/",        // общий шаблон ссылки, если у реалма нет своего url
  logoutUrl: "/auth/logout"
});

Название и версия проекта — __KOBETS_HEADER_SET_PROJECT__(data)

Отдельного блока проекта в полосе нет, но данные шапке пригодятся: projectUrl — куда ведёт имя реалма, если у реалма не задан свой url; название и версия попадают в подсказку чипа при наведении.

window.__KOBETS_HEADER_SET_PROJECT__({
  projectName: "GPS Track",
  version: "0.1.261",
  projectUrl: "https://gps.example.com"   // ссылка ведёт сюда, не на header
});

Жива ли шапка — __KOBETS_HEADER_ALIVE__()

Часы в окошке — не украшение, а watchdog: тик перепланирует сам себя, и если код шапки повис или упал, время замирает. Паузу дольше 2,5 с шапка помечает жёлтым со знаком ⚠ (метка остаётся и после того, как зависание кончилось, — её видно, когда откроете окошко). То же самое программно, без наведения:

window.__KOBETS_HEADER_ALIVE__();
// { version: "…", running: true, ticks: 42, lastTickAt: …, sinceLastTickMs: 650, stalledMs: 0 }

5. Правила для проектов

Подробные документы (контракт auth, отладка, деплой) — в репозитории kobets.info, каталог header/docs/; точка входа — HEADER-INTEGRATION-GUIDE.md.