Maestro task 919e9422-3a41-4f1f-8967-77da17f5f9f3. internal/chat implements the notify chat-channel sender (threaded webhook posts with cards for plan/list), plus the encrypted webhook settings API with strict URL validation and a masked read. See the task done-condition and the developer report on the PR.
Maestro task 919e9422-3a41-4f1f-8967-77da17f5f9f3. internal/chat implements the notify chat-channel sender (threaded webhook posts with cards for plan/list), plus the encrypted webhook settings API with strict URL validation and a masked read. See the task done-condition and the developer report on the PR.
internal/chat keeps the incoming webhook in chat_settings, sealed with
secretbox, and is the notify sender of the chat channel.
- PUT /api/v1/settings/chat-webhook {url, space_label} accepts only
https://chat.googleapis.com/v1/spaces/{space}/messages?key=…&token=…;
GET answers the space label, a masked URL tail and the last test outcome.
- POST /api/v1/settings/chat-webhook/test posts "MealQuest · test message",
answers Google Chat's HTTP status and records last_test_at/status.
- Notifications post {text}, plus cardsV2 with an "Open" button under
MEALQUEST_PUBLIC_URL for plan_ready and list_ready, threaded by
threadKey=mealquest-week-YYYY-Www with
REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD. 429 and 5xx are retried; any other
non-2xx fails the row at once through the new notify.ErrUndeliverable.
- One place builds every event's title, body and Chat text.
The webhook URL never appears in a response, log line or error; tests
against an httptest Chat endpoint scan both.
Maestro task 919e9422-3a41-4f1f-8967-77da17f5f9f3.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Restrict the decoded key and token to a URL-safe ASCII alphabet so the
16-character minimum and the four-character masked tail measure the same
thing; a token of a few multi-byte characters could otherwise be shown in
full (MQ-165-01).
Validate the raw query as exactly key=…&token=…, refusing empty
segments, a second "?", reordered, extra or repeated parameters
(MQ-165-02).
Drop configured and updated_at from the settings response so it is the
four-field contract: space_label, url_masked, last_test_at,
last_test_status; url_masked is null exactly when nothing is stored
(MQ-165-03).
Task: 919e9422-3a41-4f1f-8967-77da17f5f9f3
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Maestro task 919e9422-3a41-4f1f-8967-77da17f5f9f3. internal/chat implements the notify chat-channel sender (threaded webhook posts with cards for plan/list), plus the encrypted webhook settings API with strict URL validation and a masked read. See the task done-condition and the developer report on the PR.
internal/chat keeps the incoming webhook in chat_settings, sealed with secretbox, and is the notify sender of the chat channel. - PUT /api/v1/settings/chat-webhook {url, space_label} accepts only https://chat.googleapis.com/v1/spaces/{space}/messages?key=…&token=…; GET answers the space label, a masked URL tail and the last test outcome. - POST /api/v1/settings/chat-webhook/test posts "MealQuest · test message", answers Google Chat's HTTP status and records last_test_at/status. - Notifications post {text}, plus cardsV2 with an "Open" button under MEALQUEST_PUBLIC_URL for plan_ready and list_ready, threaded by threadKey=mealquest-week-YYYY-Www with REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD. 429 and 5xx are retried; any other non-2xx fails the row at once through the new notify.ErrUndeliverable. - One place builds every event's title, body and Chat text. The webhook URL never appears in a response, log line or error; tests against an httptest Chat endpoint scan both. Maestro task 919e9422-3a41-4f1f-8967-77da17f5f9f3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>Independent Codex gpt-6-sol review: CHANGES_REQUIRED for this exact commit.
Independent Codex gpt-6-sol review: APPROVED for this exact commit.