Skip to content

Releases: padosoft/laravel-ai-guardrails

v1.0.0 — Every documented limitation, closed

18 Jun 20:55
11bd0c1

Choose a tag to compare

The 1.0 milestone closes every entry in the README "Known limitations" list plus the deferred MCP surface. Each is a default-safe, both-states-tested config toggle; the deterministic security guarantees of v0.3.0 are unchanged. 464 tests / 1182 assertions green on PHP 8.3 / 8.4 / 8.5 × Laravel 13; PHPStan level 8; Pint clean; Infection ≥ 80 % MSI in CI.

What's closed

  • L1 — Cross-script homoglyph defense (Control B). A curated ConfusablesFolder maps Cyrillic/Greek Latin look-alikes to an ASCII skeleton before matching, so ignоre (Cyrillic о) no longer evades the screening regexes. Toggle normalization.fold_confusables (default on).
  • L2 — HTMLPurifier-grade allowlist (Control C). html_mode=allowlist now uses HTMLPurifier when ezyang/htmlpurifier is installed (robust against malformed / entity-encoded / mutation-XSS markup, all attributes stripped), with graceful fallback to the built-in allowlist when absent.
  • L3 — Opt-in tool-call sanitization (Control C). New output_handler.sanitize_tool_calls (default off — tool args are executed and governed by Controls A/D) adds a defense-in-depth pass over tool-call argument string leaves when you render/log them.
  • L4 — Turnkey HITL (Control D). ai-guardrails:hitl-install runs laravel-flow's migrations scoped from vendor; ai-guardrails:hitl-status diagnoses the whole setup and exits non-zero with targeted guidance until HITL can actually gate a call.
  • L5 — MCP surface (4th surface). Expose the guardrails to AI clients via laravel/mcp: tools screen_prompt, sanitize_output, recent_injection_audit. Default-OFF behind mcp.enabled; registered as a local server under the handle ai-guardrails.

Hardening notes

  • MCP tools are treated as an external surface: input length capped, the active ruleset version is withheld on benign screens (anti-fingerprinting), and principal ids are omitted from the audit tool by default (opt-in).
  • Compose-not-couple holds: laravel-flow only in src/Hitl, pii-redactor + HTMLPurifier only in src/Output, laravel/mcp only in src/Mcp — all enforced by the architecture test. Every new dependency is suggest (optional) with graceful degradation.

Full changelog: v0.3.0...v1.0.0

v0.3.0 — Enterprise hardening

18 Jun 10:12
0414ace

Choose a tag to compare

Enterprise-hardening line on top of the v0.2.0 admin HTTP API. Additive and backward-compatible — the four controls, the facade, the Artisan surface, and the …api.v1 envelope are unchanged; every new behaviour is a default-safe config toggle.

Highlights

  • E3 — Enforce / monitor / off modes (shadow rollout). Every control gains a modes.<control> dial. monitor detects + audits + emits but does not block — deploy guardrails in observation mode before flipping to enforce. Default enforce (no behaviour change).
  • E4 — Domain events. Every decision dispatches a domain event from the same path that writes the audit/stat record (InjectionBlocked, InjectionObserved, ToolArgumentRejected, DestructiveToolRouted, OutputSanitized, SettingsChanged) so you can wire SIEM / Slack / PagerDuty. Gated by events.enabled.
  • E5 — Audit data hygiene + GDPR retention. audit_hygiene.prompt_storage = redact (default, composes laravel-pii-redactor) | hash | truncate | raw. The sanctioned, actor-audited ai-guardrails:purge command (keep | anonymize | purge) is the only path rows leave the append-only audit.
  • E6 — Settings-change audit. PUT /settings records WHO changed WHAT to the immutable settings-change log (server-derived actor) + dispatches SettingsChanged; new GET /settings/changes.
  • E7 — Tool authorization gate + recursive scoping. Gate tool use behind a Laravel Gate ability (fail-closed) above owner-key re-scoping; owner_key_depth=recursive (default) closes nested IDOR holes.
  • E9 — Mutation testing gate. CI enforces Infection ≥ 80 % MSI over the deterministic security algorithms (via the standalone PHAR + pcov).
  • E9-API — Overview deltas. GET /overview now surfaces each control's effective mode and the active ruleset_version.

Quality

  • 423 tests / 1087 assertions green on PHP 8.3 / 8.4 / 8.5 × Laravel 13; PHPStan level 8; Pint clean; Infection ≥ 80 % MSI.
  • Every toggle tested in both states (three for enforce/monitor/off); audit stores append-only; compose-not-couple boundary enforced by the architecture test.

Full changelog: v0.2.0...v0.3.0

v0.2.0 — Admin HTTP API surface

17 Jun 21:35
7f78099

Choose a tag to compare

v0.2.0 — Admin HTTP API surface

Adds a complete, default-OFF read/config HTTP API for an admin panel, on top of the deterministic four-control core. Every endpoint is enveloped {schema_version, schema, data} and gated behind api.enabled + a required api.middleware stack (boot-throws if enabled without middleware).

Endpoints

  • GET /overview — control health + 24h injection counts
  • GET /audit, /audit/{id}, /audit/trend — append-only injection audit: keyset-paginated list, detail (+ matched span), dialect-safe per-day SQL trend
  • GET /firewall — Control A tool-argument rejections (append-only)
  • GET /output/stats — Control C per-kind neutralisation counts (html_stripped / markdown_sanitized / structured_validation_failure / pii_redaction)
  • GET /approvals, POST /approvals/{token}/approve|reject — Control D HITL queue via laravel-flow (actor principal derived server-side)
  • GET /settings, PUT /settings — runtime-overridable settings (config | database), allow-listed + type-validated; DB overrides overlaid onto live config at boot (fail-safe)
  • POST /try/screen, /try/sanitize — no-persistence sandbox

Stores

New append-only stores (Null/Array/Database) for the audit, firewall, and output-stat logs (the model + builder throw on update/delete), plus a mutable settings store — each behind its own config toggle, default-safe.

Hardening

Untrusted-input posture throughout: string-or-null query params, positive-int keyset cursors, strict ISO-8601 date parsing, LIKE-metacharacter escaping, UTF-8 scrubbing of stored text, fail-safe degradation when stores/tables are unavailable, and a compose-not-couple boundary enforced into the HTTP layer.

317 tests, PHPUnit 12 / PHP 8.3–8.5 × Laravel 13, Pint + PHPStan level 8 clean.