Menu

#442 examples: a second plugin tutorial, a minimal `doberman.audit_sinks` sink

closed
nobody
2026-08-29
2026-08-20
Anonymous
No

Originally created by: fu351

examples/plugin-guardrail/ is the one worked plugin: it registers an ExampleRule under [project.entry-points."doberman.rules"] and its README walks the round trip (install core, install the plugin editable, prove discovery, manual smoke). Rule writers have a template; audit-sink writers don't. The seam is just as ready: AUDIT_SINK_GROUP = "doberman.audit_sinks" and discover_audit_sinks() (src/doberman/engine/registry.py:45,244), the AuditSink protocol is one method, emit(self, record: dict) -> None (src/doberman/storage/sinks.py:51-58), and the built-in webhook and OTel sinks prove it in production. (#200 covers the detector example plus docs/EXTENDING.md; this is the sink sibling, and they can land in either order.)

What to do

  1. Create examples/plugin-audit-sink/ with the same layout as plugin-guardrail (pyproject.toml, src/example_audit_sink/sinks.py, tests/, README.md).
  2. ExampleAuditSink.emit(record) appends one JSON line to a file (path from an env var with a tmp default). Deliberately a hello-world: no batching, no retries, no network. Those are the webhook sink's job and the README should say so.
  3. Register it: [project.entry-points."doberman.audit_sinks"] example_sink = "example_audit_sink.sinks:ExampleAuditSink".
  4. tests/test_example_sink.py mirrors plugin-guardrail/tests/test_example_rule.py: discovered via discover_audit_sinks(), emit() writes exactly the dict it was handed and never raises (a sink that throws must not be able to break a decision).
  5. README mirrors the guardrail README's structure: What it does, Round trip, How registration works, Layout, and the same "what this plugin must never log" table, since the record it receives is already redacted and the sink must not add anything.

Packaging is the part that bites (editable install of a second package, entry-point discovery in a fresh venv), which is why this is level-6 rather than 3. The guardrail example is a working answer to every one of those questions; copy it.

Related

Tickets: #459
Tickets: #499

Discussion

  • Anonymous

    Anonymous - 2026-08-28

    Originally posted by: Maqbool61

    Assign me. I am working on it.

     
  • Anonymous

    Anonymous - 2026-08-29

    Ticket changed by: vinayjagan03

    • status: open --> closed
     

Log in to post a comment.