mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
refactor(server/db): delegate messages + reactions to dbgen; finalize D2
messages/reactions: CreateMessage, GetMessage (messageFromGen mapper),
EditMessage (EditMessageContent), DeleteMessage (SoftDeleteMessage),
AddReaction, RemoveReaction, GetReactions (GetReactionCounts),
SetMessagePinned, UpdateReadState. Retired the obsolete scanMessage.
Kept raw by design (no clean sqlc mapping): FTS search, cursor-paginated
GetMessages/GetMessagesForAPI/GetPinnedMessages, getReactionsBatch,
GetChannelUnreadCounts, GetLatestMessageID (interface{} MAX result).
D2 status: 97 db.DB methods now delegate to dbgen across every domain;
43 raw d.sqlDB calls remain by design (db.go passthroughs, migrate.go,
variable-length IN(), FTS, multi-statement transactions, PRAGMA/VACUUM).
sqlc is no longer dead code — audit A-2026-07-05 resolved. Full rationale
+ the kept-raw list in docs/plans/sqlc-adoption.md.
Verified: go build ./...; go test ./db ./service ./ws ./auth; sqlc-verify;
gofmt + go vet clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UA17KPvqGBX3XbXYnMf1rA
This commit is contained in:
@@ -18,7 +18,7 @@ accepted-risk note before the beta gate. MEDIUMs are folded into the backlog
|
||||
| A-2026-07-02 | HIGH | Client HTTP path accepts any TLS certificate (`allowSelfSigned` hardcoded; no TOFU pinning, unlike WS/LiveKit paths) | CLOSED 2026-07-19 — HTTP TOFU proxy implemented (`http_proxy.rs` + `httpProxy.ts`); REST path now cert-pinned, `acceptInvalidCerts` removed |
|
||||
| A-2026-07-03 | HIGH | Reference specs (api.md / protocol.md / schema.md) frozen at 2026-04-02; systemic drift incl. whole undocumented subsystems (voice E2EE, plugins) | CLOSED 2026-07-19 — full refresh of api.md/protocol.md/schema.md landed (all §2 fix-spec items); keep-current-per-PR rule now applies |
|
||||
| A-2026-07-04 | HIGH | Client unit test suite "KNOWN RED" and non-blocking in CI; E2E never gated | OPEN — supersedes prior #11's scope |
|
||||
| A-2026-07-05 | MEDIUM | Dead sqlc layer: `Server/db/dbgen/` (~3.5k LOC) generated + CI-verified but imported by nothing | IN PROGRESS 2026-07-19 — `dbgen` now wired into `db.DB` and load-bearing (blocks/lockouts/roles delegate); no longer dead. Remaining domains tracked in [plans/sqlc-adoption.md](plans/sqlc-adoption.md) |
|
||||
| A-2026-07-05 | MEDIUM | Dead sqlc layer: `Server/db/dbgen/` (~3.5k LOC) generated + CI-verified but imported by nothing | RESOLVED 2026-07-19 — `dbgen` wired into `db.DB`; 97 methods across all domains delegate to it (no longer dead). Remaining raw queries (variable IN / FTS / tx) tracked in [plans/sqlc-adoption.md](plans/sqlc-adoption.md) |
|
||||
| A-2026-07-06 | MEDIUM | Three coexisting DB-access styles (raw `*db.DB` in api/admin/ws, `store.Store` under service, dead dbgen) | DECIDED 2026-07-19 — single data layer: sqlc-backed db pkg, remove store/ (D2+D3) (see [plans/audit-2026-07-19-decisions.md](plans/audit-2026-07-19-decisions.md)) |
|
||||
| A-2026-07-07 | MEDIUM | Channel-visibility logic duplicated across ~4 sites with "must mirror" comments | OPEN |
|
||||
| A-2026-07-08 | MEDIUM | Protocol constants on both sides claim generation from `docs/protocol-schema.json`, which does not exist in the repo | CLOSED 2026-07-19 — codegen implemented: `docs/protocol-schema.json` + `Server/scripts/genprotocol` + `make protocol-verify` CI gate |
|
||||
|
||||
@@ -15,7 +15,7 @@ here (and the audit's closure table) as items land.
|
||||
| # | Decision point | Audit ID | Decision | Status |
|
||||
|---|----------------|----------|----------|--------|
|
||||
| D1 | `announcement` channel type (documented + offered by admin API, rejected by DB triggers) | A-2026-07-01 | **Implement end-to-end**: migration to allow the type, posting-permission semantics, admin support, client rendering, spec updates. Not a doc-strip — this becomes a real feature. | Planned (not yet greenlit to start) |
|
||||
| D2 | Data-layer direction (raw SQL vs dead sqlc `db/dbgen` vs `store.Store`) | A-2026-07-05 / A-2026-07-06 | **Adopt sqlc for real**: wire `db.DB` method bodies to the generated `dbgen` queries so sqlc becomes the actual, type-checked query layer. The `sqlc-verify` CI job stays and starts earning its keep. | **In progress — phase 1 done 2026-07-19**: `dbgen.Queries` wired into `db.DB`; blocks/lockouts/roles delegate (sqlc now load-bearing, no longer dead code). Remaining domains tracked in [sqlc-adoption.md](sqlc-adoption.md). |
|
||||
| D2 | Data-layer direction (raw SQL vs dead sqlc `db/dbgen` vs `store.Store`) | A-2026-07-05 / A-2026-07-06 | **Adopt sqlc for real**: wire `db.DB` method bodies to the generated `dbgen` queries so sqlc becomes the actual, type-checked query layer. The `sqlc-verify` CI job stays and starts earning its keep. | **Largely done 2026-07-19**: `dbgen.Queries` wired into `db.DB`; 97 methods across all domains delegate to sqlc (no longer dead code). ~43 raw calls remain by design (variable IN, FTS, multi-statement tx, PRAGMA/VACUUM) — tracked in [sqlc-adoption.md](sqlc-adoption.md). |
|
||||
| D3 | Fate of `Server/store/` (untested abstraction seam) | prior audit #6 | **Remove `store/`**: execute the prior audit's P4 "single data layer" direction. Services call the (sqlc-backed) `db` package directly; tests use in-memory SQLite instead of `MemStore`. | Planned (sequence with/after D2) |
|
||||
| D4 | Protocol constants sync (`message_types.go` / `protocolTypes.ts` claim a nonexistent `docs/protocol-schema.json`) | A-2026-07-08 | **Create real codegen**: commit an actual `protocol-schema.json` plus a generator that emits the Go and TS constant files (and, ideally, protocol.md's message table), making the "single source of truth" comment true. | **Implemented 2026-07-19**: `docs/protocol-schema.json` + `Server/scripts/genprotocol` + `make protocol-generate`/`protocol-verify` + CI gate. protocol.md table generation deferred to D7. |
|
||||
| D5 | Client HTTP TLS gap (`allowSelfSigned: true`, no TOFU pinning on the REST path) | A-2026-07-02 | **Next security work**: build the TOFU HTTP proxy in Rust (mirroring `ws_proxy.rs`) as the next security task — highest-priority security item. | **Implemented 2026-07-19** — `src-tauri/src/http_proxy.rs` (per-host loopback TCP→TLS tunnels, shared TOFU cert store + `cert-tofu` events) + `src/lib/httpProxy.ts`; REST/health/attachments routed through it; `acceptInvalidCerts`/`allowSelfSigned` and the `dangerous-settings` feature removed. See [http-tofu-proxy.md](http-tofu-proxy.md). |
|
||||
|
||||
+26
-18
@@ -25,27 +25,35 @@ Two mechanical frictions drive the per-domain effort:
|
||||
|
||||
## Status
|
||||
|
||||
### Phase 1 — done (2026-07-19)
|
||||
sqlc is now **load-bearing in production** (previously dead code):
|
||||
### Phase 1 + 2 — done (2026-07-19)
|
||||
sqlc is now **load-bearing in production** (previously dead code). **97 `db.DB`
|
||||
methods delegate** to `dbgen` across every domain; 43 raw `d.sqlDB` calls
|
||||
remain (the `db.go` passthrough helpers, `migrate.go`, and the intentionally
|
||||
raw queries listed below). Shared mappers live in `db/mappers.go`
|
||||
(`userFromGen`, `sessionFromGen`, `roleFromGen`, `ptrI64toI`/`ptrItoI64`,
|
||||
`b2i64`, `strToNullPtr`, `derefString`).
|
||||
|
||||
| Domain | Methods delegated | Notes |
|
||||
|--------|-------------------|-------|
|
||||
| blocks (`block_queries.go`) | BlockUser, UnblockUser, IsBlocked, IsEitherBlocked, ListBlockedUsers | Added `ListBlockedUsers` query. Empty result now `[]int64{}` (matches MemStore; was `nil`). |
|
||||
| lockouts (`lockout_queries.go`) | UpsertLockout, LoadActiveLockouts, CleanupExpiredLockouts, DeleteLockout | Time formatting/parsing kept in the wrapper. |
|
||||
| roles (`role_queries.go`) | GetRoleByID, ListRoles, GetRoleForUser | Shared `roleFromGen` mapper. `GetUserWithRole` (joined User+Role) stays raw. |
|
||||
Delegated domains: blocks, lockouts, roles, users + sessions, invites, profile,
|
||||
attachments, voice, dm (simple ops), channels + permission overrides, admin
|
||||
(users/settings/audit/counts), messages (create/get/edit/delete/reactions/
|
||||
pins/read-state).
|
||||
|
||||
### Phase 2 — remaining domains (raw SQL still, each survives D3)
|
||||
Convert with the same pattern; add missing queries + a `fromGen` mapper where
|
||||
needed. Rough order by mapping simplicity:
|
||||
### Deliberately kept raw (no clean sqlc mapping)
|
||||
- **Variable-length `IN(...)`** (sqlc can't express): `GetAttachmentsByMessageIDs`,
|
||||
`LinkAttachmentsToMessage`, `GetChannelTypes`.
|
||||
- **FTS / dynamic WHERE / cursor pagination**: `GetMessages`, `SearchMessages`,
|
||||
`SearchMessagesInChannels`, `GetMessagesForAPI`, `GetPinnedMessages`,
|
||||
`getReactionsBatch`, `GetChannelUnreadCounts`, `GetLatestMessageID`
|
||||
(sqlc types the `MAX()` result as `interface{}`).
|
||||
- **Multi-statement transactions**: `GetOrCreateDMChannel` (serializable tx),
|
||||
`GetUserDMChannels` (aggregate), `GetDMRecipient`, `CreateOwnerIfEmpty`,
|
||||
`CreateUserWithInvite`, `GetUserWithRole`.
|
||||
- **Non-query SQL**: `GetServerStats` PRAGMAs, `BackupToSafe` (`VACUUM INTO`),
|
||||
`AdminCreateChannel`, `CountChannelVoiceUsers`, `account.go`.
|
||||
|
||||
- **Simple/exec-heavy:** invites (`invite_queries.go`), profile
|
||||
(`profile_queries.go`), attachments (`attachment_queries.go`).
|
||||
- **Model-mapped reads:** sessions (`auth_queries.go`), users
|
||||
(`auth_queries.go` — `GetUserByID`/`GetUserByUsername`/`ListAllUsers`),
|
||||
channels (`channel_queries.go`), voice (`voice_queries.go`),
|
||||
dm (`dm_queries.go`), admin/settings (`admin_queries.go`).
|
||||
- **Complex/joined:** messages (`message_queries.go` — search, cursor
|
||||
pagination, reactions), `GetUserWithRole`, `GetServerStats`.
|
||||
These are candidates for follow-up (add `sqlc.arg`/`sqlc.slice` queries or
|
||||
accept they stay raw), but none block the D2 goal: `dbgen` is no longer dead
|
||||
and owns the SQL for the overwhelming majority of the data layer.
|
||||
|
||||
### Out of scope for D2
|
||||
- `store/` event + plugin SQL (`store/sqlite_events.go`, plugin store) — these
|
||||
|
||||
Reference in New Issue
Block a user