docs(open-questions): 10 Sparkboard Qs (Q01-Q10) with leanings
+266
@@ -0,0 +1,266 @@
|
||||
# Open Questions
|
||||
|
||||
**Status:** Living document
|
||||
**Owner:** Patrick
|
||||
**Last updated:** 2026-06-24
|
||||
|
||||
> This page captures Sparkboard-specific decisions that are **not yet locked**. Each question has a recommended **leaning** based on the Sprint 1 walking-skeleton constraints. Patrick has the final call; the leaning is what we'll build unless Patrick overrides.
|
||||
>
|
||||
> Auth and multi-tenancy questions live in plate-auth's own docs (Sparkboard consumes those decisions, not makes them).
|
||||
|
||||
---
|
||||
|
||||
## Question Map
|
||||
|
||||
| ID | Topic | Blocks Sprint | Decision needed by |
|
||||
|----|-------|--------------|-------------------|
|
||||
| Q01 | Single-org name and ID strategy | Sprint 1 (W2) | Sprint 1 kickoff |
|
||||
| Q02 | Allowlist management UX | Sprint 1 (W1) — light; Sprint 4 — heavy | Sprint 1 kickoff |
|
||||
| Q03 | Admin promotion model | Sprint 1 (W2) | Sprint 1 kickoff |
|
||||
| Q04 | Idea status workflow | Sprint 2 (Kindling) | Sprint 2 kickoff |
|
||||
| Q05 | Reaction model | 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 |
|
||||
| Q07 | PWA assets pipeline (icons, splash) | Sprint 1 (W4) | Sprint 1 mid-sprint |
|
||||
| Q08 | Mobile strategy: PWA-only vs native APK | Sprint 5 (Wildfire) | Sprint 4 retro |
|
||||
| Q09 | Real-time updates (live list refresh) | Sprint 4 (Ember) | Sprint 3 retro |
|
||||
| Q10 | Notifications: email, push, or none | Sprint 4 (Ember) | Sprint 3 retro |
|
||||
|
||||
---
|
||||
|
||||
## Q01 — Single-org name and ID strategy
|
||||
|
||||
**Question:**
|
||||
The whole of Sparkboard runs against one org. How do we identify it?
|
||||
- (A) Hardcode a magic UUID `00000000-0000-0000-0000-000000000001` everywhere.
|
||||
- (B) Look up by `org_type = 'SPARK_ORG'` on every request (assume only one row).
|
||||
- (C) Bind via `@ConfigurationProperties("sparkboard.org.id")` from `application.yml`.
|
||||
|
||||
**Why it matters:**
|
||||
This decision shows up in `IdeaController` (the `FAMILY_SPARK_ID` constant), the `SparkboardOnboardingHook`, the `V2__seed_family_spark_org.sql` migration, and any future entity that needs `org_id`.
|
||||
|
||||
**Leaning: A** (hardcode the all-zeros-with-trailing-1 magic UUID).
|
||||
|
||||
**Why:**
|
||||
- Sparkboard is single-org by definition. The constant is honest.
|
||||
- One value in one place (`IdeaController.FAMILY_SPARK_ID = UUID.fromString("00000000-0000-0000-0000-000000000001")`).
|
||||
- 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.
|
||||
|
||||
**Decision:** _Pending._
|
||||
|
||||
---
|
||||
|
||||
## Q02 — Allowlist management UX
|
||||
|
||||
**Question:**
|
||||
Who can sign in is controlled by plate-auth's allowlist. How does Patrick add/remove the 4 family humans?
|
||||
- (A) Edit `application.yml` → `plate.auth.allowlist[]` → redeploy via Gitea Actions.
|
||||
- (B) Edit a DB table → no redeploy.
|
||||
- (C) Build an admin UI (form + endpoint).
|
||||
|
||||
**Why it matters:**
|
||||
Affects W1 config shape, Sprint 4 admin-panel scope, and how forgiving the system is when a 5th human needs adding ("guest").
|
||||
|
||||
**Leaning: A** (YAML + redeploy) for v1, **B** if Patrick says manual edits feel painful, **C** is Sprint 4+.
|
||||
|
||||
**Why:**
|
||||
- 4 humans, very low churn. Editing YAML and pushing to `main` triggers a deploy and is honestly fine.
|
||||
- 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).
|
||||
|
||||
**Decision:** _Pending._
|
||||
|
||||
---
|
||||
|
||||
## Q03 — Admin promotion model
|
||||
|
||||
**Question:**
|
||||
Patrick wants to bootstrap himself (and probably the friend) as ADMIN, with the kids as MEMBER. How is that decided?
|
||||
- (A) `sparkboard.admins[]` list in `application.yml`; `SparkboardOnboardingHook` checks the user's email against it and writes ADMIN or MEMBER accordingly.
|
||||
- (B) Manual DB UPDATE after first login.
|
||||
- (C) First-user-is-admin convention.
|
||||
- (D) All users are ADMIN; no MEMBER role in v1.
|
||||
|
||||
**Why it matters:**
|
||||
Affects W2 (`SparkboardOnboardingHook` impl) and the bootstrap story for new family-member onboarding.
|
||||
|
||||
**Leaning: A** (`sparkboard.admins[]` in YAML).
|
||||
|
||||
**Why:**
|
||||
- Self-documenting (admin list is in source control).
|
||||
- No DB-edit ritual.
|
||||
- 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.
|
||||
|
||||
**Decision:** _Pending._
|
||||
|
||||
---
|
||||
|
||||
## Q04 — Idea status workflow
|
||||
|
||||
**Question:**
|
||||
In Sprint 1, the `IdeaStatus` enum exists with values `RAW`, `EXPLORING`, `BUILDING`, `SHIPPED`, `DEAD`. Default is `RAW`. **Sprint 2 (Kindling)** adds UI to change status. What's the rule?
|
||||
- (A) Free transitions: any user can move any idea from any state to any state.
|
||||
- (B) Author-only: only `Idea.authorId == currentUser.id` can change status.
|
||||
- (C) Admin-only.
|
||||
- (D) Stage-gate: only RAW→EXPLORING→BUILDING→SHIPPED, with DEAD reachable from any.
|
||||
|
||||
**Leaning: A** for v1 (free transitions), revisit if it gets messy.
|
||||
|
||||
**Why:**
|
||||
- 4 humans, low conflict probability. Free transitions = least code, most agency.
|
||||
- Author-only (B) prevents Patrick from cleaning up a kid's neglected idea, which is the wrong tradeoff for this user group.
|
||||
- Admin-only (C) makes the kids feel infantilised.
|
||||
- Stage-gate (D) is over-engineered for v1; revisit if data shows people skipping states or "stuck in BUILDING for a year" patterns.
|
||||
|
||||
**Decision:** _Pending. Not blocking Sprint 1._
|
||||
|
||||
---
|
||||
|
||||
## Q05 — Reaction model
|
||||
|
||||
**Question:**
|
||||
Sprint 2 (Kindling) introduces reactions. What does a reaction look like?
|
||||
- (A) Likes only (one-bit, per user, per idea).
|
||||
- (B) Emoji set (fixed list: 👍 ❤️ 🔥 💡 🤔).
|
||||
- (C) Custom emoji per user.
|
||||
- (D) None — skip reactions, jump to comments in Sprint 3.
|
||||
|
||||
**Leaning: B** (fixed emoji set of 4–6).
|
||||
|
||||
**Why:**
|
||||
- Likes only (A) is too cold for a family idea board.
|
||||
- Fixed emoji set (B) gives expressiveness without UX complexity (one row per `(user, idea, emoji)`).
|
||||
- Custom emoji (C) is over-engineering for 4 humans.
|
||||
- Skipping reactions (D) is plausible if comments-first feels more valuable. Decision deferred to Sprint 2 retro.
|
||||
|
||||
**Decision:** _Pending. Not blocking Sprint 1._
|
||||
|
||||
---
|
||||
|
||||
## Q06 — Security customisation: do we need any beyond plate-auth?
|
||||
|
||||
**Question:**
|
||||
plate-auth ships a default Spring Security config that secures everything under `/api/**` and exposes `/api/auth/**` for the auth flow. Does Sparkboard need to:
|
||||
- (A) Use plate-auth's defaults as-is.
|
||||
- (B) Customise the `SecurityFilterChain` (e.g., add CORS rules, custom headers, rate limiting).
|
||||
- (C) Replace plate-auth's security config entirely.
|
||||
|
||||
**Why it matters:**
|
||||
If C is the answer, plate-auth's promise of "consumers don't touch auth code" breaks.
|
||||
|
||||
**Leaning: A** (use defaults).
|
||||
|
||||
**Why:**
|
||||
- 4-user app, no rate-limiting threat.
|
||||
- Same origin (frontend + backend behind Caddy) → no CORS surface.
|
||||
- If plate-auth's defaults are wrong for Sparkboard, that's a plate-auth bug, not a Sparkboard customisation. File it back upstream.
|
||||
|
||||
**Decision:** _Pending. Sprint 1 verification: confirm A works end-to-end. Re-check in Sprint 2 if reactions/comments introduce new endpoint patterns._
|
||||
|
||||
---
|
||||
|
||||
## Q07 — PWA assets pipeline
|
||||
|
||||
**Question:**
|
||||
Sprint 1 W4 produces `manifest.json` referencing icon files. How are those assets produced?
|
||||
- (A) Hand-crafted SVG + 1–2 PNG sizes (192 + 512) committed to `frontend/public/icons/`.
|
||||
- (B) Generated from a single source SVG via a build-time tool (e.g., `pwa-asset-generator`).
|
||||
- (C) Skip icons; rely on default browser icon (PWA install will still work, just ugly).
|
||||
|
||||
**Why it matters:**
|
||||
Affects A5 acceptance ("installable PWA with correct icon"). Default browser icon (C) technically installs but doesn't feel finished.
|
||||
|
||||
**Leaning: A** (hand-crafted, 2 sizes).
|
||||
|
||||
**Why:**
|
||||
- 4 humans, no app-store. Two PNGs are enough.
|
||||
- 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.
|
||||
|
||||
**Decision:** _Pending. Sprint 1 blocker if no icon → A5 fails MT-01/MT-02._
|
||||
|
||||
---
|
||||
|
||||
## Q08 — Mobile strategy: PWA-only vs native APK
|
||||
|
||||
**Question:**
|
||||
Sprint 5 (Wildfire) optionally introduces Capacitor to package the PWA as a native APK (and iOS app). Do we go native?
|
||||
- (A) PWA only, forever. iOS share-target via PWA shortcuts; Android install via Chrome.
|
||||
- (B) PWA primary, plus a Capacitor APK for Android (cheap; native iOS deferred indefinitely).
|
||||
- (C) Full native (Capacitor APK + iOS via TestFlight + signing certs).
|
||||
|
||||
**Leaning: A** for v1; reconsider B at end of Sprint 4.
|
||||
|
||||
**Why:**
|
||||
- PWA install on iOS Safari does work (MT-01).
|
||||
- Capacitor for Android is genuinely cheap once the PWA exists.
|
||||
- iOS native is expensive (Apple developer account, signing, App Store review). Not worth it for 4 humans.
|
||||
|
||||
**Decision:** _Pending. Not blocking Sprint 1._
|
||||
|
||||
---
|
||||
|
||||
## Q09 — Real-time updates
|
||||
|
||||
**Question:**
|
||||
When User A creates an idea, does User B's open `/ideas` page refresh automatically?
|
||||
- (A) No real-time; rely on Next.js revalidation + manual refresh.
|
||||
- (B) Server-Sent Events (one-way push from backend to frontend).
|
||||
- (C) WebSockets (two-way, overkill for this).
|
||||
- (D) Polling every 10 seconds.
|
||||
|
||||
**Leaning: A** for v1/v2; **B** in Sprint 4 if it feels stale.
|
||||
|
||||
**Why:**
|
||||
- 4 humans, low concurrent-write rate. "Pull to refresh" is fine for v1.
|
||||
- SSE (B) is the cheapest real-time option (single endpoint, browser native).
|
||||
- WebSockets (C) costs more infrastructure for no real benefit at 4 users.
|
||||
- Polling (D) wastes bandwidth and battery.
|
||||
|
||||
**Decision:** _Pending. Not blocking Sprint 1._
|
||||
|
||||
---
|
||||
|
||||
## Q10 — Notifications
|
||||
|
||||
**Question:**
|
||||
Sprint 4 (Ember) lands notifications. What channels?
|
||||
- (A) Email digest (daily summary of new ideas).
|
||||
- (B) Web push (browser-side push notifications).
|
||||
- (C) Both.
|
||||
- (D) None — Sparkboard is pull-only.
|
||||
|
||||
**Why it matters:**
|
||||
Affects Sprint 4 architecture (SMTP integration vs Web Push API + VAPID keys).
|
||||
|
||||
**Leaning: A** (email digest first, then reassess for B).
|
||||
|
||||
**Why:**
|
||||
- Email is dead-simple: SMTP via SendGrid or postfix on TrueNAS; daily cron.
|
||||
- Web push requires VAPID keys, service-worker logic (sw.js becomes real, not a stub), and per-user permission grants. Higher effort, less reliable on iOS.
|
||||
- A daily email is genuinely useful for a family idea board (low rate of new items).
|
||||
- D ("none") is plausible if Sprint 3 reveals that the 4 humans naturally check the app regularly without prompting.
|
||||
|
||||
**Decision:** _Pending. Not blocking Sprint 1._
|
||||
|
||||
---
|
||||
|
||||
## Resolved Questions (Archive)
|
||||
|
||||
> When a question is decided, move it here with the resolution and date. Keeps Q01–Q10 numbering stable.
|
||||
|
||||
_None yet._
|
||||
|
||||
---
|
||||
|
||||
## Cross-references
|
||||
|
||||
- [Sprint-1-Plan](Sprint-1-Plan.md) and [Sprint-1-Plan-Part-4](Sprint-1-Plan-Part-4.md) — Sprint-1 impact of Q01, Q02, Q03, Q07
|
||||
- [Roadmap](Roadmap.md) — when each unresolved question is scheduled to bite
|
||||
- [Architecture](Architecture.md) — context for Q01 (single-org), Q06 (security)
|
||||
- plate-auth wiki — for auth-side decisions (NOT in this list)
|
||||
|
||||
---
|
||||
|
||||
_End of Open Questions. Status: **10 open, 0 resolved.**_
|
||||
Reference in New Issue
Block a user