Skip to content

Структура данных ​

Принятое направление · 5 октября 2026, роли решены 11 октября 2026 · десять таблиц созданы 11 октября 2026: пользователи, компании, владельцы, магазины, занятости, приглашения, графики, смены, запросы на изменения и элементы «Ждёт вас»; графики, магазины и людей также правят вручную, пока этого не делает ассистент · описания магазинов и людей и почасовая нагрузка магазина созданы 14 октября 2026, их пока ничто не читает · перерывы в сменах, шаблоны смен и проверка дежурного управляющего сделаны 14 октября 2026 · несколько смен в день у одного человека (разделённые смены) сделаны 14 октября 2026 · причина при каждом отклонении и кто одобрил изменение сделаны 14 октября 2026 · человекочитаемые id вместо UUID сделаны 15 октября 2026 · общее ядро API сделано 15 октября 2026, не развёрнуто: компания стала командой с ролями, добавлены сессии входа, сброс пароля, API-ключи, передача владения и очередь задач, на Prisma 8 · id в общем для всех продуктов Agentfy виде (два слова, двенадцать символов) сделаны 15 октября 2026 · время начала перерыва, число чеков на кассира в час и расчёты для дневного вида графика и листа месяца сделаны 16 октября 2026, не развёрнуто · права управляющего в своём магазине и запись о том, кто менял людей, приглашения и магазины, сделаны 19 октября 2026, не развёрнуто · управляющий необязателен для сотрудника, по запросам такого сотрудника решает владелец, проверка дежурного управляющего — только в магазине с управляющим, а ждущие запросы уходящего управляющего переходят владельцу, создано 23 октября 2026, не развёрнуто · каталог должностей у каждой команды, из которого должность человека выбирается вместо вписанной вручную, создан 30 октября 2026, не развёрнуто · правила, прочитанные в описании, хранятся рядом с ним, построено 10 ноября 2026, не развёрнуто

Shiffty хранил бы всё о магазине — людей, правила, графики и запросы на изменение — в собственной базе данных, сгруппированной по компании и магазину; агент ничего не хранит и каждый раз получает факты заново.

Человек — это одно, его место в магазине — другое. Всё, что человек может видеть или просить, следует из этого места, а не из самого человека.

Как это сгруппировано ​

Команда — это бизнес владельца (до 15 октября 2026 — компания), и у неё есть магазины. У магазина есть управляющие, сотрудники, правила, графики и один агент. Пользователь — человек, который может войти; занятость — место этого человека в одном магазине, с ролью, а в занятости сотрудника указан управляющий, которому он подчиняется. Схема — намерение, а не набор таблиц:

text
team ────┬─ team_member (user, role owner|admin|member)
         ├─ position (name, description, active|archived)
         └─ store ─┬─ employment (user, role manager|employee, manager, position, hours, skills, status)
                   │     ├─ availability_rule / availability_exception / absence / preference
                   │     └─ agent_conversation (agentfy_conversation_id, grant)
                   ├─ store_rules, shift_template, coverage_requirement, traffic
                   ├─ schedule (period, draft|published, version)
                   │     ├─ shift (employment, date, start, end, template, origin)
                   │     └─ change_request (kind, status, proposal, colleague, decision)
                   ├─ agentfy_agent (agent_id, provisioning_id, status)
                   └─ invitation (name, email, role, link, expires, status)
user ─── inbox_item («ждёт вас»)

Что есть что ​

ЧтоОдной строкой
КомандаКлиент: бизнес владельца с одним или несколькими магазинами (до 15 октября 2026 — компания)
Участник командыЧеловек в команде с ролью в ней: её единственный владелец, администратор или участник — все, кто работает в её магазинах, участники
ДолжностьОдна запись собственного списка должностей команды («Кассир», «Кладовщик»): название, описание для ассистента и даётся ли она ещё людям
Правила описанияТо, что ассистент прочитал в описании магазина, должности или человека; хранится, пока описание не изменится (с 10 ноября 2026)
МагазинОдна торговая точка; почти всё остальное принадлежит магазину
ПользовательЧеловек, который может войти
ЗанятостьМесто человека в одном магазине: управляющий или сотрудник, управляющий, которому подчиняется сотрудник, должность из списка команды, часы по договору, навыки и статус — приглашён, действует или не действует
Правило доступности, исключение из доступностиКогда человек может работать: регулярный порядок и разовые изменения в нём
ОтсутствиеОтпуск или болезнь: дни, на которые человека никогда не ставят
ПожеланиеЧего человек хотел бы; учитывается, когда возможно
Правила магазинаЧасы работы, отдых, максимум часов, длина смены, перерывы
Шаблон сменыСтандартные смены, из которых строится график
Требование к покрытиюСколько людей какой роли нужно в каждый час
ПосещаемостьНасколько загружен магазин по часам и откуда взята цифра
ГрафикОдин период одного магазина, черновиком или опубликованный, с версией
СменаОдин человек работает один отрезок одного дня — и кто её поставил: солвер, управляющий или запрос на изменение
Запрос на изменениеО чём просили, предложенное изменение, затронутый коллега, решение и статус
Разговор с агентомСвязь одной занятости с её чатом с агентом магазина и действующее разрешение действовать
Запись об агенте магазинаКакой агент на Agentfy принадлежит этому магазину и готов ли он
ПриглашениеПредложение роли в магазине конкретному человеку, с одноразовой ссылкой, сроком действия и статусом
Запись «ждёт вас»Одно дело, которое ждёт одного человека
СессияОдно устройство, на котором человек вошёл: даёт не входить заново и может быть завершена со стороны сервера
Сброс пароляОдноразовая ссылка, присланная письмом, чтобы выбрать новый пароль
API-ключКлюч, которым программа пользуется вместо входа человека, для одной команды, с тем, что ей можно
Передача владенияПредложение владельца передать команду другому участнику — пока его не примут или не отменят
ЗадачаРабота, которую API делает в фоне, к сроку или по расписанию

Поля за командой, правилами и посещаемостью перечислены во Входных данных; там это тоже черновик.

Правила, которые важны ​

  • Пользователь — это человек; занятость — место этого человека в одном магазине. Что он может видеть и делать, определяет занятость — а для владельца то, что он владеет командой.
  • У каждого человека ровно одно место (11 октября 2026): у владельца его команда, у всех остальных один магазин. Списка команд или магазинов на выбор в приложении нет.
  • Сотрудник подчиняется управляющему того же магазина или никакому. Управляющий необязателен с 23 октября 2026 (решение владельца; до того сотрудник мог быть без управляющего, только пока в магазине не было управляющих). Оставить сотрудника без управляющего может только владелец; управляющий переводит сотрудников своего магазина к другому его управляющему, но не «ни к кому». Люди управляющего — это занятости, в которых указан он; управляющие отвечают перед владельцем.
  • Управляющие и сотрудники приходят только по приглашению от владельца (или, с 15 октября 2026, администратора команды), которое приходит письмом. С 19 октября 2026 управляющий магазина тоже приглашает сотрудников в свой магазин. Сами регистрируются только владельцы.
  • Доступ к агенту даётся по занятости, а не по пользователю. Человек говорит с агентом того магазина, где работает, с правами своей роли там.
  • Команда связана с командой Agentfy, а магазин — с агентом Agentfy собственными идентификаторами Shiffty. См. Интеграцию с Agentfy.
  • Всё состояние живёт в Shiffty. Графики, запросы и решения хранятся здесь; агент каждый раз получает факты через инструменты, и Shiffty не полагается ни на что из того, что агент помнит.
  • Учётные данные Agentfy живут в окружении API и никогда — в базе данных.
  • Локальной замены Agentfy больше нет (14 октября 2026, решение владельца). С 13 октября API мог сам играть Agentfy на машине разработчика и хранил операции, разговоры, запуски, события и сообщения этой замены в пяти собственных таблицах; миграция 20261016T1038_drop_fake_agentfy (16 октября 2026) их удаляет. Таблицы настоящей интеграции остаются. См. Интеграцию с Agentfy.
  • Кто решает по запросу на изменение (11 октября 2026, из решения, что у каждого сотрудника есть конкретный управляющий): запрос сотрудника идёт его управляющему; если тот ещё не присоединился — любому управляющему магазина. Сотрудник без управляющего, сотрудник магазина без активного управляющего и управляющий отправляют запросы владельцу — с 23 октября 2026, когда управляющий стал необязательным; до того запрос сотрудника без управляющего шёл любому управляющему магазина. Когда управляющего деактивируют, запросы, ждущие его, переходят владельцу, а если он был последним активным управляющим магазина — и те, что ждут любого управляющего. Так у запроса всегда есть кто-то, кто по нему решает. Никто не решает по собственному запросу.
  • Время — магазина. У магазина есть часовой пояс (11 октября 2026). Часы работы, дата и время смены — это часы на стене магазина; «сегодня», текущая неделя и то, какая неделя идёт сейчас, считаются в часовом поясе магазина — никогда не сервера и никогда не того, кто смотрит. Часы смены — это время, которое проходит на самом деле, поэтому смена в ночь перевода часов на час короче или длиннее.
  • Данные сотрудников чувствительны. Доступность, отсутствия и причины, которые называют люди, — личная информация. Где эти данные хранятся и кто их видит, остаётся открытым вопросом, который нужно решить до любого пилота.

Где это будет храниться ​

PostgreSQL на Neon, через Prisma — с 15 октября 2026 Prisma 8: схема лежит рядом с каждой частью API, миграции написаны на TypeScript. API в репозитории настроен так; на машине разработчика вместо этого используется локальный PostgreSQL.

Общее ядро (15 октября 2026, SHIF-25; не развёрнуто). API теперь стоит на том же ядре, что и наши другие продукты: у таблиц имена строчными буквами, каждое время хранится с часовым поясом, а компания и её владелец стали командой и её участниками. Одна миграция перенесла все существующие строки в новые таблицы, сохранив все id; секреты, запечатанные старым ключом, — учётные данные агента, сохранённый контекст чата — перенести было нельзя, и они выдаются заново, когда понадобятся. Таблицы, которые добавило ядро:

  • Пользователь — теперь ещё с ролью на платформе (admin открывает настройки всей платформы, это не роль в команде) и статусом.
  • Команда — бизнес владельца: название и статус.
  • Участник команды — человек в команде: owner (ровно один), admin или member, и состоит ли он в ней ещё или ушёл. Все, кто работает в магазинах команды, — её участники; администратор может делать с людьми и приглашениями команды то же, что и владелец, но не может передать команду.
  • Сессия — одно устройство, на котором вошли. Вход возвращает короткоживущий токен доступа и токен обновления; каждое обновление заменяет токен обновления, а повторное использование старого завершает всю сессию — значит, он есть у кого-то ещё. Выход или новый пароль завершают сессии на сервере.
  • Сброс пароля — одноразовая ссылка на час, присланная письмом; хранится только её отпечаток.
  • API-ключ — для программы вместо человека: одна команда, название, что ей можно (пока — читать команду), срок действия и когда ключ последний раз использовали; хранится только отпечаток, сам ключ показывается один раз. Передача команды завершает ключи прежнего владельца.
  • Передача владения — владелец предлагает команду другому участнику; когда тот принимает, он становится владельцем, а прежний — администратором.
  • Задача — фоновая работа, хранится в базе, чтобы несколько копий API не делали её дважды: на ней работают перезагрузка настроек и сверка участников с агентами.

С 11 октября 2026 существуют десять таблиц, созданных миграциями, и больше ничего с этой страницы. Шесть из них заменяют пять таблиц от 6 октября (компании с участниками без роли и сотрудники, которые не могли войти); тестовые данные того времени удалены, как разрешил владелец. Графики и смены добавлены в тот же день, затем запросы на изменения и элементы «Ждёт вас». 14 октября 2026 добавлена таблица почасовой нагрузки магазина.

  • Пользователь — имя, почта и пароль, который хранится только в виде хеша. У приглашённого человека пароля нет, пока он не примет приглашение.

  • Команда (до 15 октября 2026 — компания) — бизнес владельца: название.

  • Участник команды (до 15 октября 2026 — только владелец, как участник компании) — см. выше.

  • Магазин — магазин команды: название, адрес, время открытия и закрытия (одно открытие в день, закрытие в тот же день), его часовой пояс (стандартное название вроде Europe/London, обязателен), описание, порядок сортировки и статус, active или inactive. Новый магазин встаёт в конец списка владельца. Описание (с 14 октября 2026) — простой текст до 4000 знаков, задуманный как контекст для будущего ассистента: формат магазина, расположение, покупатели, особенности; пока его ничто не читает.

  • Почасовая нагрузка магазина (14 октября 2026) — обычное число чеков на кассе за один час одного дня недели в одном магазине: с понедельника по воскресенье, по одному значению на каждый часовой слот от открытия до закрытия; слот называется по часу начала (17 — это 17:00–18:00; неполный последний час — тоже слот). Целое число, ноль или больше; незаполненный слот неизвестен и не хранится. Значения вне текущих часов работы сохраняются, но не показываются, так что при возврате прежних часов они появляются снова. С 16 октября 2026 их читает дневной вид графика (ниже); прогноза по-прежнему нет, и график по ним ничто не строит. Рядом магазин хранит число чеков на кассира в час (16 октября 2026): сколько чеков один кассир пробивает за час, целое число от 1 до 10 000, 80, пока его не изменят; правят его те же люди, что и почасовую нагрузку. Одна строка на магазин, день и час, а не один блок чисел на магазин — так сама база данных проверяет каждое значение, а будущий читатель может спросить про один час.

  • Занятость — место человека в одном магазине: управляющий или сотрудник, управляющий, которому подчиняется сотрудник (сама база данных не примет управляющего из другого магазина), должность из списка команды (до 30 октября 2026 — вписанная свободным текстом, см. Должность ниже), часы по договору в неделю, описание и статус, invited, active или inactive. Одна на человека. Навыков пока нет. Описание (с 14 октября 2026) — простой текст до 4000 знаков, задуманный как контекст для будущего ассистента: сильные стороны, навыки, ограничения; пока его ничто не читает. Видят его только те, кто может его менять: владелец и управляющий — для сотрудников своего магазина. Человек никогда не видит собственного описания (решение о приватности, принятое при разработке, ждёт подтверждения владельца; см. открытые вопросы).

  • Должность (30 октября 2026, по просьбе владельца) — одна запись собственного списка должностей команды, который заполняет владелец: название до 100 знаков, единственное в команде без учёта регистра и пробелов по краям («Кассир» и « кассир» — одна должность), необязательное описание до 2000 знаков — контекст для ассистента, как и у человека, — и статус, active или archived. Один список на весь бизнес, общий для всех его магазинов (ответ владельца в тот же день). Добавляет, переименовывает, описывает и архивирует должности только владелец; управляющие и сотрудники читают действующие. Удаления нет: архивная должность не даётся никому новому и остаётся у тех, у кого она есть. У человека одна должность или никакой; она выбирается из списка и никогда не вписывается — в приглашении и в окне человека. Инструменты ассистента для людей отдают должность каждого человека с её описанием, а солвер передаёт агенту описание должности один раз, вместе с людьми, у которых она есть, так же как описание человека. Вписанные раньше должности сохранены: когда появился список, различные непустые должности каждой команды стали её действующими должностями — пробелы по краям убраны, одно и то же слово в разном регистре посчитано один раз, в написании, которое сохранило большинство, — каждому человеку дана его должность, а поле со свободным текстом удалено. Пустая должность не дала никакой.

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

  • Приглашение — в команду и один из её магазинов, для конкретного человека и почты, на роль управляющего или сотрудника, со сроком действия семь дней и статусом: ожидает, принято или отозвано (с 15 октября 2026 — revoked); истёкшее показывается как истёкшее. Хранится только отпечаток (хеш) ссылки. С 15 октября 2026 ссылка отправляется письмом и по-прежнему один раз показывается тому, кто пригласил, — чтобы передать, если письмо не дошло; повторное приглашение того же адреса заменяет ожидающее. Приглашение создаёт человека и его занятость со статусом invited; принятие задаёт пароль, делает занятость active, а человека — участником команды; отзыв снова удаляет приглашённого человека.

  • График — неделя одного магазина, с понедельника по воскресенье (вместо «периода» из схемы — неделя, и версии нет), черновик или опубликован, с короткой заметкой вроде «Made by hand · not sent yet» и моментом публикации. Один на магазин и неделю.

  • Смена — один человек в один день недели графика: время начала и конца, участок (торговый зал, касса или дежурный управляющий) и кто её поставил (демо-данные, управляющий, запрос или ассистент). Человек должен работать в магазине графика, и ничего другого не примет сама база данных. Смена должна укладываться в часы работы магазина и заканчиваться после начала, поэтому через полночь смена не идёт. С 14 октября 2026 у человека может быть несколько смен в один день — разделённые смены, например 12:00–14:00 и 18:00–20:00, — до трёх, и смены одного человека в один день не могут пересекаться: одна заканчивается в 14:00, следующая начинается в 14:00 — так можно. Пересечение не примет сама база данных; предел в три смены — правило API. С 14 октября 2026 у смены есть и перерыв в минутах — от 0 до 180, шагом 5, короче самой смены; у существующих смен его нет. С 16 октября 2026 у перерыва может быть и время начала: тогда весь перерыв, от начала на его минуты, должен лежать внутри смены, а у смены без перерыва начала нет — иное отклоняет API, а начало вне смены не примет сама база данных. Перерыв без начала — это «время не задано», как у всех перерывов до этого дня; экраны пишут «1 h break 13:00–14:00», где время известно. Одобренное изменение часов сохраняет начало перерыва, пока перерыв помещается в новое время, иначе начало сбрасывается; при обмене оно переходит вместе со сменой.

  • Шаблон смены (14 октября 2026) — именованная заготовка смены магазина, например «Утро 06:00–10:00» или «День 09:00–18:00 · перерыв 60 мин»: название, начало и конец, перерыв, участок или без него и место в списке магазина. До десяти на магазин, при сохранении — в часах работы магазина. Это только заготовка: смена, сделанная из неё, копирует значения и не хранит ссылки на шаблон, поэтому изменение или удаление шаблона не меняет ни одной смены. Если часы магазина потом изменятся, шаблон, оказавшийся вне них, сохраняется, помечается и не предлагается, пока его не поправят. С 16 октября 2026 у перерыва шаблона тоже может быть время начала, по тому же правилу, что у смены, и смена из шаблона его копирует.

  • Запрос на изменение — просьба одного человека изменить одну из своих смен в своём магазине: вид (выходной, выходной с заменой, обмен, другие часы), само изменение как структурированное предложение — убрать смену, отдать её коллеге, сдвинуть её время или обменять две смены, каждый раз со сменой такой, какой она была в момент просьбы; выходной и выходной с заменой касаются дня, поэтому в день с несколькими сменами запрос берёт каждую из них (14 октября 2026), а обмен и другие часы касаются одной смены, — коллега, которого спросили (если есть), и его ответ, кто решает (конкретный управляющий, любой управляющий магазина или владелец), заголовок, строка-сводка, слова самого человека, метка («Covered», «Fits rules», «No overtime», «Needs a call», «No cover»), строки проверок, кто, когда и как решил — человек, автоматически или, позже, ассистент, — а для отклонения — названная причина (14 октября 2026). Статус идёт так: ждёт коллегу → ждёт решения → одобрен или отклонён; пока запрос ждёт, человек может его отозвать (отозван, с моментом отзыва). «Сейчас» и «Если одобрить» вычисляются из предложения и не хранятся. В наброске запрос принадлежит графику; созданный принадлежит магазину и может захватывать две недели (обмен).

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

Что происходит с запросом. Запрос, которому нужен коллега, сначала ждёт его. Коллега может отказаться без объяснения; тогда запрос заканчивается как отклонённый, и никто по нему не решал, а сотрудник видит это в «Моих запросах». Что происходит дальше, не спроектировано, поэтому больше ничего не создано. Запрос, который никто не закрывает, идёт сразу тому, кто решает. Одобрение заново проверяет смены и меняет их одним шагом, всё или ничего: если смены уже не те, о которых был запрос, или теперь нарушится правило, ничего не меняется, и тому, кто решает, сообщается, что график изменился. Отклонение ничего не меняет в графике и всегда объясняется (правило владельца, 14 октября 2026): управляющий или владелец пишет причину от 3 до 500 символов, сотрудник видит её в своём запросе, а отмена отклонения её стирает. Коллеге, который отказался, причина по-прежнему не нужна. Каждое решение говорит, кто его принял (правило владельца, 14 октября 2026): записывается, решил ли человек — и кто именно, — или решение было автоматическим или ассистента, а запрос, списки запросов, одобренные изменения в графике, диалог смены и «Мои смены» показывают «Approved by Daniel Okafor» или «Approved automatically». Сейчас каждое решение принимает человек: ничего не одобряется автоматически, и ассистент ничего не решает; два других способа записываются, чтобы такое решение, когда оно появится, никогда не показывалось как чьё-то. Решения, принятые до 14 октября 2026, считаются решениями человека, если он записан, иначе — автоматическими. Решение можно отменить, пока неделя не закончилась: отмена одобрения возвращает смены как были и не проходит, если их с тех пор снова меняли.

Проверяет пока не ассистент. В демо-запросах строки проверок слово в слово из прототипов. Запрос, созданный через API, получает собственные фиксированные проверки API: в часах работы, не меньше 11 часов отдыха (от последней смены одного дня до первой смены следующего; перерыв внутри разделённого дня отдыхом не считается), часы за неделю против договора, никаких пересечений с другими сменами человека в тот день и не больше трёх смен в день, тот же магазин — и с 14 октября 2026 предупреждение, если одобрение оставит часть часов работы дня без дежурного управляющего там, где сейчас он есть («Approving leaves no manager on duty on Wed, Oct 21, 16:00–20:00»). Строки считаются, когда запрос создан, и хранятся с ним; при решении их заново не считают. За ними нет ни решателя, ни правил покрытия; ассистент, который писал бы эти строки, появится позже.

Идёт ли неделя сейчас или прошла, не хранится. Это следует из дат и сегодняшнего дня магазина: неделя, воскресенье которой закончилось, прошла; опубликованная неделя, в которую входит сегодня, идёт; более поздняя опубликованная ждёт; черновик остаётся черновиком, пока его неделя не закончится. Часы смены — отработанные часы: конец минус начало минус перерыв (14 октября 2026); часы дня — сумма его смен. Их использует всё, что считает часы: неделя человека против договора, предупреждения и проверки запросов о часах за неделю, итоги недели, магазина и человека и то, что возвращают инструменты ассистента (до 19 октября 2026 — также тексты демо ассистента). Переработка человека за неделю — часы сверх его часов по договору. У кого часов по договору нет, у того нет и переработки.

Дежурный управляющий на все часы работы (14 октября 2026). Для каждого дня недели — открытым считается каждый день, потому что у магазина одно время работы на все дни — смены на участке дежурный управляющий вместе должны покрывать часы работы магазина; перерывы не учитываются, потому что человек в магазине. API находит непокрытые отрезки по часам магазина и отдаёт их вместе с неделей владельцу и управляющим («Tue: no manager on duty 06:00–08:00, 20:00–22:00»). Это только предупреждение: из-за него ничего не отклоняется, включая публикацию, — принцип владельца, что правила здесь подсказывают, а не запрещают. Считается участок смены, а не роль человека: участок говорит, кто отвечает за этот отрезок, поэтому управляющий на кассе не считается, а любой, кого поставили на участок дежурного управляющего, считается. Этот выбор наш, владельцу его ещё подтвердить. С 23 октября 2026 проверка действует только в магазине с активным управляющим: магазин, который владелец ведёт сам с сотрудниками, не показывает пробелов (вместо пробела в каждый день), его запросы не получают предупреждения о дежурном управляющем, а решатель не планирует там дежурство. Это тоже наш выбор, владельцу его ещё подтвердить.

Расчёты дневного вида (16 октября 2026). Для каждого часового слота каждого дня недели — тех же слотов, что у почасовой нагрузки — API отдаёт вместе с неделей четыре числа по всему магазину, что бы ни отфильтровал экран: обычное число чеков в этот день недели и час (неизвестное остаётся неизвестным); нужно касс — чеки, делённые на число чеков на кассира и округлённые вверх, не меньше одной, пока магазин открыт, и неизвестно, если неизвестны чеки; сколько людей на кассе — в сменах участка «касса» — и сколько на смене вообще. Люди считаются в человеко-часах: человек входит в час той частью, которую он там находится (смена с 09:30 даёт 0,5 в часе 09:00), минус часть перерыва с известным началом, попавшая в этот час. Перерыв без заданного начала не вычитается нигде, так что этот человек считается присутствующим всю смену, а день говорит, сколько у него таких перерывов. Числа округляются до одного знака после запятой, а час, в котором на кассе меньше людей, чем нужно касс, отмечается. Это правило подсчёта наше, владельцу его ещё подтвердить. Оно только показывает: из-за него ничего не отклоняется и ничего не планируется.

Лист месяца (16 октября 2026). Для календарного месяца API отдаёт каждую неделю с понедельника по воскресенье, которая его задевает, — от четырёх до шести — с её статусом (опубликована, черновик или графика нет); строку на каждого человека, как в неделе, с его сменами по дням и одобренными изменениями; и по каждому человеку только в пределах календарного месяца: смены, отработанные часы, выходные — дни в неделе с графиком, в которые у него нет смены, — и договор для сравнения: часы в неделю × дней в месяце ÷ 7, так что неделя, которую месяц покрывает лишь частично, считается по своим дням в нём (октябрь 2026: 31 день, 4,43 недели). Это правило наше, владельцу его ещё подтвердить. Месяц только для чтения; его видят владелец и управляющие магазина, сотрудник — нет.

Что показывает API. Недели магазина, одну неделю в виде одной сетки всех, кого может видеть спрашивающий, — сначала управляющие, затем сотрудники, у каждой строки роль человека, кому он подчиняется и может ли спрашивающий её править (14 октября 2026; до этого сотрудники и управляющие были двумя отдельными сетками), — где день человека показывает все его смены, с нарисованными на них запросами, неделю, в которую входит сегодня, собственные смены человека и часы «этой недели» для магазинов и людей. С каждой неделей он отдаёт и дни без дежурного управляющего, а для каждого магазина — его шаблоны смен (только владельцу и управляющим магазина). Для демо ассистента по сценарию (удалено из приложения 19 октября 2026; с тех пор его не вызывает ни один экран) API также отвечает, только для чтения, какие коллеги могли бы взять одну из смен спрашивающего — подменить (замена берёт каждую смену спрашивающего в этот день, и взять её может коллега, который в этот день работает в другие часы) или обменяться на одну из своих смен той же недели (предлагается только для дня с одной сменой, потому что обмен переносит одну смену) — с теми же фиксированными проверками, что и запрос, без предупреждений. Сотрудник видит свои смены только в опубликованных неделях. Управляющий видит графики своего магазина, владелец — графики всех магазинов.

Правка вручную ​

Владелец решил 11 октября 2026, что позже каждое изменение будет идти через ассистента, а пока ассистента нет, каждое изменение должно быть возможно и вручную. Всё описанное ниже создано (11 октября 2026, не развёрнуто) — это и есть та временная мера: ассистент должен взять эти действия на себя по тем же правилам.

  • Кто правит графики. Владелец правит каждую строку недель любого магазина — и сотрудников, и управляющих. Управляющий правит только сотрудников своего магазина: строки управляющих — владельца, поэтому собственные изменения управляющего идут владельцу запросами. Строки управляющих управляющий видит только для просмотра, как и до одной сетки. Сотрудник не правит ничего. Человек из другой компании или сотрудник получает «не найдено»; управляющему на строке управляющего говорится, что это график владельца.
  • Недели. Неделя создаётся пустой или копией предыдущей (каждая смена на неделю позже); копия управляющего переносит только смены сотрудников. Публикация — одно действие для всей недели, для управляющих и сотрудников одинаково. Ушедшие люди и смены вне сегодняшних часов работы в копию не попадают. Неделю правят, пока она черновик, и публикуют один раз (момент публикации записывается). Опубликованную или текущую неделю те же люди по-прежнему могут править. Прошедшую неделю изменить нельзя.
  • Смены. Смену добавляют, меняют или удаляют в сетке недели: человек — это строка, день — столбец; меняются время, перерыв — и, если нужно, время его начала — и участок. Предлагаются шаблоны смен магазина: выбранный шаблон заполняет время, перерыв и участок, которые ещё можно изменить, а пустой день можно заполнить шаблоном в два клика. День человека показывает все его смены, каждая открывается отдельно, и предлагает ещё одну — в том числе из шаблона, — пока в дне меньше трёх смен. Действуют те же правила, что и везде, в часовом поясе магазина: в часах работы, внутри недели, человек работает в магазине, до трёх непересекающихся смен в день. Меньше 11 часов отдыха и больше часов, чем по договору, показываются как предупреждения и не мешают. Всё, что записано вручную, отмечается как поставленное управляющим, правки владельца тоже.
  • Смена с открытым запросом заблокирована. Пока запрос о ней ждёт коллегу или решения, её нельзя изменить или удалить; решение или отзыв запроса её освобождает. Поэтому решение никогда не наткнётся на смену, незаметно изменившуюся под ним.
  • Запросы вручную. Сотрудник — и управляющий, для своих смен, — создаёт запрос через форму: одна из его смен на этой или следующей неделе, что ему нужно (выходной, замена коллегой, обмен на смену коллеги на той же неделе, другие часы) и необязательная причина, которая хранится как его собственные слова. Выходной и замена берут каждую смену этого дня, и форма об этом говорит. Предлагаются активные коллеги магазина с той же ролью. Запрос проходит те же проверки и то же правило, кто решает, что и раньше. Запрос можно отозвать, пока по нему не решили: в графике ничего не меняется, открытая просьба к коллеге исчезает, а запрос уходит из списка того, кто одобряет, и из счётчиков.
  • Шаблоны смен (14 октября 2026). Владелец — для любого магазина, управляющие магазина — для своего добавляют, меняют, переставляют и удаляют его шаблоны (до десяти) в разделе «Shift templates»: на странице магазина у владельца, в «Графиках» у управляющего. Сотруднику смотреть нечего.
  • Магазины. Владелец правит название, адрес, часы работы, часовой пояс, статус и описание магазина; с 19 октября 2026 (решение владельца) управляющие магазина тоже правят его часы работы и описание, и больше ничего в нём. Почасовую нагрузку правят владелец и управляющие магазина, потому что они знают его посещаемость (14 октября 2026, ждёт подтверждения владельца), и они же — число чеков на кассира в час рядом с ней (16 октября 2026). Новые часы не принимаются, если хоть одна текущая или предстоящая смена оказалась бы вне их, и мешающие смены называются. При новом часовом поясе каждая смена сохраняет своё время по часам — 08:00 остаётся 08:00, уже в новом поясе.
  • Люди. Владелец правит должность человека, часы в неделю, управляющего (управляющего того же магазина, как решено 11 октября 2026) и статус. Управляющий правит должность и часы в неделю тех, кто ему подчиняется; с 19 октября 2026 (решение владельца) также управляющего — другого управляющего того же магазина — и статус любого сотрудника своего магазина, но никогда управляющего и никогда свой собственный, а ещё приглашает сотрудников в свой магазин и отзывает эти приглашения. Описание (14 октября 2026): владелец пишет его для любого управляющего или сотрудника, в том числе при приглашении; управляющий — для любого сотрудника своего магазина, но не для управляющих и не для себя; всё остальное API отклоняет. Роль и магазин вручную не меняются. Если сделать человека неактивным, его история остаётся: смены по сегодняшний день и запросы сохраняются. Его смены после сегодняшнего дня сначала перечисляются и удаляются только после подтверждения владельца. Это не проходит, пока по одной из этих смен открыт запрос, а для управляющего — пока ему ещё кто-то подчиняется. Должности (30 октября 2026): владелец ведёт список команды на People → Positions — добавляет должность, меняет её название или описание, архивирует её и возвращает обратно; должность человека затем выбирается из действующих, либо никакая. Управляющий выбирает её для тех, кто ему подчиняется, как раньше менял должность, и не может добавлять или менять должности.
  • Кто изменил (19 октября 2026). Каждое изменение человека, приглашения или магазина — владельцем или управляющим, на экране или позже через ассистента — записывается: кто, его роль, вид изменения (деактивирован, снова активирован, новый управляющий, приглашён, отозвано, изменён) и названия изменённых полей, но никогда не их значения. С 30 октября 2026 записывается и каждое изменение должности (добавлена, изменена, архивирована, возвращена). На экране эту запись пока ничто не показывает.

Они нигде не развёрнуты; см. Что создано.

Идентификаторы ​

У каждой записи, на которую может сослаться человек или партнёр, читаемый id, и этот id — её первичный ключ (15 октября 2026, SHIF-26; не развёрнуто): store-calm-rivers-k8m4p2d7n9x3, а не 0b5c…-…. Второго id рядом нет: читаемый и есть ключ строки, и все ссылки на неё используют его.

Форма — префикс – прилагательное – существительное – двенадцать символов, только строчные ASCII, одна во всех продуктах Agentfy с 15 октября 2026 (SHIF-28; формат ниже). Префикс говорит, что это за запись: это имя модели записи в схеме базы данных, целиком, строчными буквами, слова через дефис, без сокращений (15 октября 2026, SHIF-27; правило одно для всех продуктов Agentfy). До SHIF-27 часть префиксов были сокращениями (org, emp, sched, tmpl, req и другие); одна миграция заменила каждый из них полным именем и оставила остальную часть каждого id — слова и символы — как была. Исключение одно: слово Organization пишется org (24 октября 2026, SHIF-40, решение владельца для всех продуктов Agentfy), поэтому у OrganizationConversation префикс org-conversation; миграция 20261024T1456_org_id_prefixes переименовала существовавшие id organization-…, тоже сохранив остальную часть каждого id. Id organization-… больше не распознаётся: запись по нему просто не находится.

ЗаписьМодельПрефикс
Команда (до 15 октября 2026 — компания)Teamteam
Участник командыTeamMemberteam-member
ПользовательUseruser
МагазинStorestore
ЗанятостьEmploymentemployment
ПриглашениеTeamInvitationteam-invitation
ГрафикScheduleschedule
СменаShiftshift
Шаблон сменыShiftTemplateshift-template
Почасовая нагрузкаStoreHourlyLoadstore-hourly-load
Запрос на изменениеChangeRequestchange-request
Элемент «Ждёт вас»InboxIteminbox-item
НастройкаSettingsetting
Разговор с агентомOrganizationConversationorg-conversation
Сообщение чатаOrganizationChatMessageorg-chat-message
СессияAuthSessionauth-session
Сброс пароляPasswordResetpassword-reset
API-ключTeamApiKeyteam-api-key
Передача владенияTeamOwnershipTransferteam-ownership-transfer
ЗадачаJobjob
Правила описанияDescriptionRuledescription-rule

Последние пять появились с ядром API (15 октября 2026, SHIF-25).

  • Слова — для людей, а не для уникальности. Они берутся из списков пакета human-id версии 4.1.3 (лицензия MIT) как есть — 200 прилагательных и 300 существительных, одних и тех же во всех продуктах Agentfy. Последние двенадцать символов случайны: их выбирает nanoid 3.3.11 (MIT) из криптографического источника среди 32 букв и цифр, которые нельзя перепутать (нет i, l, o, u): 60 бит, около 76 вместе со словами. При миллионе записей одного вида новый id совпадает с существующим примерно один раз на 10¹⁷.
  • Уникальность обеспечивает база. Первичный ключ не примет повтор; тогда API выбирает новый id и пишет снова, до пяти раз. Id выбирает API один раз, при создании записи, и он не меняется; в нём нет имени, даты, роли или секрета.
  • Префикс может содержать дефисы, поэтому id никогда не режется по дефисам, чтобы его найти. API сравнивает начало id со списком префиксов, сначала самые длинные: store-hourly-load-… — это почасовая нагрузка магазина, а не магазин.
  • API проверяет вид каждого переданного id. Адрес магазина с id занятости внутри или что-то, что вовсе не id, получает 400 ещё до поиска. Правильный по форме id всё равно проходит обычные права: чужой магазин выглядит так же, как несуществующий.
  • Записи, созданные до 15 октября 2026, получили новые id одной миграцией, которая переписала все ссылки на них, в том числе внутри сохранённого предложения запроса. Id, которые уже покинули Shiffty, сохранены: компания, магазин, занятость или владелец, которых Agentfy знает по id, чат, чей сохранённый контекст запечатан его id, и запрос, сделанный через ассистента. У этих немногих остаётся прежний UUID, и он по-прежнему принимается; новым записям UUID не выдаётся. Старый адрес с переписанным UUID теперь ничего не находит.
  • Переименование SHIF-27 сменило префикс у каждого id со старым префиксом, в том числе у тех, что Agentfy уже знал. Прода у Shiffty нет, такие id были только в локальных базах; Agentfy (или, до 14 октября 2026, его локальная замена) по-прежнему знает такую запись по старому id. Для локальной базы путь назад — make seed. Контекст разговора, запечатанный старым id, сброшен.
  • Компания стала командой (15 октября 2026, SHIF-25), поэтому префиксы пошли за переименованными моделями: миграция ядра превратила company-…, company-member-… и invitation-… в team-…, team-member-… и team-invitation-… — в каждом id и в каждой ссылке на него, так же, как это сделал SHIF-27, и оставила остальную часть каждого id. Как и там, собственные записи Agentfy и воспроизводимый запрос провижининга оставлены как были, а локальная база, подключённая к Agentfy, сбрасывается через make seed.
  • Не изменено: то, как вещи называет Agentfy (id его команды, агента и чата), ключи, делающие повторный вызов безопасным (idempotency keys), записи аудита, выданные доступы и учётные данные агента сохраняют свои идентификаторы.

Формат id ​

Сделано 15 октября 2026 (SHIF-28), не развёрнуто · один формат в Agentfy, Bonsite, Securify, Shiffty и Store Deputy, по правилу владельца от 15 октября 2026

ЧастьЧто это
Форма<prefix>-<adjective>-<noun>-<suffix>, например user-calm-rivers-k8m4p2d7n9x3
Префиксполное имя модели в kebab-case, слово Organization пишется org, из таблицы выше
Прилагательное, существительноепо одному слову из списков adjectives и nouns пакета human-id 4.1.3, строчными; без глаголов и наречий, без своих слов; слово с чем-то кроме a–z было бы исключено (в 4.1.3 таких нет)
Суффиксровно 12 символов из 0123456789abcdefghjkmnpqrstvwxyz (base32 Крокфорда строчными)
Случайностькриптографическая: crypto.randomBytes, суффикс — через customRandom пакета nanoid 3.3.11
Версииhuman-id 4.1.3 и nanoid 3.3.11, закреплены точно в api/package.json
Гдеapi/src/slices/setup/id/domain/idFormat.ts: formatId, isCanonicalId, isLegacyId, LEGACY_ID_FORMATS

Новые id создаются только в этом виде, функцией formatId, и ничто не создаёт id иначе. API принимает переданный id в этом виде — с префиксом своей записи и обоими словами из списков — или в одном из прежних видов Shiffty, которые он только читает:

Прежний вид (LEGACY_ID_FORMATS)ПримерВыдавался
префикс – прилагательное – существительное – шесть символов, со своими списками слов Shiffty (human-id без 13 прилагательных и 6 существительных, idWords.ts)store-calm-rivers-k8m4p215 октября 2026, SHIF-26 и SHIF-27, до SHIF-28
UUID, сохранённый миграцией SHIF-260b5c…-…до 15 октября 2026

Уже выданные id не переписываются: старый продолжает работать, новая запись получает новый вид. Вид с глаголом, с суффиксом другой длины или из шестнадцатеричных цифр, со словом не из списков получает 400, если это не один из прежних видов выше.

Одна и та же проверка во всех продуктах: при источнике, отдающем байты 0, 1, 2, … по порядку, formatId('user', source) равно user-afraid-swans-nmkjhgfedcba. Сначала выбирается прилагательное, затем существительное (каждое — по одному или двум байтам, прочитанным как число, обрезанным маской до нужного списку числа бит и выбранным заново, если вне диапазона), затем суффикс (19 байт одним запросом, nanoid читает их с последнего).

Не решено ​

  • Где размещены данные сотрудников и кто какую их часть может видеть.
  • Как долго хранятся запросы, решения и старые графики.
  • Сможет ли человек позже работать больше чем в одном магазине, а управляющий — вести несколько, и что тогда станет с правилом «один человек — один агент».
  • Решено 20 октября 2026: у владельца есть собственный агент, один на компанию, с ключом по id компании; его разговор называет владельца по id пользователя, а не по занятости (Интеграция с Agentfy). Не решено: что происходит с разговором владельца, когда компания переходит к другому владельцу.
  • Законные правила перерывов и смены через полночь: ни то ни другое пока нельзя сохранить. Когда приходится перерыв, сохранить можно с 16 октября 2026, но ничто его не предлагает.
  • Нужен ли минимальный промежуток между сменами одного дня (сейчас его нет), правильный ли предел в три смены в день и может ли человек взять выходной только на часть разделённого дня (сейчас выходной и замена берут весь день).
  • Считать ли в проверке дежурного управляющего участок (как сейчас) или роль человека, может ли магазин быть закрыт в какие-то дни (сейчас открытым считается каждый день) и пересчитывать ли проверки запроса при решении.
  • Считать ли переработку по неделе относительно часов по договору (как сейчас) или по другому правилу, например по предельному сроку из закона.
  • Как долго хранятся решённые и отозванные запросы и отвеченные элементы «Ждёт вас» (отвеченные пока уходят из списка через семь дней) и могут ли другие запросы менять больше одной смены (выходной и замена разделённого дня уже меняют).
  • Должна ли копия недели у управляющего переносить и смены управляющих, что значит неактивный магазин для его графиков и может ли человек перейти в другой магазин или на другую роль (вручную сейчас нельзя).
  • Сколько длится вход. Вход собственный у Shiffty (решено 6 октября 2026): хеши паролей и, с 15 октября 2026, сессии — в этой базе; сроки — 15 минут для токена доступа и 30 дней для сессии без использования — это значения ядра по умолчанию, а не выбор владельца. См. Экраны.

Что читать дальше ​