2
Sprint 0 Assessment
Patrick Plate edited this page 2026-06-24 20:22:49 +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 0 — Assessment

Status: Draft v1 Date: 2026-06-24 Owner: Patrick (plate-software) Purpose: Inventory InspectFlow's current auth implementation, classify each piece as lift-and-shift / needs-reshaping / leave-behind, and surface the risks of the extraction.


1. Source-of-truth inventory

InspectFlow's auth surface was built over six sub-sprints (14.1 14.6). The artifacts below were read directly from inspectflow/backend and inspectflow/frontend at the time of this assessment.

1.1 Backend — Java / Spring Boot 4.0.7

Layer Class / file Lines Domain coupling Status
Config SecurityConfig 67 Hardcoded URL list for permitAll includes InspectFlow-specific routes (/api/companies/*/public-info) Reshape — make permit-list config-driven
Filter JwtAuthenticationFilter 60 None — pure JWT extraction + SecurityContext Lift-and-shift
Filter OrgContextResolver ~80 Reads X-Org-Id header, validates via MembershipService — no concrete-org coupling Lift-and-shift
Service JwtService 97 None — pure JWT issuance using HMAC SHA-256 Lift-and-shift
Service OAuthService ~200 Calls TenantAutoMapService for MS tenant→company mapping (InspectFlow-specific) Reshape — hoist auto-map to T3 via OnboardingHook SPI
Service ExchangeService ~150 None — HMAC verify + nonce dedup (in-memory ConcurrentHashMap) Lift-and-shift (note: in-memory replay store breaks under multi-replica — flagged for v0.3)
Service MembershipService ~250 Joins to companies for display name → use OrgDisplayNameResolver SPI Reshape
Service InvitationService ~300 Mails via InvitationMailer (already abstracted in Sprint 14.3) Lift-and-shift with minor SPI surface tweak
Service AccessRequestService ~250 Same pattern as Invitation Lift-and-shift
Service LoginEventService ~120 None — async event recorder Lift-and-shift
Service AuthService ~180 Password login / register / refresh — uses User + Role only Lift-and-shift
Service OnboardingService ~200 Heavy — manages InspectFlow's "first sign-in" business-state machine Leave behind (T3) — expose OnboardingHook SPI for plate-auth to call
Service TenantAutoMapService ~150 Heavy — MS Entra tenant → InspectFlow Company auto-mapping Leave behind (T3)
Controller OAuthController ~80 None Lift-and-shift
Controller AuthController ~150 None Lift-and-shift
Controller InvitationController ~120 None Lift-and-shift
Controller AccessRequestController ~100 None Lift-and-shift
Controller AdminAuditController ~80 None Lift-and-shift
Entity User ~80 None — default_org_id is polymorphic UUID Lift-and-shift
Entity UserIdentity ~70 None — provider-agnostic Lift-and-shift
Entity Membership ~90 Polymorphic (org_type, org_id) already Lift-and-shift
Entity Invitation ~80 Polymorphic Lift-and-shift
Entity AccessRequest ~80 Polymorphic Lift-and-shift
Entity LoginEvent ~60 None Lift-and-shift
Entity Company ~120 Pure InspectFlow — addresses, embedding vector, industry Leave behind (T3)
Enums OrgType, MembershipRole, MembershipStatus, InvitationStatus, AccessRequestStatus, LoginProvider, Role ~70 total None Lift-and-shift
Migration V26 — user_identities, password_hash nullable None Renumber to V1
Migration V27 — memberships + org-FK trigger Trigger references companies Renumber to V2 + leave trigger as T3 consumer responsibility
Migration V28 — invitations + audit None Renumber to V3
Migration V29 — access_requests None Renumber to V4
Migration V30 — companies.microsoft_tenant_id Pure InspectFlow Leave in InspectFlow's migration set
Migration V31 — login_events + revinfo actor None Renumber to V6 (see note below)

Migration-count note (corrected 2026-06-24, supersedes earlier "V5 tail"): plate-auth ships 6 migrations, V1..V6. V26→V1, V27→V2, V28→V3, V29→V4, then a standalone V5__add_microsoft_tenant_id_index.sql (an index on user_identities.microsoft_tenant_id — T1 data, distinct from V30's companies.microsoft_tenant_id which is T3 and stays in InspectFlow), and finally V31→V6 create_login_events_and_revinfo_actor.sql. This matches Architecture.md §8.1, Open-Questions F2, and the 6 migration files present in plate-auth-starter/src/main/resources/db/migration/auth/. The earlier "tail is V5 not V6" phrasing was wrong and is retracted.

1.2 Frontend — TypeScript / Next.js 15 / NextAuth v5

Layer File Lines Domain coupling Status
Config auth-config.ts ~150 InspectFlow-branded provider opts, invite-token extraction from URL Reshape — extract createAuthConfig(opts) factory
Lib exchange.ts ~80 None — HMAC envelope sign + POST Lift-and-shift
Lib auth.ts ~40 Hardcoded localStorage keys (inspectflow_access_token) Reshape — make key prefix configurable
Route app/api/auth/[...nextauth]/route.ts ~10 None Lift-and-shift as default boilerplate
Route app/api/[...path]/route.ts (proxy) ~120 None — calls auth() + BACKEND_URL env var Reshape — extract createProxyHandlers(opts) factory
Middleware middleware.ts ~5 Trivial passthrough Lift-and-shift
Context auth-context.tsx ~100 Syncs NextAuth session → localStorage with InspectFlow keys Reshape — provide hook, let consumer choose persistence
Component <SignInButton />, <UserMenu />, etc. InspectFlow UI styling Leave behind — components stay per-product

1.3 What is not in InspectFlow but should be

Item Justification
PlateAuthAutoConfiguration Spring Boot starter auto-config doesn't exist yet — InspectFlow wires beans manually
PlateAuthProperties with @ConfigurationProperties("plate.auth") InspectFlow has scattered @Value("${jwt.secret}") etc. — needs consolidation
META-INF/spring/...AutoConfiguration.imports Spring Boot 3+ auto-config registration file
OrgValidator SPI Currently MembershipService.grantMembership(…) checks companies directly via repository
Default OrgDisplayNameResolver Currently joined inline in MembershipService
OnboardingHook SPI Currently OAuthService calls OnboardingService directly
createAuthConfig(opts) factory InspectFlow's auth-config.ts is mostly procedural
createProxyHandlers(opts) factory Same
Lockstep version contract documentation InspectFlow doesn't version its in-tree code as a public artifact

2. Reusability classification — summary

pie title "Auth surface — extraction classification"
    "Lift-and-shift" : 65
    "Reshape (small)" : 25
    "Leave behind (T3)" : 10
  • ~65% lift-and-shift: entities, filters, JwtService, ExchangeService, controllers, password-auth, login events, invitation flow, access request flow.
  • ~25% reshape: SecurityConfig permit-list, MembershipService FK lookup, frontend factories, config namespace.
  • ~10% leave behind (T3): Company entity, OnboardingService, TenantAutoMapService, V30 migration.

The extraction is fundamentally a rename + repackage operation with 5 well-defined SPI seams.


3. Risk register

# Risk Likelihood Impact Mitigation
R1 Flyway migration renumbering corrupts InspectFlow's flyway_schema_history Medium High — could break a production deploy Use Flyway baseline strategy: introduce flyway_schema_history_auth separate from app's table OR use installed_rank re-mapping (see Sprint-0-Plan § Migration strategy)
R2 InspectFlow ends up shadow-overriding services because SPI is too narrow Medium Medium — forks defeat purpose of library Plan v0.2 SPI follow-up; track shadow-overrides during InspectFlow migration
R3 Spring Boot 4 + Java 25 not yet GA when we ship Low (Sparkboard already committed) Medium Pin to specific stable milestone; coordinate with Sparkboard team
R4 NextAuth v5 final API differs from current beta Low Medium Pin next-auth@5.0.0-beta.X and lockstep with our v0.1 release
R5 In-memory nonce store breaks under multi-replica (already known) Certain (when scaling) Medium Documented in Roadmap.md as v0.3 work; v0.1 ships with this known limitation
R6 Gitea Package Registry npm publishing not yet configured Medium Medium Sprint 0 includes a "publish pipeline" task; validate by publishing a 0.0.0-snapshot first
R7 de.platesoft.auth.* package rename breaks downstream consumers that imported from de.platesoft.inspectflow.security.* Certain (InspectFlow consumes) Low — mechanical refactor Migration-InspectFlow.md provides exact sed/find-replace recipes
R8 Microsoft Entra ID coupling assumed (InspectFlow uses it, Sparkboard might not) Low — feature is config-gated Low Provider enabled via plate.auth.providers.microsoft.enabled=false default
R9 OrgType enum is shared across products — what if Sparkboard adds WORKSPACE and InspectFlow doesn't know about it? Medium Low — enum is in lib, value space is open Make OrgType a String-backed enum or keep as enum but document the "consumer registers their own types" pattern. Decision deferred to Open-Questions Q01.
R10 The published JAR contains entity classes — consumers must not extend or modify them Low Medium Mark entities final where Hibernate allows; document the contract in Architecture.md
R11 HMAC secret regeneration causes total session invalidation across all users Low (deliberate ops action) Low Document operational runbook; v0.3 adds kid-based rotation
R12 Java 25 LTS adoption — Sparkboard pioneer, InspectFlow currently on Java 25 already Low Low Verified InspectFlow pom.xml shows Java 25 — no risk

4. Dependencies we are accepting

Version snapshot at time of extraction (read from inspectflow/backend/pom.xml):

Dep Version Notes
Spring Boot 4.1.0 (target — InspectFlow on 4.0.7 today) Bump as part of extraction
Java 25 LTS Aligned with InspectFlow + Sparkboard
jjwt 0.12.6 HMAC SHA-256 token signing
Hibernate (Spring Boot managed) + Envers for audit
Postgres driver (Spring Boot managed)
Flyway (Spring Boot managed)
Lombok (Spring Boot managed)
MapStruct (Spring Boot managed) DTO mapping
NextAuth 5.x (beta tracking) Frontend session layer
Next.js 15+ App Router Required for auth() + duplex:"half"
React 19 Required by NextAuth v5

We accept tight coupling to these. We do not abstract over framework boundaries.


5. Effort estimate

Single-engineer days, including planning, code, tests, plan reviews:

Phase Effort Notes
Wiki documentation (this batch) 1d Done in this session
Plan Review iteration loop 0.51d Plan Reviewer + Ask Phase + Patrick GO
Repo scaffolding (Maven + npm + CI) 0.5d Gitea Actions, publish pipeline
Backend extraction (rename + repackage) 1.5d Mechanical; lots of imports to update
Backend SPI work (5 SPIs + auto-config) 1d Net new code
Flyway migration consolidation 0.5d + integration tests
Frontend extraction (factories + types) 1d
Internal tests 1d Integration tests covering exchange + auth flow
InspectFlow migration 1d Per Migration-InspectFlow.md
Sparkboard adoption dry-run 0.5d Validates Integration-Guide.md
Buffer 1d Always
Total ~910 engineer-days Sprint 0 fits in 2 calendar weeks

6. Recommendation

GO — proceed to Sprint-0-Plan v1 with the following constraints:

  1. Strict T1+T2 scope. Anything T3-flavored stays in InspectFlow until at least v0.2.
  2. 5 SPIs are mandatory in v0.1. Without them InspectFlow cannot migrate cleanly.
  3. Lockstep versioning is mandatory. Frontend and backend ship together with identical version numbers.
  4. Migration renumbering uses a separate flyway_schema_history_auth table (or equivalent) — must NOT touch InspectFlow's existing flyway_schema_history. Final decision in Open-Questions Q03.
  5. In-memory nonce store is acceptable for v0.1. Documented limitation. Multi-replica fix in v0.3.
  6. No Spring Boot 4 GA gate. Use the milestone Sparkboard team has already adopted, even if it's a release candidate.

If the Plan Reviewer disagrees with any of these, we iterate. But these are the assumptions Sprint-0-Plan v1 will be built on.


7. Open questions raised during assessment

The following items surfaced during analysis but should not block Sprint 0 planning. They are tracked in Open-Questions.md for Patrick to resolve before code starts:

  • Q01 — Concrete org table abstraction (Company stays vs. generic Organization)
  • Q02 — Microsoft Entra ID in v0.1 or defer to v0.2 (depends on Sparkboard plans)
  • Q03 — Flyway migration strategy (separate schema history table vs. baseline reset)
  • Q04 — Email magic-link provider in v0.1 or v0.2
  • Q05 — npm package name (@platesoft/auth vs alternatives)
  • Q06 — SemVer policy details (especially around peer version lockstep)
  • Q07 — Gitea publishing pipeline (Gitea Actions vs manual deploy)
  • Q08 — Spring Boot version pin (4.0.7 vs 4.1.0 vs latest milestone)

Assessment ready for Plan Reviewer. Sprint-0-Plan v1 will be drafted assuming all Section 6 recommendations hold; any Plan Reviewer pushback re-opens the recommendation list.