2
Sprint 1 Plan Part 4
Patrick Plate edited this page 2026-06-24 15:29:06 +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 Plan — "Spark" (Part 4/4)

Final chunk. Implementation order, acceptance mapping, open-question cross-references, Definition of Done, and what actually ships at the end of Sprint 1.

Previous chunks:


7. Implementation Order

The 7 workstreams are not all sequential. There is one hard prerequisite chain and one parallelisable pair.

7.1 Dependency graph

W0 Skeleton
   │
   ▼
W1 plate-auth wire-up
   │
   ├──────────────┐
   ▼              ▼
W2 Domain    W3 API (depends on W2 entity + W1 @CurrentUser)
   │              │
   └──────┬───────┘
          ▼
       W4 Frontend
          │
          ▼
   W5 Seed data (dev-only, can run in parallel with W4 once W2 is done)
          │
          ▼
       W6 Deploy + CI/CD
Order Workstream Why this position
1 W0 Skeleton Nothing builds without the repo + Maven + pnpm scaffolding.
2 W1 plate-auth wire-up Until plate-auth is wired, @CurrentUser does not exist → W3 can't compile.
3 W2 Domain Ideas table + entity + OnboardingHook impl. Unblocks both W3 and W4 (the API contract).
4a W3 API Can start as soon as Idea and IdeaService exist.
4b W5 Seed (dev) R__dev_seed_ideas.sql only needs the ideas table to exist. Can run in parallel with W3.
5 W4 Frontend Needs W3 endpoints alive (at least /api/ideas GET returning []).
6 W6 Deploy + CI/CD Last because it requires real images of W3 + W4 to ship.

7.3 Daily-granular sketch (informal)

Reality check: Sprint 1 has no day-count contract. This is a rough shape, not a commitment.

Phase Focus Outcome
Phase 1 W0 + W1 mvn -pl backend test green. Frontend builds. /login page renders. Backend boots with plate-auth auto-config.
Phase 2 W2 + start W3 Flyway migration creates spark_org + ideas. Onboarding hook registered. GET /api/ideas returns [] for authenticated user.
Phase 3 Finish W3 + start W4 POST /api/ideas works in Postman/curl with a real Bearer JWT. /ideas page renders empty list.
Phase 4 W4 /ideas/new form submits → backend persists → list refreshes. End-to-end happy path works in docker-compose up.
Phase 5 W5 + start W6 Dev seed loads 5 demo ideas locally. Backend Dockerfile builds. Frontend Dockerfile builds.
Phase 6 W6 TrueNAS deploy via Gitea Actions. https://sparkboard.plate-software.de/login reachable from public internet. PWA installable.

8. Acceptance Criteria → Workstream Mapping

Each acceptance criterion from Sprint-1-Assessment §7 maps to one or more workstreams. If a workstream is incomplete, the linked acceptance criteria cannot pass.

# Acceptance Workstreams Verification
A1 Allowlisted user can sign in via Google and reach /ideas W1 + W4 + W6 Manual: load https://sparkboard.plate-software.de, click "Sign in with Google", land on /ideas.
A2 Non-allowlisted user is rejected with a clear error W1 Manual: sign in with a non-allowlisted Google account → plate-auth rejects → error page or /login?error=access_denied.
A3 Membership auto-created for new allowlisted user (no manual step) W2 (SparkboardOnboardingHook) DB inspection: after first login, memberships table contains (user_id, 'SPARK_ORG', '00000000-0000-0000-0000-000000000001', 'MEMBER'|'ADMIN') row.
A4 Authenticated user can create + list ideas W2 + W3 + W4 E2E: log in → /ideas/new → submit → idea appears on /ideas.
A5 App is installable as PWA on iOS and Android W4 (manifest + sw.js) Manual on iPhone + Android: "Add to Home Screen" → standalone window with Sparkboard icon.
A6 App is deployed to TrueNAS via Gitea Actions on push to main W6 Watch .gitea/workflows/deploy.yml succeed; smoke-test.sh passes against https://sparkboard.plate-software.de.

8.1 Coverage matrix (workstream → acceptance)

Workstream A1 A2 A3 A4 A5 A6
W0 Skeleton
W1 plate-auth wire-up
W2 Domain
W3 API
W4 Frontend
W5 Seed (dev)
W6 Deploy

Gap check: W0 and W5 are not on the acceptance hook directly. W0 is infrastructure (without it, nothing else exists). W5 is dev productivity (no production value but speeds up manual testing on Patrick's laptop). Both stay in scope.


9. Open Questions (Sprint-1-Specific)

All Sprint-1-blocking questions have been decided 2026-06-24. The full list of Sparkboard open questions lives in Open-Questions — this section only logs the Sprint 1 decisions.

ID Question Sprint 1 Impact Decision (2026-06-24)
Q01 Single-org name + ID strategy High — affects W2 SQL + IdeaController.FAMILY_SPARK_ID constant. Option A. Hardcode FAMILY_SPARK_ID = UUID.fromString("00000000-0000-0000-0000-000000000001") as a public static final on SparkboardOnboardingHook.
Q02 Allowlist management Medium — affects W1 config shape and W6 deploy story. Option A. plate.auth.allowlist[] in application.yml. YAML edit + Gitea Actions deploy. Admin UI deferred to Sprint 4.
Q03 Admin promotion model Medium — affects W2 (SparkboardOnboardingHook logic). Option A. sparkboard.admins[] YAML list (bound by SparkboardAdminProperties). onFirstSignIn(user) reads it and writes ADMIN vs MEMBER. Initial seed (placeholders — replace before first deploy): <patrick@email>, <friend@email>, <kid1@email>, <kid2@email>.
Q07 PWA assets pipeline Low — affects W4 + manifest. Option A. Hand-craft 192×192 + 512×512 PNGs in frontend/public/icons/. No build-time generator in Sprint 1.

Non-blocking but worth noting: Q04 (idea status workflow), Q05 (reaction model), Q06 (security customisation), Q08 (mobile PWA vs native), Q09 (real-time updates), Q10 (notifications) are all Sprint 2+. They do not affect Sprint 1's surface.


10. Definition of Done

Sprint 1 is done when all of these are true simultaneously:

10.1 Code & build

  • mvn -pl backend test exits 0 on Patrick's laptop and in CI.
  • pnpm --filter frontend build exits 0 on Patrick's laptop and in CI.
  • docker compose up boots all 3 services (postgres + backend + frontend); backend logs show "Flyway migrations applied" for both flyway_schema_history and flyway_schema_history_auth.
  • No TODO markers blocking Sprint 1 acceptance in committed code (TODOs for Sprint 2+ are fine).

10.2 Functional (verified manually on TrueNAS deploy)

  • A1 — Patrick can sign in via Google → lands on /ideas.
  • A2 — A non-allowlisted Gmail rejection produces a visible error (not a 500).
  • A3 — DB inspection: memberships row for Patrick's user exists after first login.
  • A4 — Patrick creates an idea via /ideas/new → it appears on /ideas after redirect.
  • A5 — "Add to Home Screen" on iPhone Safari creates a standalone-mode Sparkboard icon.
  • A6 — A commit to main triggers .gitea/workflows/deploy.yml, which succeeds and runs smoke-test.sh against https://sparkboard.plate-software.de.

10.3 Testplan

  • All test cases in Sprint-1-Testplan marked Passed, ⏭️ Skipped (with reason), or Failed (with linked follow-up ticket).
  • No Failed test blocks an acceptance criterion.

10.4 Operations

  • https://sparkboard.plate-software.de resolves and serves the Next.js app.
  • frps tunnel on port 30011 is alive and stable for ≥1 hour of uptime.
  • Caddy correctly routes /api/* to backend and everything else to frontend.
  • Backend uses production secrets from environment variables (not literal application.yml values).
  • Postgres data survives docker compose down && docker compose up (named volume mounted).

10.5 Documentation

  • Sprint-1-Testplan is updated with actual results.
  • Open-Questions reflects any decisions made during Sprint 1.
  • README.md in sparkboard/ repo root has local-dev instructions that work on a clean checkout.

11. What Ships at End of Sprint 1

The deliverable, in plain English:

Patrick (or one of the 4 humans on the allowlist) opens https://sparkboard.plate-software.de on a phone or laptop, signs in with their Google account, lands on a list of ideas the family has captured. They tap "New idea", type a title and optional body, hit submit, and see their idea on the list. They can install the app to their home screen on iOS or Android. Anyone not on the allowlist gets a clear rejection. The whole thing was deployed by git push origin main.

11.1 What ships (concrete)

Component Status at end of S1
sparkboard.plate-software.de Live, HTTPS via IONOS + frp + Caddy, port 30011
Google sign-in (allowlisted) Works for 4 humans on allowlist
/ideas (list page) Server-rendered list, newest first
/ideas/new (create form) Title + body → POST → redirect to /ideas
PWA manifest + service worker Installable; no offline caching yet
Single org auto-membership Every first login creates a (SPARK_ORG, '00...01', MEMBER|ADMIN) row
plate-auth v0.1.0 dependency Pulled from Gitea Maven + npm registries
Gitea Actions deploy Push to main → SSH to TrueNAS → docker compose pull && docker compose up -d → smoke test
Test suite Backend mvn test green, frontend pnpm test green, E2E smoke green

11.2 What does NOT ship in S1 (intentional deferrals)

Deferred Lands in Why
Edit / delete idea Sprint 2 (Kindling) Read + create is the walking-skeleton minimum
Idea detail page Sprint 2 (Kindling) List view is enough to prove the model works
Reactions, comments Sprint 2/3 (Kindling/Flame) Single-feature focus; conversation later
Status workflow (RAW → BUILDING → SHIPPED) Sprint 2 (Kindling) Field exists on entity with default RAW, but no UI to change it
Notifications Sprint 4 (Ember) Requires push infra; not v1-critical
Offline mode / IndexedDB cache Sprint 4 (Ember) sw.js stub-only in S1 (R8 mitigation)
Native APK via Capacitor Sprint 5 (Wildfire) PWA-first; native only if PWA falls short
Admin UI for allowlist Sprint 4 (Ember) YAML + redeploy is fine for 4 humans
Per-user analytics, audit log Phoenix (optional) Not v1-critical
Multi-org support Never (Sparkboard scope) Sparkboard defines single-org. If multi-org is ever needed it becomes a different app.

12. Risk Re-check Against Plan

Cross-reference of Sprint-1-Assessment §4 risks with the workstream that owns each mitigation:

Risk Owner Mitigation in plan
R1 plate-auth incomplete on Sprint 1 start W0/W1 Sprint 1 blocked until plate-auth v0.1.0 shipped — gating is explicit.
R2 plate-auth API changes mid-sprint W1 Pin to v0.1.0 in pom.xml + package.json; refuse to bump mid-sprint.
R3 Spring Boot 4.1.0 guinea-pig issues W0 Accept; document workarounds in README.md as found.
R4 Google OAuth setup friction W1 Use plate-auth's existing OAuth config; reuse the InspectFlow Google Cloud project credentials.
R5 frp instability on port 30011 W6 Reuse existing frpc.toml pattern from InspectFlow (port 30009); same proven setup.
R6 IONOS reverse proxy quirks W6 Reuse existing pattern from inspectflow.plate-software.de.
R7 Flyway migration collision (two histories) W2 Distinct table names (flyway_schema_history vs flyway_schema_history_auth) configured in plate-auth's auto-config; no cross-history FKs.
R8 PWA install rejection W4 Hand-crafted icons; valid manifest; sw.js stub registers cleanly (no caching logic to break).
R9 Single-org assumption leaks into multi-org pattern W2/W3 FAMILY_SPARK_ID as one constant in one place. One-line refactor to read from user context when needed.
R10 Polymorphic FK ergonomics W2 Tolerated; index on (org_type, org_id) for query perf; documented.
R11 OnboardingHook race condition W2 MembershipService.upsert is idempotent; hook can run safely on every login.

All risks have a workstream and a concrete mitigation.


13. Cross-references


End of Sprint 1 Plan. Status: Draft v1, awaiting GO from Patrick.