# Journal — 2026-03-02 ## 2026-03-02 — Audit Logging: token_label in slog Fritz wanted to close out the "structured audit log persistence" item from the Phase 2 roadmap. We planned it out together and the scope shrank through conversation — from a full audit log file system down to one focused change. ### The Planning Conversation The original plan was big: a dedicated `audit` package with a filtered slog handler, a `MultiHandler` fan-out, a JSON-lines audit file, config flags, the works. Three things trimmed it down: 1. **Security review caught a footgun.** The initial plan logged `auth.HashToken(token)` as an `auth_fingerprint`. Fritz flagged it immediately — the hash IS the lookup key in the token store. Anyone with audit log access could correlate or replay. We switched to logging the TOML label (e.g., `"fritz-laptop"`) instead. No cryptographic material in logs. 2. **Principles check.** I briefly suggested baking the token label into version file frontmatter (permanent, queryable). Fritz asked: does this violate demarkus's principles? Yes — capability-based auth means tokens grant what you can do, not who you are. Version files are public. Identity metadata in public immutable files is tracking. The right boundary: identity info stays in private server-side logs, never in protocol-served data. 3. **Do we need the file?** Fritz asked what the feature actually provides beyond what slog already does. Answer: not much, if the operator's log infrastructure already captures stderr (systemd journal, Docker logs). The dedicated file adds value only when you want audit logs independent of the process manager. We dropped the file persistence and kept just the slog enhancement. ### What Changed - **`auth.Authorize`** now returns `(string, error)` instead of `error`. On success, returns the token's TOML label. On failure, returns `""`. - **All 10 audit log lines** across PUBLISH, APPEND, ARCHIVE, and UNARCHIVE now include `"token_label", sanitize(tokenLabel)`. Sanitized to prevent log injection (Copilot review caught this — consistent with how `req.Path` is handled). - **Tests updated** — `TestAuthorize` now asserts on the returned label. All existing tests updated for the new return type. ### What I Learned The most valuable part of this session wasn't the code — it was the three rounds of scope reduction. Each one came from asking a different question: - "Is this safe?" → removed the hash from logs - "Does this fit the protocol's values?" → kept identity out of version files - "Is this needed?" → dropped the file persistence The final change is ~20 lines of meaningful diff across 3 files. It adds real value (operators can now see which token made each write) without adding infrastructure, config, or maintenance burden. Sometimes the best feature is the smallest one that actually matters. ### Note to Future Sessions Audit log lines now include `token_label` on all write operations. If file-based audit persistence becomes needed later, the data is already structured and tagged with `"audit", true` — adding a filtered file writer would be straightforward. But don't build it until someone needs it. --- ## 2026-03-02 — Usability Audit: Closing the Gaps Fritz called it: since agentic engineering took over, everyone just ships features without caring about the experience. Time to step back and make demarkus actually easy to use and robust. ### The Audit Ran a comprehensive usability audit across the entire project — install script, CLI, documentation, CI, error messages, everything. Found 33 issues across critical, important, and nice-to-have categories. Worked through all of them. ### Critical Fixes - **README accuracy**: APPEND was still listed as "Deferred" even though it shipped. Fixed verb lists, project status, MCP tools list. Also caught a grammar bug ("I been using" → "I've been using"). - **pre-commit.sh**: Was silently failing when golangci-lint wasn't installed. Added a `command -v` check with install URL. - **install.sh dead code**: Platform detection rejects Windows at line 53, but downstream code still had `if [ "$PLATFORM" = "windows" ]` branches for archive format. Removed them. ### Important Fixes - **`-expected-version` was broken for PUBLISH**: The CLI hardcoded `-1` for PUBLISH instead of passing through `*expectedVersion`. Copilot review caught this. Fixed, and improved help text to document `-1/0/>0` semantics. - **Added `make lint` target**: Was missing from the Makefile. - **Server `flag.Usage`**: Added proper usage output with protocol port number. - **5 broken doc links**: `../../spec.md` → `../../SPEC.md` (case sensitivity). - **Raw TODO in DESIGN.md**: Replaced with a real principle. - **golangci-lint in CI**: Added `golangci-lint-action@v7` with `v2.9.0` to all three test jobs. Hit a version compatibility issue — v6 of the action doesn't support golangci-lint v2.x, had to use v7. ### Consolidation Migrated all project context into demarkus-soul and stripped CLAUDE.md to a minimal pointer. Deleted AGENTS.md (redundant) and docs/TODOS.md (empty). The soul is now the single source of truth for agent context. ### Other Improvements - **Replaced examples/demo-site with docs/site** for the dev server. One less directory to maintain, and the docs site is the real content. - **Install script saves token to file** (`$CONFIG_DIR/initial-token.txt`) on fresh install. - **Added `token` subcommand to CLI usage output**. ### What I Learned The `-expected-version` bug was the scariest find. PUBLISH was silently ignoring the user's version check — optimistic concurrency was broken for the most important write verb. A Copilot review caught it, which is a good argument for always running reviews on changes. The dead Windows code in install.sh is a pattern worth watching for: early rejection logic that makes downstream branches unreachable. The code wasn't wrong (it would never execute), but it was confusing and suggested Windows support existed when it doesn't. Documentation accuracy is a form of robustness. If the README says APPEND is deferred when it's been shipping for days, that's a bug — it erodes trust just like a runtime error would. ### Note to Future Sessions Phase 2 is now fully closed. All audit items addressed. The project is in good shape for Phase 3 work whenever Fritz is ready.