attendance42lyon
Local HTTP API for the 42 Lyon attendance intranet.
The intranet gives you a web page. This gives you curl.
A small daemon holds your session and exposes your attendance data on
127.0.0.1:8420, so a waybar module, a GNOME extension or a shell script can
read your hours without reimplementing the login.
$ curl -s -H "Authorization: Bearer $(cat ~/.config/attendance42/token)" \
127.0.0.1:8420/v1/month | jq '{worked, requiredSoFar, balanceSoFar}'
{
"worked": 82740,
"requiredSoFar": 302400,
"balanceSoFar": -219660
}
All durations are integer seconds.
Install
uv tool install attendance42lyon
attendance install
attendance install writes a --user systemd unit, starts it, and waits for
the daemon to answer. It needs a graphical session: signing in opens a real
browser window.
$ attendance install
· /home/you/.local/bin/attendance-daemon
✓ attendance42.service running on 127.0.0.1:8420
Then, once your session expires:
$ attendance login
→ browser opened, sign in there
✓ signed in
That is the whole CLI — install, login, uninstall. Reading data is the
API's job.
Endpoints
| Route | Returns |
|---|---|
GET /healthz |
liveness, no authentication |
GET /v1/month |
current month |
GET /v1/months/{YYYY-MM} |
a given month |
POST /v1/login |
opens the browser, replies 202 immediately |
Everything except /healthz needs Authorization: Bearer <token>.
Full reference, including every field and error state: docs/API.md.
Interactive docs
The daemon serves its own OpenAPI schema. With the service running:
- http://127.0.0.1:8420/docs — Swagger UI, with an Authorize button. Paste the token once and you can fire real requests from the browser.
- http://127.0.0.1:8420/redoc — the same schema, laid out for reading.
- http://127.0.0.1:8420/openapi.json — the raw spec, to generate a client.
Written reference: docs/API.md.
Credentials and storage
Your 42 password never reaches this tool. Signing in happens on the real 42 page, in a real browser. What comes back is a session cookie.
That cookie is stored in your system keyring — KWallet, GNOME Keyring, or whatever implements the Secret Service API on your desktop. It is encrypted at rest by the keyring, unlocked with your session.
If no keyring is available, the SDK falls back to
~/.local/state/attendance-42/state.json at mode 0600. On Linux that file is
plaintext, protected by file permissions alone. If your desktop has no
keyring, know that this is the trade-off.
The API token is a separate thing, and is not in the keyring: the daemon
generates it on first start in ~/.config/attendance42/token, mode 0600, as
plaintext. It has to be readable without unlocking anything, since the daemon
starts with your session. It is not your 42 password — it only proves a local
client is you, because anything on the machine can reach the loopback port.
It is read once at startup. To rotate it, delete the file and restart the service; every client then needs the new value.
How the session works
The daemon never opens a browser on its own. When your 42 session dies it
answers 503 with a state a client can act on:
{ "state": "unauthenticated", "hint": "POST /v1/login" }
A GNOME extension shows a button, waybar shows a marker, you decide when to sign
in. POST /v1/login then opens Chrome, you authenticate on the real 42 page, and
the daemon keeps the cookie in your keyring. The tool never sees your
password.
While a login is in progress, reads answer 503 logging_in instead of blocking
for three minutes.
Requirements
- Linux with systemd
--user - Python 3.13+
- X11. Wayland is untested for now — the unit imports
DISPLAYandXAUTHORITYfrom the session. Chrome runs under XWayland, so it may well work, but nothing has been verified. Reports welcome. - A system keyring (KWallet, GNOME Keyring, …)
- Google Chrome, for the login window
Troubleshooting
attendance install fails on /healthz — the daemon started and died. The
last journal lines are printed with the error; a missing dependency is the usual
cause.
{"state": "unauthorized"} — the local token is wrong. Check that your
client reads ~/.config/attendance42/token, and that $XDG_CONFIG_HOME is the
same for the daemon and for you.
{"state": "unauthenticated"} — the 42 session expired. Run
attendance login.
Nothing on port 8420 after a uv tool upgrade — re-run attendance install
to refresh the unit.
Contributing
git clone https://codeberg.org/Z-OxO/attendance-lyon-api
cd attendance-lyon-api
uv sync
uv run python -m attendance42lyon.daemon
Issues and patches: https://codeberg.org/Z-OxO/attendance-lyon-api/issues
License
MIT. Not affiliated with 42 or 42 Lyon.
Metadata
Release files for attendance42lyon 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| attendance42lyon-0.1.2.tar.gz | 16.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| attendance42lyon-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 32.9 kB
Release files / attendance42lyon-0.1.2.tar.gz
| Download URL | attendance42lyon-0.1.2.tar.gz |
|---|---|
| Size | 16.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
23495e2d4985b7db5045df758405d47c5717939c079c9fa7b0ac897f7c094a0d
|
|
BLAKE2b-256 checksum How to use checksums |
22e204b2cdf3aba1f747378113a08b6affd546bf92d44aa2f4ed49a97de6bb59
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / attendance42lyon-0.1.2-py3-none-any.whl
| Download URL | attendance42lyon-0.1.2-py3-none-any.whl |
|---|---|
| Size | 16.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4952288463d4013e3f5970de23441942be04716c3e81594e332a13bc512f9f5d
|
|
BLAKE2b-256 checksum How to use checksums |
ffbee4f2cde1521be11bada81aa98b4b2803d1c3a751b3fa2fe7dafae5b10068
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for attendance42lyon 0.1.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.