From f1e45a066a1b08cb2953981126b090b81c317e6a Mon Sep 17 00:00:00 2001 From: Patrick Plate Date: Wed, 24 Jun 2026 14:09:10 +0200 Subject: [PATCH] plan: add Vision.md (why we extract auth + success criteria) --- Vision.md | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 Vision.md diff --git a/Vision.md b/Vision.md new file mode 100644 index 0000000..d242bcc --- /dev/null +++ b/Vision.md @@ -0,0 +1,161 @@ +# Vision + +**Status:** Draft v1 +**Date:** 2026-06-24 +**Owner:** Patrick (plate-software) + +--- + +## Elevator pitch + +> **plate-auth** is the authentication, identity, and multi-tenancy layer that every plate-software product +> ships with — so we never write the same `JwtAuthenticationFilter` twice. + +One library, two artifacts: + +- **`de.platesoft:plate-auth-starter:0.1.x`** — a Spring Boot 4 auto-configuration starter. + Drop the dep in, configure four properties, get Google SSO + JWT + memberships + invites + access requests + admin audit. +- **`@platesoft/auth:0.1.x`** — a NextAuth v5 wiring kit for Next.js 15+ App Router. + Drop the package in, set three env vars, get the full sign-in / token exchange / proxy flow. + +Together they form the canonical answer to *"how do plate-software apps do auth?"* — backed by a single Postgres +schema, a single set of JWT semantics, and a single mental model. + +--- + +## Why we are building this + +### The forcing function: Sparkboard + +Sparkboard is plate-software's second product. It is greenfield, starts in Sprint 0, and must ship with the +same caliber of authentication that took InspectFlow six sub-sprints (14.1 – 14.6) to build. + +We have two options: + +1. **Copy-paste InspectFlow's auth code into Sparkboard.** Fast on day 1, painful forever — two divergent + forks of `JwtService`, two `signIn` callbacks to keep in sync, two security review surfaces, two breaking + changes whenever Spring or NextAuth ships a new major. +2. **Extract auth into a shared library.** Slower on day 1 (one extra sprint), cheaper for the rest of time. + +Sparkboard's existence forces option 2. Once a second consumer exists, the maintenance cost of duplication +exceeds the cost of the abstraction. + +### The strategic bet + +Every plate-software product over the next five years will need: + +- Sign in with a social/work identity provider (Google, Microsoft, optional email magic-link). +- Stateless server-side auth (JWT, no Spring session cookies). +- Multi-tenancy where one user can belong to many organizations with different roles. +- Invitations and access requests so admins don't manually wire every new user. +- An audit trail because some products will face regulated customers. + +If we make this a library, *every product* benefits from *every security fix* and *every UX improvement* — +automatically, on the next minor bump. + +--- + +## Who consumes plate-auth + +### v0.1 (Sprint 0 ship target) + +| Consumer | Status | Role | +|---|---|---| +| **InspectFlow** | Existing product, refactor target | First reference consumer. Validates that extraction is non-lossy by replacing in-tree code with the library. | +| **Sparkboard** | New product, greenfield | First day-1 consumer. Validates that *integration* (not migration) is ergonomic. | + +### v0.x (future plate-software apps) + +Anything else we build. The library is **internal** — distributed via the plate-software Gitea Package Registry. +We are not open-sourcing it. We are not building it for external customers. The audience is "us, six months +from now, starting product #3." + +--- + +## Non-goals + +To keep v0.1 shippable, the following are explicitly **out of scope**: + +| Out of scope | Why | +|---|---| +| External SSO for end-customer tenants (B2B SAML, SCIM provisioning) | No product needs it yet. Revisit in v0.4+. | +| Passwordless / WebAuthn / passkeys | Standards are stabilizing but the InspectFlow flow already has email magic-link. Add as v0.2 if a product asks. | +| OIDC server (plate-auth as identity provider for third parties) | We are an OAuth *consumer*, not a provider. Don't build this. | +| User self-service profile UI components | UI is per-product. We ship hooks and APIs, not React components. | +| Mobile native apps (iOS / Android SDKs) | Web-first. Mobile can call the same `/api/auth/exchange` endpoint and reuse the JWTs. | +| Audit log analytics / dashboards | Library emits `login_events` + Envers revisions. Visualization is a per-product concern. | + +--- + +## What success looks like + +### Sprint 0 success (ship v0.1.0) + +1. ✅ A new Spring Boot 4 app can add the starter, set `plate.auth.jwt.secret` + `plate.auth.exchange.secret` + + Google client id/secret, and have working Google SSO with JWT in under 30 minutes. +2. ✅ A new Next.js app can `npm install @platesoft/auth`, configure three env vars, and have a working + sign-in page in under 30 minutes. +3. ✅ InspectFlow's auth feature set is bit-for-bit reproducible from the library — no regression. +4. ✅ Sparkboard adopts the library on day 1 without ever seeing the InspectFlow code. + +### Six-month success (post-v0.1, calibration period) + +5. ✅ At least one security finding has been fixed *centrally* in plate-auth and propagated to both consumers + via a version bump (not a code-copy). +6. ✅ No consumer has needed to fork the library or shadow-override a service to ship a feature. (If they + have, the library has the wrong extension points and we fix them in v0.2.) +7. ✅ The library has shipped at least one minor version (v0.2) without breaking InspectFlow's `current` + branch — proving the SemVer policy is workable. + +### Long-term success (the dream) + +8. ✅ Product #3 launches with auth as a *checklist item*, not a *sub-sprint*. +9. ✅ When a CVE drops against jjwt / NextAuth / Spring Security, we patch *one* library and *all* products + are mitigated within a release cycle. +10. ✅ The decision *"how should this app do auth?"* never has to be made again. + +--- + +## Heritage + +plate-auth's design is not theoretical. It is the literal extraction of InspectFlow Sprint 14, which shipped +six sub-sprints of production-grade auth functionality: + +| Sub-sprint | Codename | What it added | +|---|---|---| +| 14.1 | Octopus Camouflage | OAuth providers, JWT filter, NextAuth signIn callback, HMAC exchange envelope | +| 14.2 | Cell Membranes | Memberships decoupled from users — `Membership(user, org_type, org_id, role, status)` | +| 14.3 | Pheromone Trails | Invitations with single-use tokens, expiry, audit trail | +| 14.4 | Honeybee Quorum | Access requests with admin review, rate limiting, justification | +| 14.5 | Tardigrade Cryptobiosis | Onboarding state machine (T3 — stays in consuming apps) | +| 14.6 | Tree Rings | Admin panel, login events, Envers revision actors | + +Every line of plate-auth v0.1 is code that has already shipped to production once. We are not designing — +we are *refactoring*. + +--- + +## Trade-offs we are accepting + +| Trade-off | Why we accept it | +|---|---| +| Slightly more upfront cost than copy-paste | Pays back the moment we touch auth code twice. | +| Plate-software-internal only, not open source | We do not want to support external users yet. Internal velocity > community. | +| Tight coupling to Spring Boot 4 + NextAuth v5 | These are the stacks we've committed to. Cross-framework abstraction would be over-engineering. | +| Postgres-only (Flyway migrations) | All plate-software products are Postgres. H2 is dev/test only. | +| Single tenant model per app (one user has memberships to many orgs *of the same type*) | InspectFlow has `org_type=COMPANY`, Sparkboard will define its own. Multi-org-type-per-user is theoretically supported by the schema but not exercised in v0.1. | + +--- + +## What this document is not + +- ❌ Not an architecture spec → see [`Architecture.md`](Architecture.md) +- ❌ Not a release plan → see [`Roadmap.md`](Roadmap.md) +- ❌ Not an extraction plan → see [`Sprint-0-Plan.md`](Sprint-0-Plan.md) +- ❌ Not an integration manual → see [`Integration-Guide.md`](Integration-Guide.md) + +It is the **why** that the rest of the wiki points at. + +--- + +*"Two products is a forcing function. Three products would have been a crisis. We are doing this now."*