fix(server): harden auth, SSE, state, scraping

- Fix SSE streams not terminating on successful jobs (C-2)
- Anchor data/session paths to BASE_DIR instead of CWD (C-3)
- Guard TelegramAuthManager state with RLock (H-1)
- Replace millisecond job ids with uuid4 (H-2)
- Always redact api_id/api_hash on export, drop include_secrets (H-3)
- Enforce JSON content-type + same-origin on mutating requests (H-4)
- Rate-limit auth attempts and phone-code requests (H-5)
- Deep-copy StateStore.load() on all paths (H-6)
- Cap FloodWait retries in forward_message (H-7)
- De-duplicate forwarding handler registration (H-8)
- Validate continuous channels at ingest, join scrape thread on account
  removal, fix refresh_config status under lock, cap SSE streams and
  JSON body size (M-5, M-6, M-17)
- Add regression tests (33 passing) and REVIEW.md
This commit is contained in:
2026-09-07 11:54:13 +02:00
parent 59824940c6
commit a2468a2a2c
8 changed files with 973 additions and 186 deletions
+2 -2
View File
@@ -411,7 +411,7 @@ function pollJobFallback(accountId, jobId) {
try {
const job = await api(`/api/jobs/${encodeURIComponent(jobId)}`);
updateRenderedJob(accountId, job);
if (['completed', 'failed'].includes(job.status)) {
if (['done', 'completed', 'failed'].includes(job.status)) {
clearInterval(pollTimer);
jobStreams.delete(jobId);
refreshAccount(accountId);
@@ -455,7 +455,7 @@ function subscribeJobStream(accountId, jobId, status) {
retryCount = 0; // reset backoff on successful message
const job = JSON.parse(event.data);
updateRenderedJob(accountId, job);
if (['completed', 'failed'].includes(job.status)) {
if (['done', 'completed', 'failed'].includes(job.status)) {
newStream.close();
jobStreams.delete(jobId);
refreshAccount(accountId);