AlgoJudge documentation0.1

Files

Reading a package, verifying it, uploading what an evaluation produced, and attaching it.

Reading

GET /api/v1/runner/files/{id}

The package and the submission's files, by the ids the claimed job carried.

A Runner is authorized against the job it holds, not against being a Runner

Without that, any approved Runner could download every test package in the installation.

A file belonging to another problem answers 404, not 403. A file id is opaque, and a 403 would confirm the bytes exist.

That is a rule about file ids and only about them. The job endpoints answer the other way round — a 404 for an id nobody issued, a 403 for a job another Runner holds — because a Runner has to be able to tell a reclaimed job from a Server that has forgotten it. Claiming says why.

sha256, and where it is checked

The integrity field is called sha256 — never hash — and it is a lowercase hexadecimal SHA-256 of the bytes.

It is computed and checked three times over the life of one file, by three different parties, and each check exists because the previous one is a claim rather than evidence:

WhoWhen
the Clientbefore uploading
the Serverover the bytes it actually received, refusing a mismatch
the Runnerover the bytes it actually received, before evaluating

A Runner verifies packageSha256 before evaluating. A mismatch is an infrastructure failure, not a verdict: the submission was never judged, and a truncated download is not somebody's program being wrong.

Hash while streaming rather than by re-reading the file afterwards. The bytes are in hand once, and a second pass hashes whatever is on disk now rather than what came off the wire.

Uploading what an evaluation produced

POST /api/v1/runner/files

Multipart: the bytes as file, with a sha256 text field. The Server recomputes the checksum and refuses to store on a mismatch — 422, checksum_mismatch — exactly as it does for anybody else. It answers the stored file's id, name, media type, size, checksum and creation time.

Attaching

Uploading stores bytes. Attaching says what they are of.

POST /api/v1/runner/jobs/{jobId}/files      { "leaseToken": "…", "fileId": "…", "name": "log" }
POST /api/v1/runner/files/attach            { "fileId": "…", "name": "runner.log" }

A fileId must name a file this Runner uploaded through POST /api/v1/runner/files and nothing points at yet — not one another Runner uploaded, not one a person did, and not one already attached. One upload, one reference: bytes wanted on the attempt and on the Runner are uploaded twice.

The two calls above say so — a 422 file.missing for a file that is none of those, and a 409 attempt.file.duplicate for a name the attempt already carries. A report may also name its attachments inline, which the accepted contract does not describe, and that path skips a bad entry in silence: an implementation reusing an id from somewhere else loses its log with nothing said.

The first attaches to the attempt this Runner holds, and needs the lease token. The second attaches to the Runner itself — a start-up log, a lscpu dump — and replaces the file under that name rather than adding another, so a chatty Runner costs a fixed amount.

name is a role, not a file name. Two are conventional on an attempt:

Name
logthe compiler and sandbox output
detailsthe per-test table

Who may read either is the activity's attachment visibility, one row per name. An unlisted name is managers-only, which is the safe direction: a problem type inventing a third attachment does not accidentally publish it.

Why the per-test table is an attachment

Because a problem may have two thousand tests per attempt. A contest's submissions came to hundreds of megabytes in a database column before it moved out of one.

That is also why extra is bounded at 2 kB: the small document rides a feed many people read, and the large one is a file fetched by whoever is entitled to it.

Upload, attach, then report — the order cannot be worked around

The Server requires the job to be Running to accept an attachment, and reporting ends that.

Report first and the attachment is refused, which means the log explaining a failure is the one thing that goes missing.

What the contract does not carry

The package format. This contract carries the bytes without reading them. standard-io@1 has its own package format specification; another problem type may define its own, and neither is part of the Server–Runner contract.

On this page