v1.0.0 — First stable release
First stable release. Plugin is now MATURITY_STABLE.
This release lands eight findings from an internal security audit, adds a PHPUnit test suite covering the new gates, and expands CI to every supported Moodle version.
🔒 Security
| ID | Title | What it does |
|---|---|---|
| F1 | Hidden chapter gate | get_status, request_regen, and the pluginfile handler now reject hidden book chapters unless the caller has mod/book:viewhiddenchapters. Previously a learner with module-level access could narrate any chapter id. |
| F2 | Lang allowlist enforcement | The lang parameter on every external function is server-validated against the admin enabled_languages allowlist. Closes an OpenAI cost-amplification DoS. |
| F3 | Pluginfile require_login scoping |
Uses require_login($course, false, $cm) so enrolment, course visibility, and activity availability rules all apply. |
| F4 | Per-asset content cap | New max_narration_chars admin setting (default 50000) refuses runaway pages before OpenAI is called. |
| F5 | Unused capability removed | local/aireader:purge was declared but never enforced. Gone. |
| F6 | HTTPS-only outbound | New http_guard helper rejects non-HTTPS endpoints, loopback, RFC1918 private addresses, link-local, and the cloud metadata service. Curl is locked to CURLPROTO_HTTPS. |
| F7 | OpenAI error sanitization | Bearer tokens, sk-… keys, and 40+ char opaque identifiers are redacted before being stored on the asset row or written to cron logs. |
| F8 | Narrower web service return types | Segment text now PARAM_NOTAGS, status messages PARAM_TEXT (previously PARAM_RAW). |
✅ Testing
- 31 PHPUnit tests across 5 files covering the URL guard, error sanitizer, override resolution chain, translation cache LRU, asset_manager helpers, and the get_status security gates.
🔁 CI
- Matrix expanded from Moodle 4.5 only to Moodle 4.5 LTS / 5.0 / 5.1 / 5.2 on PHP 8.1 / 8.2 / 8.3 / 8.4 across both PostgreSQL 16 and MariaDB 10.11.
actions/checkoutbumped to v5 (Node.js 24) ahead of GitHub's 2026-06-02 Node 20 deprecation.Gruntstep no longer hascontinue-on-error; CSS regressions and AMD-build drift now fail loudly.- Stylelint clean.
📦 Migration notes
- No schema change. The upgrade savepoint at
2026051900registers themax_narration_charsadmin default; nothing else moves. - If you had a custom role using
local/aireader:purge, that capability is gone — but it was a no-op anyway, so role behavior is unchanged.
📜 Full changelog
See CHANGELOG.md for the complete history from 0.1.0 through 1.0.0.