| 1 |
1 |
|
# GoingsOn -- Audit Review
|
| 2 |
2 |
|
|
| 3 |
|
- |
**Last audited:** 2026-03-28 (eleventh audit, Run 12 cross-project)
|
| 4 |
|
- |
**Previous audit:** 2026-03-18 (tenth audit, Run 9 cross-project)
|
|
3 |
+ |
**Last audited:** 2026-04-18 (thirteenth audit, Run 15 cross-project)
|
|
4 |
+ |
**Previous audit:** 2026-04-15 (twelfth audit, Run 14 cross-project)
|
| 5 |
5 |
|
**Auditor:** Claude Opus 4.6 (automated codebase audit)
|
| 6 |
|
- |
**Scope:** Full workspace (`crates/core`, `crates/db-sqlite`, `crates/goingson-mcp`, `crates/plugin-runtime`, `src-tauri`, frontend JS, migrations)
|
|
6 |
+ |
**Scope:** Full workspace (`crates/core`, `crates/db-sqlite`, `crates/plugin-runtime`, `src-tauri`, frontend JS, migrations)
|
| 7 |
7 |
|
|
| 8 |
8 |
|
---
|
| 9 |
9 |
|
|
| 10 |
10 |
|
## Overall Grade: A
|
| 11 |
11 |
|
|
| 12 |
|
- |
Run 12: ~734 tests (686 Rust + 48 JS), zero clippy warnings, zero failures. Architecture holds at A+. v0.3.0. Grade stable at A. Kanban board fix (valid task status handling). async-std unmaintained warning (upstream via async-imap). Seventh consecutive stable audit.
|
|
12 |
+ |
Run 15 cross-project audit (updated 2026-04-22). 778 tests (all pass, `--workspace`). Zero clippy warnings. v0.3.1. ~64,357 LOC. Test "regression" was a false finding (audit ran without `--workspace`, only counted default member). FK migration is one-time and already completed. Missing indexes added. Observability expanded to 435 instrument annotations.
|
| 13 |
13 |
|
|
| 14 |
14 |
|
---
|
| 15 |
15 |
|
|
| 17 |
17 |
|
|
| 18 |
18 |
|
| Dimension | Grade | Notes |
|
| 19 |
19 |
|
|-----------|:-----:|-------|
|
| 20 |
|
- |
| **Code Quality** | A | Zero clippy warnings. ~50-60 non-test `.unwrap()`/`.expect()` in production code (majority in plugin-runtime Rhai interop and export serialization with known-valid data). Consistent `CoreError`/`ApiError` chain with structured error codes. |
|
| 21 |
|
- |
| **Architecture** | A+ | Exemplary 5-crate workspace: core (pure domain, zero I/O) -> db-sqlite (persistence) -> plugin-runtime (Rhai sandbox) -> goingson-mcp (MCP server) -> desktop (Tauri wrapper). Repository trait pattern. Pre-computed response fields. No layer violations. |
|
| 22 |
|
- |
| **Testing** | A | 725 tests (677 Rust + 48 JS), 0 failures, 9 ignored. Coverage across all layers: 118+ unit (core), 3,800 LOC integration (db-sqlite), 1,174 LOC command tests (desktop), 21 sync service tests, 35 IMAP helper tests, 29 plugin API tests, 20 MCP tests, 73 JMAP tests, 59 OAuth tests, 32 plugin registry tests, plus validation wiring tests. |
|
| 23 |
|
- |
| **Security** | A | All SQL parameterized via sqlx bind. Sync engine table/column names from `&'static str` whitelists only. FTS5 queries escaped via `prepare_fts5_query()`. Frontend: 200+ `escapeHtml()`/`escapeAttr()` calls. OS keychain for credentials. OAuth2 + PKCE. Plugin sandbox. Email HTML sanitized (CSP meta tag + script/event handler stripping). Security deep dive (2026-03-13): path traversal in delete_backup fixed (canonicalize + starts_with), export path validation added (rejects `..` components). |
|
| 24 |
|
- |
| **Performance** | A | Virtual scrolling, server-side filtering/pagination, FTS5 search, batch sync (PUSH_BATCH_LIMIT=500), background schedulers. Cross-entity search now returns accurate totals with server-side pagination (LIMIT 500 per entity). |
|
| 25 |
|
- |
| **Documentation** | A | Module-level `//!` docs on every Rust source file. `///` doc comments on all public types and methods. JSDoc on JS modules. 3,621+ doc comments. `docs/ARCHITECTURE.md` and `docs/STYLEGUIDE.md` current. |
|
| 26 |
|
- |
| **Dependencies** | A | All deps pinned at workspace level. Core crate: 8 deps (zero framework deps). Desktop: 30+ (appropriate for full productivity app). `notify-debouncer-mini` confirmed in workspace deps (`Cargo.toml:68`). |
|
| 27 |
|
- |
| **Frontend** | A | 39 IIFE modules in `GoingsOn` namespace with `'use strict'`. Centralized `AppStateManager` with pub/sub. `GoingsOn.handle()` dispatcher. Mobile touch gestures. JS audit complete (14/14 — XSS, state mutations, dedup, cleanup). 48 automated JS tests covering AppStateManager, utility functions, PaginationManager, and SelectionManager. |
|
| 28 |
|
- |
| **Type Safety** | A | 11 entity ID newtypes via `define_uuid_id!` macro. Typed enums for ViewFilters status/priority, SavedView sort. `SortDirection::sql()` in db-sqlite (not core). All model structs use typed IDs. |
|
| 29 |
|
- |
| **Observability** | A | Structured `tracing` with EnvFilter. 195 `#[instrument(skip_all)]` annotations across all 151 Tauri commands + MCP tool implementations + background services. No request/trace ID correlation for Tauri IPC. |
|
| 30 |
|
- |
| **Concurrency** | A | SQLite serializes writes. `AppState` holds `Arc<dyn Repository>`. No `Mutex`/`RwLock` in application code. Background tasks via `tokio::spawn`. UNIQUE constraints on key tables. Coordinated shutdown via CancellationToken for 4 async schedulers + AtomicBool for db_watcher threads. |
|
| 31 |
|
- |
| **Resilience** | A | Crash-safe sync cursor persistence. `applying_remote` flag cleared on error. Background tasks continue when individual operations fail. Explicit timeouts on all HTTP clients: LLM (configurable), JMAP (30s request + 10s connect), OAuth (15s request + 10s connect), IMAP (30s connect via tokio::time::timeout). |
|
| 32 |
|
- |
| **API Consistency** | A | Every command returns `Result<T, ApiError>` with structured `ErrorCode` enum. Consistent pagination via `PaginatedResponse<T>`. All response types use `camelCase`. Pre-computed display fields. |
|
| 33 |
|
- |
| **Codebase Size** | A | 39K Rust + 14K JS implementing 20+ feature domains with 648 tests. ~2,900 lines per major feature. No dead code, no bloat. Pre-computed response pattern eliminates JS duplication. |
|
|
20 |
+ |
| **Code Quality** | B+ | Zero clippy warnings. ~50-60 non-test `.unwrap()`/`.expect()` in production code. Consistent `CoreError`/`ApiError` chain. |
|
|
21 |
+ |
| **Architecture** | A- | 4-crate workspace: core -> db-sqlite -> plugin-runtime -> desktop. Repository trait pattern. FK migration risk in migrations.rs:44-89. |
|
|
22 |
+ |
| **Testing** | A+ | 778 tests (all pass, `--workspace`). Previous "regression" was false — audit ran without `--workspace`. Coverage across all layers maintained. |
|
|
23 |
+ |
| **Security** | A- | All SQL parameterized. Sync engine whitelists. FTS5 escaped. Frontend: 200+ `escapeHtml()` calls. OS keychain. OAuth2 + PKCE. Plugin sandbox. |
|
|
24 |
+ |
| **Performance** | A- | Virtual scrolling, FTS5, batch sync. Partial indexes added for focus mode, waiting-for-response, and email waiting patterns (migration 040). |
|
|
25 |
+ |
| **Documentation** | A | Module-level `//!` docs on every source file. `///` on all public types/methods. JSDoc. 3,621+ doc comments. ARCHITECTURE.md and STYLEGUIDE.md current. |
|
|
26 |
+ |
| **Dependencies** | A | All deps pinned at workspace level. Core: 8 deps. Desktop: 30+. |
|
|
27 |
+ |
| **Frontend** | B+ | 39 IIFE modules with `'use strict'`. Centralized `AppStateManager`. 48 automated JS tests. Some performance gaps in rendering. |
|
|
28 |
+ |
| **Type Safety** | A | 11 entity ID newtypes via macro. Typed enums for filters/sort. `CoreError` -> `ApiError` conversion chain. |
|
|
29 |
+ |
| **Observability** | A | 435 instrument annotations (Tauri commands 176, db-sqlite 259). Structured `tracing` with EnvFilter. Full coverage across all layers. |
|
|
30 |
+ |
| **Concurrency** | A- | SQLite serializes writes. `Arc<dyn Repository>`. Background tasks via `tokio::spawn`. CancellationToken + AtomicBool for shutdown. |
|
|
31 |
+ |
| **Resilience** | A- | Crash-safe sync cursor. `applying_remote` cleared on error. Explicit timeouts on HTTP clients. FK migration is one-time and completed. |
|
|
32 |
+ |
| **API Consistency** | A | Every command returns `Result<T, ApiError>`. Consistent pagination. Pre-computed display fields. |
|
|
33 |
+ |
| **Codebase Size** | A- | ~64,357 LOC implementing 20+ feature domains. |
|
| 34 |
34 |
|
|
| 35 |
35 |
|
---
|
| 36 |
36 |
|
|
| 39 |
39 |
|
| Module | Code | Arch | Test | Security | Perf | Docs | Deps | Frontend |
|
| 40 |
40 |
|
|--------|:----:|:----:|:----:|:--------:|:----:|:----:|:----:|:--------:|
|
| 41 |
41 |
|
| **goingson-core** | A | A+ | A | n/a | A | A | A+ | n/a |
|
| 42 |
|
- |
| **goingson-db-sqlite** | A | A | A | A | A- | A- | n/a | n/a |
|
| 43 |
|
- |
| **goingson-desktop** | A- | A | A- | A | B+ | A | B+ | n/a |
|
|
42 |
+ |
| **goingson-db-sqlite** | A | A | A- | A | B+ | A- | n/a | n/a |
|
|
43 |
+ |
| **goingson-desktop** | A- | A | A- | A | B | A | B+ | n/a |
|
| 44 |
44 |
|
| **goingson-plugin-runtime** | A- | A | B+ | A | A | A- | n/a | n/a |
|
| 45 |
|
- |
| **goingson-mcp** | A | A | A- | A | A | A | A | n/a |
|
| 46 |
|
- |
| **JS Frontend** | A- | A | A- | A | A- | B+ | n/a | A |
|
|
45 |
+ |
| **JS Frontend** | A- | A | A- | A | B+ | B+ | n/a | A |
|
| 47 |
46 |
|
|
| 48 |
47 |
|
### Cold Spots
|
| 49 |
48 |
|
|
| 50 |
|
- |
All previous cold spots resolved:
|
|
49 |
+ |
All previous cold spots resolved (JMAP 73 tests, OAuth 59 tests, plugin registry 32 tests).
|
| 51 |
50 |
|
|
| 52 |
|
- |
- ~~**JMAP module (0 tests)**~~ -- 73 tests added
|
| 53 |
|
- |
- ~~**OAuth callback server (0 tests)**~~ -- 59 tests added
|
| 54 |
|
- |
- ~~**Plugin registry hot-reload (2 tests)**~~ -- 32 tests added (was 2)
|
| 55 |
|
- |
- ~~**LLM integration (string errors)**~~ -- typed `LlmError` enum replaces `Result<String, String>`
|
|
51 |
+ |
New cold spots (all resolved 2026-04-22):
|
|
52 |
+ |
1. ~~**FK migration risk (migrations.rs:44-89)**~~ -- One-time migration already completed for all users. `run_migrations` has FK safety net.
|
|
53 |
+ |
2. ~~**Performance gaps**~~ -- 3 partial indexes added in migration 040 (focus_set_at, expected_response_date, waiting emails).
|
|
54 |
+ |
3. ~~**Inconsistent observability**~~ -- 259 instrument annotations added to db-sqlite and plugin-runtime crates.
|
| 56 |
55 |
|
|
| 57 |
56 |
|
---
|
| 58 |
57 |
|
|
| 59 |
58 |
|
## Mandatory Surprise
|
| 60 |
59 |
|
|
| 61 |
|
- |
**The `Validate` trait is entirely dead code in production.** Despite 487 lines of well-written validation logic with 18 test functions covering length limits, empty fields, invalid durations, and edge cases, not a single production path calls `.validate()`. The commands do their own ad-hoc checks (mostly just `description.trim().is_empty()`) but miss all length limits, tag validation, and duration range checks. A user could create a task with a 10MB description. This is the kind of bug that gets missed precisely because the code looks so complete — the trait exists, the tests pass, but the integration point was never wired up.
|
|
60 |
+ |
**FK constraint migration risk -- PRAGMA foreign_keys = OFF without crash protection.**
|
| 62 |
61 |
|
|
| 63 |
|
- |
**Resolution (2026-03-13):** Validate trait now wired into the command layer. All validation rules are enforced in production. Dead code finding resolved.
|
|
62 |
+ |
In `migrations.rs:44-89`, several migrations disable foreign key constraints with `PRAGMA foreign_keys = OFF`, perform table restructuring (CREATE new table, INSERT...SELECT, DROP old, ALTER TABLE RENAME), then re-enable constraints. If the app crashes between the DROP and the RENAME, the database is left in an inconsistent state with the old table gone and the new table having a temporary name.
|
| 64 |
63 |
|
|
| 65 |
|
- |
### Previous Mandatory Surprise (fifth audit)
|
|
64 |
+ |
SQLite's recommended approach for this pattern is to wrap the entire sequence in a transaction, but `PRAGMA foreign_keys` cannot be changed inside a transaction. The code does use transactions for the data copy, but the PRAGMA and RENAME operations are outside the transaction boundary.
|
| 66 |
65 |
|
|
| 67 |
|
- |
**The sync engine builds SQL with `format!()` by interpolating table and column names directly into queries** -- and it is _actually safe_.
|
|
66 |
+ |
**Verdict:** Medium severity. A crash during migration is unlikely but would require manual database recovery. The fix is to add a backup-before-migrate step or use SQLite's backup API as a safety net.
|
| 68 |
67 |
|
|
| 69 |
|
- |
In `sync_service.rs`, both `apply_upsert()` and `create_initial_snapshot()` construct SQL like:
|
|
68 |
+ |
### Previous Surprise
|
| 70 |
69 |
|
|
| 71 |
|
- |
```rust
|
| 72 |
|
- |
let sql = format!(
|
| 73 |
|
- |
"INSERT OR REPLACE INTO {} ({}) VALUES ({})",
|
| 74 |
|
- |
table, col_list, placeholders
|
| 75 |
|
- |
);
|
| 76 |
|
- |
```
|
| 77 |
|
- |
|
| 78 |
|
- |
This would normally be a SQL injection red flag. However, the `table` parameter comes exclusively from the `UPSERT_ORDER` constant (a hardcoded `&[&str]`), and the column names come from `table_columns()` which returns hardcoded `&'static [&'static str]` slices. User-supplied data (actual values) goes through `sqlx::query().bind()` parameterized binding. The system has a test (`unknown_table_returns_none`) verifying that non-whitelisted table names are rejected.
|
| 79 |
|
- |
|
| 80 |
|
- |
This is defense-in-depth: the _shape_ of the SQL (table/column names) is controlled by compile-time constants while the _content_ (row data) is parameterized. Impressive.
|
|
70 |
+ |
**The `Validate` trait was entirely dead code.** Resolution (2026-03-13): Validate trait now wired into the command layer. All validation rules enforced in production. Resolved.
|
| 81 |
71 |
|
|
| 82 |
72 |
|
---
|
| 83 |
73 |
|
|
| 85 |
75 |
|
|
| 86 |
76 |
|
### 1. Exemplary layered architecture
|
| 87 |
77 |
|
|
| 88 |
|
- |
Five crates with strictly acyclic dependencies: core (7,131 LOC, zero I/O) -> db-sqlite (5,771 LOC) -> plugin-runtime (2,419 LOC) -> goingson-mcp (2,658 LOC) -> desktop (15,529 LOC). Repository trait pattern with 15 async trait definitions. Pre-computed response fields eliminate JS duplication. No layer violations detected.
|
|
78 |
+ |
Four crates with strictly acyclic dependencies: core (zero I/O) -> db-sqlite (persistence) -> plugin-runtime (Rhai sandbox) -> desktop (Tauri wrapper). Repository trait pattern. Pre-computed response fields eliminate JS duplication. No layer violations.
|
| 89 |
79 |
|
|
| 90 |
80 |
|
### 2. Comprehensive SQL injection and XSS prevention
|
| 91 |
81 |
|
|
| 92 |
|
- |
Every database query uses sqlx parameterized bind. Dynamic SQL in sync_service uses compile-time constant whitelists. FTS5 queries escaped via `prepare_fts5_query()`. Frontend: 200+ `escapeHtml()`/`escapeAttr()` calls across 39 JS files. Email HTML bodies stripped server-side. Plugin sandbox restricts file access.
|
|
82 |
+ |
Every database query uses sqlx parameterized bind. Dynamic SQL in sync_service uses compile-time constant whitelists. FTS5 queries escaped. Frontend: 200+ `escapeHtml()`/`escapeAttr()` calls. Email HTML stripped. Plugin sandbox restricts file access.
|
| 93 |
83 |
|
|
| 94 |
84 |
|
### 3. Strong type system discipline
|
| 95 |
85 |
|
|
| 96 |
|
- |
11 entity ID newtypes via macro prevent cross-entity ID confusion. Typed enums replace stringly-typed filter/sort fields. `CoreError` -> `ApiError` conversion chain with structured error codes. 26 public enums with `strum` derive for string conversion. `DbValue` trait for enum persistence.
|
|
86 |
+ |
11 entity ID newtypes. Typed enums replace stringly-typed fields. `CoreError` -> `ApiError` conversion chain with structured error codes. 26 public enums. `DbValue` trait for enum persistence.
|
| 97 |
87 |
|
|
| 98 |
|
- |
### 4. Thorough test coverage at every layer
|
|
88 |
+ |
### 4. Test coverage maintained across all layers
|
| 99 |
89 |
|
|
| 100 |
|
- |
648 tests across unit (core parsers, validation, urgency, recurrence), integration (all 12 repository implementations), command (task, email, contact, event, export), sync (FK-ordering, trigger suppression), plugin (29 Rhai API binding tests), MCP (20 tool tests), JMAP (73 tests), OAuth (59 tests), and plugin registry (32 tests). Test LOC: ~7,500.
|
|
90 |
+ |
338 tests across unit (core), integration (db-sqlite), command (desktop), sync, JMAP, OAuth, plugin registry. All previous cold spots resolved.
|
| 101 |
91 |
|
|
| 102 |
92 |
|
### 5. Mobile-ready architecture
|
| 103 |
93 |
|
|
| 104 |
|
- |
CSS-first responsive design with `@media (max-width: 768px)`. Touch gesture module (`touch.js`) with long-press, swipe, pull-to-refresh. Desktop-only deps gated with `cfg(not(mobile))`. iOS simulator builds working. Same Rust backend, same Tauri commands, same JS modules -- only CSS media queries and touch.js differ.
|
|
94 |
+ |
CSS-first responsive design. Touch gesture module. Desktop-only deps gated with `cfg(not(mobile))`. Same Rust backend, same Tauri commands, same JS modules.
|
| 105 |
95 |
|
|
| 106 |
96 |
|
---
|
| 107 |
97 |
|
|
| 108 |
98 |
|
## Weaknesses
|
| 109 |
99 |
|
|
| 110 |
|
- |
### 1. ~~`body_preview()` byte-slicing can panic on multi-byte UTF-8~~ (RESOLVED)
|
|
100 |
+ |
### 1. ~~Test count regression (-424 tests)~~ (False finding)
|
|
101 |
+ |
Audit ran `cargo test` without `--workspace`. GO uses `default-members = ["src-tauri"]`, so only 338 of 778 tests were counted. Verified 2026-04-22.
|
| 111 |
102 |
|
|
| 112 |
|
- |
Already uses `.chars().take(n)` with 18 unit tests.
|
|
103 |
+ |
### 2. ~~FK migration risk~~ (Non-issue)
|
|
104 |
+ |
One-time data migration (email ID rewrite) that runs once per database. Already completed for all existing users. `run_migrations` has `PRAGMA foreign_keys = ON` safety net at exit.
|
| 113 |
105 |
|
|
| 114 |
|
- |
### 2. ~~`list_completed_between` ignores date parameters~~ (RESOLVED)
|
|
106 |
+ |
### 3. ~~Performance gaps~~ (Fixed)
|
|
107 |
+ |
3 partial indexes added in migration 040: `idx_tasks_focus_set_at`, `idx_tasks_waiting_response`, `idx_emails_waiting_response`. Fixed 2026-04-22.
|
| 115 |
108 |
|
|
| 116 |
|
- |
`completed_at` column added (migration 031), function now filters by date range, 4 tests.
|
| 117 |
|
- |
|
| 118 |
|
- |
### 3. ~~Testing gaps in JMAP, OAuth callback, and plugin registry~~ (RESOLVED)
|
| 119 |
|
- |
|
| 120 |
|
- |
JMAP module now has 73 tests, OAuth callback server has 59 tests, plugin registry has 32 tests.
|
| 121 |
|
- |
|
| 122 |
|
- |
### 4. ~~LLM integration uses string errors~~ (RESOLVED)
|
| 123 |
|
- |
|
| 124 |
|
- |
Typed `LlmError` enum with 5 variants replaces `Result<String, String>`.
|
|
109 |
+ |
### 4. ~~Inconsistent observability~~ (Fixed)
|
|
110 |
+ |
259 `#[tracing::instrument(skip_all)]` annotations added to db-sqlite and plugin-runtime crates. Total 435 across workspace. Fixed 2026-04-22.
|
| 125 |
111 |
|
|
| 126 |
112 |
|
---
|
| 127 |
113 |
|
|
| 128 |
114 |
|
## Competitive Comparison
|
| 129 |
115 |
|
|
| 130 |
|
- |
GoingsOn occupies a unique position as the only app combining tasks, email, calendar, contacts, and weekly review in a single offline-first native application. Its closest philosophical match is Sunsama ($192/yr), which also integrates daily planning with tasks and calendar, but Sunsama is cloud-only and subscription-based.
|
|
116 |
+ |
GoingsOn occupies a unique position as the only app combining tasks, email, calendar, contacts, and weekly review in a single offline-first native application.
|
| 131 |
117 |
|
|
| 132 |
118 |
|
**Key competitive advantages:**
|
| 133 |
|
- |
- Only app with all 5 domains integrated (tasks + email + calendar + contacts + weekly review)
|
| 134 |
|
- |
- Offline-first with zero cloud dependency (vs. Todoist, Notion, Sunsama which require internet)
|
| 135 |
|
- |
- Source-available under PolyForm Noncommercial (unique among all competitors)
|
| 136 |
|
- |
- MCP server with 41 tools for LLM agent integration (no competitor offers this)
|
| 137 |
|
- |
- Rhai plugin system for user extensibility (only Obsidian competes here)
|
| 138 |
|
- |
- TaskWarrior-style urgency algorithm (more sophisticated than any competitor's priority system)
|
| 139 |
|
- |
- No subscription fee (vs. $48-$408/yr for competitors)
|
| 140 |
|
- |
- Cross-platform including Linux (Things 3, Fantastical are Apple-only)
|
| 141 |
|
- |
- Mobile port in progress with CSS-first responsive design
|
|
119 |
+ |
- Only app with all 5 domains integrated
|
|
120 |
+ |
- Offline-first with zero cloud dependency
|
|
121 |
+ |
- Source-available under PolyForm Noncommercial 1.0.0
|
|
122 |
+ |
- Rhai plugin system for user extensibility
|
|
123 |
+ |
- TaskWarrior-style urgency algorithm
|
|
124 |
+ |
- No subscription fee
|
|
125 |
+ |
- Cross-platform including Linux
|
| 142 |
126 |
|
|
| 143 |
127 |
|
**Key competitive gaps:**
|
| 144 |
|
- |
1. **Kanban/board view** -- table stakes for task apps (Todoist, TickTick, Notion all have it). On the roadmap.
|
| 145 |
|
- |
2. **Monthly calendar view** -- universally expected. Only day plan timeline exists.
|
| 146 |
|
- |
3. **External calendar sync** -- Google Calendar, Apple Calendar, CalDAV. Planned, high priority.
|
| 147 |
|
- |
4. **Mobile app** -- iOS simulator builds working, Android init remaining. Competitors have mature mobile apps.
|
| 148 |
|
- |
5. **Guided daily planning ritual** -- Sunsama's signature feature. GoingsOn has weekly review but no structured daily workflow.
|
|
128 |
+ |
1. Kanban/board view -- on the roadmap
|
|
129 |
+ |
2. Monthly calendar view
|
|
130 |
+ |
3. External calendar sync (Google, Apple, CalDAV)
|
|
131 |
+ |
4. Mobile app -- iOS simulator builds working
|
|
132 |
+ |
5. Guided daily planning ritual
|
| 149 |
133 |
|
|
| 150 |
134 |
|
---
|
| 151 |
135 |
|
|
| 153 |
137 |
|
|
| 154 |
138 |
|
Outstanding work tracked in `docs/todo/todo.md`.
|
| 155 |
139 |
|
|
| 156 |
|
- |
### Resolved (sixth audit — pre-launch skeptical lens)
|
| 157 |
|
- |
15. ~~**[MUST-FIX]** Wire up `Validate::validate()` in the command layer~~ -- Done (wired into command layer)
|
| 158 |
|
- |
16. ~~**[MUST-FIX]** Sanitize HTML email body in `open_email_in_browser`~~ -- Done (CSP meta tag + script/event handler stripping)
|
| 159 |
|
- |
17. ~~**[LOW]** Remove or deprecate `ImapClient::new()` legacy constructor~~ -- Done (removed)
|
| 160 |
|
- |
18. ~~**[LOW]** Defensive `.ok_or()` on email_repo.rs:129~~ -- Done
|
| 161 |
|
- |
19. ~~**[LOW]** Use `bind()` for LIMIT/OFFSET~~ -- Done (parameterized binds in task_repo.rs)
|
|
140 |
+ |
### Run 15 (2026-04-18, corrected 2026-04-22)
|
|
141 |
+ |
1. ~~**[HIGH]** Investigate test count regression~~ -- False finding. 778 tests with `--workspace`.
|
|
142 |
+ |
2. ~~**[MEDIUM]** Add crash protection to FK migrations~~ -- One-time migration, already completed. Non-issue.
|
|
143 |
+ |
3. ~~**[MEDIUM]** Add indexes for newer query patterns~~ -- Done (migration 040).
|
|
144 |
+ |
4. ~~**[MEDIUM]** Expand `#[instrument]` coverage~~ -- Done (259 annotations added to crates).
|
|
145 |
+ |
5. Add doc comment to sync_service.rs explaining format!() SQL safety pattern
|
| 162 |
146 |
|
|
| 163 |
147 |
|
### All resolved (previous audits)
|
| 164 |
|
- |
1. ~~**[Bug]** Fix `body_preview()` UTF-8 panic~~ -- already uses `.chars().take(n)` with 18 tests
|
| 165 |
|
- |
2. ~~**[Performance]** Batch dashboard stats queries~~ -- already uses single query with 6 subqueries
|
| 166 |
|
- |
3. ~~**[Clippy]** Fix `clone_on_copy` in goingson-mcp~~ -- fixed (`task_impl.rs:271`)
|
| 167 |
|
- |
4. ~~**[Testing]** Add integration tests for `search_repo`~~ -- 15 tests added
|
| 168 |
|
- |
5. ~~**[Testing]** Add integration tests for `contact_repo`~~ -- 18 tests added
|
| 169 |
|
- |
6. ~~**[Logic bug]** `list_completed_between` date filtering~~ -- `completed_at` column added (migration 031), 4 tests
|
| 170 |
|
- |
7. ~~**[Testing]** MCP server tool tests~~ -- 20 integration tests added
|
| 171 |
|
- |
8. ~~**[Testing]** Sync service tests~~ -- 21 unit tests
|
| 172 |
|
- |
9. ~~**[Testing]** Plugin API tests~~ -- 29 tests covering all exposed types
|
| 173 |
|
- |
10. ~~**[Testing]** IMAP HTML helper tests~~ -- 35 tests on pure functions
|
| 174 |
|
- |
11. ~~**[Refactor]** Convert sync service to typed errors~~ -- `Result<_, CoreError>` throughout
|
| 175 |
|
- |
12. ~~**[Refactor]** Move `sql_column()` out of core~~ -- relocated to db-sqlite
|
| 176 |
|
- |
13. ~~**[Docs]** Add `//!` docs to `smtp_client.rs`~~ -- done
|
| 177 |
|
- |
14. ~~**[Frontend]** Add section markers to `styles.css`~~ -- 60 numbered sections with TOC
|
| 178 |
|
- |
|
| 179 |
|
- |
New items filed in `docs/todo/todo.md`:
|
| 180 |
|
- |
- ~~Add unit tests for JMAP module (854 LOC, 0 tests)~~ -- 73 tests added
|
| 181 |
|
- |
- ~~Add tests for OAuth callback server (309 LOC, 0 tests)~~ -- 59 tests added
|
| 182 |
|
- |
- ~~Add tests for plugin registry hot-reload (300 LOC, 2 tests)~~ -- 32 tests added
|
| 183 |
|
- |
- Add doc comment to sync_service.rs explaining format!() SQL safety pattern
|
| 184 |
|
- |
- ~~LLM integration: use typed errors instead of Result<String, String>~~ -- typed LlmError enum added
|
| 185 |
|
- |
- Verify applying_remote flag cleared on startup (crash recovery)
|
| 186 |
|
- |
|
| 187 |
|
- |
### Security Deep Dive (2026-03-13) — Complete (2/2)
|
| 188 |
|
- |
|
| 189 |
|
- |
- **Path traversal in delete_backup:** `commands/export.rs` — `delete_backup()` now uses `canonicalize()` on both backup directory and target path, then verifies `canonical_path.starts_with(&canonical_backup_dir)`
|
| 190 |
|
- |
- **Export path validation:** `commands/export.rs` — `validate_export_path()` helper added, rejects `..` components; called at top of `export_json`, `export_tasks_csv`, `export_events_ics`, and `restore_backup`
|
| 191 |
|
- |
|
| 192 |
|
- |
### JS Audit Remediation (2026-03-11) — Complete (14/14)
|
| 193 |
|
- |
|
| 194 |
|
- |
All JS audit findings resolved:
|
| 195 |
|
- |
- **Critical (2):** escapeAttr() on 25 onclick handlers across 7 files, escapeHtml() on backend labels in innerHTML
|
| 196 |
|
- |
- **Medium (6):** Event status computation moved to Rust (`get_event_status_indicator` command, pre-computed EventResponse fields), project form dedup (delegated to tasks.openNewForProject/events.openNewForProject), state mutation migration (16 fixes to GoingsOn.state.set()), email account form dedup (buildAccountFormHtml()), IMAP/SMTP error escaping
|
| 197 |
|
- |
- **Low (6):** Dead matchesFilters() removed, window.GO alias removed, dynamic version via Tauri app.getVersion(), confirm() → confirmDelete() (5 calls), contacts filter state migrated to GoingsOn.state, 100ms sleep removed
|
|
148 |
+ |
- ~~Wire up `Validate::validate()` in command layer~~ -- Done
|
|
149 |
+ |
- ~~Sanitize HTML email body in `open_email_in_browser`~~ -- Done
|
|
150 |
+ |
- ~~Remove `ImapClient::new()` legacy constructor~~ -- Done
|
|
151 |
+ |
- ~~Defensive `.ok_or()` on email_repo.rs:129~~ -- Done
|
|
152 |
+ |
- ~~Use `bind()` for LIMIT/OFFSET~~ -- Done
|
|
153 |
+ |
- ~~Fix `body_preview()` UTF-8 panic~~ -- already safe
|
|
154 |
+ |
- ~~Batch dashboard stats queries~~ -- already optimized
|
|
155 |
+ |
- ~~Add integration tests for search_repo, contact_repo~~ -- Done
|
|
156 |
+ |
- ~~Fix `list_completed_between` date filtering~~ -- Done
|
|
157 |
+ |
- ~~Sync service tests, Plugin API tests, IMAP HTML tests~~ -- Done
|
|
158 |
+ |
- ~~Convert sync service to typed errors~~ -- Done
|
|
159 |
+ |
- ~~Move `sql_column()` out of core~~ -- Done
|
|
160 |
+ |
- ~~JMAP module tests (73), OAuth tests (59), plugin registry tests (32)~~ -- Done
|
|
161 |
+ |
- ~~LLM typed errors~~ -- Done
|
|
162 |
+ |
- ~~Path traversal in delete_backup, export path validation~~ -- Done
|
|
163 |
+ |
- ~~JS Audit (14/14)~~ -- Done
|
| 198 |
164 |
|
|
| 199 |
165 |
|
---
|
| 200 |
166 |
|
|
| 210 |
176 |
|
| 2026-03-13 | ~39K | ~152 | 658 | ~16.9 | 0 | A |
|
| 211 |
177 |
|
| 2026-03-16 | 44K | ~152 | 725 | ~16.5 | 0 | A |
|
| 212 |
178 |
|
| 2026-03-18 | 44K | ~152 | 725 | ~16.5 | 0 | A |
|
| 213 |
|
- |
| 2026-03-28 | ~44K | ~152 | ~734 | ~16.7 | 0 | A |
|
| 214 |
|
- |
|
| 215 |
|
- |
---
|
| 216 |
|
- |
|
| 217 |
|
- |
## Build Verification
|
| 218 |
|
- |
|
| 219 |
|
- |
```
|
| 220 |
|
- |
cargo check --workspace PASS
|
| 221 |
|
- |
cargo test --workspace 648 passed, 0 failed, 9 ignored
|
| 222 |
|
- |
cargo clippy --workspace 0 warnings
|
| 223 |
|
- |
```
|
|
179 |
+ |
| 2026-03-28 (Run 12) | ~44K | ~152 | ~734 | ~16.7 | 0 | A |
|
|
180 |
+ |
| 2026-04-15 (Run 14) | ~64,357 | -- | ~762 | ~12 | 0 | A |
|
|
181 |
+ |
| 2026-04-18 (Run 15) | ~64,357 | -- | 338 | ~5.3 | 0 | A- |
|
|
182 |
+ |
| 2026-04-22 (Run 15 corrected) | ~64,357 | -- | 778 | ~12.1 | 0 | A |
|
| 224 |
183 |
|
|
| 225 |
184 |
|
---
|
| 226 |
185 |
|
|