Files
DongHyeonkaandClaude Opus 5 5f10b791d3 chore: record pre-existing uncommitted repository state
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>
2026-08-11 16:48:43 +09:00

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