Achievements
Achievements are badges that students unlock on the intranet. They are meant to gamify a project: reward a milestone, a behaviour, or an easter egg with a badge that shows up on the student's profile, in a catalog and in a leaderboard.
A badge is defined once (name, image, scope, visibility), then unlocked either manually from Operator or automatically from your activity's configuration and test results. See Unlocking achievements for the unlock methods, and What students see for the student-facing pages.
This feature is recent and still evolving. Some parts of the original design are not implemented yet.
Anatomy of an achievement
| Field | Description |
|---|---|
slug | Short readable identifier, e.g. first-blood. Lowercase alphanumerics separated by single hyphens. |
name | Displayed name of the badge. |
description | Free text explaining the badge, or what it celebrates. Optional. |
tags | Free-form keywords, to organise and filter badges. |
scopeType | GLOBAL, TENANT or ACTIVITY (see Scopes). |
scopeUri | The tenant or activity the badge belongs to. Empty for GLOBAL. |
visibility | PUBLIC or SECRET (see Public or secret). |
enabled | A disabled badge cannot be unlocked and does not appear to students. |
| image | A PNG of exactly 50×50 pixels, 512 KiB maximum. Pixel art is the intended style. |
Scopes
Every achievement belongs to one of three scopes. The scope decides where the badge exists, who may manage it, and which activities may unlock it.
| Scope | Meaning | scopeUri |
|---|---|---|
GLOBAL | Badge valid across the whole intranet. | (none) |
TENANT | Badge attached to a tenant, e.g. epita-prepa-cs. | <tenantSlug> |
ACTIVITY | Badge attached to one activity. | <tenantSlug>/<activitySlug> |
Achievement URIs
A badge is referenced by its full URI, which is its scope URI followed by its slug:
| Scope | URI shape | Example |
|---|---|---|
GLOBAL | <slug> | survivor |
TENANT | <tenantSlug>/<slug> | epita-prepa-cs/first-blood |
ACTIVITY | <tenantSlug>/<activitySlug>/<slug> | epita-ing-assistants-acu/piscine-2029/memory-leak |
This URI is what you write in your activity.yml and in your test traces. A
slug only has to be unique within its scope: two activities can each define
a bonus badge without colliding, because their URIs differ.
Public or secret
- Public — the badge is listed in the catalog for everyone who can see its scope, even before it is unlocked. Students know it exists and can go after it.
- Secret — the badge stays out of the catalog until the student unlocks it. On another student's profile, a secret badge they unlocked but you did not is shown with its name and description masked, so it does not leak how to get it.
Who can manage achievements
Rights are granted per tenant, through two tenant permissions:
| Action | Required permission |
|---|---|
| Create, update, disable, delete a badge | INTRA_MANAGE_ACHIEVEMENT |
| Give or revoke a badge to or from a student | INTRA_GIVE_ACHIEVEMENT |
For a TENANT-scoped badge, the permission is checked on that tenant. For an
ACTIVITY-scoped badge, it is checked on the tenant owning the activity — the
first segment of the scope URI. GLOBAL badges are reserved to Forge
administrators.
Being a manager of the activity does not, on its own, grant any right over
achievements. Even for a badge scoped to your own activity, you need
INTRA_MANAGE_ACHIEVEMENT or INTRA_GIVE_ACHIEVEMENT on the tenant. The
original design had activity managers inherit those rights; the implementation
does not. Ask your tenant manager or contact the Forge to get the
permission added to your tenant.
Without the matching permission, the achievement endpoints answer 404 rather
than 403: an achievement you may not read is an achievement that does not
exist, as far as the API is concerned.
Managing badges in Operator
Badge definitions live in Operator, under Achievements. From there you can:
- list the badges of the tenants and activities you have access to;
- create a badge, with its image, scope, visibility and tags;
- edit a badge's name, description, tags, visibility and enabled flag;
- replace a badge's image;
- give a badge to a student, or revoke it, from the badge's detail page;
- see who unlocked a badge, and when.
A badge's slug and scope are fixed at creation: they are part of its URI and
of its image path, so they cannot be edited afterwards. Create a new badge if
you need a different slug or scope.
Lifecycle
- Disabling a badge (
enabled: false) hides it from students and blocks any new unlock, manual or automatic. Already unlocked badges stay on the profiles of the students who have them. - Deleting a badge is a soft delete. It disappears from the student-facing pages, stays visible in Operator, and the unlock history is kept. It cannot be edited or given anymore.
- Revoking an unlock removes the badge from that student. A revoked badge will not be granted again by an automatic rule; only an explicit manual give restores it.