Skip to content

feat(cli): append-only compliance audit log#102

Open
abhinav-1504 wants to merge 14 commits into
optiqor:mainfrom
abhinav-1504:feat/audit-log-issue-48
Open

feat(cli): append-only compliance audit log#102
abhinav-1504 wants to merge 14 commits into
optiqor:mainfrom
abhinav-1504:feat/audit-log-issue-48

Conversation

@abhinav-1504

Copy link
Copy Markdown

Add structured NDJSON audit log for SOC 2 / ISO 27001 / HIPAA compliance.

  • internal/audit: Logger with 8 event types, lumberjack rotation, PII redaction
  • internal/audit: Redact() strips PIDs/IPs/paths, RedactRemoteAddr for HTTP
  • internal/config: AuditConfig + PrometheusConfig.BearerToken
  • internal/ai/analyzer: ai.call audit on every LLM call (hit/miss/error)
  • internal/cli/start: daemon lifecycle, bpf.load, SIGHUP, auth.failure wired
  • internal/cli/doctor: auditLog passed to NewEngine
  • internal/doctor/engine: finding.emit wired for WARNING/CRITICAL findings
  • docs/audit-schema.md: versioned NDJSON schema documentation

Closes #48

What

Add append-only NDJSON audit log for SOC 2 / ISO 27001 / HIPAA compliance. Emits structured records for every privileged action kerno takes — config reloads, AI calls, finding emissions, auth failures, and daemon lifecycle events.

Why

Fixes #48

How

  • New internal/audit package: Logger with 8 event types, lumberjack file rotation, PII redaction (PIDs/IPs/paths stripped before any record is written)
  • cycle_id links finding.emit → ai.call for end-to-end compliance tracing
  • Bearer token mismatch on /metrics emits auth.failure audit record
  • daemon.panic captured via recover() with SHA-256 stack digest only — raw stack never written
  • docs/audit-schema.md documents the versioned NDJSON schema for compliance reviewers

Testing

  • go build ./... passes
  • go test ./... passes
  • go vet ./... passes
  • golangci-lint run ./... passes
  • Tested locally with: go test ./internal/audit/... -v -race — 30+ tests PASS, zero regressions
  • N/A — pure docs/refactor (BPF programs untouched)
  • N/A — pure docs/refactor (BPF programs untouched)
  • sudo ./bin/bpf-verify --read 5s confirms 6/6 programs still load
  • ./scripts/verify.sh passes (or specific phase: ./scripts/verify.sh quality)

Checklist

  • PR title follows Conventional Commits
  • All commits are DCO-signed (git commit -s)
  • No unrelated changes pulled in
  • Documentation updated (docs/audit-schema.md added)
  • Added/updated tests for new code paths (30+ tests in audit_test.go)
  • N/A — no new doctor rule added

@abhinav-1504 abhinav-1504 requested a review from btwshivam as a code owner May 25, 2026 08:00
@github-actions

Copy link
Copy Markdown

🚀 First PR — welcome aboard!

A few things to expect:

  1. CI: every PR runs build + race tests + lint + (eventually) the kernel matrix. If something fails, the log will tell you exactly which gate.
  2. DCO: every commit needs Signed-off-by:git commit -s adds it automatically.
  3. Conventional Commits: PR titles like feat(doctor): add new rule or fix(bpf): handle X. We squash-merge by default.
  4. Review: a maintainer will review within 72 hours. Suggestions are conversations, not orders — push back if something doesn't fit your context.

If you get stuck, reply here or jump to Discussions. We want this PR to land.

@github-actions github-actions Bot added level:critical Touches BPF, security, or release surfaces (auto-applied) documentation Improvements or additions to documentation testing Tests and test coverage area/doctor Diagnostic engine and rules area/integrations External integrations (sinks, exports, CI) area/security Security and supply chain area/ops Operations, deployment, runtime ergonomics labels May 25, 2026
@abhinav-1504 abhinav-1504 changed the title Feat/audit log issue 48 feat(audit): append-only compliance audit log for issue #48 May 25, 2026
@abhinav-1504 abhinav-1504 changed the title feat(audit): append-only compliance audit log for issue #48 feat(cli): append-only compliance audit log May 25, 2026
@abhinav-1504

Copy link
Copy Markdown
Author

Hi @btwshivam, all CI checks are passing. Let me know if you need any changes. Thanks!
Waiting for your review!!

@btwshivam btwshivam left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

genuinely solid work ... metadata-only records (prompt sizes not content), hashed payloads, nil-safe and mutex-guarded logging, IP/path redaction at the call sites. resolve the conflicting merge state first (branch is on current main HEAD locally, so a rebase/re-push should clear it). one redaction gap and a dep note inline, plus a design

question: append-only here is file-level via lumberjack, no hash chain between records, so it's not tamper-evident, is that in scope for #48 or a follow-up?

Comment thread internal/audit/audit.go Outdated
Comment thread internal/audit/audit.go
if maxMB == 0 {
maxMB = 100
}
lj := &lumberjack.Logger{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lumberjack is a new dependency, CLAUDE.md asks for the alternative considered. it's a reasonable choice for rotation, just name what you weighed it against (raw os.OpenFile with O_APPEND and no built-in rotation, say). also worth confirming the defaults fit a compliance log: Compress: true gzips rotated files and MaxBackups/MaxAge can delete old ones, which may conflict with retention requirements.

@abhinav-1504 abhinav-1504 May 31, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lumberjack was chosen over raw os.OpenFile + O_APPEND because it provides built-in size-based rotation without requiring external logrotate setup. Issue #48 explicitly says "rotation handled by the OS or the user's log shipper" — lumberjack fits that model cleanly.

Re retention: changed MaxBackups default to 0 (unlimited — lumberjack never auto-deletes). Operators who are storage-constrained can set a non-zero value, but the safe default for compliance is no auto-deletion.

Re Compress: true — this gzips rotated files only, not the active log. Operators who need uncompressed files for their log shipper can set compress: false in config.

@abhinav-1504

abhinav-1504 commented May 31, 2026

Copy link
Copy Markdown
Author

genuinely solid work ... metadata-only records (prompt sizes not content), hashed payloads, nil-safe and mutex-guarded logging, IP/path redaction at the call sites. resolve the conflicting merge state first (branch is on current main HEAD locally, so a rebase/re-push should clear it). one redaction gap and a dep note inline, plus a design

question: append-only here is file-level via lumberjack, no hash chain between records, so it's not tamper-evident, is that in scope for #48 or a follow-up?

append-only here means O_APPEND file writes via lumberjack — no hash chain between records, so not tamper-evident in the cryptographic sense.

Issue #48 doesn't require tamper-evidence — it asks for an audit trail that compliance reviewers can use to trace events.
Hash chains would be a separate concern and could be a follow-up if buyers require it.

@abhinav-1504

Copy link
Copy Markdown
Author

/retest

@github-actions

Copy link
Copy Markdown

Re-running 1 failed workflow run(s) on bbe2580.

@abhinav-1504 abhinav-1504 requested a review from btwshivam May 31, 2026 05:04
@abhinav-1504

Copy link
Copy Markdown
Author

Hi @btwshivam, I've addressed all the review feedback and updated the branch. Please take another look and let me know if any further changes are needed. Thanks!

@btwshivam

Copy link
Copy Markdown
Member

fix conflict

Add structured NDJSON audit log for SOC 2 / ISO 27001 / HIPAA compliance.

- internal/audit: Logger with 8 event types, lumberjack rotation, PII redaction
- internal/audit: Redact() strips PIDs/IPs/paths, RedactRemoteAddr for HTTP
- internal/config: AuditConfig + PrometheusConfig.BearerToken
- internal/ai/analyzer: ai.call audit on every LLM call (hit/miss/error)
- internal/cli/start: daemon lifecycle, bpf.load, SIGHUP, auth.failure wired
- internal/cli/doctor: auditLog passed to NewEngine
- internal/doctor/engine: finding.emit wired for WARNING/CRITICAL findings
- docs/audit-schema.md: versioned NDJSON schema documentation

Closes optiqor#48

Signed-off-by: Abhinav Singh Chauhan <abhinavsinghc48@gmail.com>
Signed-off-by: Abhinav Singh Chauhan <abhinavsinghc48@gmail.com>
Signed-off-by: Abhinav Singh Chauhan <abhinavsinghc48@gmail.com>
Signed-off-by: Abhinav Singh Chauhan <abhinavsinghc48@gmail.com>
@abhinav-1504 abhinav-1504 force-pushed the feat/audit-log-issue-48 branch from 33a3426 to 49ec73a Compare June 7, 2026 03:57
@github-actions

github-actions Bot commented Jun 7, 2026

Copy link
Copy Markdown

Re-running 2 failed workflow run(s) on 49ec73a.

Signed-off-by: Abhinav Singh Chauhan <abhinavsinghc48@gmail.com>
Signed-off-by: Abhinav Singh Chauhan <abhinavsinghc48@gmail.com>
@github-actions github-actions Bot added the area/release Release tooling and packaging label Jun 7, 2026
Signed-off-by: Abhinav Singh Chauhan <abhinavsinghc48@gmail.com>
Signed-off-by: Abhinav Singh Chauhan <abhinavsinghc48@gmail.com>
Signed-off-by: Abhinav Singh Chauhan <abhinavsinghc48@gmail.com>
@abhinav-1504

Copy link
Copy Markdown
Author

Hi @btwshivam, all CI checks are now passing. Ready for final review!

@abhinav-1504

Copy link
Copy Markdown
Author

/retest

@github-actions

github-actions Bot commented Jun 7, 2026

Copy link
Copy Markdown

Re-running 1 failed workflow run(s) on ff1da42.

@abhinav-1504

abhinav-1504 commented Jun 7, 2026

Copy link
Copy Markdown
Author

fix conflict

FIXED !! @btwshivam

@btwshivam btwshivam left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the audit fixes are good (bpf errors redacted, max_backups handled). but this bumps go.mod to 1.26 and rewrites ci.yml + release.yml to match, that is a repo-wide toolchain change riding in an audit-log PR. revert to 1.25 and drop the workflow edits.

Comment thread go.mod Outdated
Comment thread .github/workflows/ci.yml Outdated
Signed-off-by: Abhinav Singh Chauhan <abhinavsinghc48@gmail.com>
@abhinav-1504 abhinav-1504 force-pushed the feat/audit-log-issue-48 branch from ff1da42 to 016b9b0 Compare June 7, 2026 13:04
@github-actions github-actions Bot removed the area/release Release tooling and packaging label Jun 8, 2026
@abhinav-1504 abhinav-1504 requested a review from btwshivam June 8, 2026 11:12
@abhinav-1504

Copy link
Copy Markdown
Author

the audit fixes are good (bpf errors redacted, max_backups handled). but this bumps go.mod to 1.26 and rewrites ci.yml + release.yml to match, that is a repo-wide toolchain change riding in an audit-log PR. revert to 1.25 and drop the workflow edits.

@btwshivam — go.mod is back on 1.25.4, workflows reverted, all 17 CI checks passing. Ready for final review!

@abhinav-1504

Copy link
Copy Markdown
Author

@btwshivam Please review the PR !!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/doctor Diagnostic engine and rules area/integrations External integrations (sinks, exports, CI) area/ops Operations, deployment, runtime ergonomics area/security Security and supply chain documentation Improvements or additions to documentation level:critical Touches BPF, security, or release surfaces (auto-applied) testing Tests and test coverage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Compliance: audit log of config reloads, AI calls, and finding emissions

2 participants