Data-layer invariants for the collector — SQLite patterns, transactions, time keys, backendId isolation, ClickHouse read/write topology. Use when writing queries, touching repositories, or debugging data drift.
68
81%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
batchUpdateTrafficStats (database/repositories/traffic-writer.repository.ts); the whole flush is a single outer transaction (inner db.transaction() calls degrade to savepoints). Never commit table groups independently — a mid-flush failure plus buffer retry double-counts.buildRuleName (shared/utils/rule-name.ts). Rule type + payload (RuleSet(foo)) is the key only for single-hop DIRECT/REJECT chains. The web flow graph and gateway-rule matching depend on this.INSTR(',' || col || ',', ',' || @v || ',') — bare INSTR substring-matches (a.com inside aa.com) and silently drops values. Lists are capped at LENGTH > 4000.YYYY-MM-DDTHH:MM:00, hour YYYY-MM-DDTHH:00:00, via toMinuteKey/toHourKey (base.repository.ts). No local-time truncation.backend_id. PRAGMA foreign_keys is OFF — deleting a backend relies on the explicit table list in deleteBackendData; new tables must be added there.resolveFactTable (base.repository.ts): ≤6h → minute_dim_stats, >6h → hourly_dim_stats. Retention must respect this: hourly dim tables follow hourlyStatsDays, minute tables follow connectionLogsDays.LIMIT), use Map merges instead of nested findIndex, and prefer prepared statements cached on the instance for hot paths.modules/db/db.ts init() (env-tunable: SQLITE_CACHE_MB, SQLITE_WAL_AUTOCHECKPOINT_PAGES, SQLITE_BUSY_TIMEOUT_MS).init() — idempotent (IF NOT EXISTS / try-catch ALTER / app_config flags for one-time data migrations, see database/rule-name-cleanup.ts as the reference pattern).Read/write behavior is controlled by env flags — keep them coherent:
| Flag | Meaning |
|---|---|
CH_WRITE_ENABLED | Write traffic batches to ClickHouse |
STATS_QUERY_SOURCE | sqlite (default) / clickhouse / auto — read routing |
CH_ONLY_MODE=1 | Skip SQLite stats writes entirely (requires healthy CH writer) |
CH_STRICT_STATS=1 | Fail instead of silently falling back to SQLite reads |
Guard rails already enforced in code (modules/stats/stats-write-mode.ts): reduced SQLite writes require reads to actually prefer ClickHouse — don't bypass shouldReduceSqliteWrites/shouldSkipSqliteStatsWrites with ad-hoc env checks. When adding a range query, implement BOTH the SQLite repository method and the clickhouse.reader.ts counterpart with identical semantics, and route via a *WithRouting method in stats.service.ts.
BatchBuffer.flush returns per-group outcomes (detailOk/aggOk); the realtime store is only cleared for the groups that durably persisted. When touching flush/clear logic, preserve this contract — it is the data-loss protection added in v1.3.9.
6f72cfd
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.