Commit sur main · 8fcb985 · @paulrobertlloyd
ci: use node 26 for local development
Reponse de discussion · Discussion #1007 v1.0.0 Beta 30 – The Big Three-oh! · @eclecticpassions
The upgrade to beta 31 went smoothly after restarting the docker container, building with --no-cache, and restarting my Pi. Thanks, the old posts are working now! I miss the section with status/type/search though on the Posts page from your fork 😅.
Commentaire d’issue · Issue #843 Syndicator-mastodon only works for Notes post type, others fail · @eclecticpassions
I just upgraded to beta 31. I clicked the syndicate button for a like-of entry and I get the same error. It’s not being syndicated to my Mastodon feed like notes.
Edit: Oh I just re-read the thread. I don’t really understand what @paulrobertlloyd has said here:
For the avoidance of doubt, the intended behaviour for likes and reposts is for these to use platform-native methods where available, so a post on a Mastodon server would get liked, rather than a post being created linking to that post.
Does that mean syndication is designed for everything other than likes and bookmark post types?
And @rmdes, after upgrading to beta 31, I don’t see the type, status, search features any more on the Posts page… Was that not included from your endpoint-posts fork?
Thanks both.

Reponse de discussion · Discussion #967 IndieAuth Spec Testing · @rmdes
Will redo the whole test suite with beta 30/31 that incorporated most of the fixes and report back!
Reponse de discussion · Discussion #1007 v1.0.0 Beta 30 – The Big Three-oh! · @rmdes
Working neatly here… Beta 31
Commentaire d’issue · Issue #1012 Editor toolbar icons missing on mobile since beta.30 (getElement throws on .CodeMirror textarea) · @rmdes
Confirmed fixed on beta 31
Commentaire de pull request · PR #960 build: official container image with release, nightly and preview channels · @rmdes
Dropping the nightly. That leaves release (on release: published) and the manual preview, and docker-nightly.yml goes with it — one file plus its row in the docs table.
On lerna and husky: they were yours, both on 2022-03-25, c5c1e3d4 "ci: make lerna a dependency" and 91757e2f "ci: make husky a dependency".
They started in devDependencies (1bf21d91, e0356738) and moved that day — the same day as 44e484de "ci: make lerna play nice with workspaces", which set useWorkspaces: true. So it looks like fallout from the npm-workspaces migration rather than a runtime need.
As far as I can tell the reason no longer holds. postinstall is husky, and publish.yml installs with npm ci --ignore-scripts, so it never runs there; build.yml and deploy.yml run a plain npm ci, which installs devDependencies anyway. lerna is only invoked as npx lerna publish in that same job, where a dev dependency would resolve. I haven’t tried moving them back, so treat that as a reading of the files rather than a tested claim.
Out of scope for this PR either way — the image uses --ignore-scripts, so the only cost is the two packages riding along. Happy to open a separate PR if you want them moved.
Commentaire d’issue · Issue #843 Syndicator-mastodon only works for Notes post type, others fail · @rmdes
Yes. The report itself, a like of a URL that isn’t on your Mastodon server, is the intended behaviour: like-of and repost-of are only syndicated when the URL is on the same server. The rest of this thread is upstream now: replies to statuses on other servers thread properly (#927), and older posts open again (#964). The one thing left from my fork is making external likes and reposts optional; I’ll open a discussion for that rather than keep this open.
Commentaire d’issue · Issue #843 Syndicator-mastodon only works for Notes post type, others fail · @paulrobertlloyd
@rmdes Can this issue now be closed?
Commentaire de pull request · PR #960 build: official container image with release, nightly and preview channels · @paulrobertlloyd
I think nightly isn’t needed right now; perhaps release and manually generated preview releases is enough for now.
Also, I forget why lerna and husky are dependencies… I have vague recollections of this being needed for some reason.
Commit sur main · 52bd72c · @paulrobertlloyd
chore: publish endpoint-microsub and post-type-page v1.0.0-beta.31
Commit sur main · fb0298d · @paulrobertlloyd
ci: add from-package option for publish workflow
Reponse de discussion · Discussion #1007 v1.0.0 Beta 30 – The Big Three-oh! · @paulrobertlloyd
Beta 31 fixes a few issues introduced by this release.
Release · v1.0.0 Beta 31 · @paulrobertlloyd
This release addresses a few bugs introduced in Beta 30.
💟 Indiekit is supported by its community. This release was sponsored by @abhas and @sentience.
Commit sur main · c32ce0b · @paulrobertlloyd
fix(endpoint-share): use correctly resolved share endpoint URL
Pull request (OPEN) · PR #1013 fix(frontend): focus the editor through CodeMirror so mobile keeps its toolbar icons · @rmdes
Fixes #1012
The label click now focuses the editor with editor.codemirror.focus(), which works for both of CodeMirror’s input styles, instead of looking up .CodeMirror textarea, which does not exist on mobile and made getElement throw before the toolbar icons were swapped in.
Adds the first test for the textarea component: it mounts the editor with a mobile user agent and checks every toolbar button gets its icon. It fails on main with No element matching .CodeMirror textarea. To load the component under Node, its get-element import gains the .js extension its other import already has.
Commentaire d’issue · Issue #1012 Editor toolbar icons missing on mobile since beta.30 (getElement throws on .CodeMirror textarea) · @rmdes
Confirmed, also on mine, working on a fix, hold on !
Issue ouverte · Issue #1012 Editor toolbar icons missing on mobile since beta.30 (getElement throws on .CodeMirror textarea) · @fabiomrbarbosa
On iOS Safari (and the home-screen app), the Markdown editor toolbar renders with no icons. The buttons are there and work, but each is blank. Desktop browsers are fine.
Started with @indiekit/frontend 1.0.0-beta.30. Beta.29 shows the icons on iOS.
CodeMirror 5 picks inputStyle: "contenteditable" on mobile user agents (codemirror.js, option("inputStyle", mobile ? "contenteditable" : "textarea", …)), so on a phone there is no textarea inside .CodeMirror.
Beta.30 changed the lookup in components/textarea/index.js from a plain querySelector to the new getElement helper, which throws when nothing matches:
const $codeMirrorTextarea = getElement(this, “.CodeMirror textarea”);
That line runs after new EasyMDE(...) and before the loop that replaces EasyMDE’s Font Awesome placeholders with the inline SVG icons, so on mobile connectedCallback dies there and the icons are never swapped in. Font Awesome is not loaded (autoDownloadFontAwesome: false), so the buttons stay empty. The label click-to-focus listener is lost as well.
Look the element up leniently and fall back to CodeMirror’s own focus:
const $codeMirrorTextarea = this.querySelector(“.CodeMirror textarea”); this.$label.addEventListener(“click”, () => { if ($codeMirrorTextarea) $codeMirrorTextarea.focus(); else editor.codemirror.focus(); });
editor.codemirror.focus() works for both input styles, so the fallback could be the only branch.
Error: No element matching .CodeMirror textarea.Reponse de discussion · Discussion #1007 v1.0.0 Beta 30 – The Big Three-oh! · @rmdes
Yes, you can drop the override. The “can’t open old posts” fix is upstream now (becdf26, #924), and that was the only reason to use my fork in your case. Upgrade @indiekit/indiekit itself to beta.30 rather than just removing the override: the fix touches both endpoint-posts and endpoint-micropub, and it relies on the new uid backfill that runs at startup to give your older posts a uid to be found by. Let me know how the upgrade goes!
Reponse de discussion · Discussion #1007 v1.0.0 Beta 30 – The Big Three-oh! · @eclecticpassions
Brilliant update! So many new features and bug fixes, thank you to all the contributors. @rmdes, I was using your indiekit-endpoint-posts@^1.1.1 fork temporarily to fix the ‘can’t open old posts’ bug. Does this update mean I can remove the override now from package.json and go back to the default endpoint-posts? (I don’t have any use for the additional AI parameters / settings). Looking forward to upgrading tomorrow! 🤞
Reponse de discussion · Discussion #1007 v1.0.0 Beta 30 – The Big Three-oh! · @rmdes
Testing it now on indiekit-quickstart with the reference Eleventy theme: an image built from the v1.0.0-beta.30 tag with the Dockerfile from #960, started against a MongoDB volume left over from beta 29. The uid backfill ran on the existing posts at startup, sign-in and publishing from the editor work, and the new uid: in the post’s front matter passes through the theme untouched. userinfo answers as expected.
Next on my side: making the page post type (#954) work end to end in the quickstart and the theme, so a fresh install gets /about and friends out of the box. I’ll open an issue on the theme repo to track it.
@paulrobertlloyd, whenever you have time to review #960: with that merged, the quickstart (and our other deployments) could run the official image straight from GHCR instead of each building their own from the tag. It would make “try beta 30” a docker compose pull away.
Pull request (OPEN) · PR #1011 fix(endpoint-auth): refuse a repeated URL parameter or a client_id with dot segments · @rmdes
Fixes #1010
A URL parameter given more than once is refused as an invalid value, and so is a client_id with a . or .. path segment, checked on the raw value. Two tests, each failing (302 to the consent screen) before the change.
Issue ouverte · Issue #1010 Authorization endpoint accepts a repeated redirect_uri or a client_id with dot segments · @rmdes
Two malformed authorization requests reach the consent screen instead of being refused (packages/endpoint-auth/lib/controllers/authorization.js):
redirect_uri. Express parses redirect_uri=a&redirect_uri=b as an array, the URL check passes it, and String(redirect_uri) joins it with a comma. The consent screen then says it will redirect to a,b.client_id with a . or .. path segment, which the spec rules out for client identifiers. Only URL.canParse is checked, and parsing resolves the segments away.Found with the IndieAuth test suite (S213, S219): https://dev.indieauth.rocks/implementations/2, see #967.
Pull request (OPEN) · PR #1009 fix(endpoint-auth): refuse incomplete or plain PKCE parameters · @rmdes
Fixes #1008
PKCE stays optional, but once either parameter is given the request needs both, and the method must be S256. Otherwise the endpoint shows the usual missing parameter or invalid value error. Three tests, each failing (302 to the consent screen) before the change.
Issue ouverte · Issue #1008 Authorization endpoint accepts incomplete or plain PKCE parameters · @rmdes
The authorization endpoint decides whether to use PKCE with usePkce = code_challenge && code_challenge_method (packages/endpoint-auth/lib/controllers/authorization.js), and never checks the method. So three malformed requests go through to the consent screen instead of being refused:
code_challenge_method=plain: accepted, though the metadata only lists S256code_challenge_method=S256 without code_challenge: treated as a client not using PKCEcode_challenge without code_challenge_method: the sameThe second matters most: a challenge stripped from a real client’s request leaves a code that can be redeemed without a verifier.
Found with the IndieAuth test suite (S216, S221, S222): https://dev.indieauth.rocks/implementations/2, see #967.
Reponse de discussion · Discussion #1007 v1.0.0 Beta 30 – The Big Three-oh! · @rmdes
My god this is huge 😍
Discussion · Announcements · Discussion #1007 v1.0.0 Beta 30 – The Big Three-oh! · @paulrobertlloyd
This release adds a number of new features, fixes a suite of bugs and adds many quality of life improvements.
Key new features include:
profile scope in authentication flows and new userinfo endpointIt also begins adding support for Microsub, initially by providing the ability to interact with channels and timelines.
Much of this release wouldn’t be possible without the help of @rmdes, who incorporated many of these improvements and fixes from his fork. Thanks also goes to @aciccarello for several authorisation improvements and feedback on other issues.
💟 Indiekit is supported by its community. This release was sponsored by @abhas and @sentience.
fromCaught method to IndiekitError (cbf3654)profile scope and add userinfo endpoint (7a27fa6), closes #885url filter for endpoint urls (07f959e)uid on create (e1f3ae7)url and name query parameters (2f89cd1)token (e67466f)markdown-it-prism with microlighter (2d21f8c)url filter for absolute urls in default layout (0f8640e)uid (2581772)addCollection (df0b8f8)properties.uid (42fe338)serviceworker.js (ed98b43)user, repo and token (13275e7)user and password (5d7feaf)token (58136d3)token (22c8903)token (65e5444)access and secret keys (ffde16e)password (8c91c9f)access and secret keys (ab5bb9f)access token (ebf6225)properties.uid (b2a1d2f)getObjectId helper (5827617)GET requests with invalid bearer token (69910bf), closes #825Dockerfile that runs, on a patched MongoDB (46f17f1)grant_type at /auth (d649606)response_type to indieauth.com (fa1d368)code_verifier instead of failing (b7ad28a)me when signing authorization code (0e900a7), closes #911uid so older files don’t 404 (5394361), closes #924n token (2634ac0), closes #746uid (b5a7ce1)count() check that leaked an operation past the test (a354434)uid when deleting a post (737cb1b)update, delete and undelete (057a0ac), closes #928uid so older posts don’t 404 (becdf26), closes #924Array.isArray when wrapping a single target (3a2b7cf)tabindex clause in add-another’s focusable selector (47b995d)-, . and % (f326f60)userinfo endpoint as an absolute URL (fcad0d3)uid backfill resumable and concurrency-safe (8b9fb87)uid backfill even when it’s a no-op (9058317)try/catch (10a6022)try/catch (9951ad9)This discussion was created from the release v1.0.0 Beta 30 – The Big Three-oh!.
Release · v1.0.0 Beta 30 – The Big Three-oh! · @paulrobertlloyd
This release adds a number of new features, fixes a suite of bugs and adds many quality of life improvements.
Key new features include:
profile scope in authentication flows and new userinfo endpointIt also begins adding support for Microsub, initially by providing the ability to interact with channels and timelines.
Much of this release wouldn’t be possible without the help of @rmdes, who incorporated many of these improvements and fixes from his fork. Thanks also goes to @aciccarello for several authorisation improvements and feedback on other issues.
💟 Indiekit is supported by its community. This release was sponsored by @abhas and @sentience.
fromCaught method to IndiekitError (cbf3654)profile scope and add userinfo endpoint (7a27fa6), closes #885url filter for endpoint urls (07f959e)uid on create (e1f3ae7)url and name query parameters (2f89cd1)token (e67466f)markdown-it-prism with microlighter (2d21f8c)url filter for absolute urls in default layout (0f8640e)uid (2581772)addCollection (df0b8f8)properties.uid (42fe338)serviceworker.js (ed98b43)user, repo and token (13275e7)user and password (5d7feaf)token (58136d3)token (22c8903)token (65e5444)access and secret keys (ffde16e)password (8c91c9f)access and secret keys (ab5bb9f)access token (ebf6225)properties.uid (b2a1d2f)getObjectId helper (5827617)GET requests with invalid bearer token (69910bf), closes #825Dockerfile that runs, on a patched MongoDB (46f17f1)grant_type at /auth (d649606)response_type to indieauth.com (fa1d368)code_verifier instead of failing (b7ad28a)me when signing authorization code (0e900a7), closes #911uid so older files don’t 404 (5394361), closes #924n token (2634ac0), closes #746uid (b5a7ce1)count() check that leaked an operation past the test (a354434)uid when deleting a post (737cb1b)update, delete and undelete (057a0ac), closes #928uid so older posts don’t 404 (becdf26), closes #924Array.isArray when wrapping a single target (3a2b7cf)tabindex clause in add-another’s focusable selector (47b995d)-, . and % (f326f60)userinfo endpoint as an absolute URL (fcad0d3)uid backfill resumable and concurrency-safe (8b9fb87)uid backfill even when it’s a no-op (9058317)try/catch (10a6022)try/catch (9951ad9)Commentaire de pull request · PR #997 feat(frontend): choose an existing media file from the editor and file fields · @rmdes
Have slightly tweaked the design and fixed a small bug that appeared in Safari, but otherwise, this is a great addition. Thanks!
My pleasure!
I really missed this feature 6 month ago when I started with indiekit, I’m soo glad to be able to contribute back!
Commit sur main · b7ad28a · @rmdes
fix(endpoint-auth): refuse a missing code_verifier instead of failing
Commit sur main · fcad0d3 · @rmdes
fix(indiekit): advertise the userinfo endpoint as an absolute URL
Commentaire de pull request · PR #997 feat(frontend): choose an existing media file from the editor and file fields · @paulrobertlloyd
Have slightly tweaked the design and fixed a small bug that appeared in Safari, but otherwise, this is a great addition. Thanks!
Commit sur main · 4d71529 · @rmdes
…e fields A “Browse media” button next to the editor’s image upload and next to file-input’s upload button opens a dialog listing the media endpoint’s files (q=source, paged by uid). Choosing one inserts it into the editor, as an image for photos and a link otherwise, or fills in the file field. The dialog is a native whose markup and strings come from a localised component template, so the script holds no copy of its own.
Issue ouverte · Issue #1006 Introspection endpoint answers without authorization · @rmdes
The introspection endpoint answers without any authorization. introspectionController in packages/endpoint-auth/lib/controllers/introspection.js returns { active: true, ...claims } for any valid token posted to /auth/introspect (or sent to GET /auth/token), so anyone holding a token can read back who it belongs to and its scope. The IndieAuth spec asks for the introspection endpoint to require some form of authorization.
This fails S801 and S802 in the IndieAuth test suite: https://dev.indieauth.rocks/implementations/2 (run against main, see #967).
Before a PR, a question on the form it should take. Core’s introspectToken (packages/indiekit/lib/token.js) sends the token being checked as its own Bearer header, so requiring a bearer token would only mean a token can introspect itself. Should Indiekit’s own calls skip the HTTP round trip and verify locally when the endpoint is its own, with the HTTP endpoint requiring a separate credential (for example a token with a dedicated scope), or is self-introspection with a bearer token enough here?
Commit sur main · d143206 · @paulrobertlloyd
fix(frontend): ensure photo in card layout retains 1:1 aspect ratio
Pull request (OPEN) · PR #1005 fix(endpoint-auth): refuse a missing code_verifier instead of failing · @rmdes
Fixes #1004
A code issued with a challenge now needs code_verifier; without it the token endpoint returns 400 (missing parameter) instead of a 500. Test added alongside the invalid verifier one (fails with 500 before the change).
Issue ouverte · Issue #1004 Token request without code_verifier returns 500 · @rmdes
When a code was issued with a code_challenge, codeValidator in packages/endpoint-auth/lib/middleware/code.js calls verifyCode(code_verifier, code_challenge) whether or not code_verifier was sent. Without it, createHash().update(undefined) in lib/pkce.js throws ERR_INVALID_ARG_TYPE and the token endpoint answers 500.
The request is refused, but as a server error rather than a 400. Found with the IndieAuth test suite (S311), see #967.
Pull request (OPEN) · PR #1003 fix(indiekit): advertise the userinfo endpoint as an absolute URL · @rmdes
Fixes #1002
Adds userinfoEndpoint to the endpoints getEndpointUrls resolves against the application URL. The metadata test asserted only that userinfo_endpoint was present, which is how the relative value got through; it now checks the URL.
Issue ouverte · Issue #1002 userinfo_endpoint is advertised as a relative URL · @rmdes
The authorization server metadata lists userinfo_endpoint as /auth/userinfo. Every other endpoint is made absolute by getEndpointUrls in packages/indiekit/lib/endpoints.js, but userinfoEndpoint (added in #938) isn’t in its list, so it reaches /.well-known/oauth-authorization-server as the relative default from endpoint-auth.
A client can’t fetch a relative URL from metadata. The IndieAuth test suite at dev.indieauth.rocks fails S116 (endpoints use https) and every userinfo test on it (S701–S703), see #967.
Reponse de discussion · Discussion #967 IndieAuth Spec Testing · @rmdes
I ran it against rmendes.net, which runs endpoint-auth from main (no code difference): 46 passed, 11 failed, 16 warnings, 11 skipped. https://dev.indieauth.rocks/implementations/2
Three look like small fixes:
userinfo_endpoint is advertised as /auth/userinfo, a relative URL: getEndpointUrls in packages/indiekit/lib/endpoints.js doesn’t list userinfoEndpoint. That fails S116 and every userinfo test.code_verifier gives a 500 (createHash().update(undefined)), not a 400.Bigger ones: a code can be redeemed twice (S302), the consent screen has no deny button (S207), a registered cross-origin redirect_uri is refused (S209), and there is no refresh or revocation (#535).
Commentaire de pull request · PR #1001 fix(frontend): load the app script once the page is parsed · @paulrobertlloyd
Oh, good spot. I’ve removed the defer attribute too.
Pull request (OPEN) · PR #1001 fix(frontend): load the app script once the page is parsed · @rmdes
Fixes #1000
Drops async from the app script so it runs after the document is parsed, and custom elements are defined once their content exists. A module script is deferred by default, so defer is kept only to say so.
Checked with the proxy reproduction from the issue: five errors and no add-another buttons with async defer, none and both buttons with defer.
Issue ouverte · Issue #1000 Frontend components can start before their content is parsed · @rmdes
The app script is loaded with async defer (packages/frontend/layouts/default.njk:46). For a module script async wins, so the script can run while the page is still being parsed. It defines the custom elements, and an element that has been opened but not yet filled gets connectedCallback straight away: add-another looks for #add-button (components/add-another/index.js:27) before it exists, getElement throws, and the component never sets up.
It depends on timing, so it shows up on some loads and not others. To make it repeatable, I sent /posts/create?type=photo through a proxy that pauses for 1.5 s after the <add-another> start tag. With async defer:
No element matching #add-button
No element matching .file-input__progress
No element matching label
No element matching .label
No element matching .geo-input
and no add-another buttons. With defer alone: no errors, both buttons.
async came in with Stimulus (b9d05da), which waited for the document before connecting controllers; it became a problem when the components moved to custom elements (e.g. 914c8fd).
Commit sur main · 24b659a · @rmdes
attributes() returned on the first falsy value instead of skipping it, so everything after it was lost. The summary field’s editor-locale is empty when application.locale is unset, which dropped editor-status=“false” and editor-toolbar=“false” after it and turned the summary into a full editor.