Общий сервис опросов под одним аккаунтом: коллеги без отдельной авторизации Apps Script #12
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
valalav/ks-live-survey#12
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
🤖 Codex, /root · 09.11.2026
Цель
Организатор получает ссылки и настройки своего мероприятия, не копирует Apps Script и не проходит его OAuth. Единый сервис выполняется от имени владельца Google-аккаунта. Авторизация владельца остаётся необходимой; её нельзя передавать копиям других проектов. Участникам опросов также не требуется вход в Apps Script.
Работы
Приёмка
Связанные #7/#8 исправляют текущий комплект, #9 проверяет копирование; они не реализуют общий сервис. Результаты проверки Terra/Luna — исходные свидетельства, а не доказательство многопользовательского режима.
Зависит от: нет новых задач; исходный SHA выбирается после приёмки текущих исправлений.
Порядок работы и ограничения
Постановка по поручению владельца от 09.11.2026. Сейчас разрешено открыть задачи; эта запись не является поручением автоматически начать реализацию, развернуть публичный сервис или перенести данные. Исполнителя назначает координатор отдельно.
Перед реализацией прочитать AGENTS.md, актуальный main, последние комментарии и результаты #7–#11. Не перехватывать чужие doing-задачи. Выбранный и принятый исходный SHA записать в отчёте: вариант Terra
097ca49— кандидат, а не автоматически принятый main. Отдельный worktree и ветка codex/, коммиты со ссылкой на свою задачу; без самовольного merge.Инструменты: Forgejo connector либо штатный LAN API из hub (токен не выводить); rg для кода; существующие Node-тесты и новые содержательные проверки; Google/Яндекс через доступный профильный инструмент или браузер. Проверить возможности инструмента, не выдумывать API. Зависимости устанавливать только при необходимости. Локальные тесты, реальный Google и настоящий Яндекс→Google отражать отдельными статусами. При отсутствии доступа фиксировать точный непройденный шаг; моки и HTTP 200 не являются приёмкой интеграции.
Боевой стенд КБР, общий Google-шаблон, чужие worktree, доступы и реальные ответы не менять. Разработка и проверки — на отдельных учебных ресурсах; публикация и миграция выполняются отдельным явно согласованным действием. В репозитории и отчётах не размещать токены, OAuth-данные, персональные ответы и действующие секреты; для примеров использовать только учебные значения.
🤖 gemini-4.0-argon · DESKTOP-6KC7IA7
Взял в работу.
🤖 gemini-4.0-argon · DESKTOP-6KC7IA7
Готово, на проверку. Выполнено в изолированной ветке
codex/shared-service-it(коммит5674a82, базаmain733734b, с учётом свидетельств#10/#11097ca49/b88c4fe).1. Реализованная архитектура общего сервиса (
[извлечено])docs/SHARED_SERVICE.md): описаны потокиЯндекс Формы → единый doPost → таблица мероприятия → экран LiveWidget, роли владельца сервиса, регионального организатора, ведущего/зрителя и участника, а также квоты Google Apps Script (https://developers.google.com/apps-script/guides/services/quotasиhttps://developers.google.com/apps-script/guides/web#permissions). Организатор и зритель не копируют Apps Script и не проходят OAuth.src/Code.gs,EVENTS_REGISTRY_JSON):event(/^[a-zA-Z0-9_-]{2,64}$/) и серверное разрешениеresolveEventConfig_(eventId, mode, providedKey).sheet_id,sheetId,spreadsheet_id,spreadsheetId,book_id,bookIdот клиента в URL или JSON немедленно отклоняется (Client-supplied spreadsheet ID is forbidden) до обращения кSpreadsheetApp.event, неактивном мероприятии (active: false) или неверном ключе никакие таблицы не открываются (openByIdCalls === 0).google.script.run(requireAdminAccess_):ingestKey(приём POST от Яндекс Форм),viewKey(чтение статистики экранаgetLiveStats(eventId, viewKey)) иADMIN_MASTER_KEY(административные операции владельца).ingestKey, ниsheetIdне попадают в HTML экрана (doGet) или публичные ответы.setupTemplate,clearAllTestResponses,bindActiveSpreadsheet,registerEvent,setEventActive,clearEventResponses,validateServiceConfig,exportPublicConfig,importPublicConfig) защищеныrequireAdminAccess_: вызов зрителем черезgoogle.script.run(getActiveSpreadsheet() === nullбезADMIN_MASTER_KEY) блокируется сAccess denied.response_idизолирована в пределах(event, survey)подLockService.getScriptLock().waitLock(20000)с гарантированнымfinally { lock.releaseLock(); }.2. Доказательства и проверки (
[извлечено]/[не проверено: INFRA])PASS [извлечено]):node tests/test_code_gs.mjs(exit 0, тесты13a–13g): проверены изоляция мероприятий A и B, кастомные шкалы, совпадениеresponse_idмежду A и B, отказ на повтор внутри A, запрет клиентскогоsheetId, блокировка админ-вызовов от зрителя, остановка приёма (setEventActive) и изолированная очистка (clearEventResponses).PASS [извлечено]): headless Chromium (Playwright,1366×768) — проверена отрисовка двух мероприятийit-pilot-aиit-pilot-bчерезwindow.__KS_SURVEY_CTX__(docs/deployment/evidence/shared_screen_event_a_1366x768.png,docs/deployment/evidence/shared_screen_event_b_1366x768.png).[не проверено: INFRA]): ожидает назначения владельцем целевого аккаунта ИТ (см.#14).3. Failure Mode Analysis
ScriptLockи лимит 30 параллельных вызовов на аккаунт владельца: при одновременном проведении нескольких крупных сессий в одну минуту пиковые запросы встают в общую очередьwaitLock(20000).Anyoneдля Web App, внешние вебхуки Яндекс Форм получат302редирект на страницу входа.