Roadmap
Status: Draft v1 Date: 2026-06-24 Owner: Patrick (plate-software)
Versioning policy
plate-auth follows SemVer, but with two amendments suited to a closed-source internal library:
| Version part | Bump trigger | Consumer impact |
|---|---|---|
MAJOR (1.x.x) |
Wire contract change OR removed public API | Coordinated upgrade across all consumers |
MINOR (x.1.x) |
New feature, new SPI, new endpoint, deprecation | Drop-in upgrade — read CHANGELOG |
PATCH (x.x.1) |
Bug fix, dependency bump, internal refactor | Drop-in upgrade — no read needed |
Amendment 1 — lockstep frontend/backend versions.
@platesoft/auth@0.x.y and de.platesoft:plate-auth-starter:0.x.y always ship together with identical
version numbers. The wire contract is the union of both sides; you cannot upgrade one without the peer.
Amendment 2 — 0.x is internal-experimental.
Until 1.0.0 we may break minor versions if a consumer experience demands it. All breakage is documented
in the CHANGELOG with a migration recipe. Once 1.0.0 ships, SemVer is strict.
Release horizon
gantt
title plate-auth release horizon
dateFormat YYYY-MM-DD
axisFormat %b %Y
section v0.1 — Ship
Sprint 0 (extraction) :s0, 2026-06-24, 14d
v0.1.0 published :milestone, m1, after s0, 0d
InspectFlow migrates :ifm, after m1, 7d
Sparkboard adopts :sba, after m1, 21d
section v0.2 — Polish
SPI cleanup + Email opt-in :s2, after ifm, 21d
v0.2.0 published :milestone, m2, after s2, 0d
section v0.3 — Operate
Multi-replica nonce store :s3, after m2, 14d
Refresh rotation hardening :s3b, after s3, 14d
v0.3.0 published :milestone, m3, after s3b, 0d
section v0.4 — Open
Document SPI, write integration tests :s4, after m3, 30d
1.0.0-RC candidate :milestone, m4, after s4, 0d
Dates are indicative — Sprint 0 has a hard target (Sparkboard cannot start until v0.1 ships). Everything after Sprint 0 is "as priorities allow."
v0.1.0 — Ship (Sprint 0 deliverable)
Theme: Extract InspectFlow 14.1-14.6 verbatim. No new features. No clever refactors.
Backend (plate-auth-starter)
- ✅ Move
de.platesoft.inspectflow.*auth code underde.platesoft.auth.* - ✅
PlateAuthAutoConfigurationwith@ConditionalOnMissingBeanoverrides - ✅
PlateAuthProperties(plate.auth.*config namespace) - ✅ Flyway migrations under
classpath:db/migration/auth/V1..V6 - ✅ SPI:
OrgValidator,OrgDisplayNameResolver,InvitationMailer,AccessRequestMailer,OnboardingHook - ✅ Endpoints:
/api/auth/**,/api/invitations/**,/api/access-requests/**,/api/admin/** - ✅ Spring Boot 4.1.0 + Java 25 LTS baseline
- ✅ Published to Gitea Package Registry
Frontend (@platesoft/auth)
- ✅
createAuthConfig({ providers, exchange, secret })→ NextAuth v5NextAuthConfig - ✅ Google + Microsoft Entra ID + Email magic-link providers (opt-in via options)
- ✅
exchange/envelope.ts(Web Crypto HMAC-SHA256, Edge-runtime compatible) - ✅
createProxyHandlers({ backendUrl })with hop-by-hop header stripping +duplex:"half" - ✅
useAccessToken(),useMemberships()client hooks - ✅ Published to Gitea Package Registry npm
Validation
- ✅ InspectFlow's current auth replaced by the library — full E2E test pass
- ✅ Sparkboard greenfield setup completes in <30min using only
Integration-Guide.md - ✅ Plan Reviewer (architect mode) approves Sprint-0-Plan.md before code starts
Out of scope for v0.1:
- Multi-replica nonce store (in-memory is fine for InspectFlow + early Sparkboard)
- WebAuthn / passkeys
- Per-tenant JWT secret rotation
- Externalized audit-log sink (Loki / OpenSearch)
v0.2.0 — Polish
Theme: Make the consumer experience pleasant. Smooth the SPI corners InspectFlow + Sparkboard found.
Triggered by feedback from the two consumers during their first month using v0.1.
Likely contents
InvitationMailerdefault implementation that actually sends mail viaJavaMailSender(currently no-op logger)AccessRequestMaileradmin-notification template- Configurable invitation expiration window (currently hardcoded 7d in
InvitationService) useAccessToken()Edge-runtime safety pass — current impl usesgetSession()which is App-Router-only- Email magic-link default UX page (consumers currently have to build their own callback page)
- Better error responses (RFC 7807 Problem Details) for
/api/auth/*endpoints - TypeScript improvements: stricter
ExchangeEnvelopeshape, exported types forMembership,Invitation - ADR-style docs auto-published to wiki
Possibly v0.2 (depends on consumer demand)
- WebAuthn / passkey provider (NextAuth supports it; we add the backend plumbing)
- Per-app branding on the exchange endpoint (custom user-agent string for audit)
v0.3.0 — Operate
Theme: Run plate-auth across multiple replicas + harden refresh tokens.
Triggered when the first consumer hits horizontal scaling.
Backend
- Nonce store via Redis / Postgres instead of in-memory
ConcurrentHashMap— current impl breaks replay protection across replicas (an envelope can be replayed up to N-1 times where N = replica count). - Refresh token rotation table — currently refresh tokens are stateless JWTs which means revocation
requires a denylist. Move to opaque refresh tokens with a
refresh_tokenstable for revocation + family-tracking + reuse detection. - Configurable token signing key rotation — support a JWK Set with
kidheader so we can rotate the HMAC secret without all-user logout. - Pluggable login-event sink — emit
LoginEventto aLoginEventSinkSPI so consumers can ship to Loki / OpenSearch / Sentry instead of (or in addition to) Postgres.
Frontend
- Session sliding-expiration vs absolute-expiration toggle
- Optional
requireRoles(['ADMIN'])middleware helper
v0.4.0 — Open
Theme: Document the SPI thoroughly. Write the integration tests we wish we had at v0.1.
This is the "ready to be used by a developer who doesn't know me" version.
- Complete SPI Javadoc + TSDoc
- Integration test suite that any consumer can run against their override of
OrgValidator - Example consumer apps (minimal Sparkboard-like + minimal InspectFlow-like) checked into the plate-auth
repo under
examples/ Architecture.mdupgraded with a "how to add a new auth provider" recipe- Public-facing wiki polish — diagrams, terminology glossary, FAQ
If at this point both consumers are happy + we want to start product #3, we cut 1.0.0-RC1.
1.0.0 criteria
We do not ship 1.0.0 until:
- ✅ At least two consumers have been running v0.x in production for ≥3 months
- ✅ At least one minor upgrade (v0.x → v0.y) has been performed without breakage
- ✅ The SPI has been used to override at least three different extension points across consumers (proves the extension surface is real)
- ✅ A security review (external or internal) has signed off on the threat model
- ✅ No "must rename / must refactor" backlog items are open
If we hit 1.0.0 we promise strict SemVer thereafter — breaking changes only on major bumps,
deprecation notices ≥1 minor cycle in advance.
Deprecation policy
- Deprecation lives in code as
@Deprecated(since="0.x", forRemoval=true)+ CHANGELOG entry. - One full minor cycle of warning before removal. Something deprecated in
0.3is removed no earlier than0.5. - Migration recipe is mandatory. Every deprecation includes a
// MIGRATION:Javadoc/TSDoc comment pointing at the replacement.
What is explicitly not on the roadmap
Items that have been considered and rejected (for now):
| Idea | Why not |
|---|---|
| SAML support | No customer has asked. Adds significant code + audit surface. |
| SCIM provisioning | Same — no demand. Revisit if a B2B customer shows up. |
| Multi-org-type-per-user (e.g. user has memberships to a Company and a Club) | Schema supports it but no consumer wants it. Don't build until asked. |
| Public OIDC server (plate-auth as IdP) | We are consumers, not providers. Different threat model. Don't bend the architecture. |
| Audit log UI components | UI is per-product. Library emits structured events; consumers visualize. |
| iOS / Android SDKs | Native apps can call /api/auth/exchange directly. SDKs add maintenance load with no obvious win. |
If consumer demand justifies any of these, they get added to the roadmap with their own discovery doc.
Hypothesis-driven scoping
Each release answers (or refutes) a hypothesis. If the hypothesis is refuted, the next release adapts.
| Version | Hypothesis | How we validate |
|---|---|---|
| v0.1 | Extraction is non-lossy — InspectFlow keeps 100% of features after migration | Run full InspectFlow E2E suite post-migration |
| v0.1 | Sparkboard can start day 1 with the library | Time-to-first-signin <30min from a clean repo |
| v0.2 | The SPI is enough — no consumer needs to fork | Track GitHub-style "forks" / shadow-overrides across consumers |
| v0.3 | We hit the multi-replica nonce limitation in practice | First time a consumer scales beyond 1 replica + reports replay anomaly |
| v0.4 | Library is documented enough to onboard a stranger | Bring in a fresh contributor, time them on adding a feature |
When a hypothesis is refuted (e.g. consumers do fork the library at v0.2), the next minor turns into a "why do they fork" investigation before adding more features.
Cross-references
- Sprint 0 detail:
Sprint-0-Plan.md - Architectural rationale:
Architecture.md - Open design questions:
Open-Questions.md