phil / certificates-bundle
Certificates of completion for Symfony on Open Badges: courses and their pass criteria, certificates awarded to those who meet them, a PDF certificate with a verification QR code and the signed credential embedded, a public register, and revocation through status lists
Package info
github.com/parler-haut-interagir-librement/certificates-bundle
Type:symfony-bundle
pkg:composer/phil/certificates-bundle
Requires
- php: >=8.5
- ext-intl: *
- ext-mbstring: *
- ext-sodium: *
- doctrine/dbal: ^4.5
- doctrine/orm: ^3.7
- doctrine/persistence: ^4.1
- phil/open-badges: ^0.1@dev
- phil/open-badges-bundle: ^0.1@dev
- phil/paged-media: ^0.1@dev
- phil/paged-media-bundle: ^0.1@dev
- phil/qr-code: ^0.1@dev
- psr/clock: ^1.0
- psr/event-dispatcher: ^1.0
- symfony/config: ^8.2
- symfony/dependency-injection: ^8.2
- symfony/http-foundation: ^8.2
- symfony/http-kernel: ^8.2
- symfony/routing: ^8.2
- symfony/translation-contracts: ^3.6
- symfony/uid: ^8.2
- twig/twig: ^3.21
Requires (Dev)
- ext-zlib: *
- doctrine/doctrine-bundle: ^3.3
- phpunit/phpunit: ^13.4
- psr/log: ^3.0
- symfony/browser-kit: ^8.2
- symfony/clock: ^8.2
- symfony/console: ^8.2
- symfony/css-selector: ^8.2
- symfony/event-dispatcher: ^8.2
- symfony/framework-bundle: ^8.2
- symfony/http-client: ^8.2
- symfony/http-client-contracts: ^3.6
- symfony/lock: ^8.2
- symfony/translation: ^8.2
- symfony/twig-bridge: ^8.2
- symfony/twig-bundle: ^8.2
Suggests
- doctrine/doctrine-bundle: To store courses and certificates with the bundle's own mapping
- symfony/console: For the commands that award, revoke and show certificates
- symfony/lock: To take the status index of an award under a lock shared by every server
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-15 03:40:51 UTC
README
Certificates of completion a Symfony application awards, prints and lets anyone verify: courses and their pass criteria, a PDF with a QR code and the signed credential inside, a public register, revocation, expiry reminders, recertification and credits of continuing education.
phil/certificates-bundle builds on phil/open-badges-bundle and
phil/paged-media-bundle. The application defines its courses — what each
recognizes, the score, the minutes of training and the modules it takes to pass, how long a certificate stays valid —
and awards a certificate when a learner's attainment meets them. Each certificate carries an Open Badges 3.0
credential signed by the issuer, a code for the register and an index in the issuer's status lists.
Its PDF is drawn on a landscape page with a QR code that opens the certificate's page in the register, and the signed credential embedded as an associated file, so that the file proves itself. The register shows any certificate by its code — valid, expired or revoked — and, for each course, the certificates their holders chose to list. Revoking a certificate sets its bit in the status list the issuer publishes, so verifiers elsewhere learn it too.
A certificate that ends is expired, never revoked. Before it ends, an event tells the application to remind its holder; the holder is then recertified, with the credits of continuing education gathered meanwhile or a new attainment, and receives a new certificate linked to the one it renews.
Status
| Part | State |
|---|---|
| Courses, pass criteria (score, minutes, modules), validity in months, retiring, the end of a course | Implemented and tested |
| Awarding: criteria checked, Open Badges credential signed, recipient kept as a salted hash | Implemented and tested |
| The PDF: native drawing, QR code, credential embedded through Gotenberg as a PDF/A-3 associated file, optional PDF/A-3b and signature | Implemented and tested |
| The register: lookup by code, certificate pages, course pages with listed certificates, PDF and credential downloads | Implemented and tested |
| Revocation through Bitstring Status Lists, split into lists of a fixed size | Implemented and tested |
| Doctrine mapping and repositories | Implemented and tested |
Awards under a lock of symfony/lock, started again when the storage finds the index taken; the events CertificateAwarded and CertificateRevoked |
Implemented and tested |
Expired distinct from revoked; reminders before the end through CertificateExpiring, once per threshold |
Implemented and tested |
| Recertification: a new certificate linked to the one it renews, by credits of continuing education or an attainment | Implemented and tested |
| Credits of continuing education by member and period, toward a course, recorded once per source | Implemented and tested |
| Console commands: define a course, award, recertify, revoke, status, export of a credential, reminders, credits | Implemented and tested |
| The QR code of the PDF decoded back to the certificate's address | Tested |
| The shape of the exported credentials against what Open Badges 3.0 describes, offline | Tested |
| 1EdTech conformance testing of the issued credentials | In progress: this version is not certified; the procedure and the export are ready, and Validation says how to verify a certificate today |
Documentation
| Document | What it covers |
|---|---|
| Installation | Requirements, the bundles it builds on, the schema, the routes. |
| Configuration | Every option, with its default. |
| Courses and awarding | Defining courses and their criteria, awarding a certificate. |
| The PDF | What the certificate shows, the fonts, the embedded credential, the archival PDF, the signature. |
| The register | The pages and downloads the routes serve, and what they disclose. |
| Revocation | Revoking a certificate, the status lists. |
| Expiry and recertification | The end of certificates and courses, reminders, recertification, credits of continuing education. |
| Console commands | Defining courses, awarding, recertifying, revoking, showing, exporting, reminding and crediting from the console. |
| Validation | Where 1EdTech conformance testing stands, how to verify a certificate today, what is checked offline, and the run of 1EdTech's validator. |
| Extension points | The repositories, the URLs, the events, the print subject, the layout, the translations, other status lists. |
| Testing | The bundle's tests, and testing an application that awards certificates. |
| Reference | Every class of the bundle, with its role. |
Quick start
composer require phil/certificates-bundle
# config/routes/phil_certificates.yaml phil_certificates: resource: '@PhilCertificatesBundle/config/routes.php' prefix: /certificates
use Phil\CertificatesBundle\Application\Awarding; use Phil\CertificatesBundle\Application\Courses; use Phil\CertificatesBundle\Domain\ValueObject\Attainment; use Phil\CertificatesBundle\Domain\ValueObject\PassCriteria; $courses->define('first-aid', 'First aid', 'The gestures that save lives.', 'Score 70 % or more on the final assessment.', new PassCriteria(minimumScore: 70), validityMonths: 24); $certificate = $awarding->award('first-aid', 'Ada Lovelace', 'ada@example.org', new Attainment(score: 84), listed: true); // https://<site>/certificates/<code>, its PDF at /certificates/<code>/certificate.pdf
Conformance
1EdTech conformance testing is in progress, and this version is not certified by 1EdTech. A certificate is verified
today in the register by its code, through the verification page of phil/open-badges-bundle, by any Verifiable
Credentials 2.0 verifier that reads VC-JWT or eddsa-rdfc-2022, or by running 1EdTech's validator against a
deployed issuer; see Validation.
Requirements
PHP 8.5 or later with intl and sodium, Symfony 8.2 or later, phil/open-badges-bundle and
phil/paged-media-bundle registered. Embedding the credential in the PDF needs Gotenberg; the register needs
TwigBundle; the bundled storage needs DoctrineBundle; the commands need the Console component; the lock of the
status index needs symfony/lock.
Contributing
Contributions are welcome on the PHIL monorepo: read the contribution guide and the code of conduct. Report a vulnerability privately, as the security policy explains, never in a public issue.
License
MIT, © Philippe Gamache, doing business as Le Gnome Archiviste; a Parler Haut Interagir Librement project. See LICENSE.