Rostera Manual, as shipped in the download
Rostera — User Manual
Shift scheduling: who is on, when, and for how long. Version 3.1.4 [src: app/controllers/api.php:17].
About this manual
Every statement here was written by reading Rostera's own source, and each one carries the file it came from in a bracketed src marker. Paths are relative to the folder this docs directory sits in. If a sentence disagrees with the application, the application is right and this manual has a bug — the markers exist so you can check rather than take our word for it.
Nothing is described that the code does not do. Where something is deliberately limited, that is said plainly rather than left out.
What Rostera is
It plans shifts only — who is scheduled, when, and for how long [src: app/src/Shift.php:22].
It is not payroll, and the source rules out four separate things: it holds no pay rates or wages, touches no money, cards or bank rails, has no time clock and no biometric capture, and initiates no payments [src: app/src/Shift.php:23]. It records planned shifts and their hours.
That third exclusion is worth noticing. Rostera records what was rostered, not what was worked. If you need attendance capture, this is not that product.
Everything is whole minutes
A clock time is minutes since midnight — 09:30 is 570 — and a duration is a whole number of minutes, so an eight-hour shift is 480 [src: app/src/Shift.php:10].
There is no float anywhere in the duration or total path, so weekly totals are exact and never drift [src: app/src/Shift.php:12].
⭐ The daylight-saving handling, and why there are two different answers
This is the most careful piece of engineering in the product, and it turns on a distinction most schedulers get wrong.
A shift's real duration is computed in your business timezone with real calendar instants [src: app/src/Shift.php:103], so a shift that spans a clock change counts the time actually elapsed rather than the time the clock appears to show.
Running the product's own arithmetic on a New York shift rostered 01:00 to 05:00:
| Date | Wall clock says | Real duration |
|---|---|---|
| Ordinary day | 240 min | 240 min |
| Spring forward (the 02:00 hour does not exist) | 240 min | 180 min |
| Clocks back (the 01:00 hour happens twice) | 240 min | 300 min |
The source states the spring case explicitly [src: app/src/Shift.php:15]; the autumn case follows from the same mechanism, and is arguably the one that matters more — somebody genuinely works an extra hour that night, and the total says so.
But overlap uses wall-clock time, deliberately
Double-booking is checked on a wall-clock day-ordinal timeline, and the source gives the reason in a parenthesis worth reading twice: double-booking is about the clock the roster is written in [src: app/src/Shift.php:18].
That timeline is anchored at UTC midnight, so it is DST-immune [src: app/src/Shift.php:19].
Two different questions, two different correct answers: "how long did they actually work?" is a question about elapsed time, and "are these two shifts the same shift?" is a question about the roster. Conflating them would break one or the other.
Overlap and clashes
A shift ending exactly when the next begins is not a clash. Intervals are half-open, so a clean hand-over or back-to-back shift passes, and only a genuinely shared minute counts [src: app/src/Shift.php:217].
Overnight shifts are handled properly: a midnight-crossing shift extends past its own day's boundary, so an overnight shift on Monday correctly meets an early Tuesday one [src: app/src/Shift.php:205].
An open shift belongs to nobody and never double-books [src: app/src/Shift.php:232].
Weeks
The week-start day is configurable rather than assumed [src: app/src/Shift.php:178], and the week's dates follow from it [src: app/src/Shift.php:187].
Copy last week
Copy last week on the rota copies the week before into the week on screen, as drafts [src: app/controllers/app.php, _ro_copy_week()]. Every copy goes through the same checks as a shift made by hand: the times are re-read, an overnight shift gets its true length for its new date (an hour longer or shorter across a clock change), and the double-booking guard runs. A copy that would double-book someone, or belongs to someone no longer active, is skipped and counted in the message; an identical shift already in the week is not copied again. Nothing is published until you publish the week. Members and administrators can use it; viewers cannot.
Draft and published
Two statuses [src: app/src/Shift.php:35], with anything unrecognised falling back to draft rather than to published [src: app/src/Shift.php:262] — the safe direction, since a draft rota shown as published is worse than the reverse.
Publishing is an administrator's act, not an editor's [src: app/controllers/v3.php:23].
Users and roles
Three roles, and the source summarises them in one line: a viewer reads the rota, a member edits shifts, and an admin also publishes, decides swaps, and owns settings [src: app/controllers/v3.php:23].
| Permission | viewer | member | admin |
|---|---|---|---|
shift.read, employee.read, report.read | yes | yes | yes |
shift.write | — | yes | yes |
swap.offer | — | yes | yes |
| publishing, deciding swaps, settings | — | — | yes |
Note the pairing: a member may offer a swap but not decide one. Offering and approving are separated the same way they are in the leave product — the person affected is not the person who rules on it.
Backups are for administrators
Both backup downloads — the JSON export and the SQLite file — ask for the administrator role [src: app/controllers/api.php, backup_json() and backup_sqlite()]. Viewer and member accounts are refused, and the Security page shows the backup buttons to administrators only. Before 3.1.4 a sign-in alone was enough.
One server name
The REST interface, the agent specification and its unauthenticated probe all name the server rostera [src: app/controllers/v3.php]. Before 3.1.4 the probe said Rostera, so a client probing with GET and one calling with POST were told two different names.
The API and agent access
Five tools are exposed to an agent [src: app/controllers/v3.php:75]: listing shifts, shift detail, open shifts and a roster period on the read side; assigning a shift on the write side.
What Rostera does not do
It does not do payroll [src: app/src/Shift.php:23] — no rates, no wages, no payments.
It does not capture attendance [src: app/src/Shift.php:23]. There is no time clock and no biometric capture; it records what was rostered.
It does not count a clean hand-over as a clash [src: app/src/Shift.php:217].
It does not double-book an open shift [src: app/src/Shift.php:232].
It does not let a member publish a rota or decide a swap [src: app/controllers/v3.php:23].
It does not report wall-clock hours as worked hours across a clock change [src: app/src/Shift.php:103].