Surfaced by independent review of PR #26 (#13). Non-blocking; filed as follow-up.
Problem
Two gaps relative to the "validate slug at every entry point / defense-in-depth" goal:
- Streaming handler untested for malformed slug.
test_nat_agent.py covers the non-streaming path (test_malformed_slug_in_token_returns_400), but test_nat_agent_streaming.py has no malformed-slug test — and streaming is the primary production path. The code does call is_valid_nation_slug, but the behavior is unverified.
token_refresh handler doesn't validate nb_slug. src/lambdas/token_refresh/handler.py reads nb_slug from the stored token payload and builds f"https://{nb_slug}.nationbuilder.com/oauth/token" with no format check. It's EventBridge-internal (slug was validated at connect time), but the PR's own stated coverage is "all entry points."
Acceptance Criteria
Source: PR #26 review. Relates to epic #18.
Surfaced by independent review of PR #26 (#13). Non-blocking; filed as follow-up.
Problem
Two gaps relative to the "validate slug at every entry point / defense-in-depth" goal:
test_nat_agent.pycovers the non-streaming path (test_malformed_slug_in_token_returns_400), buttest_nat_agent_streaming.pyhas no malformed-slug test — and streaming is the primary production path. The code does callis_valid_nation_slug, but the behavior is unverified.token_refreshhandler doesn't validatenb_slug.src/lambdas/token_refresh/handler.pyreadsnb_slugfrom the stored token payload and buildsf"https://{nb_slug}.nationbuilder.com/oauth/token"with no format check. It's EventBridge-internal (slug was validated at connect time), but the PR's own stated coverage is "all entry points."Acceptance Criteria
tests/test_nat_agent_streaming.pyasserts a malformed slug in a validly-signed token yields the streaming error path (mirroring the non-streaming test)token_refresh/handler.pyvalidatesnb_slugwithis_valid_nation_slugbefore constructing the token URL; invalid slugs are skipped/loggedSource: PR #26 review. Relates to epic #18.