mirror of
https://github.com/Monkopedia/rouse-context.git
synced 2026-11-01 20:20:25 +00:00
* relay: tests for wrong-secret throttle per (IP, subdomain) (#811) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YYSPuh9bZEJkrzvnEpY1QK * relay: throttle wrong integration secrets per (IP, subdomain) (#811) After 5 invalid secrets within an hour from one IP on one subdomain, the relay closes that IP on that subdomain for the rest of the window, also when the secret is correct, and never wakes the device for a blocked attempt. Thresholds and the entry cap live under [limits]; state is an in-memory, capped, swept table, separate from the 200/min connection limiter. Docs drop the ~4M-combinations claim: the secret is a filter against casual scanning, and OAuth approval on the phone is the real gate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YYSPuh9bZEJkrzvnEpY1QK * relay: regression tests for concurrent wrong-secret bursts (#811) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YYSPuh9bZEJkrzvnEpY1QK * relay: reserve wrong-secret slots before the secret lookup (#811) The throttle checked, awaited the secret lookup, then recorded, so a concurrent burst all passed the check during a cold-cache or legacy secret_prefix lookup. Admission now reserves a slot under the map entry before the await and settles it right after validation, before any wake. In-flight distinct secrets count against the budget; connections with the same secret share a slot so a real client's burst is not refused. The window anchors at the first failure, idle entries are dropped, the full-table sweep runs at most once a second, and a block is logged at info with IP and subdomain. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YYSPuh9bZEJkrzvnEpY1QK * relay: tests for retired secrets not counting toward the throttle (#811) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YYSPuh9bZEJkrzvnEpY1QK * relay: retired secrets do not count toward the wrong-secret throttle (#811) A stale client config (e.g. an old connector after a disable/re-enable rotated its secret) retrying from a shared egress IP must not lock out the working URL. An exact match for one of the device's retired secrets is still closed like any invalid secret, but its reserved slot is released without counting. The check runs inside the same reserve/settle flow, so it cannot widen a concurrent burst. The secrets cache now carries the retired set alongside valid_secrets (filled from the same Firestore lookup and by /rotate-secret), so no extra reads are added. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YYSPuh9bZEJkrzvnEpY1QK * relay: tests for stale secrets across re-enable and shared-slot failures (#811) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YYSPuh9bZEJkrzvnEpY1QK * relay: stale_secrets list for the throttle exemption; sticky shared-slot failure (#811) The retired-secret exemption missed re-enable: /rotate-secret clears a re-enabled integration from retired_secrets, so the old connector's URL counted again and could lock out the new one. Former secrets now go to a separate stale_secrets list on the device record, used only for the exemption: every secret that stops being valid (disable, replacement on re-enable, same-subdomain re-registration) is appended, at most 16 kept, oldest dropped. It is persisted with the record, cached with valid_secrets from the same lookup and from /rotate-secret and /register, and reads empty on old records. retired_secrets keeps its #519 role unchanged. Valid secrets are checked first. A failure on a shared slot is now sticky, so a wrong guess still counts when the last sharer is dropped unsettled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YYSPuh9bZEJkrzvnEpY1QK * relay: tests for pre-deploy retired secrets staying exempt (#811) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YYSPuh9bZEJkrzvnEpY1QK * relay: exempt retired secrets from the throttle alongside stale ones (#811) Integrations disabled before stale_secrets existed only have their former secret in retired_secrets. The exemption set is now stale_secrets plus the retired values, read from the same lookup, so those stay exempt with no migration. retired_secrets semantics (#519) are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YYSPuh9bZEJkrzvnEpY1QK --------- Co-authored-by: monkopedia-coder <monkopedia-coder@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| auth-pages | ||
| design | ||
| internal | ||
| notifications | ||
| screenshots | ||
| user | ||
| agent-quickstart.md | ||
| audit.md | ||
| distribution.md | ||
| security-audit-2026-04-07.md | ||
| security-decisions.md | ||
| security.md | ||
| self-hosting.md | ||
| test-coverage-audit.md | ||
| ux-decisions.md | ||
| workflow.md | ||