Conversation
このアプリは参加者の概念を持っておらず、Occurrence には自分の responseStatus と isOrganizer しか無かった。Google は返しているのに DTO 変換で捨てていたため、 誰が招待されているか分からず、新規作成に参加者欄も入れられなかった。 **表示のみ入れ、編集は入れていない。** 公式リファレンスに「参加者から主催者へ返るのは 自分の応答状態だけ」と明記されており、主催者でない予定でゲストを編集しても Google 側で 黙って捨てられる ―― 「付けられるが外せない」より「付けたつもりが誰にも届いていない」 ほうが悪い。正しくガードするには guestsCanModify 等のフィールド追加とさらなる世代上げ (= 全利用者に再度の全同期)が要る。あわせて sendUpdates の既定が公式に文書化されて おらず(none には予定が失われうる旨の警告、all はゲスト1人追加で全員にメール)、 UI 上の明示的な選択が要る ― これは作成と同じ問いなのでまとめて決めるべき。 maxAttendees は使わない。上限を超えると切り詰めではなく**参加者本人1件だけ**を返す 仕様で、大人数の予定で一覧が丸ごと消える。代わりに DTO 側で50件に足切りし、超過時は attendeesOmitted を立てる。切り詰めても**自分と主催者は必ず残す**(一番困る欠け方を 防ぐ)。RSVP の書き戻しはサーバーが events.get から read-modify-write するので、 この打ち切りは書き込みの正しさに影響しない。 会議室(resource)は人ではないので、人数にも出欠の内訳にも入れず場所と同じ扱いで 分離する。並びは主催者→自分→元の順(応答状態で並べ替えると返事のたびに行が飛ぶ)。 新しい色は足さず、語彙と形だけで応答状態を表して予定カード側の描き分けと揃えた。 同期する項目が増えるのでバックフィル世代を 5 → 6 に上げた(web と sync の2箇所)。 web だけ先に新しくなると「サーバーがまだ返さないフィールドをバックフィル完了として 記録」して永久に欠けるため、sync が対応世代を宣言し web は min(自分, サーバー) までしか 完了記録しない。両方上げないと機能しない。 Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HGESE2zBNzoW8MYvtEySBQ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概要
このアプリは参加者の概念を持っていなかった。
Occurrenceには自分のresponseStatusとisOrganizerしか無く、Google は返しているのに DTO 変換で捨てていた。そのため誰が招待されているか分からず、新規作成に参加者欄も入れられなかった(付けたゲストを二度と外せなくなるため)。表示 → 編集 → 作成 の順で広げる方針の1段目。
編集は入れていない
公式リファレンスに **「参加者から主催者へ返るのは自分の応答状態だけ」**と明記されている。つまり主催者でない予定でゲストを編集しても Google 側で黙って捨てられる。
正しくガードするには
guestsCanModify/guestsCanInviteOthersの追加が必要で、それはさらなる世代上げ = 全利用者に再度の全同期を強いる。あわせてsendUpdatesの既定が公式に文書化されておらず(noneには「予定が同期されない/失われうる」旨の警告、allはゲスト1人追加で全員にメール)、UI 上の明示的な選択が要る ― これは作成と同じ問いなのでまとめて決めるべき。別タスクに登録済み。調査で避けた罠:
maxAttendees一覧取得時に
maxAttendeesを指定すると、上限を超えた予定は切り詰めではなく「参加者本人1件だけ」を返す。使っていたら大人数の予定で一覧が丸ごと消えていた。代わりに DTO 側で 50件に足切りし、超過時は
attendeesOmittedを立てて UI が「50人以上」と出す。切り詰めても自分と主催者は必ず残す(一番困る欠け方を防ぐ)。RSVP の書き戻しはサーバーがevents.getから read-modify-write するので、この打ち切りは書き込みの正しさに影響しない。表示
EventDetailCardに「ゲスト N人 参加x・未定x・不参加x・未返信x」の内訳と一覧resource)は人ではないので、人数にも出欠の内訳にも入れず場所と同じ扱いで分離max-height+ 内部スクロール。36人展開時もポップオーバーは 329px のまま同期する項目が増えるため、
CURRENT_SYNC_BACKFILL_VERSION(web)とSUPPORTED_SYNC_BACKFILL_VERSION(sync)を両方上げている。web だけ先に新しくなると「サーバーがまだ返さないフィールドをバックフィル完了として記録」→ 以後 forceFull が走らず永久に欠ける、という事故が過去に実際に起きている(世代4を空振り用に消費した跡がコメントに残っている)。その恒久対策として sync が
GET /api/meで対応世代を宣言し、web はmin(自分, サーバー)までしか完了記録しない。両方上げないと機能しない。この世代上げにより、各利用者の次回同期が全同期になる(ゲスト情報を取り込むため)。
検証
pnpm --filter web test1292 passed /pnpm --filter sync test640 passedドキュメント
apps/site/docs/calendar/index.htmlに「ゲスト(参加者)を見る」節を追加。編集できないことを callout で明記し、理由(非主催者の変更が届かない / 招待メールの扱いを先に決める必要がある)と回避策(Google で開く)を書いた。🤖 Generated with Claude Code
https://claude.ai/code/session_01HGESE2zBNzoW8MYvtEySBQ