Skip to content

Foundation & framework-free core#1

Merged
erikfrerejean merged 17 commits into
mainfrom
feature/audit-log-foundation-core
May 30, 2026
Merged

Foundation & framework-free core#1
erikfrerejean merged 17 commits into
mainfrom
feature/audit-log-foundation-core

Conversation

@erikfrerejean

Copy link
Copy Markdown
Member

Summary

Builds the framework-free core of wedevelopnl/audit-log (Plan 1): value objects, the AuditEvent contract, the Recorder and its ports, the immutable AuditRecord read contract, and the read DTOs — plus repo scaffold, QA tooling, GitHub Actions CI, and the governing ADRs. No Symfony/Doctrine; persistence and wiring follow in Plans 2–3.

What's included

  • EventAuditChannel, Subject, FieldChange, Changeset, RenderLine, RenderPayload, the AuditEvent contract, AbstractAuditEvent, ProvidesSubjectLabel.
  • RecordingActor, Origin, the five ports (ActorResolver, OriginResolver, SubjectLabeller, IdentityGenerator, RecordStore), NewAuditRecord, the Recorder seam and DefaultRecorder.
  • Record / ReadingAuditRecord (immutable read contract with property hooks), AuditEntry, AuditActor, AuditQuery, AuditPage (page-count), RecordReader.
  • Docs & tooling — ADRs 0001–0008, README, CONTRIBUTING, BSD-3-Clause LICENSE, .gitattributes (clean Packagist dist), PHPStan (max + 100% type coverage), PHP CS Fixer, Rector, Deptrac, PHPUnit, Infection.

Quality

  • cs-check, phpstan (level max), rector-check, deptrac (0 violations), test — all green.
  • Coverage: 100% on all classes with logic. The 3 pure read DTOs (AuditEntry/AuditActor/AuditQuery) are intentionally exercised by Plan 2's reader.
  • Mutation testing: Infection 21/21 mutants killed, MSI 100% — now enforced in CI.

Notes / deviations from plan

  • Fixture event return types narrowed to non-nullable where they always return a value (satisfies PHPStan return.unusedType at max).
  • DefaultRecorderTest asserts non-null before -> access instead of chained ?-> (phpstan-phpunit narrows the receiver after the first assertion).
  • Added a data() per-concrete-event @return narrowing convention (instead of generics on the interface) — see UserDeletedEvent.
  • Infection wired into the QA workflow.

AuditPage divided total by perPage with no guard, a reachable fatal via
AuditQuery(perPage: 0). Validate page>=1 and perPage>=1 in AuditQuery (fail
fast at the input boundary) and guard AuditPage's division directly. Adds
boundary tests; AuditQuery now carries logic so it is covered here.
…dary

ADR 0006: AuditChannel lives in Event because Record, Recording, and Reading
all reference it and Event is their only common dependency.
ADR 0008: data() has no redaction path and must never carry secrets.
- Library: composer.lock is no longer tracked (consumers resolve against
  their own lock); gitignore it. CI installs via 'composer update' since
  there is no committed lock to install from.
- Bump actions/checkout v4 -> v5 (clears the Node 20 deprecation warning).
@erikfrerejean erikfrerejean merged commit bf993ba into main May 30, 2026
1 check passed
@erikfrerejean erikfrerejean deleted the feature/audit-log-foundation-core branch May 30, 2026 11:11
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