Skip to content

docs: audit-logging recipe#15

Merged
rodrigobnogueira merged 1 commit into
mainfrom
docs/audit-logging
Jul 20, 2026
Merged

docs: audit-logging recipe#15
rodrigobnogueira merged 1 commit into
mainfrom
docs/audit-logging

Conversation

@rodrigobnogueira

Copy link
Copy Markdown
Contributor

The third django-axes gap — a persisted attempt/lockout audit trail (its AccessAttempt/AccessLog tables). The honest answer is docs, not a feature: authlock keeps credentials out of its store by design and exposes the hooks to build the trail yourself.

  • api-reference gains an Audit logging section: log each attempt at your own reportFailure/reportSuccess call site (there is deliberately no per-failure hook — it would only echo what your handler already knows), alert on lock transitions via onLockout, and surface store failures via logger — always recording identity dimensions, never the credential.
  • quick-start cross-links it; nestjs README points to it; GUIDELINES §5 names un-normalized dimensions as a bypass vector and audit logging as an app responsibility.

Docs-only; website builds (the #audit-logging anchor resolves), readme-links gate green. No version bump — CHANGELOG Unreleased gets the Docs bullet.

authlock stores only hashed counters, not an attempt log — but an audit trail
is buildable from what already exists, and django-axes's AccessAttempt/AccessLog
tables are the one capability worth answering (with docs, not a feature).

- api-reference: an "Audit logging" section — log each attempt at your own
  reportFailure/reportSuccess call site (no per-failure hook by design), alert
  on transitions via onLockout, surface store errors via logger; a prominent
  "never log the credential, only dimensions" rule.
- quick-start: cross-link to it.
- nestjs README: a short pointer.
- GUIDELINES §5: name un-normalized dimensions as a bypass vector and audit
  logging as an app responsibility bound by the never-log-credentials rule.

Docs-only; no code, no version bump.
@github-actions

Copy link
Copy Markdown

📊 Coverage Coverage Report

Metric PR Base Diff
Statements ████████████████████ 959/959 (100%) 959/959 (100%) ⚪ 0%
Branches ████████████████████ 165/165 (100%) 165/165 (100%) ⚪ 0%
Functions ████████████████████ 56/56 (100%) 56/56 (100%) ⚪ 0%
Lines ████████████████████ 959/959 (100%) 959/959 (100%) ⚪ 0%

Updated for 2778e1b | Compared against base branch

@github-actions

Copy link
Copy Markdown

⏱️ Performance Report

✅ Tests 99 passed, 0 failed, 0 skipped
🧪 Suites 22
⏱️ Total step time 27.00s 🟢 -2.00s
⚙️ Test execution 22.64s 🟢 -578ms
🐢 Slowest test suites
# Suite Tests Duration vs Base
1 LockoutStore contract — postgres (pglite) 6 12.42s 🟢 -152ms
2 LockoutStore contract — sqlite (better-sqlite3) 6 26ms ⚪ ~0
3 MysqlLockoutStore (real drizzle-mysql2 builder, fake client) 6 16ms ⚪ ~0
4 @authlock/core acceptance (framework-neutral login flow) 2 4ms ⚪ ~0
5 lockout table schema parity 4 2ms ⚪ ~0
6 deriveKeys 13 2ms ⚪ ~0
7 LockoutManager — configuration validation 8 2ms ⚪ ~0
8 LockoutManager — multi-key evaluation 4 2ms ⚪ ~0
9 LockoutStore contract — in-memory 6 1ms ⚪ ~0
10 InMemoryLockoutStore 6 1ms ⚪ ~0
🐌 Slowest individual tests
# Suite Test Duration vs Base
1 LockoutStore contract — postgres (pglite) LockoutStore contract — postgres (pglite) creates, increments (advancing lastFailureAt), then resets after the window 2.61s 🟢 -158ms
2 LockoutStore contract — postgres (pglite) LockoutStore contract — postgres (pglite) counts concurrent increments exactly — no lost updates 2.02s ⚪ ~0
3 LockoutStore contract — postgres (pglite) LockoutStore contract — postgres (pglite) clears a single key 1.97s ⚪ ~0
4 LockoutStore contract — postgres (pglite) LockoutStore contract — postgres (pglite) clearAll removes every key regardless of age 1.96s ⚪ ~0
5 LockoutStore contract — postgres (pglite) LockoutStore contract — postgres (pglite) reads a stored record, or null when the key is unknown 1.93s ⚪ ~0
6 LockoutStore contract — postgres (pglite) LockoutStore contract — postgres (pglite) clearExpired removes only records older than the cutoff and counts them 1.92s ⚪ ~0
7 MysqlLockoutStore (real drizzle-mysql2 builder, fake client) MysqlLockoutStore (real drizzle-mysql2 builder, fake client) increment issues an atomic windowed upsert then re-reads the row 13ms ⚪ ~0
8 LockoutStore contract — sqlite (better-sqlite3) LockoutStore contract — sqlite (better-sqlite3) counts concurrent increments exactly — no lost updates 12ms ⚪ ~0
9 LockoutStore contract — sqlite (better-sqlite3) LockoutStore contract — sqlite (better-sqlite3) creates, increments (advancing lastFailureAt), then resets after the window 6ms ⚪ ~0
10 @authlock/core acceptance (framework-neutral login flow) @authlock/core acceptance (framework-neutral login flow) locks a brute-force loop after the limit, then recovers after cooloff 2ms ⚪ ~0
11 LockoutStore contract — sqlite (better-sqlite3) LockoutStore contract — sqlite (better-sqlite3) reads a stored record, or null when the key is unknown 2ms ⚪ ~0
12 LockoutStore contract — sqlite (better-sqlite3) LockoutStore contract — sqlite (better-sqlite3) clearAll removes every key regardless of age 2ms ⚪ ~0
13 LockoutStore contract — sqlite (better-sqlite3) LockoutStore contract — sqlite (better-sqlite3) clearExpired removes only records older than the cutoff and counts them 2ms ⚪ ~0
14 @authlock/core acceptance (framework-neutral login flow) @authlock/core acceptance (framework-neutral login flow) exposes a semver-shaped version 1ms ⚪ ~0
15 MysqlLockoutStore (real drizzle-mysql2 builder, fake client) MysqlLockoutStore (real drizzle-mysql2 builder, fake client) get returns the mapped record when present 1ms ⚪ ~0

Updated for 2778e1b | Compared against base branch

@github-actions

Copy link
Copy Markdown

🧠 Cognitive Complexity Report

Metric PR Base Diff
Total complexity 72 72 ⚪ 0
Max function complexity 11 11 ⚪ 0
Functions measured 27 27 ⚪ 0
🧩 Most complex functions
Function Location Complexity Status
deriveKeys packages/core/key.ts:32 11 🟢 OK
validateTiers packages/core/manager.ts:28 11 🟢 OK
validateNormalize packages/core/manager.ts:72 4 🟢 OK
cooloffFor packages/core/policy.ts:10 4 🟢 OK
evaluateRecord packages/core/policy.ts:78 4 🟢 OK
mostRestrictive packages/core/manager.ts:105 3 🟢 OK
LockoutManager.clearKeys packages/core/manager.ts:259 3 🟢 OK
LockoutManager.applyFailure packages/core/manager.ts:280 3 🟢 OK
effectiveWindowMs packages/core/policy.ts:33 3 🟢 OK
InMemoryLockoutStore.clearExpired packages/core/store/in-memory.ts:49 3 🟢 OK

🧭 Cognitive complexity is reported as a review signal, not a merge gate. Prefer small, intention-revealing refactors when complexity rises.


Updated for 2778e1b | Compared against base branch

@rodrigobnogueira
rodrigobnogueira merged commit 963ea16 into main Jul 20, 2026
11 checks passed
@rodrigobnogueira
rodrigobnogueira deleted the docs/audit-logging branch July 20, 2026 15:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant