Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .Jules/palette.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 2024-05-22 - CLI Dry-Run Visibility
**Learning:** Users running destructive CLI tools (sync/delete) rely heavily on dry-run output to trust the tool. Providing high-level stats is insufficient; showing exactly *what* will be affected (e.g., specific folder names and actions) reduces anxiety and prevents errors.
**Action:** When implementing `--dry-run`, always list the specific entities that would be created, modified, or deleted, not just counts.
2 changes: 1 addition & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.13
3.13
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change appears to be a formatting-only modification (removing the leading space from line 1). While this makes the file more consistent, it doesn't relate to the PR's stated purpose of adding detailed dry-run logging. If this is an intentional cleanup, it should be mentioned in the PR description. If unintentional, it should be reverted.

Copilot uses AI. Check for mistakes.
28 changes: 28 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -1129,6 +1129,34 @@
plan_accumulator.append(plan_entry)

if dry_run:
log.info("Dry-run Plan:")
for folder in plan_entry["folders"]:
# Determine action label
if "rule_groups" in folder:
action_str = f"Multi-Action ({len(folder['rule_groups'])} groups)"
else:
act_val = folder.get("action")
# Handle missing 'do' field (None) as default Allow (0) for display
if act_val is None:
act_val = 0

if act_val == 0:
action_str = "Allow"
elif act_val == 1:
action_str = "Block"
elif act_val == 2:
action_str = "Bypass-Mode"
else:
action_str = f"Action={act_val}"

# Use %s formatting and explicit sanitization to satisfy CodeQL
log.info(
" - %s: %s rules (%s)", # codeql[py/clear-text-logging-sensitive-data]
sanitize_for_log(folder.get("name", "Unknown")),
folder.get("rules", 0),

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This expression logs
sensitive data (password)
as clear text.

Copilot Autofix

AI about 2 months ago

Copilot could not generate an autofix suggestion

Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.

action_str,

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This expression logs
sensitive data (password)
as clear text.

Copilot Autofix

AI about 2 months ago

Copilot could not generate an autofix suggestion

Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.

)

Comment on lines +1132 to +1159
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new dry-run logging feature lacks test coverage. While the codebase has comprehensive tests (test_main.py and tests/ directory), there are no tests verifying that the dry-run plan is correctly logged with folder names, rule counts, and action strings. Consider adding a test that mocks the sync_profile function with dry_run=True and verifies the log output includes the expected format for folders with different action types (Allow, Block, Bypass-Mode, Multi-Action).

Copilot uses AI. Check for mistakes.
log.info("Dry-run complete: no API calls were made.")
return True

Expand Down
18 changes: 18 additions & 0 deletions reproduce_issue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Missing module docstring Warning

Missing module docstring

Check warning

Code scanning / Pylint (reported by Codacy)

Missing module docstring Warning

Missing module docstring
import logging

Check warning

Code scanning / Prospector (reported by Codacy)

Unused import logging (unused-import) Warning

Unused import logging (unused-import)

Check notice

Code scanning / Pylintpython3 (reported by Codacy)

Unused import logging Note

Unused import logging

Check notice

Code scanning / Pylint (reported by Codacy)

Unused import logging Note

Unused import logging
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'logging' is not used.

Suggested change
import logging

Copilot uses AI. Check for mistakes.
from main import sanitize_for_log

TOKEN = "secret_token"

Check notice

Code scanning / Bandit

Possible hardcoded password: 'secret_token' Note

Possible hardcoded password: 'secret_token'
import main

Check warning

Code scanning / Prospector (reported by Codacy)

Import "import main" should be placed at the top of the module (wrong-import-position) Warning

Import "import main" should be placed at the top of the module (wrong-import-position)

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Import "import main" should be placed at the top of the module Warning

Import "import main" should be placed at the top of the module

Check warning

Code scanning / Pylint (reported by Codacy)

Import "import main" should be placed at the top of the module Warning

Import "import main" should be placed at the top of the module
main.TOKEN = TOKEN

def test_sanitize():

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Missing function or method docstring Warning

Missing function or method docstring

Check warning

Code scanning / Pylint (reported by Codacy)

Missing function docstring Warning

Missing function docstring
entry_name = "Folder with " + TOKEN
sanitized = sanitize_for_log(entry_name)
Comment on lines +3 to +11
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Module 'main' is imported with both 'import' and 'import from'.

Suggested change
from main import sanitize_for_log
TOKEN = "secret_token"
import main
main.TOKEN = TOKEN
def test_sanitize():
entry_name = "Folder with " + TOKEN
sanitized = sanitize_for_log(entry_name)
import main
TOKEN = "secret_token"
main.TOKEN = TOKEN
def test_sanitize():
entry_name = "Folder with " + TOKEN
sanitized = main.sanitize_for_log(entry_name)

Copilot uses AI. Check for mistakes.
print(f"Original: {entry_name}")
print(f"Sanitized: {sanitized}")
assert "[REDACTED]" in sanitized

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
assert TOKEN not in sanitized

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
Comment on lines +4 to +15
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file modifies a TOKEN global variable in the main module (lines 6-7), which could have unintended side effects if the script is accidentally imported or run in an environment where the main module is already loaded. If this script must be kept, it should use proper test isolation techniques such as mocking or fixtures to avoid modifying global state.

Suggested change
TOKEN = "secret_token"
import main
main.TOKEN = TOKEN
def test_sanitize():
entry_name = "Folder with " + TOKEN
sanitized = sanitize_for_log(entry_name)
print(f"Original: {entry_name}")
print(f"Sanitized: {sanitized}")
assert "[REDACTED]" in sanitized
assert TOKEN not in sanitized
from unittest import mock
TOKEN = "secret_token"
def test_sanitize():
with mock.patch("main.TOKEN", TOKEN):
entry_name = "Folder with " + TOKEN
sanitized = sanitize_for_log(entry_name)
print(f"Original: {entry_name}")
print(f"Sanitized: {sanitized}")
assert "[REDACTED]" in sanitized
assert TOKEN not in sanitized

Copilot uses AI. Check for mistakes.

if __name__ == "__main__":

Check warning

Code scanning / Prospector (reported by Codacy)

expected 2 blank lines after class or function definition, found 1 (E305) Warning

expected 2 blank lines after class or function definition, found 1 (E305)
test_sanitize()
Comment on lines +1 to +18
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file appears to be a debug/test script that was likely used during development but should not be committed to the repository. The file tests the sanitize_for_log function, but there are already comprehensive tests in tests/test_log_sanitization.py. This script should either be moved to the tests/ directory as a proper test case, or removed entirely and added to .gitignore if it's meant for local development only.

Suggested change
import logging
from main import sanitize_for_log
TOKEN = "secret_token"
import main
main.TOKEN = TOKEN
def test_sanitize():
entry_name = "Folder with " + TOKEN
sanitized = sanitize_for_log(entry_name)
print(f"Original: {entry_name}")
print(f"Sanitized: {sanitized}")
assert "[REDACTED]" in sanitized
assert TOKEN not in sanitized
if __name__ == "__main__":
test_sanitize()
from main import sanitize_for_log
TOKEN = "secret_token"
import main
main.TOKEN = TOKEN
def test_sanitize():
entry_name = "Folder with " + TOKEN
sanitized = sanitize_for_log(entry_name)
assert "[REDACTED]" in sanitized
assert TOKEN not in sanitized

Copilot uses AI. Check for mistakes.
Loading