Exams (events)
An event is a temporary context attached to an activity, during which part
of that activity becomes reachable only through a dedicated, restricted
environment. The only event type available today is EXAM.
Setting up an exam always takes two steps, in two different places:
- In
activity.yml: you declare the event and you mark which groups are restricted to it. This describes what the exam is. It is versioned with your activity. - In Operator: you create one or more scheduled events (instances of the exam). This describes when and from where the exam runs: token, opening and closing dates, duration, allowed subnets. These are not versioned and can be changed up to the last minute.
How it works
A student can take the exam only if all of these are true:
- They are a member of a group that carries an
eventRestrictionsentry for the event. - That group is subscribed to at least one submission of the activity.
- A scheduled event exists for the event, and it is open.
- Their machine's IP address is in one of the subnets allowed on that scheduled event.
- They know the token of the scheduled event.
Configuring the activity
Declaring the event
Events are declared at the root of the activity, under the events key:
events:
- slug: exam
name: Exam
type: EXAM
managers:
- alpha.manager
- beta.manager
| Property | Description | Required? |
|---|---|---|
slug | Unique name within the activity, without spaces or slashes. | Yes |
name | Name of the event. | Yes |
type | Type of the event. Only EXAM exists today. | No (always EXAM) |
managers | Forge logins of the people allowed to configure the exam in Operator. | No (default []) |
events[].managers is the only thing that grants access to the exam
configuration in Operator. Being an activity manager is not enough: if your
login is not in this list, the event will not show up in Operator for you.
Restricting groups to the event
An event on its own does nothing. What ties students to the exam is the
eventRestrictions key, which is set on groups declared at the root of the
activity:
groups:
- slug: xavier.login
logins:
- xavier.login
eventRestrictions:
- exam
- slug: john.doe
logins:
- john.doe
eventRestrictions:
- exam
A group that carries at least one eventRestrictions entry stops being a
regular group:
- Everything that group is subscribed to disappears from
intra.forge.epita.frand only shows up onexam.forge.epita.fr. - The repository of that group is only reachable through the exam Git host
(
git.exam.forge.epita.fr). Cloning or pushing it from the regular Git server is refused. - During a scheduled event, the student is additionally gated by the token, the time window and the allowed subnets.
groupsEven for an exam where every student works alone, you must declare one group
per student under the top-level groups key, because eventRestrictions
can only be set there.
This also means you must not use subscriptions.logins (nor
subscriptions.criGroups) anywhere in an exam activity.
When the intranet ingests the activity, every login found in a
subscriptions.logins or subscriptions.criGroups list gets a solo group
generated automatically, named after the login and with no event
restriction. That generated group takes precedence over the group you
declared yourself, so it is the unrestricted one that ends up attached to the
submission. The result is an activity that looks correctly configured, but
whose students are not registered for the exam at all: they get
The given token is invalid or you are not enrolled in this exam on the exam
portal, while the subject stays visible on the regular intranet.
Always subscribe your groups with subscriptions.groups, referencing the slug
of the group (not the login).
Subscribing the groups
Groups must be subscribed to at least one submission. A group that carries
eventRestrictions but is not subscribed anywhere is simply ignored and
produces no exam registration.
subscriptions:
groups:
- xavier.login # the slug of the group, not the login
- john.doe
Complete example
---
tenantSlug: example-tenant
slug: example-slug
name: "Example Exam Activity"
managers:
- example-manager
groups:
- slug: xavier.login
logins:
- xavier.login
eventRestrictions:
- exam
- slug: xavier.login2
logins:
- xavier.login2
eventRestrictions:
- exam
events:
- slug: exam
name: Exam
type: EXAM
managers:
- example-manager
assignments:
- maxLearners: 1
name: dummy assignment (can be deleted)
slug: dummy-assignment
submissions:
- handoffType: REGISTRATION_ONLY
slug: dummy-submission
dates:
closingAt: "2024-10-04T17:05:56+02:00"
openingAt: "2024-09-04T17:05:56+02:00"
publishingAt: "2024-09-04T17:05:56+02:00"
subscriptions:
groups:
- xavier.login # this is the slug of the group, not the login
- xavier.login2
Generating one group block per student is tedious. Since the group slug is free-form, using the student's login as the slug (as above) keeps the file readable and makes it easy to generate from a list of logins.
Once the file is written, deploy the activity as usual. The event only appears in Operator after the activity has been ingested.
Scheduling the exam in Operator
The dates in activity.yml control when the assignment is open. They do
not control the exam session. The actual exam window, its duration, its
token and the rooms it can be taken from are configured in Operator, under:
https://operator.forge.epita.fr/{tenantSlug}/{activitySlug}/events
That page lists the events declared in your activity.yml. Click one to get
the list of its scheduled events.
An event can hold several scheduled events. This is how you run the same exam several times: one per session, per room or per promotion, each with its own token, window and subnets.
Creating a scheduled event
Use Schedule new instance. The dialog asks for:
| Field | Description |
|---|---|
| Event Slug | Slug of this scheduled event. It cannot be changed afterwards. |
| Event Token | The string students type on the exam portal to start their session. |
| Opening At | Start of the window during which the exam can be taken. |
| Closing At | End of that window. Nobody can start or keep working after this date. |
| Duration | How long a student gets, in minutes, once they redeem the token. |
The following rules are enforced:
Opening Atmust be beforeClosing At.Durationmust be positive and must fit in the window:Opening Atplus the duration cannot be afterClosing At.- The token must be unique across every non-archived scheduled event on the whole intranet. If the token you picked is already used elsewhere, the form reports a duplicate value — pick another one.
A freshly created scheduled event has no allowed subnet, which means
nobody can use it. Open it and select the subnets before the exam, otherwise
every student is rejected with Client IP not in allowed subnet.
Editing a scheduled event
Clicking a scheduled event opens its details, with two tabs: Details and Submission Shifts.
The Details tab lets you change the token, the window, the duration, the allowed subnets, and two flags:
| Flag | Effect |
|---|---|
| Closed | Administratively closes the exam. Every access is refused with Exam is administratively closed, regardless of the dates. Use it as an emergency stop. |
| Archived | Retires the scheduled event. An archived scheduled event no longer reserves its token, so the token becomes reusable elsewhere. |
Allowed subnets
The Subnets section lists the networks known to the Forge, by room or zone. A student can only start and keep an exam session if the IP address their machine is seen with belongs to one of the subnets you enabled here.
The list itself is maintained by the Forge. If a room you need is missing, contact us.
Submission shifts
A submission shift gives extra time to a specific group on a specific scheduled event — typically for students entitled to extended exam time.
In the Submission Shifts tab, use Add Submission Shift, pick the group
in the list and give a duration in minutes. That duration is added to the
scheduled event's duration for this group only; the opening and closing dates
are unchanged, so a shift cannot push a student past Closing At.
To remove a shift, edit it and set its duration to 0.
What students do on exam day
- They go to
https://exam.forge.epita.frand sign in with their Forge account. - They are asked for the token of the scheduled event. You give it to them at the start of the exam.
- Once the token is accepted, the session starts and they get a page showing
the time remaining. The activity is then browsable on that host, and their
repository can be cloned from
git.exam.forge.epita.fr.
The countdown starts on the first token redemption and is shared by the
whole group. The session ends at the earliest of start + duration (plus any
submission shift) and the scheduled event's Closing At.
The session is bound to the login and IP address used to redeem the token. Git operations are authorized against that session, so a student has to open their session on the exam portal before they can clone or push.
Troubleshooting
| What the student sees | What to check |
|---|---|
The given token is invalid or you are not enrolled in this exam | The token, and the registration. Most of the time this is the subscriptions.logins mistake described above: make sure every student is in a top-level group that has the right eventRestrictions, and that this group is subscribed to a submission. |
Client IP not in allowed subnet | The subnets enabled on the scheduled event, and the room the student is actually in. |
Too Early, exam not opened yet | Opening At. |
Exam is closed | Closing At. |
No time remaining | The duration is over for that group, or Closing At has been reached. A submission shift can give more time. |
Exam is administratively closed | The Closed flag on the scheduled event. |
Failed to find a session linked to your user / machine | The student tried to use Git before opening their session on the exam portal, or from another machine. |
The subject shows up on intra.forge.epita.fr | The group is not restricted to the event. Check eventRestrictions and redeploy. |
| The event does not show up in Operator | Your login is not in events[].managers, or the activity has not been deployed since the event was added. |