Table of Contents
- Sprint 1 — Assessment
- 1. v0.1 baseline — what shipped
- 1.1 Backend — de.platesoft:plate-auth-starter:0.1.0
- 1.2 Frontend — @platesoft/auth@0.1.0
- 1.3 What v0.1 explicitly left behind (deferred backlog)
- 2. Consumer forecast — first-month needs
- 2.1 InspectFlow — operational pain (week 1–2)
- 2.2 Sparkboard — greenfield friction (week 1–3)
- 2.3 Hypothesis validation
- 3. v0.2 feature classification
- 3.1 Must-have (blocks at least one consumer)
- 3.2 Nice-to-have (improves DX but has a workaround)
- 3.3 Stretch (only if must-haves + nice-to-haves finish early)
- 3.4 Priority → workstream mapping
- 4. Risk register
- 5. Dependencies we are accepting
- 6. Recommendation
- 7. Cross-references
Sprint 1 — Assessment
Status: Draft v1
Date: 2026-06-24
Owner: Patrick (plate-software)
Purpose: Assess what v0.1 delivered, predict what consumers (InspectFlow + Sparkboard) will
need in their first month, classify each v0.2 feature by priority, and surface the risks of the
polish sprint. This document is the basis for Sprint-1-Plan.md.
1. v0.1 baseline — what shipped
Sprint 0 (W1–W12) extracted InspectFlow's auth/membership system into a reusable two-artifact
library. The table below is the delivered surface at the v0.1.0 tag, cross-referenced to the
Architecture tiers.
1.1 Backend — de.platesoft:plate-auth-starter:0.1.0
| Layer | Delivered | Reference |
|---|---|---|
| Auto-config | PlateAuthAutoConfiguration (explicit @Import, no @ComponentScan) + PlateAuthProperties (plate.auth.*) + META-INF/spring/...AutoConfiguration.imports |
Architecture §3 |
| Security | SecurityConfig scoped via securityMatcher(...) at @Order(100) — only plate-auth endpoints |
Q13 (decided) |
| Filter | JwtAuthenticationFilter, OrgContextResolver |
Architecture §5–6 |
| Service | JwtService, ExchangeService, OAuthService, MembershipService, InvitationService, AccessRequestService, LoginEventService |
Architecture §3.2 |
| Controller | OAuthController, AuthController, InvitationController, AccessRequestController, AdminAuditController |
Architecture §3.1 |
| Entity | User, UserIdentity, Membership, Invitation, AccessRequest, LoginEvent, RevInfo |
Architecture §7 |
| SPI | OrgValidator, OrgDisplayNameResolver, InvitationMailer, AccessRequestMailer, OnboardingHook (5 interfaces + 5 no-op/defaults via @ConditionalOnMissingBean) |
Architecture §3.4 |
| Migration | Flyway V1–V6 under classpath:db/migration/auth/ + separate flyway_schema_history_auth table |
Architecture §8.1 |
| Wire contract | WIRE_VERSION=1 constant in exchange envelope, backend rejects mismatch |
Q06 (decided) |
| Provider | Google OAuth (enabled by default); Microsoft + email toggles exist but are off | Q02/Q04 (deferred) |
1.2 Frontend — @platesoft/auth@0.1.0
| Module | Delivered | Reference |
|---|---|---|
config/ |
createAuthConfig(opts) factory → NextAuth v5 config with Google provider |
Architecture §4.1 |
exchange/ |
signEnvelope() / verifyEnvelope() using Web Crypto (Edge-safe) + exchangeWithBackend() |
Architecture §4.1 |
proxy/ |
createProxyHandlers(opts) — auth() → Bearer injection + hop-by-hop strip + duplex:"half" |
Architecture §4.1 |
middleware/ |
createAuthMiddleware(opts) with configurable publicPaths |
Architecture §4.1 |
client/ |
useAccessToken(), useMemberships(), re-export of useSession/signIn/signOut |
Architecture §4.1 |
| Build | tsup dual ESM/CJS + .d.ts |
Q09 (decided) |
1.3 What v0.1 explicitly left behind (deferred backlog)
These items were tracked in Sprint-0-Plan §11 and now form the v0.2 input backlog. Each was a deliberate deferral, not an oversight:
| # | Deferred item | Deferred because | Target |
|---|---|---|---|
| D1 | MS Entra ID provider | Extraction discipline — never in InspectFlow 14.x | v0.2 |
| D2 | Email magic-link provider | Same — InspectFlow 14.1 deferred it | v0.2 |
| D3 | LoginEventSink SPI |
DB rows + Envers sufficient for 2 consumers | v0.2 |
| D4 | Real InvitationMailer (JavaMailSender) |
No-op logger is enough to extract; real mail is polish | v0.2 |
| D5 | AccessRequestMailer template |
Same | v0.2 |
| D6 | Configurable invitation expiration | Hardcoded 7d is fine for extraction | v0.2 |
| D7 | RFC 7807 Problem Details | v0.1 errors are plain Spring Boot defaults | v0.2 |
| D8 | TS type exports (Membership, Invitation, AccessRequest) |
Consumers can cast in v0.1 | v0.2 |
| D9 | Zod schemas for envelope + DTOs | Nice-to-have | v0.2 |
| D10 | Edge-runtime safe useAccessToken() |
Current uses getSession() (App-Router-only) |
v0.2 |
| D11 | Refresh-token rotation hardening | Stateless JWT refresh accepted for v0.1 | v0.3 (Roadmap) |
2. Consumer forecast — first-month needs
The Roadmap says v0.2 is "triggered by feedback from consumers during their first month using v0.1." We cannot wait for that feedback to plan — Sparkboard is greenfield and will hit its needs on day 1. This section predicts the pain points based on what each consumer is.
flowchart LR
V01[v0.1.0 ships] --> IF[InspectFlow migrates<br/>~1 week]
V01 --> SB[Sparkboard adopts<br/>~3 weeks]
IF --> F1[Feedback wave 1<br/>operational pain]
SB --> F2[Feedback wave 2<br/>greenfield friction]
F1 --> V02[v0.2 backlog<br/>confirmed/adjusted]
F2 --> V02
2.1 InspectFlow — operational pain (week 1–2)
InspectFlow is migrating existing users from in-tree auth onto the library. Its pain points are operational, not greenfield:
| Predicted pain | Why | v0.2 feature that fixes it |
|---|---|---|
| MS Entra ID sign-in stops working | InspectFlow's V30 migration + TenantAutoMapService handled MS tenants. plate-auth v0.1 ships no MS provider — InspectFlow users with provider=microsoft identities will have broken sign-in until v0.2. |
W1 — MS Entra ID provider |
| Invitation emails silently fail | v0.1's LoggingInvitationMailer logs the URL instead of sending mail. InspectFlow admins who invite users will think the invite sent, but nothing arrives. |
W3 — Real InvitationMailer |
| Error responses are opaque | v0.1 returns Spring Boot's default JSON error body. InspectFlow's frontend has no structured way to distinguish "expired token" from "invalid credentials." | W4 — RFC 7807 Problem Details |
| Invitations expire too fast / too slow | InspectFlow's original 7d window is hardcoded. If they want 3d or 14d, they must fork. | W4 — Configurable expiration |
2.2 Sparkboard — greenfield friction (week 1–3)
Sparkboard starts from zero. Its pain is developer experience friction — things that are possible but require more boilerplate than they should:
| Predicted pain | Why | v0.2 feature that fixes it |
|---|---|---|
| No email sign-in option | Sparkboard is a 4-person family app ("Family Spark"). Google-only auth is fine for Patrick, but his friend's sons may not have Google accounts. Email magic-link is the natural second option. | W2 — Email magic-link |
| Edge middleware can't read access token | useAccessToken() calls getSession() which is App-Router-only. If Sparkboard uses Edge-runtime middleware for route protection, the hook throws. |
W5 — Edge-runtime safety |
| TypeScript types are loose | Sparkboard's frontend gets any from useMemberships() because Membership isn't exported. Runtime works, but DX is rough. |
W5 — TS improvements |
| No email UX page | Email magic-link requires a callback page. Consumers build it themselves in v0.1. | W2 — default UX page |
| Login events stuck in DB only | Sparkboard may want to tee login events to a webhook or Loki for the homelab observability stack. | W3 — LoginEventSink SPI |
2.3 Hypothesis validation
Per Roadmap § "Hypothesis-driven scoping":
v0.2 hypothesis: The SPI is enough — no consumer needs to fork.
We validate this by tracking whether InspectFlow or Sparkboard shadow-override plate-auth classes
instead of using the SPI. If they fork, the next minor becomes a "why do they fork" investigation.
v0.2 adds LoginEventSink as a new SPI specifically to prevent a fork around audit shipping.
3. v0.2 feature classification
Each v0.2 candidate from the Roadmap and the Open-Questions deferrals is classified into three tiers. Priority is driven by consumer-blocking severity, not effort.
flowchart TB
subgraph Must[Must-have — blocks a consumer]
M1[W1: MS Entra ID<br/>blocks InspectFlow]
M2[W3: Real InvitationMailer<br/>blocks invitations]
M3[W4: RFC 7807 + config expiration<br/>blocks error UX]
end
subgraph Nice[Nice-to-have — smooths DX]
N1[W2: Email magic-link<br/>Sparkboard option]
N2[W3: LoginEventSink SPI<br/>audit shipping]
N3[W3: AccessRequestMailer template]
N4[W5: TS improvements<br/>typed exports + Zod]
N5[W5: Edge-runtime safety]
end
subgraph Stretch[Stretch — if time allows]
S1[W6: Wire-version bump<br/>if contract changes]
S2[WebAuthn / passkey]
S3[Per-app branding]
end
3.1 Must-have (blocks at least one consumer)
| # | Feature | Blocks whom | Justification |
|---|---|---|---|
| W1 | MS Entra ID provider | InspectFlow | InspectFlow has live provider=microsoft identities. Without the provider, those users cannot sign in post-migration. This is a regression, not a missing feature. The SPI hooks (OnboardingHook, V5 tenant-index migration) are ready — the provider implementation is the only gap. |
| W3 | Real InvitationMailer (JavaMailSender) |
Both | v0.1's logging mailer means invitations silently fail in any non-dev environment. Any consumer that uses invitations (both do) hits this within week 1. |
| W4 | RFC 7807 Problem Details | Both | Consumers cannot build robust error UX on v0.1's opaque error bodies. This is the #1 frontend DX complaint we predict. |
3.2 Nice-to-have (improves DX but has a workaround)
| # | Feature | Workaround if skipped | Justification |
|---|---|---|---|
| W2 | Email magic-link provider | Google-only auth | Sparkboard's family users can use Google. But the friend's sons may not have accounts — email magic-link is the natural fallback. Predicted to become must-have if Sparkboard gets a non-Google user. |
| W3 | LoginEventSink SPI |
Query login_events table directly |
DB rows work. The SPI lets consumers tee to Loki/SIEM without polling. Nice for homelab observability; not blocking. |
| W3 | AccessRequestMailer template |
Same logging fallback as invitation | Less critical than invitation mailer (access requests are less frequent), but should ship together for symmetry. |
| W5 | TS improvements (typed exports + Zod) | Cast to any / manual types |
Works, but rough DX. Zod schemas enable runtime validation on the frontend. Predicted to be the #2 frontend complaint. |
| W5 | Edge-runtime safe useAccessToken() |
Don't use Edge middleware for auth | useAccessToken() currently throws in Edge runtime. Workaround: use Node middleware. But this is a footgun — should be fixed proactively. |
3.3 Stretch (only if must-haves + nice-to-haves finish early)
| # | Feature | Why stretch |
|---|---|---|
| W6 | Wire-version bump to WIRE_VERSION=2 |
Only needed if the envelope contract actually changes (e.g., adding provider-specific fields). If the MS/email providers fit the existing ExchangeEnvelope shape, no bump needed. Conditional. |
| — | WebAuthn / passkey provider | No consumer has asked. NextAuth supports it, but backend plumbing is non-trivial. Roadmap says "possibly v0.2." Defer unless a consumer explicitly requests. |
| — | Per-app branding on exchange endpoint | Custom user-agent string for audit. Low value for a 2-consumer library. Defer. |
3.4 Priority → workstream mapping
| Priority | Workstream | Effort (GLM-5.2+Lumen) |
|---|---|---|
| Must-have | W1 (MS Entra), W3 (mailers), W4 (RFC 7807 + config) | ~3 days |
| Nice-to-have | W2 (email), W3 (LoginEventSink), W5 (TS + Edge) | ~3 days |
| Stretch | W6 (wire-version + IT + publish) | ~1 day |
| Total | W1–W6 | ~7 days (fits 3 calendar weeks per Roadmap) |
4. Risk register
| # | Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|---|
| R1 | MS Entra ID provider doesn't match InspectFlow's existing TenantAutoMapService behavior |
Medium | High — InspectFlow MS users locked out | W1 must replicate the tenant→org auto-mapping via OnboardingHook. Test against InspectFlow's seeded MS identities. The V5 tenant-index migration is already shipped — use it. |
| R2 | Email magic-link introduces email enumeration vector | Medium | Medium | allowDangerousEmailAccountLinking=false (already enforced). Magic-link responses must be generic ("if the email exists, a link was sent") — no "user not found" leak. Test T-SEC11. |
| R3 | JavaMailSender default fails silently when SMTP misconfigured |
Medium | Medium | The real InvitationMailer must fail loudly — throw on mail-send failure, not swallow. Integration test with a mock SMTP (GreenMail or Testcontainers mail). Consumer must set spring.mail.host. |
| R4 | RFC 7807 Problem Details breaks v0.1 consumers' error parsing | Low | Medium | Problem Details is additive (new Content-Type: application/problem+json). v0.1 consumers that parsed the old body will see a different shape. Document in CHANGELOG. If the wire-version changes, bump WIRE_VERSION. |
| R5 | Edge-runtime safety fix changes useAccessToken() return semantics |
Low | Low | The fix makes the hook work in Edge (reads from cookie/token-store instead of getSession()). Non-Edge consumers are unaffected. Snapshot test guards the contract. |
| R6 | Wire-version bump to 2 forces a coordinated upgrade across both consumers | Medium (if triggered) | Medium | Per versioning policy, wire-version change = MINOR bump (0.2.0). Both consumers upgrade lockstep. CHANGELOG documents the migration. |
| R7 | LoginEventSink SPI fires synchronously and slows login |
Low | Medium | SPI must be async (annotated @Async or dispatched to an executor). The default no-op sink has zero overhead. Test T-UT16 measures login latency with a sink attached. |
| R8 | Zod schemas drift from backend DTOs | Low | Low | Generate Zod schemas from a single source (TS types) or use a contract test. The golden-vector approach from T-FE02 extends to schema validation. |
| R9 | MS Entra ID common tenant vs single-tenant mismatch |
Medium | Medium | Provider config must expose tenant-id as a property (plate.auth.providers.microsoft.tenant-id). Default common (multi-tenant). InspectFlow may pin to their tenant. Document in Integration-Guide.md. |
| R10 | Email magic-link token replay | Low | Medium | NextAuth Email provider generates single-use HMAC'd magic links. Backend ExchangeService already has nonce dedup. The magic-link flow goes through the same exchange envelope — reuse existing replay protection. |
| R11 | Configurable invitation expiration = 0 or negative breaks invitation creation | Low | Low | Bean-validate plate.auth.invitation.expiration-days with @Min(1) @Max(90). Fails fast at startup if out of range. |
| R12 | v0.1 ships late, compressing v0.2 timeline | Medium | Medium | v0.2 is "as priorities allow" per Roadmap. Must-haves (W1/W3/W4) can ship as v0.2.0 even if nice-to-haves slip to v0.2.1. No hard deadline except consumer pressure. |
5. Dependencies we are accepting
v0.2 adds these dependencies on top of v0.1's stack (Sprint-0-Assessment §4):
| Dep | Version | Added by | Notes |
|---|---|---|---|
spring-boot-starter-mail |
(Spring Boot managed) | W3 (real mailers) | Brings JavaMailSender. Already listed as a dep in v0.1's pom but unused — now activated. |
next-auth Email provider |
5.x (beta tracking) | W2 (magic-link) | Part of NextAuth v5, no new package. Requires nodemailer or SMTP config on the consumer side. |
zod |
^3.x | W5 (TS schemas) | Runtime validation. Ships as a dependency of @platesoft/auth, not a peer dep (consumers get it automatically). |
No new Spring Boot / Java / Postgres version changes. v0.2 stays on the v0.1 baseline.
6. Recommendation
GO — proceed to Sprint-1-Plan.md with the following constraints:
- W1 (MS Entra ID) is the critical path. It is the only must-have that fixes a regression (broken sign-in for existing InspectFlow MS users). It must land first and be tested against InspectFlow's seeded MS identities.
- W3 (mailers) and W4 (RFC 7807 + config) are must-haves but lower-risk. They can proceed in parallel with W1.
- Nice-to-haves (W2, W5) are planned but not promised. If v0.1 consumer feedback redirects priorities, these can slip to v0.2.1 without blocking the v0.2.0 release.
- Wire-version bump (W6) is conditional. Only bump
WIRE_VERSIONif the envelope contract actually changes. If MS/email providers fit the existing shape,WIRE_VERSIONstays at 1 and v0.2.0 is a pure additive release. - WebAuthn + per-app branding stay deferred. No consumer has asked. Revisit at v0.3.
- No new Flyway migrations in v0.2. The V1–V6 schema is sufficient. If MS Entra needs a new
column (e.g.,
microsoft_graph_id), add V7 — but only if the existinguser_identities.subjectfield is insufficient. Predicted: no new migration needed.
The Roadmap says v0.2 is "triggered by feedback." This assessment plans proactively so the must-haves are ready the moment v0.1 ships. Consumer feedback adjusts the nice-to-have / stretch split, not the must-have core.
7. Cross-references
- Roadmap.md — v0.2 section + hypothesis-driven scoping
- Architecture.md — SPI model, wire contract, threat model
- Open-Questions.md — Q02 (MS Entra deferred), Q04 (email deferred), Q12 (audit DB-only)
- Sprint-0-Plan.md — §11 deferred items (v0.2 backlog source)
- Sprint-0-Assessment.md — format reference + v0.1 source inventory
- Sprint-1-Plan.md — implementation plan based on this assessment
- Sprint-1-Testplan.md — test matrix for v0.2
Assessment ready for Plan Reviewer. Sprint-1-Plan v1 will be drafted assuming all Section 6 recommendations hold; any Plan Reviewer pushback re-opens the priority split.