Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
132d76a
doc(analytics): refine 031 living plan with pre-implementation decisions
bryangingechen Mar 25, 2026
38f73a0
feat(site_analytics): A1 — app scaffold, AnalyticsPageView model, set…
bryangingechen Mar 25, 2026
c4bc2cd
feat(site_analytics): A2 — ingestion endpoint, hashing, bot-filter, t…
bryangingechen Mar 25, 2026
7617645
feat(site_analytics): A3 — daily aggregate model, service, Celery task
bryangingechen Mar 25, 2026
b178e7f
feat(site_analytics): A4 — monthly aggregate model, prune task, beat …
bryangingechen Mar 25, 2026
362db4d
feat(site_analytics): A5 — admin registrations for all three models
bryangingechen Mar 25, 2026
8ce650c
feat(site_analytics): A6 — empty-UA hardening flag
bryangingechen Mar 25, 2026
d3b0555
feat(site_analytics): add CORS support; convert 031 living plan to fi…
bryangingechen Mar 25, 2026
e519e53
fix(dashboard): tolerate missing Dashboard keys in prs_to_list
bryangingechen Mar 25, 2026
3d329e2
doc: update queueboard_main_workflow.md
bryangingechen Mar 25, 2026
6a9e780
feat(dashboard): inject analytics tracking snippet into generated pages
bryangingechen Mar 25, 2026
9d80bf0
doc: expand queueboard_main_workflow.md with context and secrets table
bryangingechen Mar 25, 2026
81112e4
feat(dashboard): add privacy notice alongside analytics snippet
bryangingechen Mar 25, 2026
bc564b9
Revert "feat(dashboard): add privacy notice alongside analytics snippet"
bryangingechen Mar 25, 2026
b632cc1
feat(dashboard): add privacy notice and document disclosure rationale
bryangingechen Mar 26, 2026
bdf19d6
fix(site_analytics): pin clock in time-dependent aggregation/prune tests
bryangingechen Mar 26, 2026
e332441
feat(site_analytics): rotate visitor-hash salt monthly via DB
bryangingechen Mar 27, 2026
a85d092
doc: document site_analytics beat period settings in .env.example
bryangingechen Aug 9, 2026
58e3634
fix(dashboard): escape analytics site slug and endpoint in inline script
bryangingechen Aug 9, 2026
8fe75ac
doc(site_analytics): correct stale visitor-hash formula comment
bryangingechen Aug 9, 2026
9066243
fix(site_analytics): trust the rightmost X-Forwarded-For entry, not t…
bryangingechen Aug 9, 2026
23df6a6
feat(site_analytics): fail closed when no visitor-hash salt is config…
bryangingechen Aug 9, 2026
7f0a96d
doc(031): record the rate-limiting deferral and refresh stale privacy…
bryangingechen Aug 9, 2026
b66eeda
Merge branch 'master' into analytics-ingestion
bryangingechen Aug 31, 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
20 changes: 20 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,26 @@ ARCHIVE_RESYNC_TICK_SECONDS=600
# keeping headroom for the live sync pipeline.
ARCHIVE_RESYNC_MIN_RATE_REMAINING=2500

# Site analytics (pageview ingestion)
# Secret salt for visitor monthly hash (sha256-based; required in production).
SITE_ANALYTICS_HASH_SALT=
# Comma-separated slugs of sites allowed to post events; unknown slugs → 400.
SITE_ANALYTICS_ALLOWED_SITES=
# Raw pageview retention window in days (default 540 ≈ 18 months).
SITE_ANALYTICS_RETENTION_DAYS=540
# Reverse proxies in front of this app. X-Forwarded-For is client-controlled, so only
# this many entries from the right are trusted (Heroku's router appends exactly one).
# Set to 0 if the app is exposed directly, to ignore X-Forwarded-For entirely.
SITE_ANALYTICS_TRUSTED_PROXY_COUNT=1
# Beat period for the daily aggregation task (seconds); 0 disables the schedule.
SITE_ANALYTICS_DAILY_AGGREGATE_PERIOD_SECONDS=3600
# Beat period for the monthly aggregation task (seconds); 0 disables the schedule.
SITE_ANALYTICS_MONTHLY_AGGREGATE_PERIOD_SECONDS=86400
# Beat period for the retention pruning task (seconds); 0 disables the schedule.
SITE_ANALYTICS_PRUNE_PERIOD_SECONDS=86400
# Reject requests with an empty User-Agent (stricter bot hardening; default off).
SITE_ANALYTICS_REJECT_EMPTY_UA=0

# CI filter (opt-in allowlist)
# Set SYNCER_CI_FILTER_MODE=allowlist to enable filtering by the allow lists below.
# Substrings matched case-insensitively against CheckRun.name and StatusContext.context.
Expand Down
10 changes: 5 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Project Structure & Module Organization
- `src/queueboard/` contains the legacy Python data pipeline: GraphQL queries under `queries/`, HTML assets in `static/`, and scripts like `dashboard.py`, `process.py`, and `suggest_reviewer.py`.
- `qb_site/` hosts the Django codebase; apps live in `qb_site/{core,syncer,analyzer,api,zulip_bot}/` and share settings from `qb_site/qb_site/settings/`.
- `qb_site/` hosts the Django codebase; apps live in `qb_site/{core,syncer,analyzer,api,zulip_bot,site_analytics}/` and share settings from `qb_site/qb_site/settings/`.
- `scripts/` provides operational helpers; `test/` stores fixture JSON for dashboard regression checks; `docs/` captures architecture plans/decisions.

## Build, Test, and Development Commands
Expand Down Expand Up @@ -43,7 +43,7 @@ Notes
`set -o pipefail` / `${PIPESTATUS[0]}`, and confirm the status before trusting the output. The
same trap applies to `docker compose run ... | tail`.
- If a check "passes", confirm it actually ran. A build that dies before any test executes can
still print a plausible tail; scan for the step markers (`[1/12]` … `[12/12]`) or a test count,
still print a plausible tail; scan for the step markers (`[1/13]` … `[13/13]`) or a test count,
not just the absence of a traceback.
- Exercise dashboard generation with the provided fixtures via `uv run python -m queueboard.dashboard ...`; capture `before/` and `after/` HTML snapshots when comparing layout changes.
- Keep unit tests colocated (`test_*.py`); expand `src/queueboard/test_state_evolution.py` or add pytest modules under the relevant Django app (`qb_site/<app>/tests/`).
Expand All @@ -58,9 +58,9 @@ Notes
| 4 | `python scripts/validate_backup_policy.py` |
| 5 | `python qb_site/manage.py check` |
| 6 | `python qb_site/manage.py makemigrations --dry-run --check` |
| 7–12 | `env DJANGO_SETTINGS_MODULE=qb_site.settings.ci python qb_site/manage.py test <app>` for `core`, `syncer`, `analyzer`, `api`, `zulip_bot`, `console` |
| 7–13 | `env DJANGO_SETTINGS_MODULE=qb_site.settings.ci python qb_site/manage.py test <app>` for `core`, `syncer`, `analyzer`, `api`, `zulip_bot`, `console`, `site_analytics` |

Steps 4–12 run under `docker compose run --rm --no-deps -T web …` against cached images. Report
Steps 4–13 run under `docker compose run --rm --no-deps -T web …` against cached images. Report
which steps ran, by number.
- Document any manual data validation or backfill steps in your PR description so reviewers can reproduce the checks.

Expand Down Expand Up @@ -96,7 +96,7 @@ Notes
## Keeping AGENTS.md Files Updated
- Every directory with significant logic has its own `AGENTS.md` (mirrored as `CLAUDE.md`).
Current locations: root, `qb_site/`, `qb_site/syncer/`, `qb_site/analyzer/`,
`qb_site/zulip_bot/`, `qb_site/console/`, `src/queueboard/`.
`qb_site/zulip_bot/`, `qb_site/console/`, `qb_site/site_analytics/`, `src/queueboard/`.
- When you add, rename, or remove management commands, Celery tasks, key services, or
directory structure, update the relevant `AGENTS.md` in the same commit/PR.
- When you add a new app or significant sub-directory, create a matching `AGENTS.md`
Expand Down
Loading