Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
24dd34b
chore: normalize line endings to LF + add .gitattributes (L8 hygiene)
fyaz05 Sep 6, 2026
3066f3d
feat(P1): pinned deps + pyproject + quality CI gates + repo hygiene (…
fyaz05 Sep 6, 2026
245dec6
fix(H9): shell-free, non-destructive self-update
fyaz05 Sep 6, 2026
094ae68
feat(P2-P5): implement the FileToLink improvement plan (H2-H10, M1-M1…
fyaz05 Sep 6, 2026
0c4a2c6
test(H2, L9): pytest scaffolding + unit tier (103 tests) + integratio…
fyaz05 Sep 6, 2026
6fcff3a
refactor(H4): finish FloodWait migration (force_channel, clients) — 9…
fyaz05 Sep 6, 2026
d3dda05
recheck: close audit gaps — real fixes + permanent gates
fyaz05 Sep 6, 2026
11c75c6
audit: fix 30+ verified defects from 8-agent branch review
fyaz05 Sep 6, 2026
2dcda94
fix(security): resolve CodeQL alerts on PR diff
fyaz05 Sep 6, 2026
5c5d311
fix(security): percent-encode activation token in t.me redirect
fyaz05 Sep 6, 2026
8f9fea7
fix(security): constant-prefix concat for activate redirect
fyaz05 Sep 6, 2026
2db0c3b
audit: 8-agent second-pass fixes — verified defects + leanness
fyaz05 Sep 6, 2026
88815ff
fix(critical): naive/aware datetime crash on token activation + malfo…
fyaz05 Sep 6, 2026
855b775
fix(major): review findings across self-heal, gates, breaker, boot an…
fyaz05 Sep 6, 2026
42fd3a8
fix(infra): Makefile tabs, hash-pinned Docker install, CI sync gates …
fyaz05 Sep 6, 2026
43914ee
test: preflight chain, env-layer precedence, self-heal + transport re…
fyaz05 Sep 6, 2026
b5e83fb
fix(data): TTL backfill via supported _id-paged batches + lifecycle i…
fyaz05 Sep 6, 2026
78c02e5
fix(security): close raw-path access-log sink, drop capability-hash l…
fyaz05 Sep 6, 2026
4126b07
refactor(lean): finish dead-code sweep from the recheck pass
fyaz05 Sep 6, 2026
52e54cf
chore(infra/docs): hermetic test tier, CI lint scope, Makefile consis…
fyaz05 Sep 6, 2026
398e395
fix(security): single-pass path pseudonymization + regression tests
fyaz05 Sep 6, 2026
9ff46b1
build: enable mypy check_untyped_defs; fix the 5 latent defects it finds
fyaz05 Sep 6, 2026
1927e6b
docs: document the anonymous-sender deny rule (TOKEN/PRIVATE modes)
fyaz05 Sep 6, 2026
5a2cc09
style: lean comments branch-wide
fyaz05 Sep 6, 2026
d0449ea
fix(resilience): make bounded FloodWait handling actually reachable
fyaz05 Sep 7, 2026
c0815a6
fix(security): redact the bare legacy URL shape (capability-hash leak)
fyaz05 Sep 7, 2026
f5a7ff4
fix(data): converging TTL backfill + hardened index ensures + touch d…
fyaz05 Sep 7, 2026
3f83f89
fix(server): 503 on Mongo brownout, constant 503 bodies, deduped ladders
fyaz05 Sep 7, 2026
5d1fb36
fix(bot): owner guard, safe deletes, accurate batch summary, misc dea…
fyaz05 Sep 7, 2026
d4dac03
build(deps): drop the dead shortener-cf extra; correct floors and com…
fyaz05 Sep 7, 2026
211ac39
fix(infra): PR smoke builds, SHA-pinned actions, pinned uv, gate parity
fyaz05 Sep 7, 2026
63d0716
fix(review): apply branch review + leanness audit findings
fyaz05 Sep 17, 2026
05fa722
docs(template): ThunderGo player UX port + doc truth sweep
fyaz05 Sep 17, 2026
9277806
fix(gates): owner bypasses everything, including force-sub
fyaz05 Sep 18, 2026
dbcdb12
feat(bot): ThunderGo message takes (8 items)
fyaz05 Sep 18, 2026
b94bd6c
feat(http): disposition split, error-header uniformity, broadcast res…
fyaz05 Sep 18, 2026
1ee74bd
feat(admin): listauth pagination, image attestations
fyaz05 Sep 18, 2026
4c47619
test(player): pin cinema UI JS contract
fyaz05 Sep 18, 2026
3b4b9a3
style: trim comments to load-bearing lines
fyaz05 Sep 18, 2026
9b1591a
feat(safe-batch): embeds, tuning docs, deploy manifests, property/lea…
fyaz05 Sep 18, 2026
90e6451
fix(tokens): fail closed on legacy/corrupt expires_at, no migration n…
fyaz05 Sep 18, 2026
886b5aa
fix(ci): satisfy locked mypy 2.3.1 (InlineKeyboardButtonBuy, bytes data)
fyaz05 Sep 18, 2026
d0e70ae
fix(ci): drop provenance/sbom attestations, docker driver rejects them
fyaz05 Sep 18, 2026
3c94f92
fix: apply independent branch-audit findings (resilience, redaction, …
audit-bot Sep 18, 2026
7f714cf
style(comments): lean pass over branch changes
super-z Sep 18, 2026
ce32bda
docs: sync dep count to 7 after speedup-extra consolidation
fyaz05 Sep 18, 2026
c9d1bd5
fix(review): crash, race, XSS and consistency fixes from full-branch …
fyaz05 Sep 18, 2026
ea6203b
chore: untrack personal TODO list (stays local, not for merge)
fyaz05 Sep 18, 2026
ac77fc0
fix(update): recover orphaned config backup before early returns
fyaz05 Sep 19, 2026
80896a9
fix(deploy): merge-ready docs and ignore rules
fyaz05 Sep 19, 2026
30fb7d3
Merge origin/main into feat/improvement-plan
fyaz05 Oct 16, 2026
5c5a4b2
fix(deps): clear the pip-audit gate and unblock Windows installs
fyaz05 Oct 16, 2026
58c2fdc
chore(ci): count distinct direct dependencies, not manifest lines
fyaz05 Oct 16, 2026
dbe97b6
fix(gates): ban gate fails closed for no-sender messages
fyaz05 Oct 16, 2026
0b0d71c
fix(touch): re-merge buffered touches when the flush is cancelled
fyaz05 Oct 16, 2026
3bf0cdb
fix(deploy): bound shutdown to one budget and give containers room
fyaz05 Oct 16, 2026
7c5f731
docs: document the platform-conditional speedup extra in AGENTS.md
fyaz05 Oct 16, 2026
6b13b21
fix(deploy): keep a floor under each shutdown step
fyaz05 Oct 16, 2026
18ddda2
fix(db): scale users.id dedup and stop one index aborting the rest
fyaz05 Oct 16, 2026
0157ff7
fix(limiter): correct the RPS knob warning and update the queue notic…
fyaz05 Oct 16, 2026
ae007a6
fix(bot): escape links, gate force-sub by status, and page /listauth …
fyaz05 Oct 16, 2026
75e440e
fix(ingest): outlive slow copies, keep the updater booting, probe the…
fyaz05 Oct 16, 2026
fcb72c6
fix(review): guard dedup against missing ids and tidy a failed client…
fyaz05 Oct 16, 2026
d414bb8
test(review): pin charge-at-exec, the token CAS predicate and log esc…
fyaz05 Oct 16, 2026
f564c3e
chore(review): remove unreachable code and tautological tests
fyaz05 Oct 16, 2026
1a0ed23
docs: correct deploy, env and licence claims against the code
fyaz05 Oct 16, 2026
dd1f8b3
fix(http): stop rejecting valid multi-range requests, harden non-posi…
fyaz05 Oct 16, 2026
f268391
fix(rpc): bound the priority starvation, pin the media budget contract
fyaz05 Oct 16, 2026
0c6cff7
fix(review): two regressions an independent review caught in my own f…
fyaz05 Oct 16, 2026
d36ea13
docs: make the fairness comment accurate for both tiers
fyaz05 Oct 16, 2026
227b748
fix(bot): the two cleanups I owed, plus a shutdown bug the e2e test f…
fyaz05 Oct 16, 2026
1b0d46c
test(ci): catch a test that the marker filter silently excludes
fyaz05 Oct 16, 2026
3bfb74e
fix(bot): chunk batch links by rendered length, not by count
fyaz05 Oct 16, 2026
36a3d9b
fix(template): stop the CDN fallback from overriding the real theme
fyaz05 Oct 16, 2026
9fb94a1
fix(server): bound the vault RPC behind the legacy /watch preview
fyaz05 Oct 16, 2026
3eb61b6
test(logger): pin redaction on JsonFormatter too, not just the plain one
fyaz05 Oct 16, 2026
93eb853
fix(data): a failed bulk touch was silently losing every delta
fyaz05 Oct 16, 2026
334de29
chore(dev): make the fast loop explicit instead of folklore
fyaz05 Oct 16, 2026
d01908b
fix(server): close the log flood that load shedding opened
fyaz05 Oct 16, 2026
e509a20
fix(ingest): stop one contended file from parking the executor pool
fyaz05 Oct 16, 2026
12a3933
fix(admin): stop one failed page from truncating /listauth
fyaz05 Oct 16, 2026
b8a778e
test: pin three checks that passed for the wrong reason
fyaz05 Oct 16, 2026
8a6bfc2
fix(shutdown): fit the PaaS grace period, and stop cutting healthy stops
fyaz05 Oct 16, 2026
1e5051b
fix(stream): reclaim slots from stalled readers, pace batches by real…
fyaz05 Oct 16, 2026
adf631e
fix: the remaining test defects and code minors from the review round
fyaz05 Oct 16, 2026
36b868f
docs: correct the claims that no longer match the code
fyaz05 Oct 16, 2026
52208f8
fix(shutdown): scale the clients cap on the boot-failure paths too
fyaz05 Oct 16, 2026
48f28ff
docs: the fast-loop table was measuring a smaller suite
fyaz05 Oct 16, 2026
9427f5c
docs: record the four review items that turned out to need no change
fyaz05 Oct 16, 2026
85dd747
fix: an adversarial review found five defects in the last five commits
fyaz05 Oct 16, 2026
437fc32
fix: close the last two review findings -- one release closure, live …
fyaz05 Oct 16, 2026
74119e6
docs: record the three contracts this branch changed, and re-measure …
fyaz05 Oct 16, 2026
dd6395b
fix: a second review round found three more defects, two of them mine…
fyaz05 Oct 16, 2026
fb74b02
fix: NAME silently selects the Mongo database, and the docs said othe…
fyaz05 Oct 16, 2026
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
37 changes: 37 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
.git
.gitignore
.gitattributes
.github
.venv
.vscode
__pycache__
*.py[cod]
.pytest_cache
.ruff_cache
.mypy_cache
*.session*
**/logs/
tests/
docs/
htmlcov/
.coverage
README.md
CONTRIBUTING.md
SECURITY.md
Makefile
config.env
config.env.local
config.env.bak
config.env.tmp
*.tmp
AGENTS.md
uv.lock
requirements.txt
# build/infra files the runtime image never reads
pyproject.toml
scripts/
config_sample.env
render.yaml
app.json
heroku.yml
docker-compose.yml
11 changes: 11 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Normalize all text files to LF in the repository and working tree.
* text=auto eol=lf

# Binary assets
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.docx binary
*.session binary
27 changes: 27 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Dependabot cannot regenerate uv.lock: after each pip PR, run
#
# uv lock && uv export --frozen --no-dev --hashes -o requirements.lock
#
# and push both lockfiles to the PR branch, or CI's `uv lock --check` and the
# requirements.lock export-diff gate will fail. These PRs are expected to be
# red until that human step is done -- see the `lockfiles-stale` label.
version: 2
updates:
- package-ecosystem: pip
directory: "/"
labels:
- lockfiles-stale
schedule:
interval: weekly
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
- package-ecosystem: docker
directory: "/"
schedule:
interval: weekly
- package-ecosystem: pre-commit
directory: "/"
schedule:
interval: weekly
26 changes: 0 additions & 26 deletions .github/workflows/dockerize.yml

This file was deleted.

165 changes: 165 additions & 0 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
name: Quality Gates

on:
push:
branches: [main]
pull_request:
workflow_dispatch:

permissions:
contents: read

concurrency:
group: quality-${{ github.ref }}
cancel-in-progress: true

jobs:
quality:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0

- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.13"

# pinned: lock/export output format and gate semantics must not drift
# between commits (dependabot bumps this like any other dependency)
- name: Install uv
run: python -m pip install "uv==0.12.5"

# Install the hash-pinned lockfile (runtime + dev) so CI tests and audits
# the exact dependency graph that ships, not a fresh pip resolution.
- name: Install dependencies (locked, hash-pinned)
run: uv sync --frozen --group dev

- name: Lockfile is current with pyproject (uv.lock must never drift)
run: uv lock --check

- name: requirements.txt is in sync with pyproject (two sources of truth must agree)
run: |
uv run --locked python - <<'PY'
import sys, tomllib
deps = {d.strip() for d in tomllib.load(open("pyproject.toml", "rb"))["project"]["dependencies"]}
listed = {l.strip() for l in open("requirements.txt") if l.strip() and not l.startswith("#")}
if deps != listed:
print("pyproject:", sorted(deps))
print("requirements.txt:", sorted(listed))
sys.exit("requirements.txt drifted from pyproject [project.dependencies]")
PY

- name: requirements.lock is in sync with uv.lock (Docker consumes this)
run: |
uv export --frozen --no-dev --hashes -o /tmp/requirements.lock.check
# uv embeds the export command in the header; compare content only
diff -u <(grep -v '^#' requirements.lock) <(grep -v '^#' /tmp/requirements.lock.check)

- name: Ruff (lint + format check)
run: |
uv run ruff check Thunder/ update.py tests/ scripts/
uv run ruff format --check Thunder/ update.py tests/ scripts/

- name: Mypy (blocking)
run: uv run mypy Thunder update.py scripts/

- name: Unit tests
run: uv run pytest --cov=Thunder --cov-report=term-missing --cov-fail-under=35

# addopts = "-m unit" silently deselects any test that forgets its marker:
# an unmarked test is collected but never runs, and nothing else notices.
#
# The counts are grepped out of pytest's own summary rather than taken from
# `tail -1 | cut -d' ' -f1`: that pipeline captures whatever happens to be
# last on stdout, so any change to pytest's trailing output makes BOTH sides
# capture the same garbage, the comparison passes, and the gate silently
# stops guarding anything.
- name: No test is silently excluded by the marker filter
run: |
set -o pipefail
UNIT=$(uv run pytest -m unit --collect-only -q | grep -oE '[0-9]+/[0-9]+ tests collected' | tail -1)
ALL=$(uv run pytest -m "not integration" --collect-only -q | grep -oE '[0-9]+/[0-9]+ tests collected' | tail -1)
echo "unit=$UNIT all-non-integration=$ALL"
if [ -z "$UNIT" ] || [ -z "$ALL" ]; then
echo "::error::Could not parse the collection summary from pytest. Fix this step rather than letting it pass vacuously."
exit 1
fi
if [ "$UNIT" != "$ALL" ]; then
echo "::error::A test is missing its @pytest.mark.unit and addopts=-m unit is excluding it. Mark it, or move it to the integration tier."
exit 1
fi

# Audit the locked env: `-r requirements.txt` (direct pins only) never covered transitives.
- name: pip-audit (locked environment incl. transitives)
run: uv run pip-audit

- name: Bandit (medium-or-higher severity)
run: uv run bandit -c pyproject.toml -r Thunder update.py -ll --skip B101

- name: Vulture (dead-code gate)
run: uv run vulture Thunder update.py --min-confidence 80

- name: Dependency count gate (leanness is permanent)
run: |
# distinct package names, so a conditional platform marker for the same
# package (pyrofork[speedup] / pyrofork) does not inflate the count
COUNT=$(grep -vE '^[[:space:]]*(#|$)' requirements.txt \
| sed -E 's/[[:space:]]*;.*$//; s/[[:space:]]*\[.*\]//; s/==.*$//' \
| tr -d '\r' | sort -u | wc -l)
echo "Direct runtime deps: $COUNT"
if [ "$COUNT" -gt 7 ]; then
echo "::error::Direct dependency count increased beyond the agreed 7; justify in the PR or remove."
exit 1
fi

docker:
# Smoke-build on PRs (no secrets); publish only from main pushes so a
# feature branch can never overwrite fyaz05/thunder:latest.
if: github.repository == 'fyaz05/FileToLink' && (github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/main'))
needs: quality
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0

- name: Login to Docker Hub
if: github.event_name == 'push'
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
username: fyaz05
password: ${{ secrets.DOCKER_TOKEN }}

- name: Build and Push
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
with:
context: .
push: ${{ github.event_name == 'push' }}
# Attestations stay off: the default docker driver rejects them even
# on no-push smoke builds; revisit with a containerd-backed builder.
tags: |
fyaz05/thunder:latest
fyaz05/thunder:${{ github.sha }}

integration:
# token CAS / ingest-claim atomicity is only provable against a real
# MongoDB, and this tier never ran in CI before
needs: quality
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0

- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.13"

- name: Install uv
run: python -m pip install "uv==0.12.5"

- name: Install dependencies (locked, incl. testcontainers)
run: uv sync --frozen --group dev

- name: Integration tests (real MongoDB via testcontainers)
run: uv run pytest -m integration
env:
TEST_INTEGRATION: "1"
66 changes: 38 additions & 28 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,28 +1,38 @@
*.py[cod]
*$py.class
*.so
.venv/
.Python
config.env
log.text
.vscode/
**/__pycache__/
*.session
*.session-journal
*.session-shm
*.session-wal
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
*.py[cod]
*$py.class
*.so
.venv/
.Python
config.env
config.env.local
.coverage
htmlcov/
.pytest_cache/
.ruff_cache/
.mypy_cache/
log.txt
config.env.tmp
config.env.bak
*.tmp
Thunder/logs/
.vscode/
**/__pycache__/
*.session
*.session-journal
*.session-shm
*.session-wal
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
13 changes: 13 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.16.6
hooks:
- id: ruff-check
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
Loading
Loading