Menu

#499 examples: add plugin-audit-sink tutorial (closes #442)

closed
nobody
None
2026-08-30
2026-08-28
Anonymous
No

Originally created by: Maqbool61

Closes [#442]

Adds examples/plugin-audit-sink/ — a minimal AuditSink tutorial that
mirrors examples/plugin-guardrail/ in structure and scope.

What it does

ExampleAuditSink.emit(record) appends one JSON line to a local file
controlled by DOBERMAN_AUDIT_SINK_FILE. Deliberately hello-world: no
batching, no retries, no network — the built-in webhook sink covers those.
The package registers itself via [project.entry-points."doberman.audit_sinks"]
so discover_audit_sinks() picks it up with no core change.

Files

File What
examples/plugin-audit-sink/pyproject.toml Package metadata + doberman.audit_sinks entry point
examples/plugin-audit-sink/src/example_audit_sink/sinks.py ExampleAuditSink — emit, never-raises, thread-safe
examples/plugin-audit-sink/src/example_audit_sink/__init__.py Lazy re-export, no import-time side effects
examples/plugin-audit-sink/tests/test_example_sink.py 11 tests: discovery, emit, append, read-only, never-raises, env-var, threads
examples/plugin-audit-sink/README.md Round-trip guide, invariants table, what-never-to-log table, copy checklist
tests/unit/test_core_is_standalone.py Fix test_no_audit_sinks_registered_by_default to exclude example_* packages

Standalone test fix

test_no_audit_sinks_registered_by_default asserted discover_audit_sinks() == []
— a hard zero that fails whenever any tutorial package is installed locally.
The fix filters out anything whose module starts with example_, matching the
same pattern already used for discover_rules(). The plugin can stay installed
during a full core suite run — no uninstall step needed.

Checklist

  • [x] pytest examples/plugin-audit-sink/tests — 11 passed (plugin installed)
  • [x] pytest -n auto — 3354 passed, 0 failed, 91.69% coverage (plugin installed)
  • [x] ruff check / ruff format --check — all clean
  • [x] lint-imports — 4 contracts kept, 0 broken
  • [x] python scripts/check_markdown_links.py — 64 files, no broken links
  • [x] python -m tools.parity.generate_parity --check — passed

Related

Tickets: #442
Tickets: #501

Discussion

  • Anonymous

    Anonymous - 2026-08-29

    Originally posted by: vinayjagan03

    all CI tests pass. and visual inspection of commit looks okay. good to go :)

     
  • Anonymous

    Anonymous - 2026-08-29

    Ticket changed by: vinayjagan03

    • status: open --> closed
     
  • Anonymous

    Anonymous - 2026-08-29

    Originally posted by: fu351

    Thanks @Maqbool61, this one's in! The sink matches core's AuditSink protocol to the letter, emit(self, record: dict) -> None, and the lazy getattr re-export in init.py is the same shape as the guardrail tutorial, so the two examples read as one series. One thing I changed after the merge, in [#501]: your local editable install made discover_audit_sinks() non-empty, so the standalone guarantee test got a filter that ignores example_ modules. CI never installs the example, so the filter wasn't needed, and the guardrail tutorial solves the same problem by importing the class through sys.path in tests/unit without installing it. I moved yours to that pattern, restored the hard == [] assert, and pointed the README's CI note at the new test. If you want a bigger one, [#236] (level-6) is the ambient activity bus with a doberman.collectors entry-point seam, and after the webhook and OTel sinks you already know the seam pattern.

     

    Related

    Tickets: #236
    Tickets: #501


Log in to post a comment.