An Opus code review of the branch caught two real bugs the test suite
structurally couldn't see:
- /revocation and /introspect were never added to bootstrap/app.php's
CSRF except list, so both were fully broken (403) for any real
external client, despite every feature test passing — CSRF
verification is short-circuited entirely while running tests.
Verified live against the running app before and after the fix, and
added a regression test that asserts against the actual configured
exemptions rather than relying on request-time behavior that tests
can't exercise.
- An array-shaped `token` param (e.g. token[]=a&token[]=b) crashed
both endpoints with a 500, since this app promotes PHP warnings
("Array to string conversion") to exceptions. Fixed at the shared
root, MicropubToken::findActive(), which also closes the same latent
hole in VerifyMicropubToken's access_token param that predates this
branch. Verified live and covered with regression tests.
Also applied the review's lower-severity findings: added the missing
introspection_endpoint Link header and metadata test assertions,
removed the now-dead is_string($scopes) array branch in the Micropub
handlers and media controller (scope is unconditionally a string from
the DB now, this guarded against a JWT-array-claim shape that can no
longer occur), dropped a redundant #[Table] model attribute, sized
token_hash to its actual 64-char length, and removed a one-off inline
style in the admin view.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014625MfkGZ7GVdbqKme4a8L
Tokens now store a hashed row in micropub_tokens instead of being
self-contained signed JWTs, so a leaked or unwanted token can actually
be revoked. Since revocation already requires a DB lookup on every
request, JWT's stateless-verification benefit was gone anyway, so this
also drops the lcobucci/jwt dependency entirely.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014625MfkGZ7GVdbqKme4a8L
Replaces every raw GuzzleHttp\Client usage (Nominatim, web.archive.org,
webmention fetch/discover/send, Bridgy syndication, IndieAuth client_id
lookup, contact avatar/h-card fetch, profile image download, and the
CloudConvert screenshot pipeline) with Illuminate\Support\Facades\Http,
and enables Http::preventStrayRequests() globally in tests so any
un-faked outbound call now fails loudly instead of silently hitting the
network.
The CloudConvert retry-until-finished middleware in AppServiceProvider
is replaced by a plain polling loop in SaveScreenshot, which also fixes
a latent bug where the old middleware decoded a response object instead
of its body. Bridgy syndication jobs keep their tries=1/no-retry
semantics unchanged to avoid duplicate publishes. Guzzle's PSR-7 helpers
(Header, UriResolver, Utils) stay in SendWebMentions since Http has no
equivalent for them.
Every affected test file's Guzzle MockHandler/HandlerStack boilerplate
is replaced with Http::fake()/Http::sequence().
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P8j7cJhCiYDsGUgB7obKNQ
OwnYourSwarm sends content as an array of objects with `value` and `html`
keys per the Micropub spec. The handler now handles both forms: plain
strings and rich objects, preferring `html` over `value`.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Real OwnYourSwarm requests send the checkin h-card inside
properties.checkin (as an array), not at the top level. The code
was reading from the top-level key so no Place was ever created,
leaving checkin notes blank.
Update tests to match the real request format.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each DTO now owns its own parsing logic via fromRequest(), removing
the normalization layer from MicropubRequest entirely. UpdateHandler
gains delete support and allows replace/add/delete to compose in a
single request rather than being mutually exclusive.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each handler now declares the data class it needs via dataClass(). The
controller builds the appropriate typed DTO from the raw request array
before calling handle(), giving handlers typed property access instead
of raw array lookups.
Handlers moved to App\Services\Micropub\Handlers, data objects to
App\Services\Micropub\Data. MicropubHandlerRegistry and the interface
are documented with flow diagrams and guidance for adding new types.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add MicropubUnsupportedModelException for non-note update attempts
- Refactor UpdateHandler to throw exceptions instead of returning JsonResponse objects; extract applySyndication() to DRY up duplicated syndication URL mapping
- Fix MicropubController: InvalidTokenScopeException now returns 401 + insufficient_scope; add catches for ModelNotFoundException (404) and MicropubUnsupportedModelException (500); updates return 200 not 201
- Slim MicropubRequest.normalizeMicropubJson() to branch on action type, keeping update and create fields cleanly separated
- Update tests to match corrected status codes and error keys; remove markTestSkipped() from all update tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Trying to organise the code better. It now temporarily doesn’t support
update requests. Thought the spec defines them as SHOULD features and
not MUST features. So safe for now :)
We don’t need the complexity of S3. Sepcifically the complexity of
managing my own AWS account, flysystem made the Laravel side easy.
A command is added to copy the the S3 files over to local storage.
- Remove activity stream related code and files
- Update configuration for HtmlSanitizer and RetryGuzzle
- Add `paginate` macro for `Collection`
- Remove unused code for `Codebird`
- Simplify `FrontPageController` and `NotesController` methods
Squashed commit of the following:
commit 8ff29a8ab51ee5057ef786614ab95b005bf8918c
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Fri Feb 1 18:42:05 2019 +0000
Replace deprecated global helpers with their facade equivalents
Squashed commit of the following:
commit b9716fc406664a58ce506aa419f978853d698eff
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Sat Jan 26 15:30:43 2019 +0000
Location and checkin aren’t part of the properties anymore
Squashed commit of the following:
commit 74ed84617fcbecf661695763323e50d049a88db7
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Mon Jan 15 12:46:29 2018 +0000
Test passes so remove the dump statement
commit a7d3323be02da64f76e8ec88713e3de84a13ded7
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Mon Jan 15 12:40:35 2018 +0000
Values with spaces need to be quoted
commit 58a120bb238f14346793c388b948b7351d3b51fd
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Mon Jan 15 12:37:23 2018 +0000
We need a diplay name for the tests to work now we are using strict type checking
commit b46f177053bd697db9a4835d073f2f37e088b26f
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Mon Jan 15 12:31:29 2018 +0000
Get travis to show more info about failing test
commit 60323f3ce5a0561329a1721ee94821571cdcc86a
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Mon Jan 15 12:23:27 2018 +0000
Remove un-used namnepsace imports
commit 096d3505920bc94ff8677c77430eca0aae0be58a
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Mon Jan 15 12:21:55 2018 +0000
we need php7.2 for object type-hint
commit bb818bc19c73d02d510af9f002199f5718a54608
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Mon Jan 15 12:15:48 2018 +0000
Added lots of strict_types
Squashed commit of the following:
commit 50f1993f45a9745ff77f2956a01543b747c85b41
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Sun Dec 24 16:00:39 2017 +0000
Add feature to changelog
commit 64deec40f7bc7941bd77f95c383f3b400952cec5
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Sun Dec 24 14:19:06 2017 +0000
Only show name of location in note metadata when not a simple checkin
commit 4c9fe397f76981f2eca5749a85ece136f78bb2af
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Sun Dec 24 14:17:49 2017 +0000
Add a simple checkin for testing purposes
commit 11564ead4aaf442113d380109d0b65972484dbcf
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Sun Dec 24 14:17:05 2017 +0000
Don’t set a default value for checkins during creation
commit 832c77c205626dd0119fc602727f6808c9d7758f
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Sun Dec 24 14:16:05 2017 +0000
If note has no content, but an associated place, it is a simple checkin, set a note value appropriately
commit 8c11f9d4b058b3bd248ed02476904301def0e6fc
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Sun Dec 24 14:13:31 2017 +0000
Allow a note to not have content, in whihc case default the value to null