1
Sprint 1 Assessment
Patrick Plate edited this page 2026-06-24 21:59:30 +02:00
This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 (W1W12) 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 §56
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 V1V6 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 12)

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 13)

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 W1W6 ~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:

  1. 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.
  2. W3 (mailers) and W4 (RFC 7807 + config) are must-haves but lower-risk. They can proceed in parallel with W1.
  3. 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.
  4. Wire-version bump (W6) is conditional. Only bump WIRE_VERSION if the envelope contract actually changes. If MS/email providers fit the existing shape, WIRE_VERSION stays at 1 and v0.2.0 is a pure additive release.
  5. WebAuthn + per-app branding stay deferred. No consumer has asked. Revisit at v0.3.
  6. No new Flyway migrations in v0.2. The V1V6 schema is sufficient. If MS Entra needs a new column (e.g., microsoft_graph_id), add V7 — but only if the existing user_identities.subject field 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


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.