feat: Phase 6 — push sources, upload path and Paper plugin - #24
Open
TheMeinerLP wants to merge 2 commits into
Open
feat: Phase 6 — push sources, upload path and Paper plugin#24TheMeinerLP wants to merge 2 commits into
TheMeinerLP wants to merge 2 commits into
Conversation
Final phase of the Apus spec, on top of Phase 5b. Until now Apus pulled
worlds — from an S3 bucket or a Pterodactyl panel. This adds the reverse: a
running Paper server pushes its own world, and a user can upload one
through the UI.
- paper-worldpush: a Paper plugin that copies a live world consistently
(pause autosave, save once, copy, resume) and incrementally, uploading
only region files whose mtime or checksum changed. All copying and
uploading happens off the server thread; only the save itself touches
the main thread, because Bukkit requires it.
- Push and upload connectors in the ingest module, with the wiring so
those source types actually run.
- POST /api/uploads with presigned multipart, so world files never travel
through the API; POST /api/push/{token}, the one endpoint authenticating
with a tenant-bound service token instead of a user login, so a server
plugin doesn't stop working when a person leaves the team.
- Push tokens are provisioned by the operator: cryptographically random,
one per tenant, written only into a Secret, never surfaced in status,
events or logs.
- Upload restrictions verified empirically against real MinIO rather than
asserted: prefix confinement is structural (S3 key is a pure function of
the server-derived tenant namespace); redirecting a presigned part to a
different key returns 403 SignatureDoesNotMatch; exceeding the declared
part size returns 403; the total size cap is enforced at completion via
ListParts, never presigned, so an oversized upload never becomes a
readable object.
- States an unresolved design conflict rather than hiding it: the plugin
pushes many individual raw region files incrementally, but the staged
connector expects one object per version, so a push-triggered ingest
would likely find nothing usable. The upload path (single archive) works
end to end, proven by PushIngestEndToEndTest against real MinIO; the
plugin path needs its own design pass.
- Design spec now opens with a "Stand der Umsetzung" section describing
what shipped, that sharding was deliberately not built after its Phase 4
spike, and what remains open; corrects stale Java 21 references to 25;
fixes a stale exact-match assertion in the ingest/render contract test
that broke once level.dat was legitimately added by the writer.
This branch replaces clean/phase-6-push (PR #16), stacked on
clean2/phase-5b-ui instead of clean/phase-5b-ui. Same content otherwise.
TheMeinerLP
force-pushed
the
clean2/phase-5b-ui
branch
from
August 9, 2026 10:30
cca0062 to
38f9a36
Compare
TheMeinerLP
force-pushed
the
clean2/phase-6-push
branch
from
August 9, 2026 10:30
e3aa309 to
1396a8c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The last phase of the Apus spec. Stacked on PR #7.
Until now Apus pulled worlds — from an S3 bucket or a Pterodactyl panel. This adds the reverse: a running Paper server pushes its own world, and a user can upload one through the UI.
What this delivers
paper-worldpush— a Paper plugin that copies a live world consistently (pause autosave, save once, copy, resume) and incrementally, uploading only region files whose mtime or checksum changed. All copying and uploading happens off the server thread; only the save itself touches the main thread, because Bukkit requires it.POST /api/uploadswith presigned multipart, so world files never travel through the API.POST /api/push/{token}— the one endpoint that authenticates with a tenant-bound service token rather than a user login, because a server plugin must not stop working when a person leaves the team.Upload restrictions, measured rather than claimed
A presigned URL is a transferable credential: what it permits, it permits to anyone holding it. So these were verified empirically against real MinIO rather than asserted.
Caveat stated plainly: verified against MinIO, not independently against Ceph RGW. Same SigV4 mechanism, but that is an inference, not a second measurement.
An unresolved design conflict, stated rather than hidden
The plugin pushes many individual raw region files incrementally. The staged connector expects one object per version. The HTTP call between them is now correct, but an ingest triggered that way would likely find nothing usable.
The upload path (single archive) works end to end and is proven by
PushIngestEndToEndTestagainst real MinIO. The plugin path needs its own design pass.This surfaced because the plugin and the API endpoint were built simultaneously in separate worktrees — each side's assumption was reasonable, and neither could see the other's.
Also in this PR
level.datwas legitimately added by the writer. The check now requires every mandatory object and still rejects genuinely unexpected ones, without breaking on spec-documented sidecars.Known gaps