Context
Follow-up to #117 / #193. PR #193 added _sanitize_path_component to both confluence_toolkit.py and jira_toolkit.py (byte-for-byte identical) when implementing path-traversal sanitization for Confluence titles and Jira summaries. The duplication was accepted at the time to avoid creating a new shared module mid-PR, but every future bug-fix has to be applied twice.
Rio's #193 review flagged this:
Acceptable for now. The two implementations are byte-for-byte identical and neither toolkit imports the other; co-locating them avoids a circular-import hazard in the sources package. The practical downside is that a future bug-fix must be applied twice. A shared _atlassian_utils.py (or promotion into _atlassian.py itself) would be cleaner, but this is a nit, not a blocker.
Acceptance
Bonus opportunity
GitToolkit (#186) has its own URL-sanitization helper (_strip_url_credentials). That's a different concern (URL userinfo, not filesystem path-traversal), so doesn't belong in the same module — but worth noting for any reviewer thinking about "where do shared toolkit helpers live."
Parent
Follow-up to #117 / #193 / #195.
Context
Follow-up to #117 / #193. PR #193 added
_sanitize_path_componentto bothconfluence_toolkit.pyandjira_toolkit.py(byte-for-byte identical) when implementing path-traversal sanitization for Confluence titles and Jira summaries. The duplication was accepted at the time to avoid creating a new shared module mid-PR, but every future bug-fix has to be applied twice.Rio's #193 review flagged this:
Acceptance
_sanitize_path_componentinto a shared module — recommendbackend/app/core/sources/_pathsafe.py(a generic helper that any toolkit could reuse, not Atlassian-specific). Alternative: fold into_atlassian.pyif Confluence + Jira remain the only consumers.confluence_toolkit.pyandjira_toolkit.pyimport from the new location; delete their local copies.Bonus opportunity
GitToolkit(#186) has its own URL-sanitization helper (_strip_url_credentials). That's a different concern (URL userinfo, not filesystem path-traversal), so doesn't belong in the same module — but worth noting for any reviewer thinking about "where do shared toolkit helpers live."Parent
Follow-up to #117 / #193 / #195.