1
Sprint 1 Assessment
Patrick Plate edited this page 2026-06-24 14:48:18 +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 ("Spark")

Date: Pre-Sprint 1 planning Module: Sparkboard (greenfield) Author: Patrick Plate / Lumen (Planner) Status: Entwurf v1 — ready for Patrick GO Sprint codename: Spark Sprint goal: Walking skeleton consuming plate-auth v0.1.0, deployed to sparkboard.plate-software.de, four allowlisted users can sign in with Google and post ideas.


1. Problem analysis

Sparkboard does not exist yet. There is no codebase, no database, no deployment, no DNS, no CI pipeline. The Sprint 1 problem is therefore not "fix a bug" or "extend a feature" — it is "go from a git init to a four-human production system in one sprint."

The unique pressure on Sprint 1 is that Sparkboard must be the first real consumer of plate-auth. Every assumption plate-auth made about how its starter would be used is, by definition, validated or falsified here. If plate-auth's auto-configuration leaves a sharp edge, Sparkboard will hit it. The benefit is that we are doing this hand-in-hand with plate-auth (same developer, same wiki, same week) — defects in plate-auth's contract surface immediately and can be patched in plate-auth, not worked around in Sparkboard.

The product surface is intentionally tiny: one entity (Idea), two endpoints (GET /api/ideas, POST /api/ideas), two pages (/login, /ideas). Everything else in Sprint 1 is infrastructure: build, deploy, auth wire-up, PWA, CI/CD. The fact that the product surface is small is the strategy — it focuses Sprint 1 entirely on the integration story.


2. Affected components

Because Sparkboard is greenfield, "affected" means "created". The full v1 component inventory:

Layer Component New / Library Owner
Backend SparkboardApplication.java New Sparkboard
Backend Idea entity + IdeaRepository / IdeaService / IdeaController New Sparkboard
Backend SparkboardOnboardingHook (OnboardingHook SPI impl) New Sparkboard
Backend SparkboardAdminProperties (@ConfigurationProperties("sparkboard")) New Sparkboard
Backend Flyway migrations: V1__init.sql (Sparkboard tables only) + V2__seed_family_spark_org.sql New Sparkboard
Backend de.platesoft:plate-auth-starter:0.1.0 Library plate-auth
Backend application.yml with plate.auth.* configuration New Sparkboard
Frontend auth.ts (calls createAuthConfig from @platesoft/auth/next-auth) New Sparkboard
Frontend app/api/auth/[...nextauth]/route.ts (NextAuth handlers re-export) New Sparkboard
Frontend app/api/backend/[...path]/route.ts (calls createProxyHandlers from @platesoft/auth/proxy) New Sparkboard
Frontend app/(app)/ideas/page.tsx (list, server component) New Sparkboard
Frontend app/(app)/ideas/new/page.tsx + <IdeaForm/> New Sparkboard
Frontend app/(auth)/login/page.tsx New Sparkboard
Frontend public/manifest.json + public/sw.js + icon set + lib/sw-register.ts New Sparkboard
Frontend @platesoft/auth@0.1.0 npm package Library plate-auth
Infra docker-compose.yml (local dev) + docker-compose.prod.yml (TrueNAS) New Sparkboard
Infra IONOS Apache vhost for sparkboard.plate-software.de New Sparkboard (same template as InspectFlow/CannaManage)
Infra frpc entry on TrueNAS, port 30011 New Sparkboard
Infra DNS: sparkboard.plate-software.de CNAME New Sparkboard
CI .gitea/workflows/ci.yml (build + test) New Sparkboard
CI .gitea/workflows/deploy.yml (SSH deploy to TrueNAS) New Sparkboard
Docs This wiki New Sparkboard

What is deliberately not built (because plate-auth ships it):

  • Any User entity / table / repository
  • Any JWT-signing or JWT-validating filter
  • Any allowlist enforcement
  • Any membership / invitation / access-request table or controller
  • Any auth-exchange controller
  • Any hand-rolled proxy that injects bearer tokens
  • Any NextAuth provider config beyond createAuthConfig({ providers: { google: { ... } } })

The size of that not built list is the integration thesis.


3. Current state

There is no current state. Sprint 1 starts from the empty Gitea repo. The closest analogues are:

  • plate-auth v0.1.0 (sibling repo, expected to ship before Sprint 1 starts) — provides every auth primitive.
  • InspectFlow Sprint 14 — the origin of every auth pattern that now lives in plate-auth. Sparkboard does not copy code from InspectFlow; it consumes plate-auth instead. The patterns are similar by ancestry, not by code-reuse.
  • CannaManage — sibling project; provides the deployment shape (TrueNAS + frps + IONOS Apache + Caddy/Apache vhost + Gitea Actions). Sparkboard's docker-compose.prod.yml, Caddyfile (or Apache equivalent), and deploy.sh are pattern-mirrored from CannaManage.

4. Risk assessment

# Risk Probability Impact Mitigation
R1 plate-auth v0.1.0 ships incomplete or with a bug in single-org mode — Sparkboard is the first consumer, so it finds problems first Medium High Sprint 1 hard-blocks until plate-auth v0.1.0 is green. Sparkboard and plate-auth share a developer (Patrick), so plate-auth bugs become same-day patches, not multi-week tickets.
R2 Spring Boot 4.1 regression — Sparkboard is the SB 4.1 guinea pig in plate-software Low Medium Pin to the GA release, not RC/snapshot. If a regression appears, downgrade to SB 4.0 LTS is a one-line pom.xml change. plate-auth tests against SB 4.1 in its own CI before publishing.
R3 Google OAuth misconfiguration — wrong redirect URI, wrong scopes, wrong consent screen Medium Medium Validate end-to-end in dev with http://localhost:3000 redirect first, then add the production redirect. Document required Google Cloud Console steps in Integration Guide §1.
R4 NextAuth v5 wire-up confusion — NextAuth v5 is still relatively new and has notable differences from v4 Medium Medium @platesoft/auth/next-auth is the abstraction that hides v5 specifics. As long as that factory is correct, Sparkboard never touches NextAuth v5 internals.
R5 frps tunnel + IONOS Apache double-proxy breaks for the new port 30011 Low Medium Pattern is already validated for InspectFlow (30009) and CannaManage (30010). Copy the working frpc.toml and Apache vhost block; only change the port and hostname.
R6 TrueNAS Docker volume permissions for the Postgres data dir Medium Low Postgres image runs as UID 999 by default; the TrueNAS dataset must be chowned. Document in deploy.sh. Same lesson learned twice already (InspectFlow + CannaManage).
R7 Gitea Actions SSH deploy step — SSH key, known_hosts, sudo password Medium Medium Reuse the CannaManage workflow (appleboy/ssh-action@v1.0.0). Test the deploy script locally before committing the workflow.
R8 PWA service-worker caching the login page — users get stuck on a stale /login Low High Service worker is stub-only in v1: it registers, claims clients, but caches nothing. Caching strategy is Sprint 4 work, not Sprint 1.
R9 Allowlist typo locks out one of the four users Medium Low Allowlist is in application.yml env-substituted (PLATE_AUTH_ALLOWLIST_EMAILS). Add an admin override mechanism in Sprint 2; for Sprint 1, accept that a redeploy fixes typos.
R10 Flyway version drift between Sparkboard's history and plate-auth's history Low Medium Two separate histories (flyway_schema_history + flyway_schema_history_auth) means they cannot collide. Configured via plate-auth's plate.auth.flyway.table property.
R11 The OnboardingHook fires before plate-auth has finished persisting auth_identities — race condition on first login Low High plate-auth's contract is that the hook runs after auth_identities INSERT, in the same transaction. Verified by reading plate-auth's tests. Hypothesis logged in BigMind for resolution during Sprint 1 W1.

5. Solution options

Three options for Sprint 1 scope, scored on how aggressively they prove plate-auth.

  • Scope: Idea entity only. GET /api/ideas + POST /api/ideas. List page + create form. PWA installable. Deployed.
  • Plate-auth touch surface: maximum. Auth, allowlist, membership row, JWT, proxy, single-org config — all exercised.
  • Pro: smallest possible product surface focuses all energy on integration.
  • Pro: every Sprint 1 acceptance criterion exercises plate-auth.
  • Pro: if any Sprint 1 acceptance fails, it's almost certainly an integration issue, not a product issue — easy to localise.
  • Con: the visible product looks very thin after a sprint. Four users get an idea list and a "+" button and nothing else.
  • Effort: 23 weekends after plate-auth v0.1.0 lands.

Option B — Backend + frontend in isolation, no deploy

  • Scope: Build the backend and frontend, run them locally, demo locally. Skip the TrueNAS / frps / IONOS / Gitea Actions work.
  • Pro: less moving parts in one sprint.
  • Con: doesn't validate the most operationally risky bits (R5, R6, R7). Defers risk.
  • Con: delivers nothing the four real users can touch — defeats the point of "walking" skeleton.
  • Effort: 12 weekends.

Option C — Frontend-only mock with localStorage

  • Scope: No backend. Next.js app stores ideas in localStorage. Auth is stubbed.
  • Pro: trivially deployable as a static site.
  • Con: doesn't validate plate-auth at all. Sparkboard's entire strategic reason for existing collapses.
  • Effort: 1 weekend.

6. Recommendation

Option A — Walking skeleton.

The visible thinness of Option A is the cost, and it is the right cost. Sparkboard's strategic value is in validating plate-auth, not in shipping a four-feature product surface to four humans on weekend two. If Sprint 1 ships a real auth flow, a real membership row, a real JWT, a real proxy, and a real production deploy — and only one CRUD operation each direction — the integration thesis is proven. Sprint 2 (Kindling) adds the product features.

Option B defers the highest-risk operational work into Sprint 2, where it would compete for attention with reactions/status/comments. Bad trade.

Option C undermines the whole project. Skip.


7. Acceptance criteria (A1A6)

These are the formal gates Sprint 1 must clear before it is "done". Each is testable; the Sprint 1 Testplan maps tests onto each.

A1 — Allowlisted user can sign in with Google

Given a Gmail account in plate.auth.allowlist.emails, when the user visits https://sparkboard.plate-software.de/login and clicks "Sign in with Google", they are redirected to Google, consent, redirected back, and land on /ideas as an authenticated session. Tested by MT-01.

A2 — Non-allowlisted user is rejected with a clean error

Given a Gmail account NOT in the allowlist, when the user attempts the same flow, they see a generic "not authorised" message and no Sparkboard user record is created in any table. Tested by MT-02, IT-03.

A3 — First login auto-creates membership in Family Spark org

Given a successful first sign-in by an allowlisted user, after the flow completes, the memberships table contains exactly one row for that user_id: (user_id, 'SPARK_ORG', FAMILY_SPARK_ID, role) where role = ADMIN if the email is in sparkboard.admins[], otherwise MEMBER. Second sign-in does not create a duplicate. Tested by UT-04, IT-01, MT-03.

A4 — Any authenticated user can create and list ideas

POST /api/ideas with { title, description? } and a valid bearer token creates an Idea row with org_id = FAMILY_SPARK_ID, author_id = <token user_id>, status = RAW, and returns the new idea. GET /api/ideas returns all ideas in the Family Spark org, newest first. Tested by UT-02, UT-03, IT-02, E2E-01.

A5 — PWA installable on iOS Safari and Android Chrome

The deployed app serves a valid manifest.json with name, short_name, start_url, display: standalone, theme_color, and at least a 192×192 and 512×512 icon. The "Add to Home Screen" affordance appears on iOS Safari and Android Chrome. Once installed, the app launches in standalone mode without the browser chrome. Tested by E2E-03, MT-04, MT-05.

A6 — Deployed to https://sparkboard.plate-software.de via Gitea Actions

A merge to main triggers Gitea Actions, which builds backend and frontend images, pushes to the Gitea container registry, SSH-deploys to TrueNAS, the new containers come up healthy, and the smoke test (/api/health returns 200, /login returns 200) passes. The whole pipeline is < 10 minutes wall-clock. Tested by MT-06, MT-07.


8. plate-auth integration footprint (Sprint 1)

What Sparkboard touches in plate-auth's surface. If any of these contracts changes in v0.2, Sparkboard knows where to look:

plate-auth surface Sparkboard usage
de.platesoft:plate-auth-starter Maven artifact Declared in backend/pom.xml
plate.auth.jwt.secret config Set from env var PLATE_AUTH_JWT_SECRET
plate.auth.exchange.secret config Set from env var PLATE_AUTH_EXCHANGE_SECRET
plate.auth.allowlist.emails config List of 4 emails, env-substituted
plate.auth.providers.google.{client-id, client-secret} config Env-substituted
plate.auth.registration.enabled = false Explicit
OnboardingHook SPI Implemented by SparkboardOnboardingHook
MembershipService.upsert(userId, orgType, orgId, role) API Called from the hook
Role enum (ADMIN, MEMBER) Used by the hook
@platesoft/auth npm artifact Declared in frontend/package.json
createAuthConfig(...) factory Called from frontend/auth.ts
createProxyHandlers(...) factory Called from frontend/app/api/backend/[...path]/route.ts
flyway_schema_history_auth table Owned by plate-auth; Sparkboard's Flyway never touches it

Untouched in v1 (deliberately deferred or unneeded):

  • OrgValidator SPI (default no-op accepted)
  • OrgDisplayNameResolver SPI (default org_id rendering accepted)
  • InvitationMailer SPI (no invitations in v1)
  • AccessRequestMailer SPI (no access requests in v1)
  • React hooks from @platesoft/auth/react (Sprint 2 candidate if needed for profile page)
  • /api/auth/invite / /api/auth/access-requests HTTP endpoints (not called)

9. Out of scope (deferred to Sprint 2+)

Item Sprint
Reactions (💡🔥👀) 2 (Kindling)
Status transitions in UI 2
Idea archive / soft-delete UI 2
Idea edit 2
Idea detail page 2
Profile / account-settings page 2
Comments 3 (Flame)
Search 3
Notifications (email / web-push) 4 (Ember)
Offline cache (real SW caching) 4
Native APK (Capacitor) 5 (Wildfire)
Image attachments 5

10. Open questions

Cross-referenced to Open Questions. The four that must be answered before Sprint 1 implementation starts:

The other six on the Open Questions page affect Sprint 2+ and do not block Sprint 1.


11. Verdict

Recommendation: APPROVE Option A, A1A6 acceptance, with Q01Q03 and Q07 answered before W2 of Sprint 1 starts.

Next document: Sprint 1 — Plan breaks the recommendation into workstreams W0W6.