ინტერფეისის სეგრეგაცია (ISP)
internal/api/store_interfaces.go: 7 სეგრეგირებული ინტერფეისი, რომლებიც ცვლის 100-მეთოდიან Store მონოლითს.EmailReader (31 მეთოდი), EmailWriter (41), AccountStore (17), FolderStore (8), EntityStore(თარგები/იარლიყები/წესები/კონტაქტები/ჯგუფები/მომხმარებლები/კომენტარები), AdminStore (ადმინ/AI/MCP/ვებჰუკები/Telegram), SystemStore (მიგრაციები/FTS/რიგი/სამუშაოები).Store ინტერფეისი შენარჩუნებულია უკუთავსებადობისთვის.internal/api/handlers.go: Handler ახლა ავლენს სეგრეგირებულ ველებს (Emails, Writer, Accounts, Folders, Entities, Admin, System) მემკვიდრეობით Store-თან ერთად.Single Responsibility (SRP) — საცავის მონოლითების გაყოფა
internal/store/postgres/: storage.go 3980 → 561 სტრიქონი. ახალი ფაილები: emails.go (2020), accounts.go (387), org.go (396), integrations.go (440), folders.go (137), labels_tags.go (82), attachments.go (55).internal/store/sqlite/: სარკისებური გაყოფა (4386 → 465 სტრიქონი).internal/store/shared/crypto.go: გამოყოფილია EncryptPassword / DecryptPassword ორივე იმპლემენტაციისთვის.WithTx() დაემატა ორივე postgres.Storage და sqlite.Storage-ს ატომური ფაილთაშორისი ტრანზაქციებისთვის.DRY — დუბლირების აღმოფხვრა
internal/mime/qp.go: გაერთიანებულია DecodeQuotedPrintable — ამოღებულია 3 დუბლიკატი იმპლემენტაცია (api, sync, მკვდარი კოდი handlers.go-ში).internal/api/email_action_handlers.go: toggleEmail ჰელპერი — 3 toggle ფუნქცია ჩანაცვლებულია ერთარგუმენტიანი გადაფუთვებით.internal/store/postgres/email_columns.go: emailColumns / emailColumnsPrefixed კონსტანტები — 10 დუბლირებული სვეტების სია → 2 კონსტანტა.OCP — Registry Pattern
internal/api/email_action_registry.go: emailActions map (11 actions) registered in init(). HandleEmail switch-case replaced with O(1) map lookup. Thread-safe: write-once in init(), read-only at request time.Dependency Inversion (DIP)
internal/sync/interfaces.go: CASStore interface (1 method) + AIProvider interface (3 methods) defined in consuming package.Fetcher and Manager now depend on interfaces instead of concrete *attachment.CASStorage and *ai.Gateway. Testable without real file-system or AI.YAGNI Cleanup
internalDecodeQP + unhexDigit (dead code, −32 lines).BulkToggleFlagEmails from interface + both implementations + mock (−28 lines).sqlite.Storage.Query/QueryRow/Exec — raw SQL access not in contract (−15 lines).storage.go.bak* (−775KB).internal/sentry/ (new package): Init(), IsEnabled(), Flush(), CaptureException(), Recover(), Go() — all no-ops when SENTRY_DSN is unset, zero overhead.cmd/server/main.go: sentry.Init() after log setup, defer sentry.Flush() on shutdown, CaptureException in HTTP panic recovery.internal/api/errors.go: WriteInternalError → sentry.CaptureException(err) — all 500 errors reported with request context.internal/sync/imap_connect.go: reportProvisionalSyncError → sentry.CaptureException(err) — IMAP/auth errors tracked per account.@sentry/nextjs): sentry.client.config.ts + sentry.server.config.ts + sentry.edge.config.ts — conditional init via NEXT_PUBLIC_SENTRY_DSN.next.config.ts: withSentryConfig() — conditional wrapping, source maps upload at build time (SENTRY_AUTH_TOKEN).src/app/[locale]/error.tsx + src/app/global-error.tsx — Sentry.captureException(error) SSR/CSR წარუმატებლობისას.sentry.client.config.ts: tracePropagationTargets: [/^\/api/] — ავტომატურად ავრცელებს sentry-trace სათაურს ბექენდზე, აკავშირებს ფრონტენდის შეცდომებს ბექენდის ტრეისებთან.SENTRY_DSN / SENTRY_ENVIRONMENT / NEXT_PUBLIC_SENTRY_DSN ცვლადებით. ფრონტენდის Dockerfile იღებს SENTRY_ORG / SENTRY_PROJECT / SENTRY_AUTH_TOKEN როგორც build ARG-ები source map-ის ატვირთვისთვის.internal/api/middleware/auth.go: extractToken() პრიორიტეტი შეიცვალა — Authorization სათაური (localStorage) ახლა მოწმდება before httpOnly ქუქის წინ.localStorage-ში სინქრონულად და უგზავნის მას Authorization სათაურით.