Snapshot of the in-flight state that already existed, identically, in both this worktree and the main checkout before this session began: the initial HTTP Client platform implementation (previously untracked), the redis-lab removal, and the JPA / object-storage / notification integration work. Kept separate from this session's HTTP Client review response, which lands in the following commit, so the two bodies of work stay reviewable apart. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
4.4 KiB
4.4 KiB
Fileserver HTTP contract
Every public endpoint is listed here. FileserverDocumentationCoverageTest scans the controllers
and fails if one is missing, so this file cannot silently fall behind the code.
Public endpoints
| Method | Path | Success | Notes |
|---|---|---|---|
| POST | /v1/files |
201 READY, 202 VERIFYING |
multipart single upload |
| POST | /v1/files:raw |
201, 202 |
the whole request body is the file |
| POST | /v1/files:batch |
200 |
ordered per-part results; explicitly non-atomic |
| GET | /v1/files/{fileId} |
200 |
public metadata; never a content key or path |
| GET | /v1/files/{fileId}/content |
200, 206, 304 |
download |
| HEAD | /v1/files/{fileId}/content |
200, 304 |
identical headers, no body |
| DELETE | /v1/files/{fileId} |
202, 204 |
logical delete first |
| POST | /v1/files/{fileId}:copy |
202 |
create-only target |
| POST | /v1/files/{fileId}:move |
200 |
logical namespace change only |
| OPTIONS | /v1/uploads |
204 |
tus capability discovery |
| POST | /v1/uploads |
201 |
tus creation |
| HEAD | /v1/uploads/{uploadId} |
204 |
tus offset |
| PATCH | /v1/uploads/{uploadId} |
204 |
tus append |
| DELETE | /v1/uploads/{uploadId} |
204 |
tus termination |
| POST | /v1/experimental/draft12/uploads |
201 |
Experimental; off by default |
| PATCH | /v1/experimental/draft12/uploads/{uploadId} |
204 |
Experimental; off by default |
Management endpoints
Reachable only where both app.fileserver-platform.enabled=true and
app.fileserver-platform.admin.enabled=true, gated at the servlet chain on
app.fileserver-platform.security.admin-roles, and intended for a management
port rather than the public one.
| Method | Path |
|---|---|
| GET | /internal/fileserver/storage-health |
| GET | /internal/fileserver/capabilities |
| GET | /internal/fileserver/orphans |
| POST | /internal/fileserver/orphans:reconcile |
| POST | /internal/fileserver/files/{fileId}:reverify |
| POST | /internal/fileserver/files/{fileId}:force-delete |
| GET | /internal/fileserver/uploads/incomplete |
| POST | /internal/fileserver/uploads:cleanup |
Status codes
| Status | Condition |
|---|---|
200 |
metadata, full GET, batch result, move |
201 |
file or upload created |
202 |
verification or physical cleanup deferred |
204 |
append, cancel, bodyless update |
206 |
satisfiable Range |
304 |
validator matched on GET or HEAD |
400 |
malformed header or header combination |
401 |
unauthenticated |
403 / 404 |
denied, or hidden under the existence-hiding profile |
409 |
state, offset, or lease conflict |
410 |
expired upload resource |
411 |
require-content-length profile with no length |
412 |
precondition failed |
413 |
size or quota policy violation |
415 |
upload media type not accepted |
416 |
unsatisfiable Range; carries the real length |
422 |
digest, signature, or scanner rejection |
429 |
transfer admission or rate limit |
503 |
storage or scanner unavailable |
504 |
downstream timeout |
507 |
out of storage capacity |
Failure body
Every failure answers application/problem+json with a stable code and its URN:
{
"type": "urn:fileserver:problem:upload-offset-mismatch",
"title": "Upload offset mismatch",
"status": 409,
"code": "UPLOAD_OFFSET_MISMATCH",
"retryable": true,
"ambiguous": false,
"reconciliationRequired": false,
"traceId": "..."
}
The server-side exception message never appears. ambiguous is the field a client must read before
retrying: an ambiguous failure may already have taken effect.
Header contract
| Header | Contract |
|---|---|
Content-Type |
client value is a claim; the verified type is stored separately |
Content-Disposition |
attachment by default; scriptable types are never inline |
Accept-Ranges |
bytes |
Range |
single range by default; multi-range only under an explicit budget |
Content-Range |
actual range on 206; the unsatisfied form on 416 |
ETag |
strong validator derived from the SHA-256 |
Last-Modified |
metadata publication instant, never a filesystem timestamp |
Cache-Control |
private, no-store by default |
X-Content-Type-Options |
always nosniff on a download |
Retry-After |
on retryable 409, 429, 503, and 504 |
X-Accel-Redirect |
internal only; never forwarded to a client |