Observed
With the IdP enabled, createServer throws at plugin-registration time when no issuer is known:
Error: IdP requires issuer URL
at idpPlugin (src/idp/index.js:57)
That's correct as a guard, but it forecloses the standard ephemeral-port test pattern:
const fastify = createServer({ root, idp: true, plugins: [...] }); // throws here…
await fastify.listen({ port: 0 }); // …so we never learn the port
const base = `http://127.0.0.1:${fastify.server.address().port}`; // which the issuer needs
Chicken-and-egg: the issuer needs the port, the port is only known after listen, and the IdP demands the issuer before it.
Impact
Every plugin author writing integration tests against a composed instance (IdP + their plugin, exercising the POST /idp/credentials login bridge end-to-end) has to pin a fixed port instead. Fixed ports collide on busy dev machines and CI — this box already has 3210 (Tideholm), 3220 (Bridge) and 3230 (OMERTÀ) spoken for, and the OMERTÀ test suite had to reserve 3239 with a TEST_PORT escape hatch.
Suggested fix
Defer issuer resolution to first use rather than registration time — e.g. accept idpIssuer: () => string or, when idpIssuer is absent and the server is bound to localhost, resolve it lazily from server.address() after listen. The guard can stay for the production path (non-loopback binds without an explicit issuer should still throw).
Precedent: #601 solved the same "origin isn't knowable at activate time" problem for plugins with api.serverInfo — this is the IdP-side sibling of that issue.
Found while building the OMERTÀ plugin (third consumer of the #206 seams); findings log in solid-apps/mafia jss-plugin/NOTES.md.
Observed
With the IdP enabled,
createServerthrows at plugin-registration time when no issuer is known:That's correct as a guard, but it forecloses the standard ephemeral-port test pattern:
Chicken-and-egg: the issuer needs the port, the port is only known after
listen, and the IdP demands the issuer before it.Impact
Every plugin author writing integration tests against a composed instance (IdP + their plugin, exercising the
POST /idp/credentialslogin bridge end-to-end) has to pin a fixed port instead. Fixed ports collide on busy dev machines and CI — this box already has 3210 (Tideholm), 3220 (Bridge) and 3230 (OMERTÀ) spoken for, and the OMERTÀ test suite had to reserve 3239 with aTEST_PORTescape hatch.Suggested fix
Defer issuer resolution to first use rather than registration time — e.g. accept
idpIssuer: () => stringor, whenidpIssueris absent and the server is bound to localhost, resolve it lazily fromserver.address()after listen. The guard can stay for the production path (non-loopback binds without an explicit issuer should still throw).Precedent: #601 solved the same "origin isn't knowable at activate time" problem for plugins with
api.serverInfo— this is the IdP-side sibling of that issue.Found while building the OMERTÀ plugin (third consumer of the #206 seams); findings log in
solid-apps/mafiajss-plugin/NOTES.md.