Skip to content

docs(micropub): design proposed media-endpoint extensions - #374

Merged
davidwkeith merged 3 commits into
mainfrom
claude/issue-363-readiness-69707d
Jul 23, 2026
Merged

docs(micropub): design proposed media-endpoint extensions#374
davidwkeith merged 3 commits into
mainfrom
claude/issue-363-readiness-69707d

Conversation

@davidwkeith

Copy link
Copy Markdown
Owner

Summary

Adds the reviewed design for the proposed media-endpoint extensions to
spec/packages/micropub.md, closing #363 (roadmap #354). The section adopts
three upstream IndieWeb proposals as one feature gated behind
extensions.proposed (off by default, existing media behaviour byte-identical
when disabled):

  • Media q=source — newest-first listing (limit/offset, matching the
    post list) and by-URL lookup, returning the interop-consensus
    url/published/mime_type shape; requires the media scope (deliberate,
    justified difference from the post endpoint's scope-less q=source).
  • Upload response body201 + Location gains the upstream minimum
    { "url": ... } JSON body when enabled.
  • action=delete (+ package-defined undelete) — requires both delete
    and media scopes per the upstream proposal; strict URL-ownership
    validation (exact ${mediaEndpoint}/<key> match, UUID-format key) defends
    against forged URLs and path/key confusion.

Storage lifecycle: a new micropub_media metadata table in the existing
MICROPUB_DB binding (needed for chronological listing — R2 keys are random
UUIDs), and recoverable soft deletion via a .trash/<key> R2 prefix with a
load-bearing copy→delete→mark ordering, a four-state retry-convergence table,
and purge delegated to an R2 lifecycle rule (mediaTrashRetentionDays,
default 30). Orphaning against posts is explicitly deliberate (no reference
counting). Bindings and Config sections updated accordingly.

Design only — no implementation yet; the section states this explicitly,
mirroring how other proposed-extension designs landed (#359#362#366 etc.).

Packages affected

@dwk/micropub (spec only)

Checklist

  • Read the relevant spec(s) under spec/packages/ and updated them if
    behaviour changed
  • Added/updated colocated tests (src/*.test.ts) — not applicable, docs-only design; required coverage is enumerated in the new section for the implementation PR
  • Ran the local CI gate: pnpm lint && pnpm format:check && pnpm typecheck && pnpm build && pnpm test
  • Added a changeset (pnpm changeset) — not applicable, spec/ docs only, no published package content changes
  • Updated catalog.json / conformance/status.json — not applicable, no new worker or conformance change

🤖 Generated with Claude Code

Add the reviewed design for the proposed media-endpoint extensions to
spec/packages/micropub.md, per #363: media q=source (list and by-URL),
the JSON upload response body, and a recoverable, principal-scoped
action=delete backed by a .trash/ R2 prefix and a new micropub_media
metadata table, all gated behind extensions.proposed (off by default).

Design only — no implementation yet.

Closes #363

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@davidwkeith davidwkeith left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed against CONTRIBUTING.md: PR title (docs(micropub): design proposed media-endpoint extensions) is correct Conventional Commits style, the template's Summary/Packages affected/Checklist headings are kept verbatim, and every unchecked box carries a one-line reason — all compliant.

One design inconsistency worth resolving before/at implementation time, left as an inline comment: the new "unconditional" micropub_media metadata write introduces a 500 failure mode on upload even when extensions.proposed is off, which conflicts with this doc's own "observable behaviour is unchanged [when disabled]" claim a few paragraphs earlier. Everything else in the design (scope pairing, URL-ownership validation, the trash state machine, retention/purge story) is internally consistent and matches the patterns already established by the q=geo and Contacts sections above it.


Generated by Claude Code

Comment thread spec/packages/micropub.md
davidwkeith and others added 2 commits July 22, 2026 21:15
Address review: the unconditional micropub_media insert must not change the
media endpoint's failure surface while extensions.proposed is off. Split the
insert-failure handling by enablement — fail-closed (delete blob, 500) only
when the group is on and the row is load-bearing for q=source; best-effort
(log, keep blob, 201) when it is off, preserving today's guarantee that a
successful R2 write means a successful upload.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A GET of the media endpoint root is 405 Method Not Allowed today, not an
unsupported-query 400 — the byte-identical disabled-path claim must match.
Specify the enabled-path GET fallback (unknown/absent q → 400) explicitly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@davidwkeith davidwkeith left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed this design-only spec change against CONTRIBUTING.md — no issues found.

CONTRIBUTING.md conformance: PR opened from the template with Summary/Packages affected/Checklist headings intact, Conventional Commits title (docs(micropub): design proposed media-endpoint extensions), and the two unticked checklist items (tests, changeset) each carry a correct one-line reason rather than being silently unchecked or deleted — appropriate for a docs-only design PR per this repo's own convention ("discuss significant changes first" / spec-before-code).

Content: the design is internally consistent and thorough — the enable/disable gate, the micropub_media D1 metadata model, the load-bearing copy-then-delete trash ordering with its 4-state retry table, the deliberate scope split (media-only for q=source vs. the post endpoint's scope-less version), and the "Test coverage" checklist for the follow-up implementation PR are all well specified. I cross-checked the companion implementation in #375 against this section and it matches faithfully (see review there).

One very minor observation, not a change request: the "orphaning is deliberate" rationale (no reference-counting against posts) is a reasonable scope boundary, and it's good that it's stated explicitly rather than left implicit.

No blockers — reads as ready to merge ahead of #375, which depends on it.


Generated by Claude Code

@davidwkeith
davidwkeith merged commit d4433e1 into main Jul 23, 2026
8 of 9 checks passed
@davidwkeith
davidwkeith deleted the claude/issue-363-readiness-69707d branch July 23, 2026 04:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant