Commit graph

39 commits

Author SHA1 Message Date
4e0b8f0d0a
interal/api: replace liner array scan with hashmap lookup in domain validation
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Iac969e7dc6e4ca3f93410fccac1995636a6a6964
2026-03-02 22:38:22 +03:00
987ddd92cc
internal/aggregate: make shutdown context-aware proper goroutine sync
Adds `WaitGroup` to track background goroutine and make Shutdown respect
context deadlines

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ia7f074725717f037412dacb93e34105b6a6a6964
2026-03-02 22:38:21 +03:00
de959ec22b
nix: configure default formatter for nix fmt
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ia75cd29276e4eed2d57a37e02281d48b6a6a6964
2026-03-02 22:38:20 +03:00
2ef2dabf93
internal/aggergate: make HLL state path configurable
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I8ff8ef25ad945aae918bea97ee39d7ea6a6a6964
2026-03-02 22:38:19 +03:00
f988174145
watchdog: migrate to Cobra and Viper for config management; search /etc for configs
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I65dbf466cb030dccc7025585d6282bd26a6a6964
2026-03-02 22:38:18 +03:00
951ed9c36f
docs: link to configuration document for overview
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ie9f7132d784bf0b40e562f3190782fb36a6a6964
2026-03-02 22:38:17 +03:00
430219ee4c
docs: finalize project README
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ib2e222bfc5e5433423186584b52d53cb6a6a6964
2026-03-02 22:38:16 +03:00
4fba5e5ea3
chore: update example configuration to patch validation schema
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Id7b0fde6295fe48e2e766b9d538d3fb06a6a6964
2026-03-02 22:38:15 +03:00
bf8390a916
chore: format with golines
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I11a2f3273abf08c8cf02e0c335e26d826a6a6964
2026-03-02 22:38:14 +03:00
214c992494
chore: update test data for multi-domain support
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I789eff29d033de4c25128e6bbc17a5966a6a6964
2026-03-02 22:38:13 +03:00
cf6a68477f
web: improve Javascript beacon for Plausible 'compatibility'
Some features from Plausible that I think I'll miss. Here are some of
the noteworthy ones:

- Configuration via data attributes (api, domain, hash-mode, etc.)
- Automatic localhost detection and path exclusions
- Hash-based routing for SPA support
- Custom referrer support for events
- Duplicate pageview detection

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I6d19378404d0cb9920f12e0cdd163a8e6a6a6964
2026-03-02 22:38:12 +03:00
18fe1a8234
internal/api: better multi-sites support; validate events against allowed domains
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Iff1ced4966b4d42cfd6dfefb0cfd97696a6a6964
2026-03-02 22:38:11 +03:00
16ace569a0
meta: provide systemd template files
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I2ed3bcfa3e0f58685a883a301c898ee86a6a6964
2026-03-02 22:38:10 +03:00
63fb5d4ada
nix: add nixosModules to the flake
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I4a63fdabe0bdee972fea926bf37d78906a6a6964
2026-03-02 22:38:09 +03:00
75018f69df
nix: initial nixos module; complete packaging
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I59ec5a4f67ddae2139e72ef4c0c113366a6a6964
2026-03-02 22:38:08 +03:00
da1fab4257
internal: fix the tests broken by hardening
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: If95a5258a393542564f68b3a1ebc7ff66a6a6964
2026-03-02 22:38:07 +03:00
326cbbc68c
watchdog: more graceful shutdown; secure static file serving
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I2a55b2c4f380a1d78ec1ffa0391720256a6a6964
2026-03-02 22:38:06 +03:00
7e1ef845e8
internal/api: resolve IPv6 handling; prevent XFF spoofing & add rate limiting
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ibe415a133bbc8bd533a21ed1ccd44cf36a6a6964
2026-03-02 22:38:05 +03:00
8187608b38
internal/api: centralize constants; improve validation & santize errors
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I3c3e4acb12a5a965bfaba950bf9aa5776a6a6964
2026-03-02 22:38:04 +03:00
8392992b41
internal/aggregate: optimize HyperLogLog to prevent O(16384) operations
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ibc7e6d7a86e8679e299c46debee9683f6a6a6964
2026-03-02 22:38:03 +03:00
bb56df6423
internal/aggregate: optimize path registry for read-heavy workloads
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ibc477830b471fe09838b7477fe73ffa56a6a6964
2026-03-02 22:38:02 +03:00
ffb4ab2295
internal/normalize: harden against possible attacks; optimize registry
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Iaf89cda3c480d6a8371e5f146ee95fcf6a6a6964
2026-03-02 22:38:01 +03:00
b2256183e1
config: add security and performance sections to sample config; validate
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ieda42bcbd09014c45fb14bee579f829c6a6a6964
2026-03-02 22:38:01 +03:00
c3b77696aa
internal: centralize size/length constants; better DoS protection
...also adds a bounded custom event registry for cardinality control but
I ran out of space in the commit message. Praise be to the long
descriptions...

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ic205f69804c7fb24c39fa84abdd9546b6a6a6964
2026-03-02 22:38:00 +03:00
371c5f3506
chore: bump deps; tidy
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I78644673019b40dffe3d5900cb7cba806a6a6964
2026-03-02 22:37:59 +03:00
993e47e603
internal/aggregate: add HyperLogLog unique visitor tracking
Extracts IP from X-Forwarded-For/X-Real-IP/RemoteAddr. Only active
when `config.Site.SaltRotation` is set.

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ieef93b81e9894fc2e9e129451bf2dfdf6a6a6964
2026-03-02 22:37:58 +03:00
b6f2380a20
web: Javascript beacon for client-side tracking; custom event API
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I8e1f329ad3dfe7ba3f34ce450b1e1a0f6a6a6964
2026-03-02 22:37:57 +03:00
b894833ac7
various: HTTP server; migrate to cobra pattern for repository
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ifac6e992b77dfaf92e3059944aa871f16a6a6964
2026-03-02 22:37:56 +03:00
e0ec475a81
internal/api: ingestion handler; wire normalization pipeline
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I1890a039b874fcc76ac4a545c2901d4e6a6a6964
2026-03-02 22:37:55 +03:00
c5109ace92
internal/api: add event model with validation
Supports both pageview and custom event types

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Iaf48291cd952865ea9ec21361ae33c746a6a6964
2026-03-02 22:37:54 +03:00
bc4d3fed53
internal: initial metrics aggregator
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I9cdd6e2b33bb65182568db9db4460bc46a6a6964
2026-03-02 22:37:53 +03:00
ce848ed6f0
internal: add bounded path registry to prevent cardinality explosion
"cardinality explosion" would make for an epic rock band name...

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I53cceb00ab9b17039b1fb1389977bf6b6a6a6964
2026-03-02 22:37:52 +03:00
be4534bac8
internal: add referrer classification
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ibcaa09bfd4767876ea1cdd5b61c53b476a6a6964
2026-03-02 22:37:51 +03:00
0691e5ee34
internal: implement path normalization w/ configurable rules
Strips query strings and URL fragmenets, prevents unbounded Prometheus
metrics by normalizing paths like:

- `/users/12345/profile -> /users/:id/profile`
- `/page?utm_source=twitter -> /page`
- `/a/../b -> /b`

etc.

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I72f2fa2452f4666567143d052b5716476a6a6964
2026-03-02 22:37:50 +03:00
28abcf50e2
docs: improve introduction paragraph; tiny cleanup
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I2d331809c915f4695603b72ff52857cc6a6a6964
2026-03-02 22:37:49 +03:00
b4f3828895
meta: add direnv support
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I27df8e0c8b731759748fc6c1a734ded76a6a6964
2026-03-02 22:37:48 +03:00
4c84393286
config: data structures; basic tests
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ia7d6f19a46ec8a4987ea429ec6502f676a6a6964
2026-03-02 22:37:47 +03:00
3fca34dd6f
nix: initial tooling
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Iabcad180d133f01d3c98e3d5fc9630b26a6a6964
2026-03-02 22:37:46 +03:00
7146a61326
initial commit
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Id13648d9d5579614595101592739fe2a6a6a6964
2026-03-02 22:37:45 +03:00