docs: lock Q01/Q02/Q03/Q07 — Sprint-1 design decisions confirmed

Q01: Single-org ID strategy → Option A.
     Hardcode FAMILY_SPARK_ID = UUID.fromString("00000000-0000-0000-0000-000000000001")
     as public static final on SparkboardOnboardingHook. Used by IdeaController,
     the hook, and V2__seed_family_spark_org.sql.

Q02: Allowlist management UX → Option A.
     plate.auth.allowlist[] in application.yml.
     YAML edit + Gitea Actions deploy. Admin UI deferred to Sprint 4 (Ember).

Q03: Admin promotion model → Option A.
     sparkboard.admins[] YAML list (bound by SparkboardAdminProperties).
     SparkboardOnboardingHook.onFirstSignIn(user) reads it and writes
     Role.ADMIN if user.email() is in the list, otherwise Role.MEMBER.
     Initial seed (placeholders — replace before first deploy):
       <patrick@email>, <friend@email>, <kid1@email>, <kid2@email>.

Q07: PWA assets pipeline → Option A.
     Hand-craft 192×192 + 512×512 PNGs in frontend/public/icons/.
     No build-time generator in Sprint 1. Asset tooling revisited Sprint 4+.

Changes:
- Open-Questions.md: status overview + Q01/Q02/Q03/Q07 detail blocks
  flipped to 'Decided 2026-06-24'; resolved archive populated with Q01-Q03,
  Q07, F3, F4 rows; footer status now '6 open, 4 resolved'.
- Sprint-1-Plan-Part-4.md §9: 'Open Questions' table flipped to
  'Decision' column with locked answers.
- Home.md: '📜 Decisions log' section added with all 4 Q-decisions
  + F3/F4 reviewer findings, linking to Open-Questions for rationale.
Patrick Plate
2026-06-24 15:29:06 +02:00
parent f970504b93
commit 6f1f9837c4
3 changed files with 49 additions and 27 deletions
+16 -1
@@ -18,7 +18,7 @@ A web app at `sparkboard.plate-software.de` with a Spring Boot 4.1 + Java 25 bac
**Sprint 0 — Waiting.** Sparkboard cannot start coding until `plate-auth v0.1.0` is published to the Gitea Package Registry. Sparkboard's entire auth/multi-tenancy story is **outsourced** to that library. Sprint 1 ("Spark") begins the moment `de.platesoft:plate-auth-starter:0.1.0` and `@platesoft/auth:0.1.0` are pullable. **Sprint 0 — Waiting.** Sparkboard cannot start coding until `plate-auth v0.1.0` is published to the Gitea Package Registry. Sparkboard's entire auth/multi-tenancy story is **outsourced** to that library. Sprint 1 ("Spark") begins the moment `de.platesoft:plate-auth-starter:0.1.0` and `@platesoft/auth:0.1.0` are pullable.
**Sprint 1 — Spark.** Walking skeleton that imports `plate-auth`, configures it for single-org mode ("Family Spark"), implements one [`SparkboardOnboardingHook.afterFirstLogin()`](Architecture.md#single-org-mode-and-onboardinghook), adds a single `ideas` table, and ships to TrueNAS. Acceptance A1A6. **Sprint 1 — Spark.** Walking skeleton that imports `plate-auth`, configures it for single-org mode ("Family Spark"), implements one [`SparkboardOnboardingHook.onFirstSignIn()`](Architecture.md#single-org-mode-and-onboardinghook), adds a single `ideas` table, and ships to TrueNAS. Acceptance A1A6.
See [Roadmap](Roadmap.md) for the full multi-sprint arc. See [Roadmap](Roadmap.md) for the full multi-sprint arc.
@@ -52,6 +52,21 @@ What Sparkboard inherits from the wider `plate-software` family:
--- ---
## 📜 Decisions log
| Date | ID | Decision |
|------|----|----------|
| 2026-06-24 | Q01 | Single-org ID: hardcode `FAMILY_SPARK_ID = UUID.fromString("00000000-0000-0000-0000-000000000001")` on `SparkboardOnboardingHook` |
| 2026-06-24 | Q02 | Allowlist: `plate.auth.allowlist[]` in `application.yml` (YAML edit + redeploy via Gitea Actions) |
| 2026-06-24 | Q03 | Admin promotion: `sparkboard.admins[]` YAML list; `onFirstSignIn` writes ADMIN vs MEMBER |
| 2026-06-24 | Q07 | PWA icons: hand-crafted 192×192 + 512×512 PNGs in `frontend/public/icons/`; no build-time generator |
| 2026-06-24 | F3 | Onboarding hook renamed `afterFirstLogin(OnboardingContext)``onFirstSignIn(AuthenticatedUser)` (plate-auth spelling wins) |
| 2026-06-24 | F4 | UT-06 test class moved to `de.plate.sparkboard.onboarding.SparkboardOnboardingHookTest` |
Full rationale lives in [Open Questions](Open-Questions.md). Sprint-1-Plan-Part-4 § 9 carries the per-decision Sprint 1 impact.
---
## 🔗 External links ## 🔗 External links
| Link | What | | Link | What |
+26 -19
@@ -12,18 +12,18 @@
## Question Map ## Question Map
| ID | Topic | Blocks Sprint | Decision needed by | | ID | Topic | Status | Blocks Sprint | Decision needed by |
|----|-------|--------------|-------------------| |----|-------|--------|--------------|-------------------|
| Q01 | Single-org name and ID strategy | Sprint 1 (W2) | Sprint 1 kickoff | | Q01 | Single-org name and ID strategy | ✅ Decided 2026-06-24 — **A** | Sprint 1 (W2) | Sprint 1 kickoff |
| Q02 | Allowlist management UX | Sprint 1 (W1) — light; Sprint 4 — heavy | Sprint 1 kickoff | | Q02 | Allowlist management UX | ✅ Decided 2026-06-24 — **A** | Sprint 1 (W1) — light; Sprint 4 — heavy | Sprint 1 kickoff |
| Q03 | Admin promotion model | Sprint 1 (W2) | Sprint 1 kickoff | | Q03 | Admin promotion model | ✅ Decided 2026-06-24 — **A** | Sprint 1 (W2) | Sprint 1 kickoff |
| Q04 | Idea status workflow | Sprint 2 (Kindling) | Sprint 2 kickoff | | Q04 | Idea status workflow | ⏳ Open | Sprint 2 (Kindling) | Sprint 2 kickoff |
| Q05 | Reaction model | Sprint 2 (Kindling) | Sprint 2 kickoff | | Q05 | Reaction model | ⏳ Open | Sprint 2 (Kindling) | Sprint 2 kickoff |
| Q06 | Security customisation: do we need any beyond plate-auth? | Sprint 1 (W1) — confirm "no"; Sprint 2 — re-check | Sprint 1 kickoff | | Q06 | Security customisation: do we need any beyond plate-auth? | ⏳ Open | Sprint 1 (W1) — confirm "no"; Sprint 2 — re-check | Sprint 1 kickoff |
| Q07 | PWA assets pipeline (icons, splash) | Sprint 1 (W4) | Sprint 1 mid-sprint | | Q07 | PWA assets pipeline (icons, splash) | ✅ Decided 2026-06-24 — **A** | Sprint 1 (W4) | Sprint 1 mid-sprint |
| Q08 | Mobile strategy: PWA-only vs native APK | Sprint 5 (Wildfire) | Sprint 4 retro | | Q08 | Mobile strategy: PWA-only vs native APK | ⏳ Open | Sprint 5 (Wildfire) | Sprint 4 retro |
| Q09 | Real-time updates (live list refresh) | Sprint 4 (Ember) | Sprint 3 retro | | Q09 | Real-time updates (live list refresh) | ⏳ Open | Sprint 4 (Ember) | Sprint 3 retro |
| Q10 | Notifications: email, push, or none | Sprint 4 (Ember) | Sprint 3 retro | | Q10 | Notifications: email, push, or none | ⏳ Open | Sprint 4 (Ember) | Sprint 3 retro |
--- ---
@@ -46,7 +46,7 @@ This decision shows up in `IdeaController` (the `FAMILY_SPARK_ID` constant), the
- Trivial to refactor to option C the moment a second org appears (which is "never" for Sparkboard, but might be relevant if the pattern is lifted into a different app). - Trivial to refactor to option C the moment a second org appears (which is "never" for Sparkboard, but might be relevant if the pattern is lifted into a different app).
- Option B costs a DB roundtrip per request for no value. Option C costs configuration ceremony for no value. - Option B costs a DB roundtrip per request for no value. Option C costs configuration ceremony for no value.
**Decision:** _Pending._ **Decision:** **Decided 2026-06-24 — Option A.** Hardcode `FAMILY_SPARK_ID = UUID.fromString("00000000-0000-0000-0000-000000000001")` as a `public static final` on `SparkboardOnboardingHook`. Used by `IdeaController`, the hook, and the `V2__seed_family_spark_org.sql` migration. Refactor to option C only when a second org appears (not in Sprint 15).
--- ---
@@ -68,7 +68,7 @@ Affects W1 config shape, Sprint 4 admin-panel scope, and how forgiving the syste
- DB-backed allowlist (B) adds an entire CRUD surface; not worth it in Sprint 1. - DB-backed allowlist (B) adds an entire CRUD surface; not worth it in Sprint 1.
- Admin UI (C) is multi-week work; explicitly scheduled in Sprint 4 (Ember) on the [Roadmap](Roadmap.md). - Admin UI (C) is multi-week work; explicitly scheduled in Sprint 4 (Ember) on the [Roadmap](Roadmap.md).
**Decision:** _Pending._ **Decision:** **Decided 2026-06-24 — Option A.** Allowlist lives in `application.yml` under `plate.auth.allowlist[]` (bound by plate-auth's `PlateAuthProperties`). Adding/removing a family member is a YAML edit + Gitea Actions deploy. DB-backed allowlist (B) and admin UI (C) deferred to Sprint 4 (Ember) at the earliest.
--- ---
@@ -92,7 +92,7 @@ Affects W2 (`SparkboardOnboardingHook` impl) and the bootstrap story for new fam
- Idempotent (re-running the hook against the same user with same admin list = no diff). - Idempotent (re-running the hook against the same user with same admin list = no diff).
- Option D (all ADMIN) is tempting for simplicity, but Sprint 2+ will care about MEMBER vs ADMIN (e.g., admin-only delete), so introducing the distinction now costs almost nothing. - Option D (all ADMIN) is tempting for simplicity, but Sprint 2+ will care about MEMBER vs ADMIN (e.g., admin-only delete), so introducing the distinction now costs almost nothing.
**Decision:** _Pending._ **Decision:** **Decided 2026-06-24 — Option A.** Admin list lives in `application.yml` under `sparkboard.admins[]` (bound by `SparkboardAdminProperties`). `SparkboardOnboardingHook.onFirstSignIn(user)` reads it and writes `Role.ADMIN` if `user.email()` is in the list, otherwise `Role.MEMBER`. Initial seed list (placeholders — replace before first deploy): `<patrick@email>`, `<friend@email>`, `<kid1@email>`, `<kid2@email>`.
--- ---
@@ -178,7 +178,7 @@ Affects A5 acceptance ("installable PWA with correct icon"). Default browser ico
- Asset-generator tooling (B) is Sprint 4+ when we care about iOS splash screens, maskable icons, dark-mode variants. - Asset-generator tooling (B) is Sprint 4+ when we care about iOS splash screens, maskable icons, dark-mode variants.
- C fails the spirit of A5. - C fails the spirit of A5.
**Decision:** _Pending. Sprint 1 blocker if no icon → A5 fails MT-01/MT-02._ **Decision:** **Decided 2026-06-24 — Option A.** Hand-craft 2 PNGs (192×192 and 512×512), commit to `frontend/public/icons/icon-192.png` and `frontend/public/icons/icon-512.png`, reference both from `frontend/public/manifest.json`. No build-time generator in Sprint 1. Asset-generator tooling (Option B) revisited in Sprint 4+ when iOS splash / maskable / dark-mode variants are needed.
--- ---
@@ -248,9 +248,16 @@ Affects Sprint 4 architecture (SMTP integration vs Web Push API + VAPID keys).
## Resolved Questions (Archive) ## Resolved Questions (Archive)
> When a question is decided, move it here with the resolution and date. Keeps Q01Q10 numbering stable. > When a question is decided, the full text stays in place (numbering stays stable). This section is a quick-reference log of decisions.
_None yet._ | ID | Topic | Decision | Date |
|----|-------|----------|------|
| Q01 | Single-org name and ID strategy | **A** — Hardcode `FAMILY_SPARK_ID = 00000000-0000-0000-0000-000000000001` | 2026-06-24 |
| Q02 | Allowlist management UX | **A**`plate.auth.allowlist[]` in `application.yml` | 2026-06-24 |
| Q03 | Admin promotion model | **A**`sparkboard.admins[]` YAML list, read by `SparkboardOnboardingHook.onFirstSignIn` | 2026-06-24 |
| Q07 | PWA assets pipeline | **A** — Hand-crafted 192×192 + 512×512 PNGs in `frontend/public/icons/` | 2026-06-24 |
| F3 | Reviewer finding — hook method spelling | Renamed `afterFirstLogin(OnboardingContext)``onFirstSignIn(AuthenticatedUser)` across all sparkboard docs (plate-auth spelling wins) | 2026-06-24 |
| F4 | Reviewer finding — UT-06 package typo | `de.plate.sparkboard.auth.SparkboardOnboardingHookTest``de.plate.sparkboard.onboarding.SparkboardOnboardingHookTest` | 2026-06-24 |
--- ---
@@ -263,4 +270,4 @@ _None yet._
--- ---
_End of Open Questions. Status: **10 open, 0 resolved.**_ _End of Open Questions. Status: **6 open, 4 resolved.** (Q01, Q02, Q03, Q07 decided 2026-06-24.)_
+7 -7
@@ -94,14 +94,14 @@ Each acceptance criterion from [Sprint-1-Assessment §7](Sprint-1-Assessment.md#
## 9. Open Questions (Sprint-1-Specific) ## 9. Open Questions (Sprint-1-Specific)
These questions block or change Sprint 1 if answered "differently than the leaning." The full list of Sparkboard open questions lives in [Open-Questions](Open-Questions.md) — this section only highlights the ones Sprint 1 touches. All Sprint-1-blocking questions have been **decided 2026-06-24**. The full list of Sparkboard open questions lives in [Open-Questions](Open-Questions.md) — this section only logs the Sprint 1 decisions.
| ID | Question | Sprint 1 Impact | Leaning | | ID | Question | Sprint 1 Impact | ✅ Decision (2026-06-24) |
|----|----------|----------------|---------| |----|----------|----------------|--------------------------|
| **Q01** | Single-org name + ID strategy: hardcode `00000000-0000-0000-0000-000000000001` or compute? | High — affects W2 SQL + `IdeaController.FAMILY_SPARK_ID` constant. | Hardcode the all-zeros-with-trailing-1 magic UUID. Trivial to refactor to a `@ConfigurationProperties` lookup later. | | **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: edit `application.yml` and redeploy, or admin UI? | Medium — affects W1 config shape and W6 deploy story. | YAML + redeploy in v1. Admin UI is Sprint 4+. | | **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: bootstrap admins via `sparkboard.admins[]` config, or DB seed? | Medium — affects W2 (`SparkboardOnboardingHook` logic). | Config-driven (`sparkboard.admins[]`). Hook reads it at hook time and writes `ADMIN` vs `MEMBER`. | | **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: hand-crafted SVGs/PNGs in `frontend/public/` or generated? | Low — affects W4 + manifest. | Hand-crafted for v1 (4 humans, no app-store presence). Generated assets are Sprint 4. | | **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. > **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.