POST /api/media/delete with a page deletes any file in the bundle, the page's own _index.md included #269
Labels
No labels
bug
enhancement
needs-triage
ready-for-agent
ready-for-human
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/deckle#269
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
POST /api/media/deletewith a bundle reference ({ref, page}) removes anyregular file in the page's bundle directory that passes the traversal guard:
the page's own
_index.md, a translation_index.de.md, a straynotes.txt,a dotfile. None of these is a media resource, and
.mdfiles are pages andtranslations whose own operations handle links and translation state; this
route does none of that and only takes a
media deletesnapshot.Desired: a bundle delete removes a file only when the bundle listing
(
GET /api/media/bundle) would show it. Any other name answers404 library.refNotFound {ref}, leaves the file untouched and takes nosnapshot. Library references are unaffected.
Reproduced during triage with a server test: deletes of
_index.md,_index.de.mdandnotes.txtagainstservices/_index.mdall answered200 {}and removed the files.Decisions
in the bundle directory, not a
.mdfile, whose leading bytes sniff as anallowed type. Reason: the listing is the editor's view of the bundle's media
and the route's contract is a media delete; everything else in a bundle has
an owner elsewhere (page delete, translation delete) or no business being
touched through this route.
404 library.refNotFound, the code a missing filealready gets. Reason: the route resolves media references; a name that is not
a media resource of the bundle is not a reference it knows, and reusing the
code needs no new registry entry or client catalog string (ADR 0020) for a
state the editor never produces.
rule has one owner). The predicate the listing in
internal/server/media.goapplies inline today (skip directories, skip
.md, sniff the type) becomesone named function that both the listing and the delete call. Its home is
the agent's call;
internal/mediabesideBundleRefandDeleteis thenatural one. No "same as the listing" comment anywhere.
that does not decode and serves no bytes.
Acceptance criteria
_index.md, of_index.<lang>.md, of anon-media file and of a dotfile each answers
404 library.refNotFoundwith
args.ref, the file is still on disk, and no WIP snapshot was taken.200 {}and removes the file (the existing bundle delete test keeps passing).
deleted, and a file the listing omits cannot.
.md/sniff rule is evaluated in one function; the listing and thedelete both call it and the server has no second copy.
docs/api.md, sectionPOST /api/media/delete: states that a bundlereference must name a file the bundle listing shows, and the 404 line
covers that case.
GET /api/media/bundleneeds no change.go test ./...andgo vet ./...pass, including the route docs test ininternal/server.Out of scope
operations.
Verification
Original report
Found while verifying docs/api.md for #264.
handleMediaDelete(internal/server/media.go, bundle branch) accepts any bare filename as a bundle reference (media.IsBundleRef: non-empty, no/) and callsmedia.Delete(dir, ref), which only guards against traversal. Soremoves the page's own content file (and
_index.de.mdwould remove a translation) outside the page operations: no translation handling, no link rewriting, only amedia deletesnapshot.GET /api/media/bundlenever lists.mdfiles, so the editor does not offer this, but the route accepts it.Expected: a bundle delete refuses a reference that is not a bundle resource the bundle listing would show (at least every
.mdfile), with a coded 400/404.docs/api.md documents the route as the code behaves today.