Skip to content

Deprecate endpoints - #149

Merged
skupriienko merged 13 commits into
masterfrom
deprecate-endpoints
Sep 14, 2026
Merged

skupriienko merged 13 commits into
masterfrom
deprecate-endpoints

Conversation

@skupriienko

@skupriienko skupriienko commented Sep 12, 2026 •

Copy link
Copy Markdown
Collaborator

Links:

Jira

Actions:

  • Architecture & Developer Experience (DX):

    • Static O(1) Route Registry Additions (routes.py): Registered missing static route definitions in ROUTE_MAP for contactslist_csvdata and batchjob_csverror to eliminate runtime dynamic path resolution overhead.
    • Sub-Action Hyphenation Engine: Re-implemented native CamelCase-to-kebab-case transformation for sub-actions in Endpoint.__init__ (e.g., statistics_linkClick $\rightarrow$ statistics/link-click).
    • Stream Query Parameter Normalization & Casting: Introduced Endpoint._cast_query_param and _normalize_stream_filters to automatically parse and cast multidict query filter values (such as urllib.parse.parse_qs arrays) to native scalar or collection types (int, float, bool, list, tuple, set).
    • Custom Headers Pass-Through: Added optional headers mapping parameters to Endpoint.__call__, create(), and update() for per-request header injection.
    • Stream Early-Exit Optimization: Enhanced Endpoint.stream() to monitor the API Total response field, automatically halting generator pagination once current_offset + len(data) >= total.
    • Samples Modernization: Refactored samples/segments_sample.py to use campaigndraft and updated samples/smoke_readme_runner.py health checks to use canonical endpoints eventcallbackurl and template_contents.
  • API Deprecation Advisory:

    • Non-Breaking Advisory Mapping (DEPRECATION_ADVISORY): Implemented an automated deprecation system in routes.py that intercepts retired Mailjet endpoints and emits actionable DeprecationWarning notices directing developers to official replacements:
      • newsletter and sub-resources (newsletter_*) $\rightarrow$ campaigndraft / campaigndraft_*
      • Legacy statistics (apikeytotals, campaignstatistics, liststatistics, domainstatistics, etc.) $\rightarrow$ statcounters / statistics_recipientEsp
      • SDK alias webhook $\rightarrow$ canonical REST resource eventcallbackurl
      • Ambiguous template routes (template_update, templates_contents) $\rightarrow$ template.update(id=...) or template_detailcontent (v3) / template_contents (v1)
  • Security & Guardrails (OWASP):

    • Deep Redaction Hierarchy (CWE-316): Expanded RedactingFilter to recursively sanitize complex data structures, including structured typing.NamedTuple instances, Pydantic-compatible objects with model_dump(), arbitrary __dict__ instances, and set/frozenset collections.
    • Control Character Sanitization (CWE-20 / CWE-117): Neutralized unprintable ASCII control characters ([\x00-\x1f\x7f]) in SecurityGuard.sanitize_log_trace before whitespace normalization to prevent log forging and trace corruption.
    • Strict Timeout Type Guard (CWE-400 / CWE-843): Explicitly rejected boolean flags (True/False) in SecurityGuard.validate_timeout to prevent accidental type coercion to numeric 1.0/0.0 seconds.
    • File Boundary Enforcement (CWE-400): Added explicit Path.is_file() validation in SecurityGuard.check_file_size to block directories or special devices from triggering file-size checks.
    • Header Injection Hardening (CWE-113): Broadened header sanitization across Client.api_call to accept Mapping[str, str | None] and screen all non-None string representations for CRLF injection sequences.
    • Email IDN Parsing (RFC 3490): Switched domain extraction in SecurityGuard.normalize_domain to rpartition("@") and strictly scoped exception interception to UnicodeError.
  • Testing & CI/CD Hygiene:

    • Fuzz Harnesses & Dictionary Expansion: Updated tests/fuzz/fuzzer.dict with new static routes, streaming tokens, HTML/XSS triggers, IDN tags, and secret patterns. Extended fuzz_endpoint.py, fuzz_guardrails.py, and fuzz_redacting_filter.py to cover stream mutation, auth coercion, and complex redaction pathways.
    • Legacy Route Deprecation Tests: Added unit test coverage verifying that all entries in DEPRECATION_ADVISORY emit expected DeprecationWarning messages with appropriate migration guidance.
    • Workflow Cleanup: Removed redundant .github/workflows/cflite_build.yml and .github/workflows/cflite_cron.yml CI tasks.

Verification & Testing:

Ensure API credentials (MJ_APIKEY_PUBLIC and MJ_APIKEY_PRIVATE) are set in your local environment, then run the verification steps below:

1. Run the Unit & Integration Test Suite:
Validates new routing endpoints, deprecation warnings, and custom header propagation.

pytest tests/ -v

2. Verify Deprecation Warnings Specifically:
Runs legacy endpoint tests to ensure all deprecation warnings are properly triggered and formatted.

pytest tests/unit/test_legacy_deprecations.py -v

3. Run the Fuzzing Suite:
Verifies that expanded route mappings, pagination normalization, and redaction logic catch mutated inputs cleanly without unhandled crashes.

bash manage.sh fuzz_all 600

4. Execute the Updated Sample Runners:
Validates that sample scripts execute successfully against canonical endpoints without triggering deprecation warnings.

python samples/smoke_readme_runner.py
python samples/segments_sample.py

- Support typing.NamedTuple and object __dict__/model_dump redaction in RedactingFilter
- Enforce regular file check before size evaluation to prevent CWE-400 resource exhaustion
- Disallow boolean types in timeout evaluation to prevent silent coercion
- Harden IDN normalization via rpartition and catch specific UnicodeError bounds
- Filter control characters [\x00-\x1f\x7f] and normalize whitespace in log traces
- Update test_guardrails suite with edge cases covering CWE-22, CWE-400, and logging extras
…t pagination

- Register DEPRECATION_ADVISORY mapping legacy endpoints (newsletter, stats, webhook)
- Add static routes for contactslist_csvdata, batchjob_csverror, contact_data, and widget
- Emit active DeprecationWarning on deprecated route access in Endpoint._build_url
- Preserve CamelCase to kebab-case conversion for sub-actions in Endpoint.__init__
- Implement query parameter casting (_cast_query_param) and snapshot isolation in stream()
- Allow custom headers forwarding in create() and update() methods
- Add comprehensive unit tests covering routing branches, sub-actions, and deprecations
- Replace deprecated newsletter.create with campaigndraft.create in segments_sample.py
- Update smoke_readme_runner health checks to use canonical eventcallbackurl
- Align Content API v1 test to use template_contents instead of templates_contents
…utes

- Extend fuzz_endpoint with pagination and generator stream mutation paths
- Add auth coercion, HTML SpamGuard, and safe kwargs filtering to fuzz_guardrails
- Expand fuzz_redacting_filter to exercise Set and Object redaction pathways
- Update fuzzer.dict with new static routes, parameters, and encoding payloads
@skupriienko skupriienko self-assigned this Sep 12, 2026
Comment thread tests/fuzz/fuzz_endpoint.py Fixed
Comment thread tests/integration/test_client.py Dismissed
Comment thread tests/integration/test_client.py Dismissed
@skupriienko
skupriienko marked this pull request as ready for review September 14, 2026 09:33
@skupriienko
skupriienko merged commit d36e17f into master Sep 14, 2026
27 checks passed
@skupriienko
skupriienko deleted the deprecate-endpoints branch September 14, 2026 10:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant