ВозможностиОрганизации
Документация
    Ring Platform

    Децентрализованное самостроящееся будущее

    Войти
    Организации
    Возможности
    Магазин
    Документация
    Концепции платформы
    RING ЭкономикаSonoratek LLCГлобальное влияниеAI встречает Web3
    Начать
    Быстрый стартКалькуляторДорожная карта
    Конфиденциальность|Контакты
    v1.106.26|Sonoratek LLC

    Documentation

    Концепции, ценность и типичные сценарии клонирования — меньше кода.

    Добро пожаловать в Ring
    Краткий справочник
    С чего начать
    Предварительные требования
    Установка
    Первый успех
    Следующие шаги
    Функции
    Store
    Склад и остатки
    Управление вендорами
    Комиссии и расчёты
    Членство и кредиты
    SubscriptionConductor
    PaymentConductor
    Ring Oracle
    Интеграция платежей
    Интеграция WayForPay
    Web3 Кошелек
    WalletConductor
    Реферальные коды (Refcodes)
    Шторка страницы
    NFT Exhibition Marketplace
    Система Стейкинга Токенов
    Организации
    Возможности
    AI Matcher
    Messaging
    Peer Games
    News
    Блоги участников
    Система Резервирования Имён Пользователей
    Научный редактор
    Уведомления
    Push-уведомления через FCM (Ring)
    Email AI-CRM
    Ring Mailer и RingdomX Mail
    Протокол Tunnel
    Authentication
    Безопасность и соответствие
    Система локалей
    Мобильный Опыт
    Паттерны Оптимизации Производительности
    Примеры
    Quick Start
    Базовая настройка
    White Label
    Custom Branding
    Интеграция Web3
    Реальные Проекты
    Advanced Features
    Кастомизация
    Быстрый старт — ваш первый клон Ring
    Руководство по кастомизации
    Vertical Presets (SSOT)
    Руководство по Ringization
    Branding
    Темы оформления
    Features
    Localization
    Настройка токеномики
    Интеграция платёжного шлюза
    Референсные деплои Ring
    Конфигурация проекта
    Публичные переменные окружения
    Секреты Order Lab
    Project ID WalletConnect (Reown Cloud)
    Поддерживаемые сервисы
    Вики NODUS (знания проекта)
    Плейбук конфигурации
    Web3
    Token launch jurisdictions
    Кошелёк
    Советы по безопасности кошелька
    Интеграции
    Ethereum-кошельки (Wagmi v3)
    Развёртывание
    Развёртывание на собственном сервере
    Vercel
    Docker
    Конфигурация Окружения
    Мониторинг и аналитика
    Оптимизация производительности
    Резервное копирование и восстановление
    Архитектура
    Data Model
    Security
    Real Time
    Discovery Mutation Sync
    Архитектура PaymentConductor
    Wallet Conductor
    Архитектура News Kingdom
    Бекенд Сервисы
    Интеграция Firebase
    Разработка
    Ring MCP Server
    OSS и enterprise

    Быстрый вход (CTO · аудиторы · агенты)

    Приветствие — миссия и аудитории
    Краткий справочник
    С чего начать
    Архитектура и Auth.js
    Режимы бэкенда и базы данных (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Деплой (Docker · k8s)
    Безопасность и соответствие требованиям
    ringdom.org — база LegioX
    Исходный код — лицензия MIT (GitHub)

    Documentation

    Концепции, ценность и типичные сценарии клонирования — меньше кода.

    Добро пожаловать в Ring
    Краткий справочник
    С чего начать
    Предварительные требования
    Установка
    Первый успех
    Следующие шаги
    Функции
    Store
    Склад и остатки
    Управление вендорами
    Комиссии и расчёты
    Членство и кредиты
    SubscriptionConductor
    PaymentConductor
    Ring Oracle
    Интеграция платежей
    Интеграция WayForPay
    Web3 Кошелек
    WalletConductor
    Реферальные коды (Refcodes)
    Шторка страницы
    NFT Exhibition Marketplace
    Система Стейкинга Токенов
    Организации
    Возможности
    AI Matcher
    Messaging
    Peer Games
    News
    Блоги участников
    Система Резервирования Имён Пользователей
    Научный редактор
    Уведомления
    Push-уведомления через FCM (Ring)
    Email AI-CRM
    Ring Mailer и RingdomX Mail
    Протокол Tunnel
    Authentication
    Безопасность и соответствие
    Система локалей
    Мобильный Опыт
    Паттерны Оптимизации Производительности
    Примеры
    Quick Start
    Базовая настройка
    White Label
    Custom Branding
    Интеграция Web3
    Реальные Проекты
    Advanced Features
    Кастомизация
    Быстрый старт — ваш первый клон Ring
    Руководство по кастомизации
    Vertical Presets (SSOT)
    Руководство по Ringization
    Branding
    Темы оформления
    Features
    Localization
    Настройка токеномики
    Интеграция платёжного шлюза
    Референсные деплои Ring
    Конфигурация проекта
    Публичные переменные окружения
    Секреты Order Lab
    Project ID WalletConnect (Reown Cloud)
    Поддерживаемые сервисы
    Вики NODUS (знания проекта)
    Плейбук конфигурации
    Web3
    Token launch jurisdictions
    Кошелёк
    Советы по безопасности кошелька
    Интеграции
    Ethereum-кошельки (Wagmi v3)
    Развёртывание
    Развёртывание на собственном сервере
    Vercel
    Docker
    Конфигурация Окружения
    Мониторинг и аналитика
    Оптимизация производительности
    Резервное копирование и восстановление
    Архитектура
    Data Model
    Security
    Real Time
    Discovery Mutation Sync
    Архитектура PaymentConductor
    Wallet Conductor
    Архитектура News Kingdom
    Бекенд Сервисы
    Интеграция Firebase
    Разработка
    Ring MCP Server
    OSS и enterprise

    Быстрый вход (CTO · аудиторы · агенты)

    Приветствие — миссия и аудитории
    Краткий справочник
    С чего начать
    Архитектура и Auth.js
    Режимы бэкенда и базы данных (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Деплой (Docker · k8s)
    Безопасность и соответствие требованиям
    ringdom.org — база LegioX
    Исходный код — лицензия MIT (GitHub)

    Documentation

    Концепции, ценность и типичные сценарии клонирования — меньше кода.

    Добро пожаловать в Ring
    Краткий справочник
    С чего начать
    Предварительные требования
    Установка
    Первый успех
    Следующие шаги
    Функции
    Store
    Склад и остатки
    Управление вендорами
    Комиссии и расчёты
    Членство и кредиты
    SubscriptionConductor
    PaymentConductor
    Ring Oracle
    Интеграция платежей
    Интеграция WayForPay
    Web3 Кошелек
    WalletConductor
    Реферальные коды (Refcodes)
    Шторка страницы
    NFT Exhibition Marketplace
    Система Стейкинга Токенов
    Организации
    Возможности
    AI Matcher
    Messaging
    Peer Games
    News
    Блоги участников
    Система Резервирования Имён Пользователей
    Научный редактор
    Уведомления
    Push-уведомления через FCM (Ring)
    Email AI-CRM
    Ring Mailer и RingdomX Mail
    Протокол Tunnel
    Authentication
    Безопасность и соответствие
    Система локалей
    Мобильный Опыт
    Паттерны Оптимизации Производительности
    Примеры
    Quick Start
    Базовая настройка
    White Label
    Custom Branding
    Интеграция Web3
    Реальные Проекты
    Advanced Features
    Кастомизация
    Быстрый старт — ваш первый клон Ring
    Руководство по кастомизации
    Vertical Presets (SSOT)
    Руководство по Ringization
    Branding
    Темы оформления
    Features
    Localization
    Настройка токеномики
    Интеграция платёжного шлюза
    Референсные деплои Ring
    Конфигурация проекта
    Публичные переменные окружения
    Секреты Order Lab
    Project ID WalletConnect (Reown Cloud)
    Поддерживаемые сервисы
    Вики NODUS (знания проекта)
    Плейбук конфигурации
    Web3
    Token launch jurisdictions
    Кошелёк
    Советы по безопасности кошелька
    Интеграции
    Ethereum-кошельки (Wagmi v3)
    Развёртывание
    Развёртывание на собственном сервере
    Vercel
    Docker
    Конфигурация Окружения
    Мониторинг и аналитика
    Оптимизация производительности
    Резервное копирование и восстановление
    Архитектура
    Data Model
    Security
    Real Time
    Discovery Mutation Sync
    Архитектура PaymentConductor
    Wallet Conductor
    Архитектура News Kingdom
    Бекенд Сервисы
    Интеграция Firebase
    Разработка
    Ring MCP Server
    OSS и enterprise

    Быстрый вход (CTO · аудиторы · агенты)

    Приветствие — миссия и аудитории
    Краткий справочник
    С чего начать
    Архитектура и Auth.js
    Режимы бэкенда и базы данных (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Деплой (Docker · k8s)
    Безопасность и соответствие требованиям
    ringdom.org — база LegioX
    Исходный код — лицензия MIT (GitHub)
    Ring Logo

    Loading documentation...

    Preparing Ring content

    Ring Logo

    Loading documentation...

    Preparing Ring content

    Ring Logo

    Loading documentation...

    Preparing Ring content

    Возможности

    Ring Opportunities это цикл предложения ↔ спроса для каждого клона: участники публикуют предложения и запросы (плюс специализированные типы), Matcher оценивает заинтересованных пользователей, а уведомления приглашают их связаться, не дожидаясь, пока кто-то будет искать в ленте.

    Список просмотра на /opportunities это именная лента: каждая карточка показывает безопасного для публики автора, человеческие теги и Like / Save / Hide / Contact. Живые вставки по-прежнему приходят через Tunnel; панель просмотра больше не показывает строку статуса websocket.

    Используйте вкладки Founder / Developer в боковой панели документации, чтобы отфильтровать эту страницу. Frontmatter audience управляет блоками на странице; видимость в боковой панели управляется lib/docs/audience-curated-docs.ts.

    Маркетинговые KPI не являются телеметрией продукта

    Старые тексты заявляли фиксированные проценты точности, экономию на найме и «15k+ пользователей». Эти цифры устарели. Актуальные числа берутся из аналитики Admin → Matcher и трафика клона. Пороги Matcher это конфиг (ring-config.json → matcher, переопределяется в настройках платформы), а не SLA для всего королевства.

    Традиционные доски и Ring

    РаньшеЭквивалент в Ring
    Опубликовать вакансию и надеяться, что кто-то найдётОпубликовать возможность → Matcher оценивает кандидатов → уведомление с короткими пояснениями
    Только предложения (работодатель → талант)Двойная природа: offer и request плюс специализированные типы
    Одна таксономия объявленийWhite-label ограничение opportunities.enabledTypes (16 по умолчанию в Layer1 / конфиге org)
    Ручное обогащениеНеобязательное LLM автозаполнение при создании (OpportunityAutoFillService)
    Непрозрачное ранжированиеВосемь оцениваемых факторов (MatchFactors в lib/ai/types.ts) + настраиваемый scoreThreshold
    UUID автора на карточкахБезопасные для публики имя / аватар; username только когда publicProfile равен true
    Чипы sourceMessageId:Скрытые машинные теги; From chat только для владельца, когда есть происхождение
    «Live Updates Active / via websocket» в просмотреТихий useRealtimeOpportunities; строка статуса остаётся только на странице деталей
    Отдельные копилкиКоллективные копилки и копилки строителей через Public Pools (путь пожертвований работает; on-chain escrow ограничен)

    Цикл подбора (общее)

    Создание возможности → подбор → уведомление

    Значения Matcher по умолчанию при установке (ring-config.json → matcher): scoreThreshold 0.7, maxMatches 10, autoApprove false, autoApproveMinScore 0.7, llmConfidenceGate 0.8. Env может переопределить автоодобрение через MATCHER_AUTO_APPROVE / MATCHER_AUTO_APPROVE_MIN_SCORE (см. features/admin/platform-settings/matcher-config.ts). Ограничивайте число совпадений через MAX_MATCHES_PER_OPPORTUNITY.

    Факторы оценки, пути LLM и эвристики и длина пояснений описаны на странице AI Matcher. Пороги выше это значения установки по умолчанию, а не опубликованный KPI точности.

    Почему это важно для вашего клона

    Возможности превращают ваш Ring в локальный маркетплейс намерений: люди публикуют, что могут предоставить и что им нужно. Matcher отправляет уместные приглашения вместо того, чтобы полагаться на прокрутку ленты. Специализированные типы (вакансии, коллективные заказы, услуги по расписанию, программа/инвестиция → CRM, квесты кастомизации Ring) ограничиваются для каждого клона, поэтому вы запускаете только те циклы, которые нужны вашей вертикали.

    Организации

    Связывайте возможности с верифицированными организациями через contactInfo.linkedEntity / organizationId.

    Уведомления

    Приглашения по совпадению это настоящие уведомления, а не маркетинговые email-рассылки.

    Сообщения

    Contact открывает . Преобразования задач из чата сохраняют для владельца глубокую ссылку .

    Карта реализации

    АспектПроверенный путь
    Типы / SerializedOpportunityfeatures/opportunities/types/index.ts (creator?, viewer?, likes?)
    Ограничение включённых типовfeatures/opportunities/lib/opportunity-enabled-types.ts ← ring-config.json opportunities.enabledTypes
    Матрица создания по ролямfeatures/opportunities/lib/opportunity-permissions.ts (MEMBER_OFFER_TYPES, REQUEST_TYPES, SUBSCRIBER_TYPES, confidential)
    Создание + AI-конвейерfeatures/opportunities/services/create-opportunity.ts
    Список / поискget-opportunities.ts, search-opportunities.ts: исключение скрытых + attachOpportunityFeedFields
    Сводки авторовget-opportunity-creators.ts (name / displayName / username, если публичный / avatar)

    Рекомендуемый путь

    Используйте ring-ai-matcher-specialist (или навык Cursor из того же семейства) с промптом, ожидающим одобрения:

    «Проверь цикл Opportunities этого клона: выведи opportunities.enabledTypes и matcher из ring-config.json, подтверди, что env для LLM задан, сделай пробное создание одного offer и одного request, сообщи MatchFactors и перевёл бы autoApprove pending→active. Открой /opportunities как два пользователя и подтверди, что карточки показывают имена (а не UUID), Hide исключает после перезагрузки, а Contact ведёт на /messages?user=. Не меняй platform_settings, пока я не одобрю.»

    Чеклист входных данных: ключ клона, доступ администратора, имеющиеся учётные данные LLM, тестовый id организации для organizationId.

    Ручной путь

    1. 1

      Задайте opportunities.enabledTypes и matcher.* в ring-config.json; передеплойте или перезагрузите снимок конфига так, как ваш клон делает это для ring-config.

    2. 2

      В Admin → Matcher / AI settings оставьте автоодобрение выключенным; задайте scoreThreshold / maxMatches под толерантность вашей вертикали.

    3. 3

      Создайте тестовую возможность через UI выбора типа (или POST /api/opportunities); откройте My Opportunities на /opportunities/my.

    4. 4

      Убедитесь, что пользователь с совпадением получил уведомление и что списки поиска обновляются (Tunnel / мягкое обновление) без выдуманного шага переиндексации. Убедитесь, что у списка просмотра нет строки статуса websocket.

    Частые вопросы

    Влияние

    Будет ли Matcher автоматически публиковать каждое новое объявление?

    Нет. По умолчанию matcher.autoApprove равен false. Когда включено, maybeAutoApproveOpportunity всё равно требует порогов оценки и уверенности LLM (autoApproveMinScore, llmConfidenceGate).

    Получу ли я «95% точности подбора» для всего королевства?

    Нет. Считайте исторические маркетинговые проценты устаревшими. Используйте аналитику Admin Matcher для своего тенанта.

    Остаются ли авторы анонимными в ленте?

    Нет. Аутентифицированные зрители видят имя и аватар. Username добавляется только когда publicProfile равен true. Флага postAnonymously нет.

    Миграция

    У нас всё ещё есть конвертеры Firestore, нужны ли они?

    Только когда DB_BACKEND_MODE=firebase-full. Клоны PostgreSQL используют opportunity-db-mapper.ts и SerializedOpportunity.

    Куда делся /opportunities/my-opportunities?

    Удалён. Каноническая панель это /opportunities/my через ROUTES.MY_OPPORTUNITIES.

    Почему исчезли чипы sourceMessageId:?

    Это было машинное происхождение, а не теги пользователя. Новые преобразования записывают metadata.source; карточка скрывает устаревшие закодированные теги и показывает владельцу From chat, когда есть id разговора.

    Эксплуатация

    Почему никто не получил уведомление?

    Проверьте доступность LLM, порог оценки Matcher, maxMatches и фильтры блокировки организаций в matcher-notification-filter. Уведомления идут через features/notifications/services/notification-service.

    Почему Hide возвращается, когда я вхожу как другой пользователь?

    Кэш курсорной ленты имеет ключ для каждого зрителя. Hide хранится в user_content_interactions для этого пользователя; следующий getOpportunitiesForRole с этим viewerUserId применяет not-in.

    Как связаны деньги коллективных заказов и копилки?

    Специализации возможностей могут содержать JSONB metadata (напр. слоты коллективного заказа). Копилки общественного финансирования и SSOT выплат строителям описаны в Public Pools; не придумывайте API «донат-продуктов» PSP как путь для копилок.

    Связанная документация

    Related documentation

    Opportunities API

    Следующий шаг: контракт REST-маршрутов, поля обогащения списка и пагинация поиска против просмотра.

    Discovery Mutation Sync

    Зависит от: как syncOpportunityDiscovery инвалидирует кэш и публикует события Tunnel.

    Ring Tasks

    Тот же процесс: convertTaskToOpportunity записывает metadata.source для чипа From chat.

    Real-Time Messaging

    Тот же процесс: Contact использует /messages?user=; From chat использует /messages?c=.

    1. Документация
    2. /Функции
    3. /Возможности

    Обновлено 26 окт. 2026 г.11 мин прослушивания

    Возможности

    Ring Opportunities это цикл предложения ↔ спроса для каждого клона: участники публикуют предложения и запросы (плюс специализированные типы), Matcher оценивает заинтересованных пользователей, а уведомления приглашают их связаться, не дожидаясь, пока кто-то будет искать в ленте.

    Список просмотра на /opportunities это именная лента: каждая карточка показывает безопасного для публики автора, человеческие теги и Like / Save / Hide / Contact. Живые вставки по-прежнему приходят через Tunnel; панель просмотра больше не показывает строку статуса websocket.

    Используйте вкладки Founder / Developer в боковой панели документации, чтобы отфильтровать эту страницу. Frontmatter audience управляет блоками на странице; видимость в боковой панели управляется lib/docs/audience-curated-docs.ts.

    Маркетинговые KPI не являются телеметрией продукта

    Старые тексты заявляли фиксированные проценты точности, экономию на найме и «15k+ пользователей». Эти цифры устарели. Актуальные числа берутся из аналитики Admin → Matcher и трафика клона. Пороги Matcher это конфиг (ring-config.json → matcher, переопределяется в настройках платформы), а не SLA для всего королевства.

    Традиционные доски и Ring

    РаньшеЭквивалент в Ring
    Опубликовать вакансию и надеяться, что кто-то найдётОпубликовать возможность → Matcher оценивает кандидатов → уведомление с короткими пояснениями
    Только предложения (работодатель → талант)Двойная природа: offer и request плюс специализированные типы
    Одна таксономия объявленийWhite-label ограничение opportunities.enabledTypes (16 по умолчанию в Layer1 / конфиге org)
    Ручное обогащениеНеобязательное LLM автозаполнение при создании (OpportunityAutoFillService)
    Непрозрачное ранжированиеВосемь оцениваемых факторов (MatchFactors в lib/ai/types.ts) + настраиваемый scoreThreshold
    UUID автора на карточкахБезопасные для публики имя / аватар; username только когда publicProfile равен true
    Чипы sourceMessageId:Скрытые машинные теги; From chat только для владельца, когда есть происхождение
    «Live Updates Active / via websocket» в просмотреТихий useRealtimeOpportunities; строка статуса остаётся только на странице деталей
    Отдельные копилкиКоллективные копилки и копилки строителей через Public Pools (путь пожертвований работает; on-chain escrow ограничен)

    Цикл подбора (общее)

    Создание возможности → подбор → уведомление

    Значения Matcher по умолчанию при установке (ring-config.json → matcher): scoreThreshold 0.7, maxMatches 10, autoApprove false, autoApproveMinScore 0.7, llmConfidenceGate 0.8. Env может переопределить автоодобрение через MATCHER_AUTO_APPROVE / MATCHER_AUTO_APPROVE_MIN_SCORE (см. features/admin/platform-settings/matcher-config.ts). Ограничивайте число совпадений через MAX_MATCHES_PER_OPPORTUNITY.

    Факторы оценки, пути LLM и эвристики и длина пояснений описаны на странице AI Matcher. Пороги выше это значения установки по умолчанию, а не опубликованный KPI точности.

    Почему это важно для вашего клона

    Возможности превращают ваш Ring в локальный маркетплейс намерений: люди публикуют, что могут предоставить и что им нужно. Matcher отправляет уместные приглашения вместо того, чтобы полагаться на прокрутку ленты. Специализированные типы (вакансии, коллективные заказы, услуги по расписанию, программа/инвестиция → CRM, квесты кастомизации Ring) ограничиваются для каждого клона, поэтому вы запускаете только те циклы, которые нужны вашей вертикали.

    Организации

    Связывайте возможности с верифицированными организациями через contactInfo.linkedEntity / organizationId.

    Уведомления

    Приглашения по совпадению это настоящие уведомления, а не маркетинговые email-рассылки.

    Сообщения

    Contact открывает . Преобразования задач из чата сохраняют для владельца глубокую ссылку .

    Карта реализации

    АспектПроверенный путь
    Типы / SerializedOpportunityfeatures/opportunities/types/index.ts (creator?, viewer?, likes?)
    Ограничение включённых типовfeatures/opportunities/lib/opportunity-enabled-types.ts ← ring-config.json opportunities.enabledTypes
    Матрица создания по ролямfeatures/opportunities/lib/opportunity-permissions.ts (MEMBER_OFFER_TYPES, REQUEST_TYPES, SUBSCRIBER_TYPES, confidential)
    Создание + AI-конвейерfeatures/opportunities/services/create-opportunity.ts
    Список / поискget-opportunities.ts, search-opportunities.ts: исключение скрытых + attachOpportunityFeedFields
    Сводки авторовget-opportunity-creators.ts (name / displayName / username, если публичный / avatar)

    Рекомендуемый путь

    Используйте ring-ai-matcher-specialist (или навык Cursor из того же семейства) с промптом, ожидающим одобрения:

    «Проверь цикл Opportunities этого клона: выведи opportunities.enabledTypes и matcher из ring-config.json, подтверди, что env для LLM задан, сделай пробное создание одного offer и одного request, сообщи MatchFactors и перевёл бы autoApprove pending→active. Открой /opportunities как два пользователя и подтверди, что карточки показывают имена (а не UUID), Hide исключает после перезагрузки, а Contact ведёт на /messages?user=. Не меняй platform_settings, пока я не одобрю.»

    Чеклист входных данных: ключ клона, доступ администратора, имеющиеся учётные данные LLM, тестовый id организации для organizationId.

    Ручной путь

    1. 1

      Задайте opportunities.enabledTypes и matcher.* в ring-config.json; передеплойте или перезагрузите снимок конфига так, как ваш клон делает это для ring-config.

    2. 2

      В Admin → Matcher / AI settings оставьте автоодобрение выключенным; задайте scoreThreshold / maxMatches под толерантность вашей вертикали.

    3. 3

      Создайте тестовую возможность через UI выбора типа (или POST /api/opportunities); откройте My Opportunities на /opportunities/my.

    4. 4

      Убедитесь, что пользователь с совпадением получил уведомление и что списки поиска обновляются (Tunnel / мягкое обновление) без выдуманного шага переиндексации. Убедитесь, что у списка просмотра нет строки статуса websocket.

    Частые вопросы

    Влияние

    Будет ли Matcher автоматически публиковать каждое новое объявление?

    Нет. По умолчанию matcher.autoApprove равен false. Когда включено, maybeAutoApproveOpportunity всё равно требует порогов оценки и уверенности LLM (autoApproveMinScore, llmConfidenceGate).

    Получу ли я «95% точности подбора» для всего королевства?

    Нет. Считайте исторические маркетинговые проценты устаревшими. Используйте аналитику Admin Matcher для своего тенанта.

    Остаются ли авторы анонимными в ленте?

    Нет. Аутентифицированные зрители видят имя и аватар. Username добавляется только когда publicProfile равен true. Флага postAnonymously нет.

    Миграция

    У нас всё ещё есть конвертеры Firestore, нужны ли они?

    Только когда DB_BACKEND_MODE=firebase-full. Клоны PostgreSQL используют opportunity-db-mapper.ts и SerializedOpportunity.

    Куда делся /opportunities/my-opportunities?

    Удалён. Каноническая панель это /opportunities/my через ROUTES.MY_OPPORTUNITIES.

    Почему исчезли чипы sourceMessageId:?

    Это было машинное происхождение, а не теги пользователя. Новые преобразования записывают metadata.source; карточка скрывает устаревшие закодированные теги и показывает владельцу From chat, когда есть id разговора.

    Эксплуатация

    Почему никто не получил уведомление?

    Проверьте доступность LLM, порог оценки Matcher, maxMatches и фильтры блокировки организаций в matcher-notification-filter. Уведомления идут через features/notifications/services/notification-service.

    Почему Hide возвращается, когда я вхожу как другой пользователь?

    Кэш курсорной ленты имеет ключ для каждого зрителя. Hide хранится в user_content_interactions для этого пользователя; следующий getOpportunitiesForRole с этим viewerUserId применяет not-in.

    Как связаны деньги коллективных заказов и копилки?

    Специализации возможностей могут содержать JSONB metadata (напр. слоты коллективного заказа). Копилки общественного финансирования и SSOT выплат строителям описаны в Public Pools; не придумывайте API «донат-продуктов» PSP как путь для копилок.

    Связанная документация

    Related documentation

    Opportunities API

    Следующий шаг: контракт REST-маршрутов, поля обогащения списка и пагинация поиска против просмотра.

    Discovery Mutation Sync

    Зависит от: как syncOpportunityDiscovery инвалидирует кэш и публикует события Tunnel.

    Ring Tasks

    Тот же процесс: convertTaskToOpportunity записывает metadata.source для чипа From chat.

    Real-Time Messaging

    Тот же процесс: Contact использует /messages?user=; From chat использует /messages?c=.

    1. Документация
    2. /Функции
    3. /Возможности

    Обновлено 26 окт. 2026 г.11 мин прослушивания

    Возможности

    Ring Opportunities это цикл предложения ↔ спроса для каждого клона: участники публикуют предложения и запросы (плюс специализированные типы), Matcher оценивает заинтересованных пользователей, а уведомления приглашают их связаться, не дожидаясь, пока кто-то будет искать в ленте.

    Список просмотра на /opportunities это именная лента: каждая карточка показывает безопасного для публики автора, человеческие теги и Like / Save / Hide / Contact. Живые вставки по-прежнему приходят через Tunnel; панель просмотра больше не показывает строку статуса websocket.

    Используйте вкладки Founder / Developer в боковой панели документации, чтобы отфильтровать эту страницу. Frontmatter audience управляет блоками на странице; видимость в боковой панели управляется lib/docs/audience-curated-docs.ts.

    Маркетинговые KPI не являются телеметрией продукта

    Старые тексты заявляли фиксированные проценты точности, экономию на найме и «15k+ пользователей». Эти цифры устарели. Актуальные числа берутся из аналитики Admin → Matcher и трафика клона. Пороги Matcher это конфиг (ring-config.json → matcher, переопределяется в настройках платформы), а не SLA для всего королевства.

    Традиционные доски и Ring

    РаньшеЭквивалент в Ring
    Опубликовать вакансию и надеяться, что кто-то найдётОпубликовать возможность → Matcher оценивает кандидатов → уведомление с короткими пояснениями
    Только предложения (работодатель → талант)Двойная природа: offer и request плюс специализированные типы
    Одна таксономия объявленийWhite-label ограничение opportunities.enabledTypes (16 по умолчанию в Layer1 / конфиге org)
    Ручное обогащениеНеобязательное LLM автозаполнение при создании (OpportunityAutoFillService)
    Непрозрачное ранжированиеВосемь оцениваемых факторов (MatchFactors в lib/ai/types.ts) + настраиваемый scoreThreshold
    UUID автора на карточкахБезопасные для публики имя / аватар; username только когда publicProfile равен true
    Чипы sourceMessageId:Скрытые машинные теги; From chat только для владельца, когда есть происхождение
    «Live Updates Active / via websocket» в просмотреТихий useRealtimeOpportunities; строка статуса остаётся только на странице деталей
    Отдельные копилкиКоллективные копилки и копилки строителей через Public Pools (путь пожертвований работает; on-chain escrow ограничен)

    Цикл подбора (общее)

    Создание возможности → подбор → уведомление

    Значения Matcher по умолчанию при установке (ring-config.json → matcher): scoreThreshold 0.7, maxMatches 10, autoApprove false, autoApproveMinScore 0.7, llmConfidenceGate 0.8. Env может переопределить автоодобрение через MATCHER_AUTO_APPROVE / MATCHER_AUTO_APPROVE_MIN_SCORE (см. features/admin/platform-settings/matcher-config.ts). Ограничивайте число совпадений через MAX_MATCHES_PER_OPPORTUNITY.

    Факторы оценки, пути LLM и эвристики и длина пояснений описаны на странице AI Matcher. Пороги выше это значения установки по умолчанию, а не опубликованный KPI точности.

    Почему это важно для вашего клона

    Возможности превращают ваш Ring в локальный маркетплейс намерений: люди публикуют, что могут предоставить и что им нужно. Matcher отправляет уместные приглашения вместо того, чтобы полагаться на прокрутку ленты. Специализированные типы (вакансии, коллективные заказы, услуги по расписанию, программа/инвестиция → CRM, квесты кастомизации Ring) ограничиваются для каждого клона, поэтому вы запускаете только те циклы, которые нужны вашей вертикали.

    Организации

    Связывайте возможности с верифицированными организациями через contactInfo.linkedEntity / organizationId.

    Уведомления

    Приглашения по совпадению это настоящие уведомления, а не маркетинговые email-рассылки.

    Сообщения

    Contact открывает . Преобразования задач из чата сохраняют для владельца глубокую ссылку .

    Карта реализации

    АспектПроверенный путь
    Типы / SerializedOpportunityfeatures/opportunities/types/index.ts (creator?, viewer?, likes?)
    Ограничение включённых типовfeatures/opportunities/lib/opportunity-enabled-types.ts ← ring-config.json opportunities.enabledTypes
    Матрица создания по ролямfeatures/opportunities/lib/opportunity-permissions.ts (MEMBER_OFFER_TYPES, REQUEST_TYPES, SUBSCRIBER_TYPES, confidential)
    Создание + AI-конвейерfeatures/opportunities/services/create-opportunity.ts
    Список / поискget-opportunities.ts, search-opportunities.ts: исключение скрытых + attachOpportunityFeedFields
    Сводки авторовget-opportunity-creators.ts (name / displayName / username, если публичный / avatar)

    Рекомендуемый путь

    Используйте ring-ai-matcher-specialist (или навык Cursor из того же семейства) с промптом, ожидающим одобрения:

    «Проверь цикл Opportunities этого клона: выведи opportunities.enabledTypes и matcher из ring-config.json, подтверди, что env для LLM задан, сделай пробное создание одного offer и одного request, сообщи MatchFactors и перевёл бы autoApprove pending→active. Открой /opportunities как два пользователя и подтверди, что карточки показывают имена (а не UUID), Hide исключает после перезагрузки, а Contact ведёт на /messages?user=. Не меняй platform_settings, пока я не одобрю.»

    Чеклист входных данных: ключ клона, доступ администратора, имеющиеся учётные данные LLM, тестовый id организации для organizationId.

    Ручной путь

    1. 1

      Задайте opportunities.enabledTypes и matcher.* в ring-config.json; передеплойте или перезагрузите снимок конфига так, как ваш клон делает это для ring-config.

    2. 2

      В Admin → Matcher / AI settings оставьте автоодобрение выключенным; задайте scoreThreshold / maxMatches под толерантность вашей вертикали.

    3. 3

      Создайте тестовую возможность через UI выбора типа (или POST /api/opportunities); откройте My Opportunities на /opportunities/my.

    4. 4

      Убедитесь, что пользователь с совпадением получил уведомление и что списки поиска обновляются (Tunnel / мягкое обновление) без выдуманного шага переиндексации. Убедитесь, что у списка просмотра нет строки статуса websocket.

    Частые вопросы

    Влияние

    Будет ли Matcher автоматически публиковать каждое новое объявление?

    Нет. По умолчанию matcher.autoApprove равен false. Когда включено, maybeAutoApproveOpportunity всё равно требует порогов оценки и уверенности LLM (autoApproveMinScore, llmConfidenceGate).

    Получу ли я «95% точности подбора» для всего королевства?

    Нет. Считайте исторические маркетинговые проценты устаревшими. Используйте аналитику Admin Matcher для своего тенанта.

    Остаются ли авторы анонимными в ленте?

    Нет. Аутентифицированные зрители видят имя и аватар. Username добавляется только когда publicProfile равен true. Флага postAnonymously нет.

    Миграция

    У нас всё ещё есть конвертеры Firestore, нужны ли они?

    Только когда DB_BACKEND_MODE=firebase-full. Клоны PostgreSQL используют opportunity-db-mapper.ts и SerializedOpportunity.

    Куда делся /opportunities/my-opportunities?

    Удалён. Каноническая панель это /opportunities/my через ROUTES.MY_OPPORTUNITIES.

    Почему исчезли чипы sourceMessageId:?

    Это было машинное происхождение, а не теги пользователя. Новые преобразования записывают metadata.source; карточка скрывает устаревшие закодированные теги и показывает владельцу From chat, когда есть id разговора.

    Эксплуатация

    Почему никто не получил уведомление?

    Проверьте доступность LLM, порог оценки Matcher, maxMatches и фильтры блокировки организаций в matcher-notification-filter. Уведомления идут через features/notifications/services/notification-service.

    Почему Hide возвращается, когда я вхожу как другой пользователь?

    Кэш курсорной ленты имеет ключ для каждого зрителя. Hide хранится в user_content_interactions для этого пользователя; следующий getOpportunitiesForRole с этим viewerUserId применяет not-in.

    Как связаны деньги коллективных заказов и копилки?

    Специализации возможностей могут содержать JSONB metadata (напр. слоты коллективного заказа). Копилки общественного финансирования и SSOT выплат строителям описаны в Public Pools; не придумывайте API «донат-продуктов» PSP как путь для копилок.

    Связанная документация

    Related documentation

    Opportunities API

    Следующий шаг: контракт REST-маршрутов, поля обогащения списка и пагинация поиска против просмотра.

    Discovery Mutation Sync

    Зависит от: как syncOpportunityDiscovery инвалидирует кэш и публикует события Tunnel.

    Ring Tasks

    Тот же процесс: convertTaskToOpportunity записывает metadata.source для чипа From chat.

    Real-Time Messaging

    Тот же процесс: Contact использует /messages?user=; From chat использует /messages?c=.

    1. Документация
    2. /Функции
    3. /Возможности

    Обновлено 26 окт. 2026 г.11 мин прослушивания

    /messages?user=<createdBy>
    From chat

    Публичные пулы

    Когда связанная копилка наполняется, строители получают чистый нативный токен (комиссия роли из publicPools.platformFeePercentByRole).

    Лента просмотра (/opportunities)

    Посетители и участники видят компактные карточки: чип типа, заголовок, описание в две строки, подпись автора, относительное время публикации, человеческие теги, число лайков и иконки действий.

    ДействиеКтоЧто происходит
    LikeВошедший зрительПереключает коллекцию likes; сердце заполняется из opportunity.viewer.liked
    SaveВошедший зрительПереключает user_content_interactions (save); состояние берётся из viewer.saved
    HideВошедший зрительОтмечает not_interested; в сессии Hidden · Undo; следующий запрос списка исключает id
    ContactSubscriber и выше; скрыто на своих постахСразу переходит на /messages?user=<createdBy>; Matcher contact_intent работает по возможности и не должен блокировать переход
    From chatТолько владелец, когда объявление пришло из задачиОткрывает /messages?c=<conversationId>

    Флага анонимной публикации нет. Аутентифицированные зрители видят имя и аватар автора. Username показывается только на публичных профилях. Пустое имя отображается как Member или Private User.

    Query-параметры правой панели (q, types, categories, location, priority) теперь применяются на сервере: если присутствует любой из них, GET /api/opportunities запускает сервис поиска вместо простого списка, поэтому фильтры охватывают весь набор, а не только загруженную страницу.

    Посетители могут просматривать (с 2026-10-17)

    Гости больше не упираются в стену входа на /opportunities, /opportunities/<id>, /entities и /entities/<id>. Они видят только публичные неконфиденциальные объявления. Like, Save, Hide и Contact по-прежнему требуют учётной записи, а открытие Add отправляет гостя на вход с callbackUrl, содержащим выбранный ?type=, поэтому после входа он возвращается к той же форме.

    My Opportunities на /opportunities/my это панель владельца (Edit / Delete / View). Счётчики вкладок Saved и Applied сейчас жёстко заданы как 0, не считайте их живыми метриками.

    Типичные сценарии клонов

    1. Сообщество талантов и партнёрств: включите job, offer, request, partnership; держите автоодобрение Matcher выключенным, пока не доверяете оценке.
    2. Коммерческая вертикаль: включите collective_order, scheduled_services, asset_rental, bounty, tender с рейками Wallet / PaymentConductor.
    3. Сообщество поселенцев и строителей Ringdom: включите ring_customization и program, чтобы квесты кастомизации и программы институций попадали в CRM.

    Чеклист оператора

    1. Убедитесь, что флаг функции / whitelabel включает opportunities.
    2. Задайте opportunities.enabledTypes в ring-config.json (не предполагайте, что каждый член union OpportunityType виден в UI).
    3. Настройте LLM (LLM_PROVIDER, OPENAI_API_KEY или ANTHROPIC_API_KEY, LLM_MODEL), прежде чем ожидать автозаполнение / пояснения LLM.
    4. Настройте Matcher в Admin → Matcher / Platform Settings → AI → Matcher (порог, максимум совпадений, автоодобрение).
    5. Научите участников My Opportunities на /opportunities/my (ROUTES.MY_OPPORTUNITIES); устаревший /opportunities/my-opportunities удалён.
    6. Убедитесь, что карточки просмотра показывают имена (а не UUID) и что Hide сохраняется после обновления для этого пользователя.
    Like / save / hide зрителяget-viewer-interactions.ts ← likes + user_content_interactions
    Теги / происхождение из чатаlib/opportunity-tags.ts (splitOpportunityTags)
    Карточка / список лентыopportunity-feed-card.tsx, opportunity-list.tsx
    Взаимодействияapp/_actions/opportunity-interactions.ts
    Ядро Matcherlib/ai/matcher.ts + OpportunityMatchingService
    Автозаполнениеfeatures/opportunities/services/auto-fill-service.ts
    Автоодобрениеfeatures/opportunities/services/auto-approval-service.ts
    PG JSONB ↔ клиентfeatures/opportunities/lib/opportunity-db-mapper.ts
    Синхронизация после измененийfeatures/opportunities/lib/opportunity-mutation-sync.ts → syncOpportunityDiscovery
    Программа → CRMfeatures/opportunities/lib/program-crm-ingest.ts
    UI Server Actionsapp/_actions/opportunities.ts
    Устаревший Firestorelib/converters/opportunity-converter.ts только когда DB_BACKEND_MODE=firebase-full

    База данных: типичные рабочие клоны используют DB_BACKEND_MODE=k8s-postgres-fcm (также supabase-fcm). Сервисы возвращают SerializedOpportunity (даты как строки ISO). Не придумывайте DATABASE_MODE=firebase_only.

    Список просмотра (проверено)

    1. 1

      (protected)/opportunities/page.tsx и GET /api/opportunities передают viewerUserId: session.user.id в getOpportunitiesForRole. Сначала загружаются скрытые id, затем запрос использует оператор DatabaseService not-in для opportunities.id. PostgreSQLAdapter отображает id в opportunities / likes на SQL-колонку (а не data->>'id').

    2. 2

      attachOpportunityFeedFields добавляет creator, viewer и likes. Карточки инициализируют useOptimistic из opportunity.viewer (прежнее оптимистичное состояние с постоянной базой никогда не показывало saved/liked). После Like / Save / Hide onInteractionChange обновляет элемент курсорной ленты, чтобы флаги сессии оставались согласованными.

    3. 3

      useCursorFeed хранится 24 ч в localStorage. Отпечаток списка это …|viewer=<userId>, поэтому одна учётная запись не наследует like/save/hide другой. Перезагрузки накладывают серверные initialItems на кэшированные строки по id (hooks/use-cursor-feed.ts).

    4. 4

      Просмотр сохраняет useRealtimeOpportunities({ autoConnect: true }) для тихой подписки на туннель. Фрагменты создания содержат creator { id, name, avatar }, поэтому вставленные вживую карточки не показываются как «Private User». Страница деталей (opportunity-details.tsx) всё ещё показывает строку Live Updates.

    convertTaskToOpportunity записывает metadata.source: { kind: 'chat_task', messageId, conversationId } и tags: []. splitOpportunityTags по-прежнему разбирает устаревшие теги sourceMessageId: / sourceConversationId: / chat_task при рендере. Задачи заполнения исторических данных нет.

    Видимость и статус

    • Видимость: public | subscriber | member | confidential | entity
    • Видимость entity: лид, адресованный одной организации. Могут читать администраторы платформы, автор и участники связанного organizationId (loadViewerEntityAccessIds в features/entities/lib/entity-roles.ts). Subscribers могут её устанавливать. Публичные списки её никогда не содержат.
    • Заполнение: миграция 052_opportunity_visibility_backfill.sql устанавливает отсутствующий visibility в public и отсутствующий isConfidential в false, потому что фильтры списка теперь требуют оба. Примените её один раз на базах, созданных до неё (она поставляется с .down.sql).
    • Статус: draft | pending | active | closed | expired | archived
    • Конфиденциальное создание/редактирование требует ролей с конфиденциальным доступом (canCreateOpportunityConfidential / canEditOpportunity)

    Ограничения по ролям (создание)

    ГруппаТипы (примеры)Минимальная роль
    Предложения участниковoffer, job, partnership, volunteer, mentorship, resource, event, ring_customization, program, collective_order, tender, asset_rentalпривилегии member
    Запросыrequestsubscriber и выше
    Специальные для subscribercv, scheduled_services, bountysubscriber и выше
    Другие члены unionнапр. будущие типы, которых нет в наборах включённых/правadmin и выше (и должны быть включены)

    Гостевой доступ (проверено)

    lib/auth/layout-guards/session-auth-guard.tsx пропускает анонимные запросы ровно для /entities, /opportunities и их путей деталей /<id> (не add или my). Каждый другой защищённый маршрут перенаправляет на вход с callbackUrl, содержащим исходный путь и query.

    ПоверхностьПоведение для гостя
    Страница /opportunities и GET /api/opportunitiesРоль visitor; результаты отфильтрованы до visibility public (или не задано) и isConfidential !== true
    Страница /opportunities/<id>Читает строку напрямую; конфиденциальные или непубличные строки перенаправляют на вход
    GET /api/opportunities/<id>, маршруты поискаПо-прежнему возвращают 401 без сессии

    Типы из пакетов и петиции

    • features/opportunities/lib/opportunity-type-policy.ts это пустая заглушка Layer 1. Пакет Layer 2 перезаписывает её, чтобы объявить дополнительные типы с minRole, requiresEntity, видимостью и статусом по умолчанию и хуком buildMetadata. Её читают canCreateOpportunityType и страница добавления.
    • POST /api/opportunities/<id>/sign записывает одну рекомендательную подпись на каждого вошедшего пользователя в metadata.signedUserIds, signatureCount и signatureTarget (по умолчанию 250). Layer 1 поставляет маршрут; UI подписания приходит из пакета.

    Контракты маршрутов, тело создания и JSON списка описаны на странице Opportunities API. Like / Save / Hide / Contact это Server Actions (app/_actions/opportunity-interactions.ts), а не REST. MCP GET /api/mcp/v1/opportunities сейчас не передаёт viewerUserId.

    После изменений syncOpportunityDiscovery инвалидирует теги кэша, выполняет revalidatePath для списка/деталей/my и публикует Tunnel opportunity:*. Это не сбрасывает клиентский useCursorFeed: наложение + отпечаток зрителя обеспечивают актуальность просмотра.

    Env для LLM / Matcher (шаблон)

    Ключи, описанные в env.local.template: LLM_PROVIDER, OPENAI_API_KEY, ANTHROPIC_API_KEY, LLM_MODEL, MAX_MATCHES_PER_OPPORTUNITY, MATCHING_MAX_TOKENS. Без рабочего провайдера Matcher откатывается к пояснениям без LLM / на основе тегов с меньшей уверенностью.

    Entities

    Тот же процесс: привязка к организациям и верифицированные авторы возможностей.

    Notifications

    Тот же процесс: приглашения по совпадению доставляются как уведомления платформы.

    Public Pools & DAO Jars

    См. также: выплаты из коллективных копилок и копилок строителей владельцам возможностей.

    AI Matcher

    Подробно: MatchFactors, оценка LLM против эвристики и длина пояснений.

    Admin console

    Подробно: вкладка Admin Matcher и настройки AI платформы для порогов.

    /messages?user=<createdBy>
    From chat

    Публичные пулы

    Когда связанная копилка наполняется, строители получают чистый нативный токен (комиссия роли из publicPools.platformFeePercentByRole).

    Лента просмотра (/opportunities)

    Посетители и участники видят компактные карточки: чип типа, заголовок, описание в две строки, подпись автора, относительное время публикации, человеческие теги, число лайков и иконки действий.

    ДействиеКтоЧто происходит
    LikeВошедший зрительПереключает коллекцию likes; сердце заполняется из opportunity.viewer.liked
    SaveВошедший зрительПереключает user_content_interactions (save); состояние берётся из viewer.saved
    HideВошедший зрительОтмечает not_interested; в сессии Hidden · Undo; следующий запрос списка исключает id
    ContactSubscriber и выше; скрыто на своих постахСразу переходит на /messages?user=<createdBy>; Matcher contact_intent работает по возможности и не должен блокировать переход
    From chatТолько владелец, когда объявление пришло из задачиОткрывает /messages?c=<conversationId>

    Флага анонимной публикации нет. Аутентифицированные зрители видят имя и аватар автора. Username показывается только на публичных профилях. Пустое имя отображается как Member или Private User.

    Query-параметры правой панели (q, types, categories, location, priority) теперь применяются на сервере: если присутствует любой из них, GET /api/opportunities запускает сервис поиска вместо простого списка, поэтому фильтры охватывают весь набор, а не только загруженную страницу.

    Посетители могут просматривать (с 2026-10-17)

    Гости больше не упираются в стену входа на /opportunities, /opportunities/<id>, /entities и /entities/<id>. Они видят только публичные неконфиденциальные объявления. Like, Save, Hide и Contact по-прежнему требуют учётной записи, а открытие Add отправляет гостя на вход с callbackUrl, содержащим выбранный ?type=, поэтому после входа он возвращается к той же форме.

    My Opportunities на /opportunities/my это панель владельца (Edit / Delete / View). Счётчики вкладок Saved и Applied сейчас жёстко заданы как 0, не считайте их живыми метриками.

    Типичные сценарии клонов

    1. Сообщество талантов и партнёрств: включите job, offer, request, partnership; держите автоодобрение Matcher выключенным, пока не доверяете оценке.
    2. Коммерческая вертикаль: включите collective_order, scheduled_services, asset_rental, bounty, tender с рейками Wallet / PaymentConductor.
    3. Сообщество поселенцев и строителей Ringdom: включите ring_customization и program, чтобы квесты кастомизации и программы институций попадали в CRM.

    Чеклист оператора

    1. Убедитесь, что флаг функции / whitelabel включает opportunities.
    2. Задайте opportunities.enabledTypes в ring-config.json (не предполагайте, что каждый член union OpportunityType виден в UI).
    3. Настройте LLM (LLM_PROVIDER, OPENAI_API_KEY или ANTHROPIC_API_KEY, LLM_MODEL), прежде чем ожидать автозаполнение / пояснения LLM.
    4. Настройте Matcher в Admin → Matcher / Platform Settings → AI → Matcher (порог, максимум совпадений, автоодобрение).
    5. Научите участников My Opportunities на /opportunities/my (ROUTES.MY_OPPORTUNITIES); устаревший /opportunities/my-opportunities удалён.
    6. Убедитесь, что карточки просмотра показывают имена (а не UUID) и что Hide сохраняется после обновления для этого пользователя.
    Like / save / hide зрителяget-viewer-interactions.ts ← likes + user_content_interactions
    Теги / происхождение из чатаlib/opportunity-tags.ts (splitOpportunityTags)
    Карточка / список лентыopportunity-feed-card.tsx, opportunity-list.tsx
    Взаимодействияapp/_actions/opportunity-interactions.ts
    Ядро Matcherlib/ai/matcher.ts + OpportunityMatchingService
    Автозаполнениеfeatures/opportunities/services/auto-fill-service.ts
    Автоодобрениеfeatures/opportunities/services/auto-approval-service.ts
    PG JSONB ↔ клиентfeatures/opportunities/lib/opportunity-db-mapper.ts
    Синхронизация после измененийfeatures/opportunities/lib/opportunity-mutation-sync.ts → syncOpportunityDiscovery
    Программа → CRMfeatures/opportunities/lib/program-crm-ingest.ts
    UI Server Actionsapp/_actions/opportunities.ts
    Устаревший Firestorelib/converters/opportunity-converter.ts только когда DB_BACKEND_MODE=firebase-full

    База данных: типичные рабочие клоны используют DB_BACKEND_MODE=k8s-postgres-fcm (также supabase-fcm). Сервисы возвращают SerializedOpportunity (даты как строки ISO). Не придумывайте DATABASE_MODE=firebase_only.

    Список просмотра (проверено)

    1. 1

      (protected)/opportunities/page.tsx и GET /api/opportunities передают viewerUserId: session.user.id в getOpportunitiesForRole. Сначала загружаются скрытые id, затем запрос использует оператор DatabaseService not-in для opportunities.id. PostgreSQLAdapter отображает id в opportunities / likes на SQL-колонку (а не data->>'id').

    2. 2

      attachOpportunityFeedFields добавляет creator, viewer и likes. Карточки инициализируют useOptimistic из opportunity.viewer (прежнее оптимистичное состояние с постоянной базой никогда не показывало saved/liked). После Like / Save / Hide onInteractionChange обновляет элемент курсорной ленты, чтобы флаги сессии оставались согласованными.

    3. 3

      useCursorFeed хранится 24 ч в localStorage. Отпечаток списка это …|viewer=<userId>, поэтому одна учётная запись не наследует like/save/hide другой. Перезагрузки накладывают серверные initialItems на кэшированные строки по id (hooks/use-cursor-feed.ts).

    4. 4

      Просмотр сохраняет useRealtimeOpportunities({ autoConnect: true }) для тихой подписки на туннель. Фрагменты создания содержат creator { id, name, avatar }, поэтому вставленные вживую карточки не показываются как «Private User». Страница деталей (opportunity-details.tsx) всё ещё показывает строку Live Updates.

    convertTaskToOpportunity записывает metadata.source: { kind: 'chat_task', messageId, conversationId } и tags: []. splitOpportunityTags по-прежнему разбирает устаревшие теги sourceMessageId: / sourceConversationId: / chat_task при рендере. Задачи заполнения исторических данных нет.

    Видимость и статус

    • Видимость: public | subscriber | member | confidential | entity
    • Видимость entity: лид, адресованный одной организации. Могут читать администраторы платформы, автор и участники связанного organizationId (loadViewerEntityAccessIds в features/entities/lib/entity-roles.ts). Subscribers могут её устанавливать. Публичные списки её никогда не содержат.
    • Заполнение: миграция 052_opportunity_visibility_backfill.sql устанавливает отсутствующий visibility в public и отсутствующий isConfidential в false, потому что фильтры списка теперь требуют оба. Примените её один раз на базах, созданных до неё (она поставляется с .down.sql).
    • Статус: draft | pending | active | closed | expired | archived
    • Конфиденциальное создание/редактирование требует ролей с конфиденциальным доступом (canCreateOpportunityConfidential / canEditOpportunity)

    Ограничения по ролям (создание)

    ГруппаТипы (примеры)Минимальная роль
    Предложения участниковoffer, job, partnership, volunteer, mentorship, resource, event, ring_customization, program, collective_order, tender, asset_rentalпривилегии member
    Запросыrequestsubscriber и выше
    Специальные для subscribercv, scheduled_services, bountysubscriber и выше
    Другие члены unionнапр. будущие типы, которых нет в наборах включённых/правadmin и выше (и должны быть включены)

    Гостевой доступ (проверено)

    lib/auth/layout-guards/session-auth-guard.tsx пропускает анонимные запросы ровно для /entities, /opportunities и их путей деталей /<id> (не add или my). Каждый другой защищённый маршрут перенаправляет на вход с callbackUrl, содержащим исходный путь и query.

    ПоверхностьПоведение для гостя
    Страница /opportunities и GET /api/opportunitiesРоль visitor; результаты отфильтрованы до visibility public (или не задано) и isConfidential !== true
    Страница /opportunities/<id>Читает строку напрямую; конфиденциальные или непубличные строки перенаправляют на вход
    GET /api/opportunities/<id>, маршруты поискаПо-прежнему возвращают 401 без сессии

    Типы из пакетов и петиции

    • features/opportunities/lib/opportunity-type-policy.ts это пустая заглушка Layer 1. Пакет Layer 2 перезаписывает её, чтобы объявить дополнительные типы с minRole, requiresEntity, видимостью и статусом по умолчанию и хуком buildMetadata. Её читают canCreateOpportunityType и страница добавления.
    • POST /api/opportunities/<id>/sign записывает одну рекомендательную подпись на каждого вошедшего пользователя в metadata.signedUserIds, signatureCount и signatureTarget (по умолчанию 250). Layer 1 поставляет маршрут; UI подписания приходит из пакета.

    Контракты маршрутов, тело создания и JSON списка описаны на странице Opportunities API. Like / Save / Hide / Contact это Server Actions (app/_actions/opportunity-interactions.ts), а не REST. MCP GET /api/mcp/v1/opportunities сейчас не передаёт viewerUserId.

    После изменений syncOpportunityDiscovery инвалидирует теги кэша, выполняет revalidatePath для списка/деталей/my и публикует Tunnel opportunity:*. Это не сбрасывает клиентский useCursorFeed: наложение + отпечаток зрителя обеспечивают актуальность просмотра.

    Env для LLM / Matcher (шаблон)

    Ключи, описанные в env.local.template: LLM_PROVIDER, OPENAI_API_KEY, ANTHROPIC_API_KEY, LLM_MODEL, MAX_MATCHES_PER_OPPORTUNITY, MATCHING_MAX_TOKENS. Без рабочего провайдера Matcher откатывается к пояснениям без LLM / на основе тегов с меньшей уверенностью.

    Entities

    Тот же процесс: привязка к организациям и верифицированные авторы возможностей.

    Notifications

    Тот же процесс: приглашения по совпадению доставляются как уведомления платформы.

    Public Pools & DAO Jars

    См. также: выплаты из коллективных копилок и копилок строителей владельцам возможностей.

    AI Matcher

    Подробно: MatchFactors, оценка LLM против эвристики и длина пояснений.

    Admin console

    Подробно: вкладка Admin Matcher и настройки AI платформы для порогов.

    /messages?user=<createdBy>
    From chat

    Публичные пулы

    Когда связанная копилка наполняется, строители получают чистый нативный токен (комиссия роли из publicPools.platformFeePercentByRole).

    Лента просмотра (/opportunities)

    Посетители и участники видят компактные карточки: чип типа, заголовок, описание в две строки, подпись автора, относительное время публикации, человеческие теги, число лайков и иконки действий.

    ДействиеКтоЧто происходит
    LikeВошедший зрительПереключает коллекцию likes; сердце заполняется из opportunity.viewer.liked
    SaveВошедший зрительПереключает user_content_interactions (save); состояние берётся из viewer.saved
    HideВошедший зрительОтмечает not_interested; в сессии Hidden · Undo; следующий запрос списка исключает id
    ContactSubscriber и выше; скрыто на своих постахСразу переходит на /messages?user=<createdBy>; Matcher contact_intent работает по возможности и не должен блокировать переход
    From chatТолько владелец, когда объявление пришло из задачиОткрывает /messages?c=<conversationId>

    Флага анонимной публикации нет. Аутентифицированные зрители видят имя и аватар автора. Username показывается только на публичных профилях. Пустое имя отображается как Member или Private User.

    Query-параметры правой панели (q, types, categories, location, priority) теперь применяются на сервере: если присутствует любой из них, GET /api/opportunities запускает сервис поиска вместо простого списка, поэтому фильтры охватывают весь набор, а не только загруженную страницу.

    Посетители могут просматривать (с 2026-10-17)

    Гости больше не упираются в стену входа на /opportunities, /opportunities/<id>, /entities и /entities/<id>. Они видят только публичные неконфиденциальные объявления. Like, Save, Hide и Contact по-прежнему требуют учётной записи, а открытие Add отправляет гостя на вход с callbackUrl, содержащим выбранный ?type=, поэтому после входа он возвращается к той же форме.

    My Opportunities на /opportunities/my это панель владельца (Edit / Delete / View). Счётчики вкладок Saved и Applied сейчас жёстко заданы как 0, не считайте их живыми метриками.

    Типичные сценарии клонов

    1. Сообщество талантов и партнёрств: включите job, offer, request, partnership; держите автоодобрение Matcher выключенным, пока не доверяете оценке.
    2. Коммерческая вертикаль: включите collective_order, scheduled_services, asset_rental, bounty, tender с рейками Wallet / PaymentConductor.
    3. Сообщество поселенцев и строителей Ringdom: включите ring_customization и program, чтобы квесты кастомизации и программы институций попадали в CRM.

    Чеклист оператора

    1. Убедитесь, что флаг функции / whitelabel включает opportunities.
    2. Задайте opportunities.enabledTypes в ring-config.json (не предполагайте, что каждый член union OpportunityType виден в UI).
    3. Настройте LLM (LLM_PROVIDER, OPENAI_API_KEY или ANTHROPIC_API_KEY, LLM_MODEL), прежде чем ожидать автозаполнение / пояснения LLM.
    4. Настройте Matcher в Admin → Matcher / Platform Settings → AI → Matcher (порог, максимум совпадений, автоодобрение).
    5. Научите участников My Opportunities на /opportunities/my (ROUTES.MY_OPPORTUNITIES); устаревший /opportunities/my-opportunities удалён.
    6. Убедитесь, что карточки просмотра показывают имена (а не UUID) и что Hide сохраняется после обновления для этого пользователя.
    Like / save / hide зрителяget-viewer-interactions.ts ← likes + user_content_interactions
    Теги / происхождение из чатаlib/opportunity-tags.ts (splitOpportunityTags)
    Карточка / список лентыopportunity-feed-card.tsx, opportunity-list.tsx
    Взаимодействияapp/_actions/opportunity-interactions.ts
    Ядро Matcherlib/ai/matcher.ts + OpportunityMatchingService
    Автозаполнениеfeatures/opportunities/services/auto-fill-service.ts
    Автоодобрениеfeatures/opportunities/services/auto-approval-service.ts
    PG JSONB ↔ клиентfeatures/opportunities/lib/opportunity-db-mapper.ts
    Синхронизация после измененийfeatures/opportunities/lib/opportunity-mutation-sync.ts → syncOpportunityDiscovery
    Программа → CRMfeatures/opportunities/lib/program-crm-ingest.ts
    UI Server Actionsapp/_actions/opportunities.ts
    Устаревший Firestorelib/converters/opportunity-converter.ts только когда DB_BACKEND_MODE=firebase-full

    База данных: типичные рабочие клоны используют DB_BACKEND_MODE=k8s-postgres-fcm (также supabase-fcm). Сервисы возвращают SerializedOpportunity (даты как строки ISO). Не придумывайте DATABASE_MODE=firebase_only.

    Список просмотра (проверено)

    1. 1

      (protected)/opportunities/page.tsx и GET /api/opportunities передают viewerUserId: session.user.id в getOpportunitiesForRole. Сначала загружаются скрытые id, затем запрос использует оператор DatabaseService not-in для opportunities.id. PostgreSQLAdapter отображает id в opportunities / likes на SQL-колонку (а не data->>'id').

    2. 2

      attachOpportunityFeedFields добавляет creator, viewer и likes. Карточки инициализируют useOptimistic из opportunity.viewer (прежнее оптимистичное состояние с постоянной базой никогда не показывало saved/liked). После Like / Save / Hide onInteractionChange обновляет элемент курсорной ленты, чтобы флаги сессии оставались согласованными.

    3. 3

      useCursorFeed хранится 24 ч в localStorage. Отпечаток списка это …|viewer=<userId>, поэтому одна учётная запись не наследует like/save/hide другой. Перезагрузки накладывают серверные initialItems на кэшированные строки по id (hooks/use-cursor-feed.ts).

    4. 4

      Просмотр сохраняет useRealtimeOpportunities({ autoConnect: true }) для тихой подписки на туннель. Фрагменты создания содержат creator { id, name, avatar }, поэтому вставленные вживую карточки не показываются как «Private User». Страница деталей (opportunity-details.tsx) всё ещё показывает строку Live Updates.

    convertTaskToOpportunity записывает metadata.source: { kind: 'chat_task', messageId, conversationId } и tags: []. splitOpportunityTags по-прежнему разбирает устаревшие теги sourceMessageId: / sourceConversationId: / chat_task при рендере. Задачи заполнения исторических данных нет.

    Видимость и статус

    • Видимость: public | subscriber | member | confidential | entity
    • Видимость entity: лид, адресованный одной организации. Могут читать администраторы платформы, автор и участники связанного organizationId (loadViewerEntityAccessIds в features/entities/lib/entity-roles.ts). Subscribers могут её устанавливать. Публичные списки её никогда не содержат.
    • Заполнение: миграция 052_opportunity_visibility_backfill.sql устанавливает отсутствующий visibility в public и отсутствующий isConfidential в false, потому что фильтры списка теперь требуют оба. Примените её один раз на базах, созданных до неё (она поставляется с .down.sql).
    • Статус: draft | pending | active | closed | expired | archived
    • Конфиденциальное создание/редактирование требует ролей с конфиденциальным доступом (canCreateOpportunityConfidential / canEditOpportunity)

    Ограничения по ролям (создание)

    ГруппаТипы (примеры)Минимальная роль
    Предложения участниковoffer, job, partnership, volunteer, mentorship, resource, event, ring_customization, program, collective_order, tender, asset_rentalпривилегии member
    Запросыrequestsubscriber и выше
    Специальные для subscribercv, scheduled_services, bountysubscriber и выше
    Другие члены unionнапр. будущие типы, которых нет в наборах включённых/правadmin и выше (и должны быть включены)

    Гостевой доступ (проверено)

    lib/auth/layout-guards/session-auth-guard.tsx пропускает анонимные запросы ровно для /entities, /opportunities и их путей деталей /<id> (не add или my). Каждый другой защищённый маршрут перенаправляет на вход с callbackUrl, содержащим исходный путь и query.

    ПоверхностьПоведение для гостя
    Страница /opportunities и GET /api/opportunitiesРоль visitor; результаты отфильтрованы до visibility public (или не задано) и isConfidential !== true
    Страница /opportunities/<id>Читает строку напрямую; конфиденциальные или непубличные строки перенаправляют на вход
    GET /api/opportunities/<id>, маршруты поискаПо-прежнему возвращают 401 без сессии

    Типы из пакетов и петиции

    • features/opportunities/lib/opportunity-type-policy.ts это пустая заглушка Layer 1. Пакет Layer 2 перезаписывает её, чтобы объявить дополнительные типы с minRole, requiresEntity, видимостью и статусом по умолчанию и хуком buildMetadata. Её читают canCreateOpportunityType и страница добавления.
    • POST /api/opportunities/<id>/sign записывает одну рекомендательную подпись на каждого вошедшего пользователя в metadata.signedUserIds, signatureCount и signatureTarget (по умолчанию 250). Layer 1 поставляет маршрут; UI подписания приходит из пакета.

    Контракты маршрутов, тело создания и JSON списка описаны на странице Opportunities API. Like / Save / Hide / Contact это Server Actions (app/_actions/opportunity-interactions.ts), а не REST. MCP GET /api/mcp/v1/opportunities сейчас не передаёт viewerUserId.

    После изменений syncOpportunityDiscovery инвалидирует теги кэша, выполняет revalidatePath для списка/деталей/my и публикует Tunnel opportunity:*. Это не сбрасывает клиентский useCursorFeed: наложение + отпечаток зрителя обеспечивают актуальность просмотра.

    Env для LLM / Matcher (шаблон)

    Ключи, описанные в env.local.template: LLM_PROVIDER, OPENAI_API_KEY, ANTHROPIC_API_KEY, LLM_MODEL, MAX_MATCHES_PER_OPPORTUNITY, MATCHING_MAX_TOKENS. Без рабочего провайдера Matcher откатывается к пояснениям без LLM / на основе тегов с меньшей уверенностью.

    Entities

    Тот же процесс: привязка к организациям и верифицированные авторы возможностей.

    Notifications

    Тот же процесс: приглашения по совпадению доставляются как уведомления платформы.

    Public Pools & DAO Jars

    См. также: выплаты из коллективных копилок и копилок строителей владельцам возможностей.

    AI Matcher

    Подробно: MatchFactors, оценка LLM против эвристики и длина пояснений.

    Admin console

    Подробно: вкладка Admin Matcher и настройки AI платформы для порогов.