Files
studipsync/AGENTS.md
2025-11-14 16:02:27 +01:00

6.9 KiB
Raw Blame History

StudIP Sync Agent

Goal

Implement a command-line tool in Rust that performs a one-way sync of files from Stud.IP (JSON:API at Uni Trier) to the local filesystem. [web:68]
The local directory structure must be: <semester>/<course>/<studip-folders>/<files>. [web:88]

Environment

  • Target OS: Linux (Arch, follow XDG base directory conventions). [web:135]
  • Language: Rust (2021 edition).
  • Use reqwest + tokio for HTTP and async, serde for JSON and TOML, and standard Rust CLI patterns. [web:111][web:131]
  • Build as a single binary named studip-sync.

Code Quality: Formatting and Linting

  • Use rustfmt as the standard formatter for all Rust code; code must be kept cargo fmt clean. [web:144][web:148]
  • Use clippy as the linter; the project must pass cargo clippy --all-targets --all-features -- -D warnings with no warnings. [web:144][web:149][web:159]
  • Add a rustfmt.toml and (optionally) a clippy.toml where needed, but prefer default settings to stay idiomatic. [web:144][web:151]
  • If CI is present, include steps that run cargo fmt --all -- --check, cargo clippy --all-targets --all-features -- -D warnings, and cargo test. [web:147][web:150][web:159]

API

  • Base URL: configurable, default https://studip.uni-trier.de. [web:68]
  • JSON:API root: <base_url>/jsonapi.php/v1. [web:68]
  • Authentication: HTTP Basic (username/password), encoded once as base64 and stored in TOML config. [web:1][web:118]
  • Use JSON:API routes such as:
    • GET /users/me to resolve the current user and related links (courses, folders, file-refs). [web:68][web:106]
    • GET /users/{user_id}/courses to list enrolled courses. [web:85]
    • Course-specific routes for folders and documents/file-refs, using the documented JSON:API routes for Stud.IP (e.g. /courses/{course_id}/documents). [web:88][web:93]

Configuration (TOML, including paths)

All configuration and state in this project must use TOML. [web:131]

  • Primary config file: XDG-compliant, e.g. ~/.config/studip-sync/config.toml. [web:131][web:135]
  • Example config.toml keys:

base_url = "https://studip.uni-trier.de"
jsonapi_path = "/jsonapi.php/v1"

# Authorization header value without the "Basic " prefix, base64("username:password").

basic_auth_b64 = "..."

# Local base directory for synced files.

download_root = "/home/<user>/StudIP"

# Maximum concurrent HTTP downloads.

max_concurrent_downloads = 3

  • The download_root directory determines where the tool creates semester/course/folders/files. [web:68]
  • The config file must be created with mode 0600 and never contain anything except necessary settings and the base64-encoded credential. [web:118][web:122]

Credentials and auth

  • On first run (or when running studip-sync auth), prompt interactively for username and password. [web:118]
  • Construct username:password, base64-encode it, and store the result as basic_auth_b64 in config.toml. [web:1][web:118]
  • At runtime, send Authorization: Basic <basic_auth_b64> on all JSON:API requests. [web:1][web:68]
  • Never log or print the password, basic_auth_b64, or full Authorization header. [web:118][web:128]
  • On HTTP 401 or 403 from a known-good endpoint like /users/me, treat this as auth failure:
  • Non-interactive runs: exit with a non-zero code and a clear message asking the user to run studip-sync auth. [web:118]
  • Interactive runs: optionally prompt again and update basic_auth_b64.

State (TOML as well)

  • State file must also be TOML, stored under XDG data dir, e.g. ~/.local/share/studip-sync/state.toml. [web:131][web:135]
  • State is non-secret cached data:

user_id = "cbcee42edfea9232fecc3e414ef79d06"

[semesters."ws2526"]
id = "830eb86ad41d8f695d016647d557218a"
title = "Wintersemester 2025/26"

[semesters."ss25"]
id = "..."
title = "Sommersemester 2025"

[courses."830eb86a-...-course-id"]
name = "Rechnerstrukturen - Übung"
semester_key = "ws2526"
last_sync = "2025-11-14T12:34:56Z"

  • The tool should:
  • Cache user_id after the first successful /users/me call. [web:68][web:106]
  • Cache semester IDs and human-readable keys (ws2526, ss25) after discovering them via JSON:API. [web:68]
  • Optionally store course and last-sync metadata to reduce API calls (e.g. using filter[since] if supported). [web:88][web:93]

Directory structure

  • All downloads must go under download_root, respecting: download_root/<semester_key>/<course_name>/<studip_folder_path>/<file>.
  • semester_key is resolved from the state file (ws2526, ss25, etc.). [web:68]
  • course_name and Stud.IP folder/file names should be normalized to safe filesystem paths (handle spaces, umlauts, and special characters) while staying human-readable. [web:68][web:104]

Sync semantics

  • One-way sync: Stud.IP → local filesystem only; never upload or modify data on Stud.IP. [web:68]
  • Default behavior:
  • Create directories and download new or changed files under download_root.
  • Never delete local files by default.
  • Provide optional flags:
  • --prune: delete local files that no longer exist on Stud.IP.
  • --dry-run: print planned actions (creates/downloads/deletes) without modifying the filesystem.

Minimizing API usage and load

  • Use cached user_id and semester mappings from state.toml to avoid repeated discovery calls. [web:68]
  • When listing course documents, use JSON:API pagination and any available filters (e.g. filter[since]) supported by Stud.IPs document routes. [web:88][web:93]
  • Avoid re-downloading unchanged files by checking JSON:API attributes such as ID, size, and modification time against the stored state. [web:93][web:106]

CLI interface

  • Binary name: studip-sync.
  • Subcommands:
  • studip-sync auth: set or update credentials; writes config.toml.
  • studip-sync sync: perform sync from Stud.IP to download_root.
  • studip-sync list-courses: list known courses with semester keys and IDs from state (refreshing if needed).
  • Use standard exit codes:
  • 0 on success.
  • Non-zero on errors (auth failure, network error, JSON parse error, filesystem failure). [web:118]

Performance & safety

  • Limit concurrent HTTP requests (configurable via max_concurrent_downloads, default 3). [web:68]
  • Stream file downloads directly to disk; do not load entire files into memory. [web:88]
  • Handle HTTP and I/O errors gracefully with clear messages and without panicking.
  • Keep dependencies minimal and use idiomatic Rust project structuring for maintainability. [web:136][web:137]

Extensibility

  • Internally, separate concerns into modules:
  • config (TOML load/save for config and state).
  • studip_client (JSON:API HTTP client).
  • sync (sync logic and directory mapping).
  • cli (argument parsing, subcommands). [web:136][web:137]
  • Represent core entities as Rust types: Semester, Course, Folder, FileRef. [web:68][web:93]
  • Design so that a future MoodleProvider can implement the same internal traits (e.g. LmsProvider) without changing the CLI surface.