Skip to content
Merged
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
1 change: 0 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ GAS_STATION_SIDE_ID="gas_station_side_id"
LONGTITUDE_LATITUDE="location longtitude,latitude"
DISCORD_WEBHOOK_URL="discord_webhook_url"
HAMMERSPOON_ALERT_URL="http://localhost:9181/alert"
HAMMERSPOON_TASK_URL="http://localhost:9181/task"
MAIL_ACCOUNT="email account"
MAIL_PASSWORD='email app engine password'
MAIL_PERSON_LIST='["receiver email list"]'
Expand Down
7 changes: 3 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ npx @tailwindcss/cli -i src/safe_family/static/css/input.css \

The project uses **two DB access styles in parallel**:

1. **SQLAlchemy ORM** (`src/safe_family/core/extensions.py` → `db`) — used for `users`, `token_blocklist`, `long_term_goals`, `notes`, `tags`, `media`, `note_sync_ops`, `auth_codes`, `agile_config`.
1. **SQLAlchemy ORM** (`src/safe_family/core/extensions.py` → `db`) — used for `users`, `token_blocklist`, `notes`, `tags`, `media`, `note_sync_ops`, `auth_codes`, `agile_config`.
2. **Raw psycopg2** (`get_db_connection()` in `extensions.py`) — used by logs, suspicious, block_list, filter_rule, schedule_rules, todo_list. These tables are not in SQLAlchemy models and must be created manually (see `scripts/notesync_schema.sql` and `docs/implementation.md`).

Tests stub the raw connection with `FakeConnection`/`FakeCursor` (see `tests/conftest.py`). Notesync tests use a real SQLite DB via `notesync_app` fixture.
Expand All @@ -95,7 +95,6 @@ All blueprints are registered in `src/safe_family/app.py`:
| `auth_bp` | `core/auth.py` | `/auth` |
| `user_bp` | `users/users.py` | `/users` |
| `todo_bp` | `todo/todo.py` | — |
| `goals_bp` | `todo/goals.py` | — |
| `api_bp` | `api/routes.py` | `/api` |

### Key subsystems
Expand All @@ -104,12 +103,12 @@ All blueprints are registered in `src/safe_family/app.py`:

**URL blocking pipeline** — `urls/receiver.py` ingests AdGuard Home log events at `POST /logs`; `urls/analyzer.py` aggregates them into `logs_daily` and derives `suspicious` entries; `urls/blocker.py` toggles AdGuard rule lists and router gateway traffic via HTTP calls. Cooldown logic prevents rapid toggling.

**Scheduler (`rules/scheduler.py`)** — APScheduler `BackgroundScheduler` loads cron rules from the `schedule_rules` table at startup. Uses Postgres advisory locks for leader election across multiple Gunicorn workers. Daily jobs archive tasks and run log analysis. Overdue tasks trigger Hammerspoon/email notifications.
**Scheduler (`rules/scheduler.py`)** — APScheduler `BackgroundScheduler` loads cron rules from the `schedule_rules` table at startup. Uses Postgres advisory locks for leader election across multiple Gunicorn workers. A daily job runs log analysis. Overdue tasks trigger Hammerspoon/email notifications.

**Auto Git (`auto_git/auto_git.py`)** — exports block list and filter rules to files and auto-commits/pushes to a rules repository. SSH keys are required (mounted from `~/.ssh` in Docker).

**Config** — `config/settings.py` loads all env vars. `DB_PARAMS` (JSON string) is the legacy path; individual `DB_USER`/`DB_HOST`/`DB_NAME`/`DB_PASSWORD`/`DB_PORT` vars (preferred for Docker) take precedence.

### Raw SQL tables (not in ORM)

`logs`, `logs_daily`, `suspicious`, `block_list`, `filter_rule`, `schedule_rules`, `user_rule_assignment`, `todo_list`, `long_term_goals_his`, `block_types` — see `docs/implementation.md` for column details. `scripts/migrate.py` is the migration hook.
`logs`, `logs_daily`, `suspicious`, `block_list`, `filter_rule`, `schedule_rules`, `user_rule_assignment`, `todo_list`, `block_types` — see `docs/implementation.md` for column details. `scripts/migrate.py` is the migration hook.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ integrations.
- Rule toggles for AdGuard and router traffic control with cooldown safeguards.
- Scheduler with APScheduler plus Postgres advisory locks for safe multi-process jobs.
- Notesync API with LWW conflict handling, tags, and media attachments.
- Todo planner with time slots, long-term goals, and weekly summaries.
- Todo planner with time slots and a completion heatmap.
- Notifications via email, Discord webhooks, and local Hammerspoon alerts.
- Auto Git export/import for block list rules.

Expand Down Expand Up @@ -149,7 +149,7 @@ Integrations (optional, feature-specific):
- Router: `ROUTER_IP`
- Email: `MAIL_ACCOUNT`, `MAIL_PASSWORD`, `MAIL_PERSON_LIST`
- Discord: `DISCORD_WEBHOOK_URL`
- Hammerspoon: `HAMMERSPOON_ALERT_URL`, `HAMMERSPOON_TASK_URL`
- Hammerspoon: `HAMMERSPOON_ALERT_URL`
- OAuth: `GITHUB_CLIENT_ID`, `GITHUB_CLIENT_SECRET`, `GOOGLE_CLIENT_ID`,
`GOOGLE_CLIENT_SECRET`, `GOOGLE_CLIENT_PROJECT_ID`, `GOOGLE_CALLBACK_ROUTE`

Expand Down
4 changes: 0 additions & 4 deletions config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,6 @@ class Settings:
"HAMMERSPOON_ALERT_URL",
"http://localhost:9181/alert",
)
HAMMERSPOON_TASK_URL = os.environ.get(
"HAMMERSPOON_TASK_URL",
"http://localhost:9181/task",
)

# Notesync settings
NOTESYNC_API_KEY = os.environ.get("NOTESYNC_API_KEY", "")
Expand Down
4 changes: 1 addition & 3 deletions deploy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@ The dump.sql file created most of the tables, but it missed the following table
- auth_codes
- token_blocklist

Todo & Goals Tables:
Todo Tables:
- todo_list
- long_term_goals
- long_term_goals_his

Rules & Scheduling Tables:
- schedule_rules
Expand Down
12 changes: 1 addition & 11 deletions docs/coverage-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ src/safe_family/rules/scheduler.py | 363 | 73% | Background jobs and advisory lo
src/safe_family/urls/blocker.py | 129 | 61% | AdGuard and router rule toggles
src/safe_family/urls/analyzer.py | 87 | 75% | Log parsing and analysis
src/safe_family/api/routes.py | 106 | 77% | Notesync API + notes list
src/safe_family/todo/goals.py | 115 | 92% | Separated long-term goals logic (New)
src/safe_family/urls/notes.py | 68 | 86% | UI for notes viewer (pagination/media)

Secondary modules close to 80 or above:
Expand Down Expand Up @@ -84,17 +83,11 @@ Suggested files to extend:
- [x] done_todo updates status
- [ ] done_todo auto-complete after end time
- [x] mark_status invalid + success paths
- [x] notify_feedback/notify_current_task routes
- [x] split_slot success + forbidden paths
- [x] long-term goal create/update/reorder/start/stop/delete/update due (in goals.py)
- [x] update_tag success + forbidden paths
- [x] unknown_metadata filtering
- [x] goals page renders and admin user switching

Suggested files to extend:
- tests/test_todo.py
- tests/test_units.py
- tests/test_goals_route.py

### Scheduler and automation
- [x] _ensure_scheduler_leader returns False when lock not acquired
Expand Down Expand Up @@ -137,7 +130,7 @@ Suggested files to extend:
### Notifications
- [x] email notification formats and recipients
- [x] Discord notification payloads and empty webhook behavior
- [x] Hammerspoon alert/task only sends when server reachable
- [x] Hammerspoon alert only sends when server reachable

Suggested files to extend:
- tests/test_notifier.py
Expand All @@ -152,12 +145,9 @@ Suggested files to extend:

### CLI tools and reports
- [ ] analyze: invalid args, custom ranges
- [x] weekly_diff output formatting
- [x] weekly_diff missing files
- [x] weekly_metrics no data vs data
- [x] weekly_metrics output file/dir paths
- [x] weekly_metrics DB query path
- [ ] gentags: empty or malformed input

Suggested files to extend:
- tests/test_cli_analyze.py
Expand Down
17 changes: 10 additions & 7 deletions docs/implementation.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,12 @@ Files:
- src/safe_family/core/schemas.py

Scope:
- SQLAlchemy models: User, TokenBlocklist, LongTermGoal
- Raw SQL tables used by features: logs, logs_daily, suspicious, block_list, filter_rule, schedule_rules, user_rule_assignment, todo_list, long_term_goals_his, block_types
- SQLAlchemy models: User, TokenBlocklist
- Raw SQL tables used by features: logs, logs_daily, suspicious, block_list, filter_rule, schedule_rules, user_rule_assignment, todo_list, block_types

Note: the long-term goals feature was removed. Its tables are not dropped
automatically; the operator can remove them by hand with:
`DROP TABLE long_term_goals; DROP TABLE long_term_goals_his;`

Steps:
1) Keep model methods aligned with DB behavior (save/delete helpers).
Expand Down Expand Up @@ -133,15 +137,15 @@ Files:
Scope:
- APScheduler jobs loaded from `schedule_rules`
- Leader election and advisory locks
- Daily jobs: archive completed tasks, analyze logs
- Daily job: analyze logs
- Realtime notifications: overdue task feedback

Validation:
- `pytest tests/test_scheduler.py`

---

### Task 8: Todo system and long-term goals
### Task 8: Todo system

Files:
- src/safe_family/todo/todo.py
Expand All @@ -151,8 +155,7 @@ Files:
Scope:
- Daily time slot planning (weekday/holiday/custom)
- CRUD for tasks and completion status
- Split slots, tag updates, weekly summary, unknown metadata
- Long-term goals with tracking and reordering
- Split slots

Validation:
- `pytest tests/test_todo.py`
Expand All @@ -168,7 +171,7 @@ Files:
Scope:
- Email via Flask-Mail
- Discord webhook updates
- Hammerspoon alerts and task notifications
- Hammerspoon alerts

Validation:
- `pytest tests/test_notifier.py`
Expand Down
5 changes: 2 additions & 3 deletions docs/todo-week-heatmap-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ reserved card** (`.sf-heatmap-reserve`).
## Key decision: no database schema change

`todo_list` already retains full per-date history — the daily save in
`todo_page()` only deletes/rewrites *today's* rows, and the nightly
`archive_completed_tasks` job only touches `long_term_goals`, never
`todo_list`. Every column needed already exists: `username`, `date`,
`todo_page()` only deletes/rewrites *today's* rows, so historical
`todo_list` rows are never touched. Every column needed already exists: `username`, `date`,
`time_slot`, `completed`, `completion_status`.

Only DB change (optional, recommended): an index in `scripts/migrate.py`:
Expand Down
34 changes: 0 additions & 34 deletions scripts/test.out

This file was deleted.

2 changes: 0 additions & 2 deletions src/safe_family/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
from src.safe_family.core.extensions import db, jwt, mail
from src.safe_family.core.models import User
from src.safe_family.rules.scheduler import schedule_rules_bp
from src.safe_family.todo.goals import goals_bp
from src.safe_family.todo.todo import todo_bp
from src.safe_family.urls.analyzer import analyze_bp
from src.safe_family.urls.blocker import rules_toggle_bp
Expand Down Expand Up @@ -66,7 +65,6 @@ def inject_motto():
app.register_blueprint(auth_bp, url_prefix="/auth")
app.register_blueprint(user_bp, url_prefix="/users")
app.register_blueprint(todo_bp)
app.register_blueprint(goals_bp)

# For debug
# from flask import current_app
Expand Down
109 changes: 0 additions & 109 deletions src/safe_family/cli/gentags.py

This file was deleted.

Loading
Loading